From 66ed7e8f155362fd305f834a172f780daa809d4f Mon Sep 17 00:00:00 2001 From: Anurag Chouhan Date: Wed, 18 Apr 2018 19:21:20 +0530 Subject: [PATCH 0001/1299] icnss: Set fw down at server exit indication Set FW down at server exit indication and ignore qmi assert. CRs-Fixed: 2226499 Change-Id: Idf52eff58993e35573043ee1eb985638bd97cf85 Signed-off-by: Anurag Chouhan --- drivers/soc/qcom/icnss_qmi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/icnss_qmi.c b/drivers/soc/qcom/icnss_qmi.c index 55ae54514dcc..ccfa74a1e2e6 100644 --- a/drivers/soc/qcom/icnss_qmi.c +++ b/drivers/soc/qcom/icnss_qmi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1123,7 +1123,15 @@ static int wlfw_new_server(struct qmi_handle *qmi, static void wlfw_del_server(struct qmi_handle *qmi, struct qmi_service *service) { + struct icnss_priv *priv = container_of(qmi, struct icnss_priv, qmi); + icnss_pr_dbg("WLFW server delete\n"); + + if (priv) { + set_bit(ICNSS_FW_DOWN, &priv->state); + icnss_ignore_fw_timeout(true); + } + icnss_driver_event_post(ICNSS_DRIVER_EVENT_SERVER_EXIT, 0, NULL); } -- GitLab From 5ee5050ea7756707d95e5865cc9872d0f2e985a0 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Mon, 21 May 2018 18:51:08 -0700 Subject: [PATCH 0002/1299] msm: usb_bam: remove unused uninitialized variable Remove the local variable 'bam' in usb_bam_sps_events() along with the not very useful log message that was accessing it uninitialized. Change-Id: I07bd5f7c14463af17311ee6a1092f7b89bf017d1 Signed-off-by: Jack Pham --- drivers/platform/msm/usb_bam.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c index ab877f296520..148ca2fb3653 100644 --- a/drivers/platform/msm/usb_bam.c +++ b/drivers/platform/msm/usb_bam.c @@ -962,7 +962,6 @@ int usb_bam_disconnect_pipe(enum usb_ctrl bam_type, u8 idx) static void usb_bam_sps_events(enum sps_callback_case sps_cb_case, void *user) { int i; - int bam; struct usb_bam_ctx_type *ctx = user; struct usb_bam_pipe_connect *pipe_connect; struct usb_bam_event_info *event_info; @@ -976,8 +975,6 @@ static void usb_bam_sps_events(enum sps_callback_case sps_cb_case, void *user) spin_lock(&ctx->usb_bam_lock); ctx->is_bam_inactivity = true; - log_event_dbg("%s: Inactivity happened on bam=%s,%d\n", - __func__, (char *)user, bam); for (i = 0; i < ctx->max_connections; i++) { pipe_connect = &ctx->usb_bam_connections[i]; -- GitLab From 5e02c63e407f469b23ef16f3abbca7acd6f3da1b Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Thu, 17 May 2018 01:00:02 -0700 Subject: [PATCH 0003/1299] msm: vidc: Fix double list_del in rbr event processing Do not use mbuf after kref_put_mbuf() instead get the mbuf from the registered bufs list to use it again. Using the same mbuf after kref_put_mbuf() might lead to video failures. Change-Id: I69f03ca1f9b7d607d407952e7a83d4977962cc5d Signed-off-by: Maheshwar Ajja --- .../media/platform/msm/vidc/msm_vidc_common.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index a9bf66952f61..9e03d7917100 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -6269,6 +6269,7 @@ void handle_release_buffer_reference(struct msm_vidc_inst *inst, struct msm_vidc_buffer *temp; bool found = false; int i = 0; + u32 planes[VIDEO_MAX_PLANES] = {0}; mutex_lock(&inst->flush_lock); mutex_lock(&inst->registeredbufs.lock); @@ -6282,6 +6283,10 @@ void handle_release_buffer_reference(struct msm_vidc_inst *inst, } } if (found) { + /* save device_addr */ + for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) + planes[i] = mbuf->smem[i].device_addr; + /* send RBR event to client */ msm_vidc_queue_rbr_event(inst, mbuf->vvb.vb2_buf.planes[0].m.fd, @@ -6299,6 +6304,7 @@ void handle_release_buffer_reference(struct msm_vidc_inst *inst, if (!mbuf->smem[0].refcount) { list_del(&mbuf->list); kref_put_mbuf(mbuf); + mbuf = NULL; } } else { print_vidc_buffer(VIDC_ERR, "mbuf not found", inst, mbuf); @@ -6316,8 +6322,8 @@ void handle_release_buffer_reference(struct msm_vidc_inst *inst, */ found = false; list_for_each_entry(temp, &inst->registeredbufs.list, list) { - if (msm_comm_compare_vb2_plane(inst, mbuf, - &temp->vvb.vb2_buf, 0)) { + if (msm_comm_compare_device_plane(temp, planes, 0)) { + mbuf = temp; found = true; break; } @@ -6337,9 +6343,11 @@ void handle_release_buffer_reference(struct msm_vidc_inst *inst, /* don't queue the buffer */ found = false; } - /* clear DEFERRED flag, if any, as the buffer is going to be queued */ - if (found) + /* clear required flags as the buffer is going to be queued */ + if (found) { mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED; + mbuf->flags &= ~MSM_VIDC_FLAG_RBR_PENDING; + } unlock: mutex_unlock(&inst->registeredbufs.lock); -- GitLab From 590aaf426c51276f15ae19283084db82f8e432ae Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Samavedam Date: Tue, 22 May 2018 16:19:49 -0700 Subject: [PATCH 0004/1299] usb: dwc3: Enable l1_suspend_n signal for host mode L1 suspend enables the PHY's utmi clock to be powered off during L1 suspend which can save power during audio playback using usb audio headphones Change-Id: I9711ed625df119c48f4edddb8d1a0e48315e037b Signed-off-by: Vamsi Krishna Samavedam --- drivers/usb/dwc3/core.c | 21 +++++++++++++++++++++ drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/dwc3-msm.c | 5 +++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 10a3ff124290..c6583538ee68 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -132,6 +132,27 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) dwc3_writel(dwc->regs, DWC3_GCTL, reg); } +void dwc3_en_sleep_mode(struct dwc3 *dwc) +{ + u32 reg; + + if (dwc->dis_enblslpm_quirk) + return; + + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg |= DWC3_GUSB2PHYCFG_ENBLSLPM; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); +} + +void dwc3_dis_sleep_mode(struct dwc3 *dwc) +{ + u32 reg; + + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); +} + void dwc3_set_mode(struct dwc3 *dwc, u32 mode) { unsigned long flags; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 64e0fd0b33cf..8642e20bb2bc 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1322,6 +1322,8 @@ struct dwc3_gadget_ep_cmd_params { /* prototypes */ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode); +void dwc3_en_sleep_mode(struct dwc3 *dwc); +void dwc3_dis_sleep_mode(struct dwc3 *dwc); void dwc3_set_mode(struct dwc3 *dwc, u32 mode); u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type); diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 85142b7e5d7e..98e345a97748 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -2468,8 +2468,7 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) /* Disable HSPHY auto suspend */ dwc3_msm_write_reg(mdwc->base, DWC3_GUSB2PHYCFG(0), dwc3_msm_read_reg(mdwc->base, DWC3_GUSB2PHYCFG(0)) & - ~(DWC3_GUSB2PHYCFG_ENBLSLPM | - DWC3_GUSB2PHYCFG_SUSPHY)); + ~DWC3_GUSB2PHYCFG_SUSPHY); /* Disable wakeup capable for HS_PHY IRQ & SS_PHY_IRQ if enabled */ if (mdwc->lpm_flags & MDWC3_ASYNC_IRQ_WAKE_CAPABILITY) { @@ -3664,6 +3663,7 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on) usb_register_notify(&mdwc->host_nb); dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); + dwc3_en_sleep_mode(dwc); mdwc->usbdev_nb.notifier_call = msm_dwc3_usbdev_notify; usb_register_atomic_notify(&mdwc->usbdev_nb); ret = dwc3_host_init(dwc); @@ -3791,6 +3791,7 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on) */ dwc3_msm_block_reset(mdwc, false); dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); + dwc3_dis_sleep_mode(dwc); mdwc->in_device_mode = true; usb_gadget_vbus_connect(&dwc->gadget); #ifdef CONFIG_SMP -- GitLab From 79a5a3af469e5d38c649dbe3dc7340d96990fd68 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Wed, 25 Oct 2017 14:39:06 +0530 Subject: [PATCH 0005/1299] usb: f_uac2: Add support for UAC2 function Add support for the UAC2 function with the configfs framework. Also fix the audio quality issues by increasing the number of USB_XFERS. Change-Id: Ie94aee43dd52b0b711778420e485af72730dd28b Signed-off-by: Sriharsha Allenki --- drivers/usb/gadget/function/f_uac2.c | 67 +++++++++++++++++++++++++++- drivers/usb/gadget/function/u_uac2.h | 2 +- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index f05c3f3e6103..addc082f5bcf 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -18,6 +18,9 @@ #include "u_audio.h" #include "u_uac2.h" +/* Keep everyone on toes */ +#define USB_XFERS 8 + /* * The driver implements a simple UAC_2 topology. * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture @@ -292,6 +295,13 @@ static struct usb_endpoint_descriptor hs_epout_desc = { .bInterval = 4, }; +static struct usb_ss_ep_comp_descriptor ss_epout_comp_desc = { + .bLength = sizeof(ss_epout_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + .wBytesPerInterval = cpu_to_le16(1024), +}; + /* CS AS ISO OUT Endpoint */ static struct uac2_iso_endpoint_descriptor as_iso_out_desc = { .bLength = sizeof as_iso_out_desc, @@ -369,6 +379,13 @@ static struct usb_endpoint_descriptor hs_epin_desc = { .bInterval = 4, }; +static struct usb_ss_ep_comp_descriptor ss_epin_comp_desc = { + .bLength = sizeof(ss_epin_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + .wBytesPerInterval = cpu_to_le16(1024), +}; + /* CS AS ISO IN Endpoint */ static struct uac2_iso_endpoint_descriptor as_iso_in_desc = { .bLength = sizeof as_iso_in_desc, @@ -441,6 +458,38 @@ static struct usb_descriptor_header *hs_audio_desc[] = { NULL, }; +static struct usb_descriptor_header *ss_audio_desc[] = { + (struct usb_descriptor_header *)&iad_desc, + (struct usb_descriptor_header *)&std_ac_if_desc, + + (struct usb_descriptor_header *)&ac_hdr_desc, + (struct usb_descriptor_header *)&in_clk_src_desc, + (struct usb_descriptor_header *)&out_clk_src_desc, + (struct usb_descriptor_header *)&usb_out_it_desc, + (struct usb_descriptor_header *)&io_in_it_desc, + (struct usb_descriptor_header *)&usb_in_ot_desc, + (struct usb_descriptor_header *)&io_out_ot_desc, + + (struct usb_descriptor_header *)&std_as_out_if0_desc, + (struct usb_descriptor_header *)&std_as_out_if1_desc, + + (struct usb_descriptor_header *)&as_out_hdr_desc, + (struct usb_descriptor_header *)&as_out_fmt1_desc, + (struct usb_descriptor_header *)&hs_epout_desc, + (struct usb_descriptor_header *)&ss_epout_comp_desc, + (struct usb_descriptor_header *)&as_iso_out_desc, + + (struct usb_descriptor_header *)&std_as_in_if0_desc, + (struct usb_descriptor_header *)&std_as_in_if1_desc, + + (struct usb_descriptor_header *)&as_in_hdr_desc, + (struct usb_descriptor_header *)&as_in_fmt1_desc, + (struct usb_descriptor_header *)&hs_epin_desc, + (struct usb_descriptor_header *)&ss_epin_comp_desc, + (struct usb_descriptor_header *)&as_iso_in_desc, + NULL, +}; + struct cntrl_cur_lay3 { __u32 dCUR; }; @@ -529,6 +578,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) return ret; } std_ac_if_desc.bInterfaceNumber = ret; + iad_desc.bFirstInterface = ret; uac2->ac_intf = ret; uac2->ac_alt = 0; @@ -580,8 +630,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; - ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL, - NULL); + ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, + ss_audio_desc, NULL); if (ret) return ret; @@ -1009,6 +1059,19 @@ static struct usb_function *afunc_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(uac2, afunc_alloc_inst, afunc_alloc); + +static int afunc_init(void) +{ + return usb_function_register(&uac2usb_func); +} +module_init(afunc_init); + +static void __exit afunc_exit(void) +{ + usb_function_unregister(&uac2usb_func); +} +module_exit(afunc_exit); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yadwinder Singh"); MODULE_AUTHOR("Jaswinder Singh"); diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h index 19eeb83538a5..f2d1a2b83eff 100644 --- a/drivers/usb/gadget/function/u_uac2.h +++ b/drivers/usb/gadget/function/u_uac2.h @@ -22,7 +22,7 @@ #define UAC2_DEF_PSRATE 48000 #define UAC2_DEF_PSSIZE 2 #define UAC2_DEF_CCHMASK 0x3 -#define UAC2_DEF_CSRATE 64000 +#define UAC2_DEF_CSRATE 44100 #define UAC2_DEF_CSSIZE 2 #define UAC2_DEF_REQ_NUM 2 -- GitLab From 7fcb25a07d8dd8322196f19ae631cbe1bfa13797 Mon Sep 17 00:00:00 2001 From: Mihir Shete Date: Thu, 27 Mar 2014 13:04:15 +0530 Subject: [PATCH 0006/1299] cfg80211: unblock user hint when cfg80211_regdom is intersected If the driver is loaded when cfg80211_regdom is intersected then user hint will fail for the first time since cfg80211 does not have a check to see if cfg80211_regdom is intersected. Add a check to see if cf80211_regdom is intersected and allow the user hint to be processed. Change-Id: Iba9cdd32470e29d35d3bb35012eb404b7c78d601 CRs-Fixed: 639538 Signed-off-by: Mihir Shete --- net/wireless/reg.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 6dfb274c27b1..bbd39109aad6 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -419,6 +419,11 @@ static bool is_user_regdom_saved(void) return true; } +static bool is_cfg80211_regdom_intersected(void) +{ + return is_intersected_alpha2(get_cfg80211_regdom()->alpha2); +} + static const struct ieee80211_regdomain * reg_copy_regd(const struct ieee80211_regdomain *src_regd) { @@ -1875,9 +1880,14 @@ __reg_process_hint_user(struct regulatory_request *user_request) */ if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE || lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || - lr->initiator == NL80211_REGDOM_SET_BY_USER) && - regdom_changes(lr->alpha2)) - return REG_REQ_IGNORE; + lr->initiator == NL80211_REGDOM_SET_BY_USER)) { + if (lr->intersect) { + if (!is_cfg80211_regdom_intersected()) + return REG_REQ_IGNORE; + } else if (regdom_changes(lr->alpha2)) { + return REG_REQ_IGNORE; + } + } if (!regdom_changes(user_request->alpha2)) return REG_REQ_ALREADY_SET; -- GitLab From 53aaccb478425c8cfa9eaa3366c6d5f4ba1f6a37 Mon Sep 17 00:00:00 2001 From: Sachin Ahuja Date: Mon, 28 Apr 2014 15:26:53 +0530 Subject: [PATCH 0007/1299] cfg80211: avoid restoring the regulatory during disconnect Driver configures the default country code during bootup. When STA disconnects, cfg80211 restore the regulatory setting to world domain.cfg80211 should remain in the default country code and not restore to world reg domain. Change-Id: I01ccdc4d2831cf252a4b35f9f856f3256d9b7429 CRs-Fixed: 1023778 Signed-off-by: Sachin Ahuja [joshc: fixed hunk in disconnect_work() - moved cfg80211_is_all_countryie_ignore() check into new location, collapsed conditional and use upstream REGULATORY_COUNTRY_IE_IGNORE regulatory flag] Signed-off-by: Josh Cartwright --- net/wireless/sme.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index d014aea07160..c7cd051e986e 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -51,6 +51,29 @@ struct cfg80211_conn { bool auto_auth, prev_bssid_valid; }; +static bool cfg80211_is_all_countryie_ignore(void) +{ + struct cfg80211_registered_device *rdev; + struct wireless_dev *wdev; + bool is_all_countryie_ignore = true; + + list_for_each_entry(rdev, &cfg80211_rdev_list, list) { + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { + wdev_lock(wdev); + if (!(wdev->wiphy->regulatory_flags & + REGULATORY_COUNTRY_IE_IGNORE)) { + is_all_countryie_ignore = false; + wdev_unlock(wdev); + goto out; + } + wdev_unlock(wdev); + } + } + +out: + return is_all_countryie_ignore; +} + static void cfg80211_sme_free(struct wireless_dev *wdev) { if (!wdev->conn) @@ -658,7 +681,8 @@ static bool cfg80211_is_all_idle(void) static void disconnect_work(struct work_struct *work) { rtnl_lock(); - if (cfg80211_is_all_idle()) + if (cfg80211_is_all_idle() && + !cfg80211_is_all_countryie_ignore()) regulatory_hint_disconnect(); rtnl_unlock(); } -- GitLab From 017044fd3db263d353427b8d6796a7d5225b8f7e Mon Sep 17 00:00:00 2001 From: Shashank Babu Chinta Venkata Date: Fri, 1 Jun 2018 11:28:18 -0700 Subject: [PATCH 0008/1299] ARM: dts: msm: move default display for SM8150 CDP and MTP to overlay Move default display for sm8150 MTP and CDP to their respective overlay files. Change-Id: Iddd79d1e8a0cbdd4253f062cb1b3fe66d5d1e445 Signed-off-by: Shashank Babu Chinta Venkata --- arch/arm64/boot/dts/qcom/sm8150-cdp-overlay.dts | 4 ++++ arch/arm64/boot/dts/qcom/sm8150-cdp.dtsi | 4 ---- arch/arm64/boot/dts/qcom/sm8150-mtp-overlay.dts | 4 ++++ arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi | 4 ---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-cdp-overlay.dts index 20c9e2ddf327..a466bace1e2b 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-cdp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-cdp-overlay.dts @@ -25,3 +25,7 @@ compatible = "qcom,sm8150-cdp", "qcom,sm8150", "qcom,cdp"; qcom,board-id = <1 0>; }; + +&dsi_sharp_4k_dsc_cmd_display { + qcom,dsi-display-active; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-cdp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-cdp.dtsi index cf5a6bcd98e8..4dad8f419340 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-cdp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-cdp.dtsi @@ -253,10 +253,6 @@ }; }; -&dsi_sharp_4k_dsc_cmd_display { - qcom,dsi-display-active; -}; - &ufsphy_mem { compatible = "qcom,ufs-phy-qmp-v4"; diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-mtp-overlay.dts index 4721c8b51c48..877a93e7cfb9 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp-overlay.dts @@ -25,3 +25,7 @@ compatible = "qcom,sm8150-mtp", "qcom,sm8150", "qcom,mtp"; qcom,board-id = <8 0>; }; + +&dsi_sharp_4k_dsc_cmd_display { + qcom,dsi-display-active; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi index 57c9c44fa260..eedce940b0d2 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi @@ -237,10 +237,6 @@ qcom,platform-reset-gpio = <&tlmm 6 0>; }; -&dsi_sharp_4k_dsc_cmd_display { - qcom,dsi-display-active; -}; - &qupv3_se9_i2c { status = "ok"; nq@28 { -- GitLab From 3db8c841d2f799bf3811312944997a153c120972 Mon Sep 17 00:00:00 2001 From: Ajay Singh Parmar Date: Tue, 24 Apr 2018 11:58:01 -0700 Subject: [PATCH 0009/1299] drm/msm/dp: process link update with cp irq In some cases, sink can issue CP (Content Protection) interrupt along with link update interrupt. Handle link update request first and then cp irq to make sure link has been updated properly before re-authentication. Change-Id: I9fc14b426f20eb3c08dc64f2787a7acd2f5cfa06 Signed-off-by: Ajay Singh Parmar Signed-off-by: Tatenda Chipeperekwa --- drivers/gpu/drm/msm/dp/dp_display.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 5818caac4c82..a2df284b70dc 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -824,11 +824,6 @@ static void dp_display_attention_work(struct work_struct *work) if (!dp->power_on) goto mst_attention; - if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->cp_irq) { - if (!dp->hdcp.ops->cp_irq(dp->hdcp.data)) - goto mst_attention; - } - if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) { dp_display_handle_disconnect(dp); @@ -856,16 +851,17 @@ static void dp_display_attention_work(struct work_struct *work) goto mst_attention; } - if (dp->link->sink_request & DP_LINK_STATUS_UPDATED) { + if (dp->link->sink_request & DP_TEST_LINK_TRAINING) { + dp->link->send_test_response(dp->link); dp_display_handle_maintenance_req(dp); goto mst_attention; } - if (dp->link->sink_request & DP_TEST_LINK_TRAINING) { - dp->link->send_test_response(dp->link); + if (dp->link->sink_request & DP_LINK_STATUS_UPDATED) dp_display_handle_maintenance_req(dp); - } + if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->cp_irq) + dp->hdcp.ops->cp_irq(dp->hdcp.data); mst_attention: dp_display_mst_attention(dp); } -- GitLab From 23cdb2e222292d4645c9ddd290090cc52d7288ea Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 1 Jun 2018 17:46:23 -0700 Subject: [PATCH 0010/1299] drm/msm/sde: reduce the arguments to setup_scaler3 function Remove unnecessary arguments passed to setup_scaler3 function in planes as most of the arguments can be derived from the sde_plane and sde_plane_state structures. Change-Id: Ie112f5d95532eea564c159ae5aadfe5727c6c6f8 Signed-off-by: Veera Sundaram Sankaran --- drivers/gpu/drm/msm/sde/sde_plane.c | 34 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index e0e9d10c5d98..f44e74561220 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -1077,23 +1077,26 @@ static int _sde_plane_setup_scaler3_lut(struct sde_plane *psde, } static void _sde_plane_setup_scaler3(struct sde_plane *psde, - struct sde_plane_state *pstate, - uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h, - struct sde_hw_scaler3_cfg *scale_cfg, - const struct sde_format *fmt, + struct sde_plane_state *pstate, const struct sde_format *fmt, uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v) { - uint32_t decimated, i; - - if (!psde || !pstate || !scale_cfg || !fmt || !chroma_subsmpl_h || - !chroma_subsmpl_v) { - SDE_ERROR( - "psde %d pstate %d scale_cfg %d fmt %d smp_h %d smp_v %d\n", - !!psde, !!pstate, !!scale_cfg, !!fmt, chroma_subsmpl_h, - chroma_subsmpl_v); + uint32_t decimated, i, src_w, src_h, dst_w, dst_h; + struct sde_hw_scaler3_cfg *scale_cfg; + + if (!psde || !pstate || !fmt || + !chroma_subsmpl_h || !chroma_subsmpl_v) { + SDE_ERROR("psde %d pstate %d fmt %d smp_h %d smp_v %d\n", + !!psde, !!pstate, !!fmt, chroma_subsmpl_h, + chroma_subsmpl_v); return; } + scale_cfg = &pstate->scaler3_cfg; + src_w = psde->pipe_cfg.src_rect.w; + src_h = psde->pipe_cfg.src_rect.h; + dst_w = psde->pipe_cfg.dst_rect.w; + dst_h = psde->pipe_cfg.dst_rect.h; + memset(scale_cfg, 0, sizeof(*scale_cfg)); memset(&pstate->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext)); @@ -1501,12 +1504,7 @@ static void _sde_plane_setup_scaler(struct sde_plane *psde, if (rc || pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2) { /* calculate default config for QSEED3 */ - _sde_plane_setup_scaler3(psde, pstate, - psde->pipe_cfg.src_rect.w, - psde->pipe_cfg.src_rect.h, - psde->pipe_cfg.dst_rect.w, - psde->pipe_cfg.dst_rect.h, - &pstate->scaler3_cfg, fmt, + _sde_plane_setup_scaler3(psde, pstate, fmt, chroma_subsmpl_h, chroma_subsmpl_v); } } else if (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V1 || -- GitLab From 544f86ff0ac3508ee96a26a1f84c3b16069d6e11 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 17 Apr 2018 16:33:10 +0200 Subject: [PATCH 0011/1299] mm: prepare for FAULT_FLAG_SPECULATIVE When speculating faults (without holding mmap_sem) we need to validate that the vma against which we loaded pages is still valid when we're ready to install the new PTE. Therefore, replace the pte_offset_map_lock() calls that (re)take the PTL with pte_map_lock() which can fail in case we find the VMA changed since we started the fault. Signed-off-by: Peter Zijlstra (Intel) [Port to 4.12 kernel] [Remove the comment about the fault_env structure which has been implemented as the vm_fault structure in the kernel] [move pte_map_lock()'s definition upper in the file] [move the define of FAULT_FLAG_SPECULATIVE later in the series] [review error path in do_swap_page(), do_anonymous_page() and wp_page_copy()] Signed-off-by: Laurent Dufour Change-Id: Id6dfae130fbfdd4bb92aa6415d6f1db7ef833266 [vinmenon@codeaurora.org: fix trivial merge conflicts] Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:10 Signed-off-by: Vinayak Menon --- mm/memory.c | 88 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 29 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 6fb74d4bf7bb..c0e7fb2e111d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2270,6 +2270,13 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr, } EXPORT_SYMBOL_GPL(apply_to_page_range); +static inline bool pte_map_lock(struct vm_fault *vmf) +{ + vmf->pte = pte_offset_map_lock(vmf->vma->vm_mm, vmf->pmd, + vmf->address, &vmf->ptl); + return true; +} + /* * handle_pte_fault chooses page fault handler according to an entry which was * read non-atomically. Before making any commitment, on those architectures @@ -2459,25 +2466,26 @@ static int wp_page_copy(struct vm_fault *vmf) const unsigned long mmun_start = vmf->address & PAGE_MASK; const unsigned long mmun_end = mmun_start + PAGE_SIZE; struct mem_cgroup *memcg; + int ret = VM_FAULT_OOM; if (unlikely(anon_vma_prepare(vma))) - goto oom; + goto out; if (is_zero_pfn(pte_pfn(vmf->orig_pte))) { new_page = alloc_zeroed_user_highpage_movable(vma, vmf->address); if (!new_page) - goto oom; + goto out; } else { new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vmf->address); if (!new_page) - goto oom; + goto out; cow_user_page(new_page, old_page, vmf->address, vma); } if (mem_cgroup_try_charge(new_page, mm, GFP_KERNEL, &memcg, false)) - goto oom_free_new; + goto out_free_new; __SetPageUptodate(new_page); @@ -2486,7 +2494,10 @@ static int wp_page_copy(struct vm_fault *vmf) /* * Re-check the pte - we dropped the lock */ - vmf->pte = pte_offset_map_lock(mm, vmf->pmd, vmf->address, &vmf->ptl); + if (!pte_map_lock(vmf)) { + ret = VM_FAULT_RETRY; + goto out_uncharge; + } if (likely(pte_same(*vmf->pte, vmf->orig_pte))) { if (old_page) { if (!PageAnon(old_page)) { @@ -2569,12 +2580,14 @@ static int wp_page_copy(struct vm_fault *vmf) put_page(old_page); } return page_copied ? VM_FAULT_WRITE : 0; -oom_free_new: +out_uncharge: + mem_cgroup_cancel_charge(new_page, memcg, false); +out_free_new: put_page(new_page); -oom: +out: if (old_page) put_page(old_page); - return VM_FAULT_OOM; + return ret; } /** @@ -2595,8 +2608,8 @@ static int wp_page_copy(struct vm_fault *vmf) int finish_mkwrite_fault(struct vm_fault *vmf) { WARN_ON_ONCE(!(vmf->vma->vm_flags & VM_SHARED)); - vmf->pte = pte_offset_map_lock(vmf->vma->vm_mm, vmf->pmd, vmf->address, - &vmf->ptl); + if (!pte_map_lock(vmf)) + return VM_FAULT_RETRY; /* * We might have raced with another page fault while we released the * pte_offset_map_lock. @@ -2714,8 +2727,11 @@ static int do_wp_page(struct vm_fault *vmf) get_page(vmf->page); pte_unmap_unlock(vmf->pte, vmf->ptl); lock_page(vmf->page); - vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + if (!pte_map_lock(vmf)) { + unlock_page(vmf->page); + put_page(vmf->page); + return VM_FAULT_RETRY; + } if (!pte_same(*vmf->pte, vmf->orig_pte)) { unlock_page(vmf->page); pte_unmap_unlock(vmf->pte, vmf->ptl); @@ -2903,11 +2919,16 @@ int do_swap_page(struct vm_fault *vmf) if (!page) { /* - * Back out if somebody else faulted in this pte - * while we released the pte lock. + * Back out if the VMA has changed in our back during + * a speculative page fault or if somebody else + * faulted in this pte while we released the pte lock. */ - vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + if (!pte_map_lock(vmf)) { + delayacct_clear_flag(DELAYACCT_PF_SWAPIN); + ret = VM_FAULT_RETRY; + goto out; + } + if (likely(pte_same(*vmf->pte, vmf->orig_pte))) ret = VM_FAULT_OOM; delayacct_clear_flag(DELAYACCT_PF_SWAPIN); @@ -2960,10 +2981,13 @@ int do_swap_page(struct vm_fault *vmf) } /* - * Back out if somebody else already faulted in this pte. + * Back out if the VMA has changed in our back during a speculative + * page fault or if somebody else already faulted in this pte. */ - vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, vmf->address, - &vmf->ptl); + if (!pte_map_lock(vmf)) { + ret = VM_FAULT_RETRY; + goto out_cancel_cgroup; + } if (unlikely(!pte_same(*vmf->pte, vmf->orig_pte))) goto out_nomap; @@ -3040,8 +3064,9 @@ int do_swap_page(struct vm_fault *vmf) out: return ret; out_nomap: - mem_cgroup_cancel_charge(page, memcg, false); pte_unmap_unlock(vmf->pte, vmf->ptl); +out_cancel_cgroup: + mem_cgroup_cancel_charge(page, memcg, false); out_page: unlock_page(page); out_release: @@ -3092,8 +3117,8 @@ static int do_anonymous_page(struct vm_fault *vmf) !mm_forbids_zeropage(vma->vm_mm)) { entry = pte_mkspecial(pfn_pte(my_zero_pfn(vmf->address), vma->vm_page_prot)); - vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + if (!pte_map_lock(vmf)) + return VM_FAULT_RETRY; if (!pte_none(*vmf->pte)) goto unlock; ret = check_stable_address_space(vma->vm_mm); @@ -3128,14 +3153,16 @@ static int do_anonymous_page(struct vm_fault *vmf) if (vma->vm_flags & VM_WRITE) entry = pte_mkwrite(pte_mkdirty(entry)); - vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, vmf->address, - &vmf->ptl); - if (!pte_none(*vmf->pte)) + if (!pte_map_lock(vmf)) { + ret = VM_FAULT_RETRY; goto release; + } + if (!pte_none(*vmf->pte)) + goto unlock_and_release; ret = check_stable_address_space(vma->vm_mm); if (ret) - goto release; + goto unlock_and_release; /* Deliver the page fault to userland, check inside PT lock */ if (userfaultfd_missing(vma)) { @@ -3157,10 +3184,12 @@ static int do_anonymous_page(struct vm_fault *vmf) unlock: pte_unmap_unlock(vmf->pte, vmf->ptl); return ret; +unlock_and_release: + pte_unmap_unlock(vmf->pte, vmf->ptl); release: mem_cgroup_cancel_charge(page, memcg, false); put_page(page); - goto unlock; + return ret; oom_free_page: put_page(page); oom: @@ -3253,8 +3282,9 @@ static int pte_alloc_one_map(struct vm_fault *vmf) * pte_none() under vmf->ptl protection when we return to * alloc_set_pte(). */ - vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, vmf->address, - &vmf->ptl); + if (!pte_map_lock(vmf)) + return VM_FAULT_RETRY; + return 0; } -- GitLab From b17c74805d07f3ec74282e24878e00db9a83da64 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:11 +0200 Subject: [PATCH 0012/1299] mm: introduce pte_spinlock for FAULT_FLAG_SPECULATIVE When handling page fault without holding the mmap_sem the fetch of the pte lock pointer and the locking will have to be done while ensuring that the VMA is not touched in our back. So move the fetch and locking operations in a dedicated function. Change-Id: If93ab95b1d22b7195e1c15b57315021f6be7c394 Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:11 Signed-off-by: Vinayak Menon --- mm/memory.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index c0e7fb2e111d..088b0b893fc0 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2270,6 +2270,13 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr, } EXPORT_SYMBOL_GPL(apply_to_page_range); +static inline bool pte_spinlock(struct vm_fault *vmf) +{ + vmf->ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd); + spin_lock(vmf->ptl); + return true; +} + static inline bool pte_map_lock(struct vm_fault *vmf) { vmf->pte = pte_offset_map_lock(vmf->vma->vm_mm, vmf->pmd, @@ -3763,8 +3770,8 @@ static int do_numa_page(struct vm_fault *vmf) * validation through pte_unmap_same(). It's of NUMA type but * the pfn may be screwed if the read is non atomic. */ - vmf->ptl = pte_lockptr(vma->vm_mm, vmf->pmd); - spin_lock(vmf->ptl); + if (!pte_spinlock(vmf)) + return VM_FAULT_RETRY; if (unlikely(!pte_same(*vmf->pte, vmf->orig_pte))) { pte_unmap_unlock(vmf->pte, vmf->ptl); goto out; @@ -3956,8 +3963,8 @@ static int handle_pte_fault(struct vm_fault *vmf) if (pte_protnone(vmf->orig_pte) && vma_is_accessible(vmf->vma)) return do_numa_page(vmf); - vmf->ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd); - spin_lock(vmf->ptl); + if (!pte_spinlock(vmf)) + return VM_FAULT_RETRY; entry = vmf->orig_pte; if (unlikely(!pte_same(*vmf->pte, entry))) goto unlock; -- GitLab From 52bf7a902ff168f8367883eb251203c2a6a1920a Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:12 +0200 Subject: [PATCH 0013/1299] mm: make pte_unmap_same compatible with SPF pte_unmap_same() is making the assumption that the page table are still around because the mmap_sem is held. This is no more the case when running a speculative page fault and additional check must be made to ensure that the final page table are still there. This is now done by calling pte_spinlock() to check for the VMA's consistency while locking for the page tables. This is requiring passing a vm_fault structure to pte_unmap_same() which is containing all the needed parameters. As pte_spinlock() may fail in the case of a speculative page fault, if the VMA has been touched in our back, pte_unmap_same() should now return 3 cases : 1. pte are the same (0) 2. pte are different (VM_FAULT_PTNOTSAME) 3. a VMA's changes has been detected (VM_FAULT_RETRY) The case 2 is handled by the introduction of a new VM_FAULT flag named VM_FAULT_PTNOTSAME which is then trapped in cow_user_page(). If VM_FAULT_RETRY is returned, it is passed up to the callers to retry the page fault while holding the mmap_sem. Change-Id: Iaccfa0d877334f4343f8b0ec3400af5070ff5864 Acked-by: David Rientjes Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:12 [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- include/linux/mm.h | 1 + mm/memory.c | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index d6f98baf9e96..baecf4b2d40b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1185,6 +1185,7 @@ static inline void clear_page_pfmemalloc(struct page *page) #define VM_FAULT_DONE_COW 0x1000 /* ->fault has fully handled COW */ #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */ +#define VM_FAULT_PTNOTSAME 0x4000 /* Page table entries have changed */ #define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \ VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \ diff --git a/mm/memory.c b/mm/memory.c index 088b0b893fc0..96075dcff303 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2291,21 +2291,29 @@ static inline bool pte_map_lock(struct vm_fault *vmf) * parts, do_swap_page must check under lock before unmapping the pte and * proceeding (but do_wp_page is only called after already making such a check; * and do_anonymous_page can safely check later on). + * + * pte_unmap_same() returns: + * 0 if the PTE are the same + * VM_FAULT_PTNOTSAME if the PTE are different + * VM_FAULT_RETRY if the VMA has changed in our back during + * a speculative page fault handling. */ -static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd, - pte_t *page_table, pte_t orig_pte) +static inline int pte_unmap_same(struct vm_fault *vmf) { - int same = 1; + int ret = 0; + #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) if (sizeof(pte_t) > sizeof(unsigned long)) { - spinlock_t *ptl = pte_lockptr(mm, pmd); - spin_lock(ptl); - same = pte_same(*page_table, orig_pte); - spin_unlock(ptl); + if (pte_spinlock(vmf)) { + if (!pte_same(*vmf->pte, vmf->orig_pte)) + ret = VM_FAULT_PTNOTSAME; + spin_unlock(vmf->ptl); + } else + ret = VM_FAULT_RETRY; } #endif - pte_unmap(page_table); - return same; + pte_unmap(vmf->pte); + return ret; } static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va, struct vm_area_struct *vma) @@ -2871,10 +2879,19 @@ int do_swap_page(struct vm_fault *vmf) pte_t pte; int locked; int exclusive = 0; - int ret = 0; + int ret; - if (!pte_unmap_same(vma->vm_mm, vmf->pmd, vmf->pte, vmf->orig_pte)) + ret = pte_unmap_same(vmf); + if (ret) { + /* + * If pte != orig_pte, this means another thread did the + * swap operation in our back. + * So nothing else to do. + */ + if (ret == VM_FAULT_PTNOTSAME) + ret = 0; goto out; + } entry = pte_to_swp_entry(vmf->orig_pte); if (unlikely(non_swap_entry(entry))) { -- GitLab From f98b74c6157e6b573983bc4f87cb9c9fff2337b4 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:13 +0200 Subject: [PATCH 0014/1299] mm: introduce INIT_VMA() Some VMA struct fields need to be initialized once the VMA structure is allocated. Currently this only concerns anon_vma_chain field but some other will be added to support the speculative page fault. Instead of spreading the initialization calls all over the code, let's introduce a dedicated inline function. Change-Id: I9f6b29dc74055354318b548e2b6b22c37d4c61bb Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:13 [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- fs/exec.c | 2 +- include/linux/mm.h | 5 +++++ kernel/fork.c | 2 +- mm/mmap.c | 10 +++++----- mm/nommu.c | 2 +- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 062159d22976..f6f4ed966c73 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -311,7 +311,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm) vma->vm_start = vma->vm_end - PAGE_SIZE; vma->vm_flags = VM_SOFTDIRTY | VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); - INIT_LIST_HEAD(&vma->anon_vma_chain); + INIT_VMA(vma); err = insert_vm_struct(mm, vma); if (err) diff --git a/include/linux/mm.h b/include/linux/mm.h index baecf4b2d40b..3f645a8b7ceb 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1240,6 +1240,11 @@ struct zap_details { pgoff_t last_index; /* Highest page->index to unmap */ }; +static inline void INIT_VMA(struct vm_area_struct *vma) +{ + INIT_LIST_HEAD(&vma->anon_vma_chain); +} + struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_t pte, bool with_public_device); #define vm_normal_page(vma, addr, pte) _vm_normal_page(vma, addr, pte, false) diff --git a/kernel/fork.c b/kernel/fork.c index 2b8a70d31108..9d3eb700dfa2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -654,7 +654,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, if (!tmp) goto fail_nomem; *tmp = *mpnt; - INIT_LIST_HEAD(&tmp->anon_vma_chain); + INIT_VMA(tmp); retval = vma_dup_policy(mpnt, tmp); if (retval) goto fail_nomem_policy; diff --git a/mm/mmap.c b/mm/mmap.c index cb5a0cc3ff13..18e05edf539f 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1676,7 +1676,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr, vma->vm_flags = vm_flags; vma->vm_page_prot = vm_get_page_prot(vm_flags); vma->vm_pgoff = pgoff; - INIT_LIST_HEAD(&vma->anon_vma_chain); + INIT_VMA(vma); if (file) { if (vm_flags & VM_DENYWRITE) { @@ -2562,7 +2562,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, /* most fields are the same, copy all, and then fixup */ *new = *vma; - INIT_LIST_HEAD(&new->anon_vma_chain); + INIT_VMA(new); if (new_below) new->vm_end = addr; @@ -2933,7 +2933,7 @@ static int do_brk_flags(unsigned long addr, unsigned long request, unsigned long return -ENOMEM; } - INIT_LIST_HEAD(&vma->anon_vma_chain); + INIT_VMA(vma); vma->vm_mm = mm; vma->vm_start = addr; vma->vm_end = addr + len; @@ -3152,7 +3152,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, new_vma->vm_pgoff = pgoff; if (vma_dup_policy(vma, new_vma)) goto out_free_vma; - INIT_LIST_HEAD(&new_vma->anon_vma_chain); + INIT_VMA(new_vma); if (anon_vma_clone(new_vma, vma)) goto out_free_mempol; if (new_vma->vm_file) @@ -3293,7 +3293,7 @@ static struct vm_area_struct *__install_special_mapping( if (unlikely(vma == NULL)) return ERR_PTR(-ENOMEM); - INIT_LIST_HEAD(&vma->anon_vma_chain); + INIT_VMA(vma); vma->vm_mm = mm; vma->vm_start = addr; vma->vm_end = addr + len; diff --git a/mm/nommu.c b/mm/nommu.c index 17c00d93de2e..040bde3ef3f7 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1244,7 +1244,7 @@ unsigned long do_mmap(struct file *file, region->vm_flags = vm_flags; region->vm_pgoff = pgoff; - INIT_LIST_HEAD(&vma->anon_vma_chain); + INIT_VMA(vma); vma->vm_flags = vm_flags; vma->vm_pgoff = pgoff; -- GitLab From 184ccc18de5fca9d7e40c093cfba316af121c4f7 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 17 Apr 2018 16:33:14 +0200 Subject: [PATCH 0015/1299] mm: VMA sequence count Wrap the VMA modifications (vma_adjust/unmap_page_range) with sequence counts such that we can easily test if a VMA is changed. The unmap_page_range() one allows us to make assumptions about page-tables; when we find the seqcount hasn't changed we can assume page-tables are still valid. The flip side is that we cannot distinguish between a vma_adjust() and the unmap_page_range() -- where with the former we could have re-checked the vma bounds against the address. Signed-off-by: Peter Zijlstra (Intel) [Port to 4.12 kernel] [Build depends on CONFIG_SPECULATIVE_PAGE_FAULT] [Introduce vm_write_* inline function depending on CONFIG_SPECULATIVE_PAGE_FAULT] [Fix lock dependency between mapping->i_mmap_rwsem and vma->vm_sequence by using vm_raw_write* functions] [Fix a lock dependency warning in mmap_region() when entering the error path] [move sequence initialisation INIT_VMA()] Signed-off-by: Laurent Dufour Change-Id: Ibc23ef3b9dbb80323c0f24cb06da34b4c3a8fa71 Patch-mainline: linux-mm @ 17 Apr 2018 16:33:14 [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- include/linux/mm.h | 44 ++++++++++++++++++++++++++++++++++++++++ include/linux/mm_types.h | 3 +++ mm/memory.c | 2 ++ mm/mmap.c | 31 ++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+) diff --git a/include/linux/mm.h b/include/linux/mm.h index 3f645a8b7ceb..2d286223901d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1243,6 +1243,9 @@ struct zap_details { static inline void INIT_VMA(struct vm_area_struct *vma) { INIT_LIST_HEAD(&vma->anon_vma_chain); +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + seqcount_init(&vma->vm_sequence); +#endif } struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, @@ -1327,6 +1330,47 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping, unmap_mapping_range(mapping, holebegin, holelen, 0); } +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT +static inline void vm_write_begin(struct vm_area_struct *vma) +{ + write_seqcount_begin(&vma->vm_sequence); +} +static inline void vm_write_begin_nested(struct vm_area_struct *vma, + int subclass) +{ + write_seqcount_begin_nested(&vma->vm_sequence, subclass); +} +static inline void vm_write_end(struct vm_area_struct *vma) +{ + write_seqcount_end(&vma->vm_sequence); +} +static inline void vm_raw_write_begin(struct vm_area_struct *vma) +{ + raw_write_seqcount_begin(&vma->vm_sequence); +} +static inline void vm_raw_write_end(struct vm_area_struct *vma) +{ + raw_write_seqcount_end(&vma->vm_sequence); +} +#else +static inline void vm_write_begin(struct vm_area_struct *vma) +{ +} +static inline void vm_write_begin_nested(struct vm_area_struct *vma, + int subclass) +{ +} +static inline void vm_write_end(struct vm_area_struct *vma) +{ +} +static inline void vm_raw_write_begin(struct vm_area_struct *vma) +{ +} +static inline void vm_raw_write_end(struct vm_area_struct *vma) +{ +} +#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */ + extern void truncate_pagecache(struct inode *inode, loff_t new); extern void truncate_setsize(struct inode *inode, loff_t newsize); void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to); diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 561c23ebf4d7..8f1478057812 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -344,6 +344,9 @@ struct vm_area_struct { struct mempolicy *vm_policy; /* NUMA policy for the VMA */ #endif struct vm_userfaultfd_ctx vm_userfaultfd_ctx; +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + seqcount_t vm_sequence; +#endif } __randomize_layout; struct core_thread { diff --git a/mm/memory.c b/mm/memory.c index 96075dcff303..0f4650f56750 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1499,6 +1499,7 @@ void unmap_page_range(struct mmu_gather *tlb, unsigned long next; BUG_ON(addr >= end); + vm_write_begin(vma); tlb_start_vma(tlb, vma); pgd = pgd_offset(vma->vm_mm, addr); do { @@ -1508,6 +1509,7 @@ void unmap_page_range(struct mmu_gather *tlb, next = zap_p4d_range(tlb, vma, pgd, addr, next, details); } while (pgd++, addr = next, addr != end); tlb_end_vma(tlb, vma); + vm_write_end(vma); } diff --git a/mm/mmap.c b/mm/mmap.c index 18e05edf539f..032206f8fe27 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -692,6 +692,30 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, long adjust_next = 0; int remove_next = 0; + /* + * Why using vm_raw_write*() functions here to avoid lockdep's warning ? + * + * Locked is complaining about a theoretical lock dependency, involving + * 3 locks: + * mapping->i_mmap_rwsem --> vma->vm_sequence --> fs_reclaim + * + * Here are the major path leading to this dependency : + * 1. __vma_adjust() mmap_sem -> vm_sequence -> i_mmap_rwsem + * 2. move_vmap() mmap_sem -> vm_sequence -> fs_reclaim + * 3. __alloc_pages_nodemask() fs_reclaim -> i_mmap_rwsem + * 4. unmap_mapping_range() i_mmap_rwsem -> vm_sequence + * + * So there is no way to solve this easily, especially because in + * unmap_mapping_range() the i_mmap_rwsem is grab while the impacted + * VMAs are not yet known. + * However, the way the vm_seq is used is guarantying that we will + * never block on it since we just check for its value and never wait + * for it to move, see vma_has_changed() and handle_speculative_fault(). + */ + vm_raw_write_begin(vma); + if (next) + vm_raw_write_begin(next); + if (next && !insert) { struct vm_area_struct *exporter = NULL, *importer = NULL; @@ -902,6 +926,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, anon_vma_merge(vma, next); mm->map_count--; mpol_put(vma_policy(next)); + vm_raw_write_end(next); kmem_cache_free(vm_area_cachep, next); /* * In mprotect's case 6 (see comments on vma_merge), @@ -916,6 +941,8 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, * "vma->vm_next" gap must be updated. */ next = vma->vm_next; + if (next) + vm_raw_write_begin(next); } else { /* * For the scope of the comment "next" and @@ -962,6 +989,10 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, if (insert && file) uprobe_mmap(insert); + if (next && next != vma) + vm_raw_write_end(next); + vm_raw_write_end(vma); + validate_mm(mm); return 0; -- GitLab From 41530993596b811ce3349224ed6f35839678b071 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:15 +0200 Subject: [PATCH 0016/1299] mm: protect VMA modifications using VMA sequence count The VMA sequence count has been introduced to allow fast detection of VMA modification when running a page fault handler without holding the mmap_sem. This patch provides protection against the VMA modification done in : - madvise() - mpol_rebind_policy() - vma_replace_policy() - change_prot_numa() - mlock(), munlock() - mprotect() - mmap_region() - collapse_huge_page() - userfaultd registering services In addition, VMA fields which will be read during the speculative fault path needs to be written using WRITE_ONCE to prevent write to be split and intermediate values to be pushed to other CPUs. Change-Id: Ic36046b7254e538b6baf7144c50ae577ee7f2074 Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:15 [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- fs/proc/task_mmu.c | 5 ++++- fs/userfaultfd.c | 17 ++++++++++++---- mm/khugepaged.c | 3 +++ mm/madvise.c | 6 +++++- mm/mempolicy.c | 51 ++++++++++++++++++++++++++++++---------------- mm/mlock.c | 13 +++++++----- mm/mmap.c | 22 ++++++++++++-------- mm/mprotect.c | 4 +++- mm/swap_state.c | 8 ++++++-- 9 files changed, 89 insertions(+), 40 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 0db728ae1ff2..587bc1613170 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1221,8 +1221,11 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, goto out_mm; } for (vma = mm->mmap; vma; vma = vma->vm_next) { - vma->vm_flags &= ~VM_SOFTDIRTY; + vm_write_begin(vma); + WRITE_ONCE(vma->vm_flags, + vma->vm_flags & ~VM_SOFTDIRTY); vma_set_page_prot(vma); + vm_write_end(vma); } downgrade_write(&mm->mmap_sem); break; diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 5811bb06a0cc..6b2d138a4923 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -656,8 +656,11 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs) octx = vma->vm_userfaultfd_ctx.ctx; if (!octx || !(octx->features & UFFD_FEATURE_EVENT_FORK)) { + vm_write_begin(vma); vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX; - vma->vm_flags &= ~(VM_UFFD_WP | VM_UFFD_MISSING); + WRITE_ONCE(vma->vm_flags, + vma->vm_flags & ~(VM_UFFD_WP | VM_UFFD_MISSING)); + vm_write_end(vma); return 0; } @@ -883,8 +886,10 @@ static int userfaultfd_release(struct inode *inode, struct file *file) vma = prev; else prev = vma; - vma->vm_flags = new_flags; + vm_write_begin(vma); + WRITE_ONCE(vma->vm_flags, new_flags); vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX; + vm_write_end(vma); } up_write(&mm->mmap_sem); mmput(mm); @@ -1443,8 +1448,10 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx, * the next vma was merged into the current one and * the current one has not been updated yet. */ - vma->vm_flags = new_flags; + vm_write_begin(vma); + WRITE_ONCE(vma->vm_flags, new_flags); vma->vm_userfaultfd_ctx.ctx = ctx; + vm_write_end(vma); skip: prev = vma; @@ -1602,8 +1609,10 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx, * the next vma was merged into the current one and * the current one has not been updated yet. */ - vma->vm_flags = new_flags; + vm_write_begin(vma); + WRITE_ONCE(vma->vm_flags, new_flags); vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX; + vm_write_end(vma); skip: prev = vma; diff --git a/mm/khugepaged.c b/mm/khugepaged.c index 29221602d802..fa40aca44c42 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -1011,6 +1011,7 @@ static void collapse_huge_page(struct mm_struct *mm, if (mm_find_pmd(mm, address) != pmd) goto out; + vm_write_begin(vma); anon_vma_lock_write(vma->anon_vma); pte = pte_offset_map(pmd, address); @@ -1046,6 +1047,7 @@ static void collapse_huge_page(struct mm_struct *mm, pmd_populate(mm, pmd, pmd_pgtable(_pmd)); spin_unlock(pmd_ptl); anon_vma_unlock_write(vma->anon_vma); + vm_write_end(vma); result = SCAN_FAIL; goto out; } @@ -1080,6 +1082,7 @@ static void collapse_huge_page(struct mm_struct *mm, set_pmd_at(mm, address, pmd, _pmd); update_mmu_cache_pmd(vma, address, pmd); spin_unlock(pmd_ptl); + vm_write_end(vma); *hpage = NULL; diff --git a/mm/madvise.c b/mm/madvise.c index 86e514bace7e..ca3bcc9f9d1f 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -184,7 +184,9 @@ static long madvise_behavior(struct vm_area_struct *vma, /* * vm_flags is protected by the mmap_sem held in write mode. */ - vma->vm_flags = new_flags; + vm_write_begin(vma); + WRITE_ONCE(vma->vm_flags, new_flags); + vm_write_end(vma); out: return error; } @@ -450,9 +452,11 @@ static void madvise_free_page_range(struct mmu_gather *tlb, .private = tlb, }; + vm_write_begin(vma); tlb_start_vma(tlb, vma); walk_page_range(addr, end, &free_walk); tlb_end_vma(tlb, vma); + vm_write_end(vma); } static int madvise_free_single_vma(struct vm_area_struct *vma, diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 1d916bcf3c45..095a3fd3226e 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -379,8 +379,11 @@ void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new) struct vm_area_struct *vma; down_write(&mm->mmap_sem); - for (vma = mm->mmap; vma; vma = vma->vm_next) + for (vma = mm->mmap; vma; vma = vma->vm_next) { + vm_write_begin(vma); mpol_rebind_policy(vma->vm_policy, new); + vm_write_end(vma); + } up_write(&mm->mmap_sem); } @@ -578,9 +581,11 @@ unsigned long change_prot_numa(struct vm_area_struct *vma, { int nr_updated; + vm_write_begin(vma); nr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1); if (nr_updated) count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated); + vm_write_end(vma); return nr_updated; } @@ -681,6 +686,7 @@ static int vma_replace_policy(struct vm_area_struct *vma, if (IS_ERR(new)) return PTR_ERR(new); + vm_write_begin(vma); if (vma->vm_ops && vma->vm_ops->set_policy) { err = vma->vm_ops->set_policy(vma, new); if (err) @@ -688,11 +694,17 @@ static int vma_replace_policy(struct vm_area_struct *vma, } old = vma->vm_policy; - vma->vm_policy = new; /* protected by mmap_sem */ + /* + * The speculative page fault handler accesses this field without + * hodling the mmap_sem. + */ + WRITE_ONCE(vma->vm_policy, new); + vm_write_end(vma); mpol_put(old); return 0; err_out: + vm_write_end(vma); mpol_put(new); return err; } @@ -1584,23 +1596,28 @@ COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start, compat_ulong_t, len, struct mempolicy *__get_vma_policy(struct vm_area_struct *vma, unsigned long addr) { - struct mempolicy *pol = NULL; + struct mempolicy *pol; - if (vma) { - if (vma->vm_ops && vma->vm_ops->get_policy) { - pol = vma->vm_ops->get_policy(vma, addr); - } else if (vma->vm_policy) { - pol = vma->vm_policy; + if (!vma) + return NULL; - /* - * shmem_alloc_page() passes MPOL_F_SHARED policy with - * a pseudo vma whose vma->vm_ops=NULL. Take a reference - * count on these policies which will be dropped by - * mpol_cond_put() later - */ - if (mpol_needs_cond_ref(pol)) - mpol_get(pol); - } + if (vma->vm_ops && vma->vm_ops->get_policy) + return vma->vm_ops->get_policy(vma, addr); + + /* + * This could be called without holding the mmap_sem in the + * speculative page fault handler's path. + */ + pol = READ_ONCE(vma->vm_policy); + if (pol) { + /* + * shmem_alloc_page() passes MPOL_F_SHARED policy with + * a pseudo vma whose vma->vm_ops=NULL. Take a reference + * count on these policies which will be dropped by + * mpol_cond_put() later + */ + if (mpol_needs_cond_ref(pol)) + mpol_get(pol); } return pol; diff --git a/mm/mlock.c b/mm/mlock.c index 658ad5562dca..c8ea725535b0 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -439,7 +439,9 @@ static unsigned long __munlock_pagevec_fill(struct pagevec *pvec, void munlock_vma_pages_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - vma->vm_flags &= VM_LOCKED_CLEAR_MASK; + vm_write_begin(vma); + WRITE_ONCE(vma->vm_flags, vma->vm_flags & VM_LOCKED_CLEAR_MASK); + vm_write_end(vma); while (start < end) { struct page *page; @@ -562,10 +564,11 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev, * It's okay if try_to_unmap_one unmaps a page just after we * set VM_LOCKED, populate_vma_page_range will bring it back. */ - - if (lock) - vma->vm_flags = newflags; - else + if (lock) { + vm_write_begin(vma); + WRITE_ONCE(vma->vm_flags, newflags); + vm_write_end(vma); + } else munlock_vma_pages_range(vma, start, end); out: diff --git a/mm/mmap.c b/mm/mmap.c index 032206f8fe27..a31734d6140b 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -843,17 +843,18 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, } if (start != vma->vm_start) { - vma->vm_start = start; + WRITE_ONCE(vma->vm_start, start); start_changed = true; } if (end != vma->vm_end) { - vma->vm_end = end; + WRITE_ONCE(vma->vm_end, end); end_changed = true; } - vma->vm_pgoff = pgoff; + WRITE_ONCE(vma->vm_pgoff, pgoff); if (adjust_next) { - next->vm_start += adjust_next << PAGE_SHIFT; - next->vm_pgoff += adjust_next; + WRITE_ONCE(next->vm_start, + next->vm_start + (adjust_next << PAGE_SHIFT)); + WRITE_ONCE(next->vm_pgoff, next->vm_pgoff + adjust_next); } if (root) { @@ -1760,13 +1761,15 @@ unsigned long mmap_region(struct file *file, unsigned long addr, out: perf_event_mmap(vma); + vm_write_begin(vma); vm_stat_account(mm, vm_flags, len >> PAGE_SHIFT); if (vm_flags & VM_LOCKED) { if (!((vm_flags & VM_SPECIAL) || is_vm_hugetlb_page(vma) || vma == get_gate_vma(current->mm))) mm->locked_vm += (len >> PAGE_SHIFT); else - vma->vm_flags &= VM_LOCKED_CLEAR_MASK; + WRITE_ONCE(vma->vm_flags, + vma->vm_flags & VM_LOCKED_CLEAR_MASK); } if (file) @@ -1779,9 +1782,10 @@ unsigned long mmap_region(struct file *file, unsigned long addr, * then new mapped in-place (which must be aimed as * a completely new data area). */ - vma->vm_flags |= VM_SOFTDIRTY; + WRITE_ONCE(vma->vm_flags, vma->vm_flags | VM_SOFTDIRTY); vma_set_page_prot(vma); + vm_write_end(vma); return addr; @@ -2410,8 +2414,8 @@ int expand_downwards(struct vm_area_struct *vma, mm->locked_vm += grow; vm_stat_account(mm, vma->vm_flags, grow); anon_vma_interval_tree_pre_update_vma(vma); - vma->vm_start = address; - vma->vm_pgoff -= grow; + WRITE_ONCE(vma->vm_start, address); + WRITE_ONCE(vma->vm_pgoff, vma->vm_pgoff - grow); anon_vma_interval_tree_post_update_vma(vma); vma_gap_update(vma); spin_unlock(&mm->page_table_lock); diff --git a/mm/mprotect.c b/mm/mprotect.c index fc969367ef60..44d3a9c8f0e7 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -361,12 +361,14 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, * vm_flags and vm_page_prot are protected by the mmap_sem * held in write mode. */ - vma->vm_flags = newflags; + vm_write_begin(vma); + WRITE_ONCE(vma->vm_flags, newflags); dirty_accountable = vma_wants_writenotify(vma, vma->vm_page_prot); vma_set_page_prot(vma); change_protection(vma, start, end, vma->vm_page_prot, dirty_accountable, 0); + vm_write_end(vma); /* * Private VM_LOCKED VMA becoming writable: trigger COW to avoid major diff --git a/mm/swap_state.c b/mm/swap_state.c index 2348a7ae18e8..6b2fa4835719 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -560,6 +560,10 @@ static unsigned long swapin_nr_pages(unsigned long offset) * the readahead. * * Caller must hold down_read on the vma->vm_mm if vmf->vma is not NULL. + * This is needed to ensure the VMA will not be freed in our back. In the case + * of the speculative page fault handler, this cannot happen, even if we don't + * hold the mmap_sem. Callees are assumed to take care of reading VMA's fields + * using READ_ONCE() to read consistent values. */ struct page *swap_cluster_readahead(swp_entry_t entry, gfp_t gfp_mask, struct vm_fault *vmf) @@ -652,9 +656,9 @@ static inline void swap_ra_clamp_pfn(struct vm_area_struct *vma, unsigned long *start, unsigned long *end) { - *start = max3(lpfn, PFN_DOWN(vma->vm_start), + *start = max3(lpfn, PFN_DOWN(READ_ONCE(vma->vm_start)), PFN_DOWN(faddr & PMD_MASK)); - *end = min3(rpfn, PFN_DOWN(vma->vm_end), + *end = min3(rpfn, PFN_DOWN(READ_ONCE(vma->vm_end)), PFN_DOWN((faddr & PMD_MASK) + PMD_SIZE)); } -- GitLab From f831a4284883a9c5a927dda4125f95c5f739ed45 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:16 +0200 Subject: [PATCH 0017/1299] mm: protect mremap() against SPF hanlder If a thread is remapping an area while another one is faulting on the destination area, the SPF handler may fetch the vma from the RB tree before the pte has been moved by the other thread. This means that the moved ptes will overwrite those create by the page fault handler leading to page leaked. CPU 1 CPU2 enter mremap() unmap the dest area copy_vma() Enter speculative page fault handler >> at this time the dest area is present in the RB tree fetch the vma matching dest area create a pte as the VMA matched Exit the SPF handler move_ptes() > it is assumed that the dest area is empty, > the move ptes overwrite the page mapped by the CPU2. To prevent that, when the VMA matching the dest area is extended or created by copy_vma(), it should be marked as non available to the SPF handler. The usual way to so is to rely on vm_write_begin()/end(). This is already in __vma_adjust() called by copy_vma() (through vma_merge()). But __vma_adjust() is calling vm_write_end() before returning which create a window for another thread. This patch adds a new parameter to vma_merge() which is passed down to vma_adjust(). The assumption is that copy_vma() is returning a vma which should be released by calling vm_raw_write_end() by the callee once the ptes have been moved. Change-Id: Icd338ad6e9b3c97b7334d3b8d30a8badfa2a4efa Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:16 [vinmenon@codeaurora.org: changes in vma_merge arguments related to the anon vma user name which is not suppported upstream.] Signed-off-by: Vinayak Menon --- include/linux/mm.h | 23 +++++++++++++++----- mm/mmap.c | 53 +++++++++++++++++++++++++++++++++++----------- mm/mremap.c | 13 ++++++++++++ 3 files changed, 72 insertions(+), 17 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 2d286223901d..5a6493b9111a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2138,16 +2138,29 @@ void anon_vma_interval_tree_verify(struct anon_vma_chain *node); extern int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin); extern int __vma_adjust(struct vm_area_struct *vma, unsigned long start, unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert, - struct vm_area_struct *expand); + struct vm_area_struct *expand, bool keep_locked); static inline int vma_adjust(struct vm_area_struct *vma, unsigned long start, unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert) { - return __vma_adjust(vma, start, end, pgoff, insert, NULL); + return __vma_adjust(vma, start, end, pgoff, insert, NULL, false); } -extern struct vm_area_struct *vma_merge(struct mm_struct *, + +extern struct vm_area_struct *__vma_merge(struct mm_struct *mm, + struct vm_area_struct *prev, unsigned long addr, unsigned long end, + unsigned long vm_flags, struct anon_vma *anon, struct file *file, + pgoff_t pgoff, struct mempolicy *mpol, struct vm_userfaultfd_ctx uff, + const char __user *user, bool keep_locked); + +static inline struct vm_area_struct *vma_merge(struct mm_struct *mm, struct vm_area_struct *prev, unsigned long addr, unsigned long end, - unsigned long vm_flags, struct anon_vma *, struct file *, pgoff_t, - struct mempolicy *, struct vm_userfaultfd_ctx, const char __user *); + unsigned long vm_flags, struct anon_vma *anon, struct file *file, + pgoff_t off, struct mempolicy *pol, struct vm_userfaultfd_ctx uff, + const char __user *user) +{ + return __vma_merge(mm, prev, addr, end, vm_flags, anon, file, off, + pol, uff, user, false); +} + extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *); extern int __split_vma(struct mm_struct *, struct vm_area_struct *, unsigned long addr, int new_below); diff --git a/mm/mmap.c b/mm/mmap.c index a31734d6140b..2855b682f58a 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -680,7 +680,7 @@ static inline void __vma_unlink_prev(struct mm_struct *mm, */ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert, - struct vm_area_struct *expand) + struct vm_area_struct *expand, bool keep_locked) { struct mm_struct *mm = vma->vm_mm; struct vm_area_struct *next = vma->vm_next, *orig_vma = vma; @@ -796,8 +796,12 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, importer->anon_vma = exporter->anon_vma; error = anon_vma_clone(importer, exporter); - if (error) + if (error) { + if (next && next != vma) + vm_raw_write_end(next); + vm_raw_write_end(vma); return error; + } } } again: @@ -992,7 +996,8 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, if (next && next != vma) vm_raw_write_end(next); - vm_raw_write_end(vma); + if (!keep_locked) + vm_raw_write_end(vma); validate_mm(mm); @@ -1133,13 +1138,13 @@ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags, * parameter) may establish ptes with the wrong permissions of NNNN * instead of the right permissions of XXXX. */ -struct vm_area_struct *vma_merge(struct mm_struct *mm, +struct vm_area_struct *__vma_merge(struct mm_struct *mm, struct vm_area_struct *prev, unsigned long addr, unsigned long end, unsigned long vm_flags, struct anon_vma *anon_vma, struct file *file, pgoff_t pgoff, struct mempolicy *policy, struct vm_userfaultfd_ctx vm_userfaultfd_ctx, - const char __user *anon_name) + const char __user *anon_name, bool keep_locked) { pgoff_t pglen = (end - addr) >> PAGE_SHIFT; struct vm_area_struct *area, *next; @@ -1189,10 +1194,11 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, /* cases 1, 6 */ err = __vma_adjust(prev, prev->vm_start, next->vm_end, prev->vm_pgoff, NULL, - prev); + prev, keep_locked); } else /* cases 2, 5, 7 */ err = __vma_adjust(prev, prev->vm_start, - end, prev->vm_pgoff, NULL, prev); + end, prev->vm_pgoff, NULL, prev, + keep_locked); if (err) return NULL; khugepaged_enter_vma_merge(prev, vm_flags); @@ -1210,10 +1216,12 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, anon_name)) { if (prev && addr < prev->vm_end) /* case 4 */ err = __vma_adjust(prev, prev->vm_start, - addr, prev->vm_pgoff, NULL, next); + addr, prev->vm_pgoff, NULL, next, + keep_locked); else { /* cases 3, 8 */ err = __vma_adjust(area, addr, next->vm_end, - next->vm_pgoff - pglen, NULL, next); + next->vm_pgoff - pglen, NULL, next, + keep_locked); /* * In case 3 area is already equal to next and * this is a noop, but in case 8 "area" has @@ -3152,9 +3160,21 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, if (find_vma_links(mm, addr, addr + len, &prev, &rb_link, &rb_parent)) return NULL; /* should never get here */ - new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), - vma->vm_userfaultfd_ctx, vma_get_anon_name(vma)); + + /* There is 3 cases to manage here in + * AAAA AAAA AAAA AAAA + * PPPP.... PPPP......NNNN PPPP....NNNN PP........NN + * PPPPPPPP(A) PPPP..NNNNNNNN(B) PPPPPPPPPPPP(1) NULL + * PPPPPPPPNNNN(2) + * PPPPNNNNNNNN(3) + * + * new_vma == prev in case A,1,2 + * new_vma == next in case B,3 + */ + new_vma = __vma_merge(mm, prev, addr, addr + len, vma->vm_flags, + vma->anon_vma, vma->vm_file, pgoff, + vma_policy(vma), vma->vm_userfaultfd_ctx, + vma_get_anon_name(vma), true); if (new_vma) { /* * Source vma may have been merged into new_vma @@ -3194,6 +3214,15 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, get_file(new_vma->vm_file); if (new_vma->vm_ops && new_vma->vm_ops->open) new_vma->vm_ops->open(new_vma); + /* + * As the VMA is linked right now, it may be hit by the + * speculative page fault handler. But we don't want it to + * to start mapping page in this area until the caller has + * potentially move the pte from the moved VMA. To prevent + * that we protect it right now, and let the caller unprotect + * it once the move is done. + */ + vm_raw_write_begin(new_vma); vma_link(mm, new_vma, prev, rb_link, rb_parent); *need_rmap_locks = false; } diff --git a/mm/mremap.c b/mm/mremap.c index 049470aa1e3e..8ed1a1d6eaed 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -302,6 +302,14 @@ static unsigned long move_vma(struct vm_area_struct *vma, if (!new_vma) return -ENOMEM; + /* new_vma is returned protected by copy_vma, to prevent speculative + * page fault to be done in the destination area before we move the pte. + * Now, we must also protect the source VMA since we don't want pages + * to be mapped in our back while we are copying the PTEs. + */ + if (vma != new_vma) + vm_raw_write_begin(vma); + moved_len = move_page_tables(vma, old_addr, new_vma, new_addr, old_len, need_rmap_locks); if (moved_len < old_len) { @@ -318,6 +326,8 @@ static unsigned long move_vma(struct vm_area_struct *vma, */ move_page_tables(new_vma, new_addr, vma, old_addr, moved_len, true); + if (vma != new_vma) + vm_raw_write_end(vma); vma = new_vma; old_len = new_len; old_addr = new_addr; @@ -326,7 +336,10 @@ static unsigned long move_vma(struct vm_area_struct *vma, mremap_userfaultfd_prep(new_vma, uf); arch_remap(mm, old_addr, old_addr + old_len, new_addr, new_addr + new_len); + if (vma != new_vma) + vm_raw_write_end(vma); } + vm_raw_write_end(new_vma); /* Conceal VM_ACCOUNT so old reservation is not undone */ if (vm_flags & VM_ACCOUNT) { -- GitLab From 39bb6bae6718445963f86df376f4b4e6136b374e Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:17 +0200 Subject: [PATCH 0018/1299] mm: protect SPF handler against anon_vma changes The speculative page fault handler must be protected against anon_vma changes. This is because page_add_new_anon_rmap() is called during the speculative path. In addition, don't try speculative page fault if the VMA don't have an anon_vma structure allocated because its allocation should be protected by the mmap_sem. In __vma_adjust() when importer->anon_vma is set, there is no need to protect against speculative page faults since speculative page fault is aborted if the vma->anon_vma is not set. When calling page_add_new_anon_rmap() vma->anon_vma is necessarily valid since we checked for it when locking the pte and the anon_vma is removed once the pte is unlocked. So even if the speculative page fault handler is running concurrently with do_unmap(), as the pte is locked in unmap_region() - through unmap_vmas() - and the anon_vma unlinked later, because we check for the vma sequence counter which is updated in unmap_page_range() before locking the pte, and then in free_pgtables() so when locking the pte the change will be detected. Change-Id: I6c1f3b5c811d1ddd7b3f769082e8bbd40f5b52a0 Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:17 [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- mm/memory.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mm/memory.c b/mm/memory.c index 0f4650f56750..1b298ea770b8 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -617,7 +617,9 @@ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *vma, * Hide vma from rmap and truncate_pagecache before freeing * pgtables */ + vm_write_begin(vma); unlink_anon_vmas(vma); + vm_write_end(vma); unlink_file_vma(vma); if (is_vm_hugetlb_page(vma)) { @@ -631,7 +633,9 @@ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *vma, && !is_vm_hugetlb_page(next)) { vma = next; next = vma->vm_next; + vm_write_begin(vma); unlink_anon_vmas(vma); + vm_write_end(vma); unlink_file_vma(vma); } free_pgd_range(tlb, addr, vma->vm_end, -- GitLab From 896469ccd88ae858b66828d7e5d918b799c02cf9 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:18 +0200 Subject: [PATCH 0019/1299] mm: cache some VMA fields in the vm_fault structure When handling speculative page fault, the vma->vm_flags and vma->vm_page_prot fields are read once the page table lock is released. So there is no more guarantee that these fields would not change in our back. They will be saved in the vm_fault structure before the VMA is checked for changes. This patch also set the fields in hugetlb_no_page() and __collapse_huge_page_swapin even if it is not need for the callee. Signed-off-by: Laurent Dufour Change-Id: I9821f02ea32ef220b57b8bfd817992bbf71bbb1d Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:18 [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- include/linux/mm.h | 10 ++++++++-- mm/huge_memory.c | 6 +++--- mm/hugetlb.c | 2 ++ mm/khugepaged.c | 2 ++ mm/memory.c | 50 ++++++++++++++++++++++++---------------------- mm/migrate.c | 2 +- 6 files changed, 42 insertions(+), 30 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 5a6493b9111a..5c0689db0e5a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -350,6 +350,12 @@ struct vm_fault { * page table to avoid allocation from * atomic context. */ + /* + * These entries are required when handling speculative page fault. + * This way the page handling is done using consistent field values. + */ + unsigned long vma_flags; + pgprot_t vma_page_prot; }; /* page entry size for vm->huge_fault() */ @@ -668,9 +674,9 @@ void free_compound_page(struct page *page); * pte_mkwrite. But get_user_pages can cause write faults for mappings * that do not have writing enabled, when used by access_process_vm. */ -static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma) +static inline pte_t maybe_mkwrite(pte_t pte, unsigned long vma_flags) { - if (likely(vma->vm_flags & VM_WRITE)) + if (likely(vma_flags & VM_WRITE)) pte = pte_mkwrite(pte); return pte; } diff --git a/mm/huge_memory.c b/mm/huge_memory.c index a403d29da6fd..11dfaf83eef3 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1187,8 +1187,8 @@ static int do_huge_pmd_wp_page_fallback(struct vm_fault *vmf, pmd_t orig_pmd, for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) { pte_t entry; - entry = mk_pte(pages[i], vma->vm_page_prot); - entry = maybe_mkwrite(pte_mkdirty(entry), vma); + entry = mk_pte(pages[i], vmf->vma_page_prot); + entry = maybe_mkwrite(pte_mkdirty(entry), vmf->vma_flags); memcg = (void *)page_private(pages[i]); set_page_private(pages[i], 0); page_add_new_anon_rmap(pages[i], vmf->vma, haddr, false); @@ -2114,7 +2114,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, entry = pte_swp_mksoft_dirty(entry); } else { entry = mk_pte(page + i, READ_ONCE(vma->vm_page_prot)); - entry = maybe_mkwrite(entry, vma); + entry = maybe_mkwrite(entry, vma->vm_flags); if (!write) entry = pte_wrprotect(entry); if (!young) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index b1f841a9edd4..c5976d5323be 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -3692,6 +3692,8 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma, .vma = vma, .address = address, .flags = flags, + .vma_flags = vma->vm_flags, + .vma_page_prot = vma->vm_page_prot, /* * Hard to debug if it ends up being * used by a callee that assumes diff --git a/mm/khugepaged.c b/mm/khugepaged.c index fa40aca44c42..4144c20e250e 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -887,6 +887,8 @@ static bool __collapse_huge_page_swapin(struct mm_struct *mm, .flags = FAULT_FLAG_ALLOW_RETRY, .pmd = pmd, .pgoff = linear_page_index(vma, address), + .vma_flags = vma->vm_flags, + .vma_page_prot = vma->vm_page_prot, }; /* we only decide to swapin, if there is enough young ptes */ diff --git a/mm/memory.c b/mm/memory.c index 1b298ea770b8..1cdbadb5df0c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1822,7 +1822,7 @@ static int insert_pfn(struct vm_area_struct *vma, unsigned long addr, out_mkwrite: if (mkwrite) { entry = pte_mkyoung(entry); - entry = maybe_mkwrite(pte_mkdirty(entry), vma); + entry = maybe_mkwrite(pte_mkdirty(entry), vma->vm_flags); } set_pte_at(mm, addr, pte, entry); @@ -2454,7 +2454,7 @@ static inline void wp_page_reuse(struct vm_fault *vmf) flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte)); entry = pte_mkyoung(vmf->orig_pte); - entry = maybe_mkwrite(pte_mkdirty(entry), vma); + entry = maybe_mkwrite(pte_mkdirty(entry), vmf->vma_flags); if (ptep_set_access_flags(vma, vmf->address, vmf->pte, entry, 1)) update_mmu_cache(vma, vmf->address, vmf->pte); pte_unmap_unlock(vmf->pte, vmf->ptl); @@ -2530,8 +2530,8 @@ static int wp_page_copy(struct vm_fault *vmf) inc_mm_counter_fast(mm, MM_ANONPAGES); } flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte)); - entry = mk_pte(new_page, vma->vm_page_prot); - entry = maybe_mkwrite(pte_mkdirty(entry), vma); + entry = mk_pte(new_page, vmf->vma_page_prot); + entry = maybe_mkwrite(pte_mkdirty(entry), vmf->vma_flags); /* * Clear the pte entry and flush it first, before updating the * pte with the new entry. This will avoid a race condition @@ -2592,7 +2592,7 @@ static int wp_page_copy(struct vm_fault *vmf) * Don't let another task, with possibly unlocked vma, * keep the mlocked page. */ - if (page_copied && (vma->vm_flags & VM_LOCKED)) { + if (page_copied && (vmf->vma_flags & VM_LOCKED)) { lock_page(old_page); /* LRU manipulation */ if (PageMlocked(old_page)) munlock_vma_page(old_page); @@ -2628,7 +2628,7 @@ static int wp_page_copy(struct vm_fault *vmf) */ int finish_mkwrite_fault(struct vm_fault *vmf) { - WARN_ON_ONCE(!(vmf->vma->vm_flags & VM_SHARED)); + WARN_ON_ONCE(!(vmf->vma_flags & VM_SHARED)); if (!pte_map_lock(vmf)) return VM_FAULT_RETRY; /* @@ -2730,7 +2730,7 @@ static int do_wp_page(struct vm_fault *vmf) * We should not cow pages in a shared writeable mapping. * Just mark the pages writable and/or call ops->pfn_mkwrite. */ - if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) == + if ((vmf->vma_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) return wp_pfn_shared(vmf); @@ -2777,7 +2777,7 @@ static int do_wp_page(struct vm_fault *vmf) return VM_FAULT_WRITE; } unlock_page(vmf->page); - } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) == + } else if (unlikely((vmf->vma_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))) { return wp_page_shared(vmf); } @@ -3038,9 +3038,9 @@ int do_swap_page(struct vm_fault *vmf) inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES); dec_mm_counter_fast(vma->vm_mm, MM_SWAPENTS); - pte = mk_pte(page, vma->vm_page_prot); + pte = mk_pte(page, vmf->vma_page_prot); if ((vmf->flags & FAULT_FLAG_WRITE) && reuse_swap_page(page, NULL)) { - pte = maybe_mkwrite(pte_mkdirty(pte), vma); + pte = maybe_mkwrite(pte_mkdirty(pte), vmf->vma_flags); vmf->flags &= ~FAULT_FLAG_WRITE; ret |= VM_FAULT_WRITE; exclusive = RMAP_EXCLUSIVE; @@ -3064,7 +3064,7 @@ int do_swap_page(struct vm_fault *vmf) swap_free(entry); if (mem_cgroup_swap_full(page) || - (vma->vm_flags & VM_LOCKED) || PageMlocked(page)) + (vmf->vma_flags & VM_LOCKED) || PageMlocked(page)) try_to_free_swap(page); unlock_page(page); if (page != swapcache && swapcache) { @@ -3122,7 +3122,7 @@ static int do_anonymous_page(struct vm_fault *vmf) pte_t entry; /* File mapping without ->vm_ops ? */ - if (vma->vm_flags & VM_SHARED) + if (vmf->vma_flags & VM_SHARED) return VM_FAULT_SIGBUS; /* @@ -3146,7 +3146,7 @@ static int do_anonymous_page(struct vm_fault *vmf) if (!(vmf->flags & FAULT_FLAG_WRITE) && !mm_forbids_zeropage(vma->vm_mm)) { entry = pte_mkspecial(pfn_pte(my_zero_pfn(vmf->address), - vma->vm_page_prot)); + vmf->vma_page_prot)); if (!pte_map_lock(vmf)) return VM_FAULT_RETRY; if (!pte_none(*vmf->pte)) @@ -3179,8 +3179,8 @@ static int do_anonymous_page(struct vm_fault *vmf) */ __SetPageUptodate(page); - entry = mk_pte(page, vma->vm_page_prot); - if (vma->vm_flags & VM_WRITE) + entry = mk_pte(page, vmf->vma_page_prot); + if (vmf->vma_flags & VM_WRITE) entry = pte_mkwrite(pte_mkdirty(entry)); if (!pte_map_lock(vmf)) { @@ -3377,7 +3377,7 @@ static int do_set_pmd(struct vm_fault *vmf, struct page *page) for (i = 0; i < HPAGE_PMD_NR; i++) flush_icache_page(vma, page + i); - entry = mk_huge_pmd(page, vma->vm_page_prot); + entry = mk_huge_pmd(page, vmf->vma_page_prot); if (write) entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); @@ -3451,11 +3451,11 @@ int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg, return VM_FAULT_NOPAGE; flush_icache_page(vma, page); - entry = mk_pte(page, vma->vm_page_prot); + entry = mk_pte(page, vmf->vma_page_prot); if (write) - entry = maybe_mkwrite(pte_mkdirty(entry), vma); + entry = maybe_mkwrite(pte_mkdirty(entry), vmf->vma_flags); /* copy-on-write page */ - if (write && !(vma->vm_flags & VM_SHARED)) { + if (write && !(vmf->vma_flags & VM_SHARED)) { inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES); page_add_new_anon_rmap(page, vma, vmf->address, false); mem_cgroup_commit_charge(page, memcg, false, false); @@ -3494,7 +3494,7 @@ int finish_fault(struct vm_fault *vmf) /* Did we COW the page? */ if ((vmf->flags & FAULT_FLAG_WRITE) && - !(vmf->vma->vm_flags & VM_SHARED)) + !(vmf->vma_flags & VM_SHARED)) page = vmf->cow_page; else page = vmf->page; @@ -3748,7 +3748,7 @@ static int do_fault(struct vm_fault *vmf) ret = VM_FAULT_SIGBUS; else if (!(vmf->flags & FAULT_FLAG_WRITE)) ret = do_read_fault(vmf); - else if (!(vma->vm_flags & VM_SHARED)) + else if (!(vmf->vma_flags & VM_SHARED)) ret = do_cow_fault(vmf); else ret = do_shared_fault(vmf); @@ -3805,7 +3805,7 @@ static int do_numa_page(struct vm_fault *vmf) * accessible ptes, some can allow access by kernel mode. */ pte = ptep_modify_prot_start(vma->vm_mm, vmf->address, vmf->pte); - pte = pte_modify(pte, vma->vm_page_prot); + pte = pte_modify(pte, vmf->vma_page_prot); pte = pte_mkyoung(pte); if (was_writable) pte = pte_mkwrite(pte); @@ -3839,7 +3839,7 @@ static int do_numa_page(struct vm_fault *vmf) * Flag if the page is shared between multiple address spaces. This * is later used when determining whether to group tasks together */ - if (page_mapcount(page) > 1 && (vma->vm_flags & VM_SHARED)) + if (page_mapcount(page) > 1 && (vmf->vma_flags & VM_SHARED)) flags |= TNF_SHARED; last_cpupid = page_cpupid_last(page); @@ -3883,7 +3883,7 @@ static int wp_huge_pmd(struct vm_fault *vmf, pmd_t orig_pmd) return vmf->vma->vm_ops->huge_fault(vmf, PE_SIZE_PMD); /* COW handled on pte level: split pmd */ - VM_BUG_ON_VMA(vmf->vma->vm_flags & VM_SHARED, vmf->vma); + VM_BUG_ON_VMA(vmf->vma_flags & VM_SHARED, vmf->vma); __split_huge_pmd(vmf->vma, vmf->pmd, vmf->address, false, NULL); return VM_FAULT_FALLBACK; @@ -4030,6 +4030,8 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address, .flags = flags, .pgoff = linear_page_index(vma, address), .gfp_mask = __get_fault_gfp_mask(vma), + .vma_flags = vma->vm_flags, + .vma_page_prot = vma->vm_page_prot, }; unsigned int dirty = flags & FAULT_FLAG_WRITE; struct mm_struct *mm = vma->vm_mm; diff --git a/mm/migrate.c b/mm/migrate.c index 1236449b4777..d7f53612f983 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -239,7 +239,7 @@ static bool remove_migration_pte(struct page *page, struct vm_area_struct *vma, */ entry = pte_to_swp_entry(*pvmw.pte); if (is_write_migration_entry(entry)) - pte = maybe_mkwrite(pte, vma); + pte = maybe_mkwrite(pte, vma->vm_flags); if (unlikely(is_zone_device_page(new))) { if (is_device_private_page(new)) { -- GitLab From 53fc4df45c1ff3a3b4d0300472288ff45c43dc8e Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:19 +0200 Subject: [PATCH 0020/1299] mm/migrate: Pass vm_fault pointer to migrate_misplaced_page() migrate_misplaced_page() is only called during the page fault handling so it's better to pass the pointer to the struct vm_fault instead of the vma. This way during the speculative page fault path the saved vma->vm_flags could be used. Change-Id: I254a7c9d91dca9ee8a9afd5eccd6de9af5dc8bc0 Acked-by: David Rientjes Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:19 Signed-off-by: Vinayak Menon --- include/linux/migrate.h | 4 ++-- mm/memory.c | 2 +- mm/migrate.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/migrate.h b/include/linux/migrate.h index a2246cf670ba..18c7980d9513 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -127,14 +127,14 @@ static inline void __ClearPageMovable(struct page *page) #ifdef CONFIG_NUMA_BALANCING extern bool pmd_trans_migrating(pmd_t pmd); extern int migrate_misplaced_page(struct page *page, - struct vm_area_struct *vma, int node); + struct vm_fault *vmf, int node); #else static inline bool pmd_trans_migrating(pmd_t pmd) { return false; } static inline int migrate_misplaced_page(struct page *page, - struct vm_area_struct *vma, int node) + struct vm_fault *vmf, int node) { return -EAGAIN; /* can't migrate now */ } diff --git a/mm/memory.c b/mm/memory.c index 1cdbadb5df0c..a8de63caa300 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3853,7 +3853,7 @@ static int do_numa_page(struct vm_fault *vmf) } /* Migrate to the requested node */ - migrated = migrate_misplaced_page(page, vma, target_nid); + migrated = migrate_misplaced_page(page, vmf, target_nid); if (migrated) { page_nid = target_nid; flags |= TNF_MIGRATED; diff --git a/mm/migrate.c b/mm/migrate.c index d7f53612f983..6149dc62a0f1 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1940,7 +1940,7 @@ bool pmd_trans_migrating(pmd_t pmd) * node. Caller is expected to have an elevated reference count on * the page that will be dropped by this function before returning. */ -int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma, +int migrate_misplaced_page(struct page *page, struct vm_fault *vmf, int node) { pg_data_t *pgdat = NODE_DATA(node); @@ -1953,7 +1953,7 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma, * with execute permissions as they are probably shared libraries. */ if (page_mapcount(page) != 1 && page_is_file_cache(page) && - (vma->vm_flags & VM_EXEC)) + (vmf->vma_flags & VM_EXEC)) goto out; /* -- GitLab From 34e57df243342691c6d5a98ce99eae45a2e1f1ca Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:20 +0200 Subject: [PATCH 0021/1299] mm: introduce __lru_cache_add_active_or_unevictable The speculative page fault handler which is run without holding the mmap_sem is calling lru_cache_add_active_or_unevictable() but the vm_flags is not guaranteed to remain constant. Introducing __lru_cache_add_active_or_unevictable() which has the vma flags value parameter instead of the vma pointer. Change-Id: I68decbe0f80847403127c45c97565e47512532e9 Acked-by: David Rientjes Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:20 [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- include/linux/swap.h | 10 ++++++++-- mm/memory.c | 8 ++++---- mm/swap.c | 6 +++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 4d128336ed68..827aa3d26100 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -332,8 +332,14 @@ extern void swap_setup(void); extern void add_page_to_unevictable_list(struct page *page); -extern void lru_cache_add_active_or_unevictable(struct page *page, - struct vm_area_struct *vma); +extern void __lru_cache_add_active_or_unevictable(struct page *page, + unsigned long vma_flags); + +static inline void lru_cache_add_active_or_unevictable(struct page *page, + struct vm_area_struct *vma) +{ + return __lru_cache_add_active_or_unevictable(page, vma->vm_flags); +} /* linux/mm/vmscan.c */ extern unsigned long zone_reclaimable_pages(struct zone *zone); diff --git a/mm/memory.c b/mm/memory.c index a8de63caa300..91158f1cd193 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2541,7 +2541,7 @@ static int wp_page_copy(struct vm_fault *vmf) ptep_clear_flush_notify(vma, vmf->address, vmf->pte); page_add_new_anon_rmap(new_page, vma, vmf->address, false); mem_cgroup_commit_charge(new_page, memcg, false, false); - lru_cache_add_active_or_unevictable(new_page, vma); + __lru_cache_add_active_or_unevictable(new_page, vmf->vma_flags); /* * We call the notify macro here because, when using secondary * mmu page tables (such as kvm shadow page tables), we want the @@ -3055,7 +3055,7 @@ int do_swap_page(struct vm_fault *vmf) if (unlikely(page != swapcache && swapcache)) { page_add_new_anon_rmap(page, vma, vmf->address, false); mem_cgroup_commit_charge(page, memcg, false, false); - lru_cache_add_active_or_unevictable(page, vma); + __lru_cache_add_active_or_unevictable(page, vmf->vma_flags); } else { do_page_add_anon_rmap(page, vma, vmf->address, exclusive); mem_cgroup_commit_charge(page, memcg, true, false); @@ -3205,7 +3205,7 @@ static int do_anonymous_page(struct vm_fault *vmf) inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES); page_add_new_anon_rmap(page, vma, vmf->address, false); mem_cgroup_commit_charge(page, memcg, false, false); - lru_cache_add_active_or_unevictable(page, vma); + __lru_cache_add_active_or_unevictable(page, vmf->vma_flags); setpte: set_pte_at(vma->vm_mm, vmf->address, vmf->pte, entry); @@ -3459,7 +3459,7 @@ int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg, inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES); page_add_new_anon_rmap(page, vma, vmf->address, false); mem_cgroup_commit_charge(page, memcg, false, false); - lru_cache_add_active_or_unevictable(page, vma); + __lru_cache_add_active_or_unevictable(page, vmf->vma_flags); } else { inc_mm_counter_fast(vma->vm_mm, mm_counter_file(page)); page_add_file_rmap(page, false); diff --git a/mm/swap.c b/mm/swap.c index a77d68f2c1b6..274981cf0652 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -479,12 +479,12 @@ void add_page_to_unevictable_list(struct page *page) * directly back onto it's zone's unevictable list, it does NOT use a * per cpu pagevec. */ -void lru_cache_add_active_or_unevictable(struct page *page, - struct vm_area_struct *vma) +void __lru_cache_add_active_or_unevictable(struct page *page, + unsigned long vma_flags) { VM_BUG_ON_PAGE(PageLRU(page), page); - if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED)) { + if (likely((vma_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED)) { SetPageActive(page); lru_cache_add(page); return; -- GitLab From 3db290da0d4d40ec5b7b356e0e852cb910b848c2 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:22 +0200 Subject: [PATCH 0022/1299] mm: introduce __page_add_new_anon_rmap() When dealing with speculative page fault handler, we may race with VMA being split or merged. In this case the vma->vm_start and vm->vm_end fields may not match the address the page fault is occurring. This can only happens when the VMA is split but in that case, the anon_vma pointer of the new VMA will be the same as the original one, because in __split_vma the new->anon_vma is set to src->anon_vma when *new = *vma. So even if the VMA boundaries are not correct, the anon_vma pointer is still valid. If the VMA has been merged, then the VMA in which it has been merged must have the same anon_vma pointer otherwise the merge can't be done. So in all the case we know that the anon_vma is valid, since we have checked before starting the speculative page fault that the anon_vma pointer is valid for this VMA and since there is an anon_vma this means that at one time a page has been backed and that before the VMA is cleaned, the page table lock would have to be grab to clean the PTE, and the anon_vma field is checked once the PTE is locked. This patch introduce a new __page_add_new_anon_rmap() service which doesn't check for the VMA boundaries, and create a new inline one which do the check. When called from a page fault handler, if this is not a speculative one, there is a guarantee that vm_start and vm_end match the faulting address, so this check is useless. In the context of the speculative page fault handler, this check may be wrong but anon_vma is still valid as explained above. Change-Id: I72c47830181579f8c9618df879077d321653b5f1 Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:22 [vinmenon@codeaurora.org: trivial merge conflict fixes + checkpatch fixes] Signed-off-by: Vinayak Menon --- include/linux/rmap.h | 12 ++++++++++-- mm/memory.c | 8 ++++---- mm/rmap.c | 5 ++--- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 988d176472df..505a29e8c16d 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -174,8 +174,16 @@ void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long, bool); void do_page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long, int); -void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, - unsigned long, bool); +void __page_add_new_anon_rmap(struct page *page, struct vm_area_struct *vma, + unsigned long address, bool compound); +static inline void page_add_new_anon_rmap(struct page *page, + struct vm_area_struct *vma, + unsigned long address, bool compound) +{ + VM_BUG_ON_VMA(address < vma->vm_start || address >= vma->vm_end, vma); + __page_add_new_anon_rmap(page, vma, address, compound); +} + void page_add_file_rmap(struct page *, bool); void page_remove_rmap(struct page *, bool); diff --git a/mm/memory.c b/mm/memory.c index 3bd4c644089d..f8efb3efe2e9 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2545,7 +2545,7 @@ static int wp_page_copy(struct vm_fault *vmf) * thread doing COW. */ ptep_clear_flush_notify(vma, vmf->address, vmf->pte); - page_add_new_anon_rmap(new_page, vma, vmf->address, false); + __page_add_new_anon_rmap(new_page, vma, vmf->address, false); mem_cgroup_commit_charge(new_page, memcg, false, false); __lru_cache_add_active_or_unevictable(new_page, vmf->vma_flags); /* @@ -3060,7 +3060,7 @@ int do_swap_page(struct vm_fault *vmf) /* ksm created a completely new copy */ if (unlikely(page != swapcache && swapcache)) { - page_add_new_anon_rmap(page, vma, vmf->address, false); + __page_add_new_anon_rmap(page, vma, vmf->address, false); mem_cgroup_commit_charge(page, memcg, false, false); __lru_cache_add_active_or_unevictable(page, vmf->vma_flags); } else { @@ -3210,7 +3210,7 @@ static int do_anonymous_page(struct vm_fault *vmf) } inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES); - page_add_new_anon_rmap(page, vma, vmf->address, false); + __page_add_new_anon_rmap(page, vma, vmf->address, false); mem_cgroup_commit_charge(page, memcg, false, false); __lru_cache_add_active_or_unevictable(page, vmf->vma_flags); setpte: @@ -3464,7 +3464,7 @@ int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg, /* copy-on-write page */ if (write && !(vmf->vma_flags & VM_SHARED)) { inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES); - page_add_new_anon_rmap(page, vma, vmf->address, false); + __page_add_new_anon_rmap(page, vma, vmf->address, false); mem_cgroup_commit_charge(page, memcg, false, false); __lru_cache_add_active_or_unevictable(page, vmf->vma_flags); } else { diff --git a/mm/rmap.c b/mm/rmap.c index b874c4761e84..5d657329191e 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -1133,7 +1133,7 @@ void do_page_add_anon_rmap(struct page *page, } /** - * page_add_new_anon_rmap - add pte mapping to a new anonymous page + * __page_add_new_anon_rmap - add pte mapping to a new anonymous page * @page: the page to add the mapping to * @vma: the vm area in which the mapping is added * @address: the user virtual address mapped @@ -1143,12 +1143,11 @@ void do_page_add_anon_rmap(struct page *page, * This means the inc-and-test can be bypassed. * Page does not have to be locked. */ -void page_add_new_anon_rmap(struct page *page, +void __page_add_new_anon_rmap(struct page *page, struct vm_area_struct *vma, unsigned long address, bool compound) { int nr = compound ? hpage_nr_pages(page) : 1; - VM_BUG_ON_VMA(address < vma->vm_start || address >= vma->vm_end, vma); __SetPageSwapBacked(page); if (compound) { VM_BUG_ON_PAGE(!PageTransHuge(page), page); -- GitLab From feb3e8b60b7b57c5bb9cd8124575917c821a71f3 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:21 +0200 Subject: [PATCH 0023/1299] mm: introduce __vm_normal_page() When dealing with the speculative fault path we should use the VMA's field cached value stored in the vm_fault structure. Currently vm_normal_page() is using the pointer to the VMA to fetch the vm_flags value. This patch provides a new __vm_normal_page() which is receiving the vm_flags flags value as parameter. Note: The speculative path is turned on for architecture providing support for special PTE flag. So only the first block of vm_normal_page is used during the speculative path. Change-Id: I0f2c4ab1212fbca449bdf6e7993dafa0d41044bc Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:21 Signed-off-by: Vinayak Menon --- include/linux/mm.h | 18 +++++++++++++++--- mm/memory.c | 25 ++++++++++++++++--------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 5c0689db0e5a..17b0b3e7a37b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1254,9 +1254,21 @@ static inline void INIT_VMA(struct vm_area_struct *vma) #endif } -struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, - pte_t pte, bool with_public_device); -#define vm_normal_page(vma, addr, pte) _vm_normal_page(vma, addr, pte, false) +struct page *__vm_normal_page(struct vm_area_struct *vma, unsigned long addr, + pte_t pte, bool with_public_device, + unsigned long vma_flags); +static inline struct page *_vm_normal_page(struct vm_area_struct *vma, + unsigned long addr, pte_t pte, + bool with_public_device) +{ + return __vm_normal_page(vma, addr, pte, with_public_device, + vma->vm_flags); +} +static inline struct page *vm_normal_page(struct vm_area_struct *vma, + unsigned long addr, pte_t pte) +{ + return _vm_normal_page(vma, addr, pte, false); +} struct page *vm_normal_page_pmd(struct vm_area_struct *vma, unsigned long addr, pmd_t pmd); diff --git a/mm/memory.c b/mm/memory.c index 91158f1cd193..3bd4c644089d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -776,7 +776,8 @@ static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr, } /* - * vm_normal_page -- This function gets the "struct page" associated with a pte. + * __vm_normal_page -- This function gets the "struct page" associated with + * a pte. * * "Special" mappings do not wish to be associated with a "struct page" (either * it doesn't exist, or it exists but they don't want to touch it). In this @@ -822,8 +823,9 @@ static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr, #else # define HAVE_PTE_SPECIAL 0 #endif -struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, - pte_t pte, bool with_public_device) +struct page *__vm_normal_page(struct vm_area_struct *vma, unsigned long addr, + pte_t pte, bool with_public_device, + unsigned long vma_flags) { unsigned long pfn = pte_pfn(pte); @@ -832,7 +834,7 @@ struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, goto check_pfn; if (vma->vm_ops && vma->vm_ops->find_special_page) return vma->vm_ops->find_special_page(vma, addr); - if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)) + if (vma_flags & (VM_PFNMAP | VM_MIXEDMAP)) return NULL; if (is_zero_pfn(pfn)) return NULL; @@ -863,9 +865,13 @@ struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, } /* !HAVE_PTE_SPECIAL case follows: */ + /* + * This part should never get called when CONFIG_SPECULATIVE_PAGE_FAULT + * is set. This is mainly because we can't rely on vm_start. + */ - if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) { - if (vma->vm_flags & VM_MIXEDMAP) { + if (unlikely(vma_flags & (VM_PFNMAP|VM_MIXEDMAP))) { + if (vma_flags & VM_MIXEDMAP) { if (!pfn_valid(pfn)) return NULL; goto out; @@ -874,7 +880,7 @@ struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, off = (addr - vma->vm_start) >> PAGE_SHIFT; if (pfn == vma->vm_pgoff + off) return NULL; - if (!is_cow_mapping(vma->vm_flags)) + if (!is_cow_mapping(vma_flags)) return NULL; } } @@ -2721,7 +2727,8 @@ static int do_wp_page(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; - vmf->page = vm_normal_page(vma, vmf->address, vmf->orig_pte); + vmf->page = __vm_normal_page(vma, vmf->address, vmf->orig_pte, false, + vmf->vma_flags); if (!vmf->page) { /* * VM_MIXEDMAP !pfn_valid() case, or VM_SOFTDIRTY clear on a @@ -3812,7 +3819,7 @@ static int do_numa_page(struct vm_fault *vmf) ptep_modify_prot_commit(vma->vm_mm, vmf->address, vmf->pte, pte); update_mmu_cache(vma, vmf->address, vmf->pte); - page = vm_normal_page(vma, vmf->address, pte); + page = __vm_normal_page(vma, vmf->address, pte, false, vmf->vma_flags); if (!page) { pte_unmap_unlock(vmf->pte, vmf->ptl); return 0; -- GitLab From eba2eb1ba01f49af76fe23edf8658e4442fccc22 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:23 +0200 Subject: [PATCH 0024/1299] mm: protect mm_rb tree with a rwlock This change is inspired by the Peter's proposal patch [1] which was protecting the VMA using SRCU. Unfortunately, SRCU is not scaling well in that particular case, and it is introducing major performance degradation due to excessive scheduling operations. To allow access to the mm_rb tree without grabbing the mmap_sem, this patch is protecting it access using a rwlock. As the mm_rb tree is a O(log n) search it is safe to protect it using such a lock. The VMA cache is not protected by the new rwlock and it should not be used without holding the mmap_sem. To allow the picked VMA structure to be used once the rwlock is released, a use count is added to the VMA structure. When the VMA is allocated it is set to 1. Each time the VMA is picked with the rwlock held its use count is incremented. Each time the VMA is released it is decremented. When the use count hits zero, this means that the VMA is no more used and should be freed. This patch is preparing for 2 kind of VMA access : - as usual, under the control of the mmap_sem, - without holding the mmap_sem for the speculative page fault handler. Access done under the control the mmap_sem doesn't require to grab the rwlock to protect read access to the mm_rb tree, but access in write must be done under the protection of the rwlock too. This affects inserting and removing of elements in the RB tree. The patch is introducing 2 new functions: - vma_get() to find a VMA based on an address by holding the new rwlock. - vma_put() to release the VMA when its no more used. These services are designed to be used when access are made to the RB tree without holding the mmap_sem. When a VMA is removed from the RB tree, its vma->vm_rb field is cleared and we rely on the WMB done when releasing the rwlock to serialize the write with the RMB done in a later patch to check for the VMA's validity. When free_vma is called, the file associated with the VMA is closed immediately, but the policy and the file structure remained in used until the VMA's use count reach 0, which may happens later when exiting an in progress speculative page fault. [1] https://patchwork.kernel.org/patch/5108281/ Change-Id: I9ecc922b8efa4b28975cc6a8e9531284c24ac14e Cc: Peter Zijlstra (Intel) Cc: Matthew Wilcox Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:23 [vinmenon@codeaurora.org: fix the return of put_vma] Signed-off-by: Vinayak Menon --- include/linux/mm.h | 1 + include/linux/mm_types.h | 4 ++ kernel/fork.c | 3 + mm/init-mm.c | 3 + mm/internal.h | 6 ++ mm/mmap.c | 115 +++++++++++++++++++++++++++++---------- 6 files changed, 104 insertions(+), 28 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 17b0b3e7a37b..b44e0b2f9975 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1251,6 +1251,7 @@ static inline void INIT_VMA(struct vm_area_struct *vma) INIT_LIST_HEAD(&vma->anon_vma_chain); #ifdef CONFIG_SPECULATIVE_PAGE_FAULT seqcount_init(&vma->vm_sequence); + atomic_set(&vma->vm_ref_count, 1); #endif } diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 8f1478057812..121a5796bbe4 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -346,6 +346,7 @@ struct vm_area_struct { struct vm_userfaultfd_ctx vm_userfaultfd_ctx; #ifdef CONFIG_SPECULATIVE_PAGE_FAULT seqcount_t vm_sequence; + atomic_t vm_ref_count; /* see vma_get(), vma_put() */ #endif } __randomize_layout; @@ -364,6 +365,9 @@ struct kioctx_table; struct mm_struct { struct vm_area_struct *mmap; /* list of VMAs */ struct rb_root mm_rb; +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + rwlock_t mm_rb_lock; +#endif u32 vmacache_seqnum; /* per-thread vmacache */ #ifdef CONFIG_MMU unsigned long (*get_unmapped_area) (struct file *filp, diff --git a/kernel/fork.c b/kernel/fork.c index 9d3eb700dfa2..d323550d6c14 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -811,6 +811,9 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, mm->mmap = NULL; mm->mm_rb = RB_ROOT; mm->vmacache_seqnum = 0; +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + rwlock_init(&mm->mm_rb_lock); +#endif atomic_set(&mm->mm_users, 1); atomic_set(&mm->mm_count, 1); init_rwsem(&mm->mmap_sem); diff --git a/mm/init-mm.c b/mm/init-mm.c index f94d5d15ebc0..e71ac37a98c4 100644 --- a/mm/init-mm.c +++ b/mm/init-mm.c @@ -17,6 +17,9 @@ struct mm_struct init_mm = { .mm_rb = RB_ROOT, +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + .mm_rb_lock = __RW_LOCK_UNLOCKED(init_mm.mm_rb_lock), +#endif .pgd = swapper_pg_dir, .mm_users = ATOMIC_INIT(2), .mm_count = ATOMIC_INIT(1), diff --git a/mm/internal.h b/mm/internal.h index 1df011f62480..7a2d10376775 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -40,6 +40,12 @@ void page_writeback_init(void); int do_swap_page(struct vm_fault *vmf); +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT +extern struct vm_area_struct *get_vma(struct mm_struct *mm, + unsigned long addr); +extern void put_vma(struct vm_area_struct *vma); +#endif + void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma, unsigned long floor, unsigned long ceiling); diff --git a/mm/mmap.c b/mm/mmap.c index 2855b682f58a..aa5bf9a71e5b 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -160,6 +160,27 @@ void unlink_file_vma(struct vm_area_struct *vma) } } +static void __free_vma(struct vm_area_struct *vma) +{ + if (vma->vm_file) + fput(vma->vm_file); + mpol_put(vma_policy(vma)); + kmem_cache_free(vm_area_cachep, vma); +} + +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT +void put_vma(struct vm_area_struct *vma) +{ + if (atomic_dec_and_test(&vma->vm_ref_count)) + __free_vma(vma); +} +#else +static inline void put_vma(struct vm_area_struct *vma) +{ + __free_vma(vma); +} +#endif + /* * Close a vm structure and free it, returning the next. */ @@ -170,10 +191,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) might_sleep(); if (vma->vm_ops && vma->vm_ops->close) vma->vm_ops->close(vma); - if (vma->vm_file) - fput(vma->vm_file); - mpol_put(vma_policy(vma)); - kmem_cache_free(vm_area_cachep, vma); + put_vma(vma); return next; } @@ -393,6 +411,14 @@ static void validate_mm(struct mm_struct *mm) #define validate_mm(mm) do { } while (0) #endif +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT +#define mm_rb_write_lock(mm) write_lock(&(mm)->mm_rb_lock) +#define mm_rb_write_unlock(mm) write_unlock(&(mm)->mm_rb_lock) +#else +#define mm_rb_write_lock(mm) do { } while (0) +#define mm_rb_write_unlock(mm) do { } while (0) +#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */ + RB_DECLARE_CALLBACKS(static, vma_gap_callbacks, struct vm_area_struct, vm_rb, unsigned long, rb_subtree_gap, vma_compute_subtree_gap) @@ -411,26 +437,37 @@ static void vma_gap_update(struct vm_area_struct *vma) } static inline void vma_rb_insert(struct vm_area_struct *vma, - struct rb_root *root) + struct mm_struct *mm) { + struct rb_root *root = &mm->mm_rb; + /* All rb_subtree_gap values must be consistent prior to insertion */ validate_mm_rb(root, NULL); rb_insert_augmented(&vma->vm_rb, root, &vma_gap_callbacks); } -static void __vma_rb_erase(struct vm_area_struct *vma, struct rb_root *root) +static void __vma_rb_erase(struct vm_area_struct *vma, struct mm_struct *mm) { + struct rb_root *root = &mm->mm_rb; /* * Note rb_erase_augmented is a fairly large inline function, * so make sure we instantiate it only once with our desired * augmented rbtree callbacks. */ + mm_rb_write_lock(mm); rb_erase_augmented(&vma->vm_rb, root, &vma_gap_callbacks); + mm_rb_write_unlock(mm); /* wmb */ + + /* + * Ensure the removal is complete before clearing the node. + * Matched by vma_has_changed()/handle_speculative_fault(). + */ + RB_CLEAR_NODE(&vma->vm_rb); } static __always_inline void vma_rb_erase_ignore(struct vm_area_struct *vma, - struct rb_root *root, + struct mm_struct *mm, struct vm_area_struct *ignore) { /* @@ -438,21 +475,21 @@ static __always_inline void vma_rb_erase_ignore(struct vm_area_struct *vma, * with the possible exception of the "next" vma being erased if * next->vm_start was reduced. */ - validate_mm_rb(root, ignore); + validate_mm_rb(&mm->mm_rb, ignore); - __vma_rb_erase(vma, root); + __vma_rb_erase(vma, mm); } static __always_inline void vma_rb_erase(struct vm_area_struct *vma, - struct rb_root *root) + struct mm_struct *mm) { /* * All rb_subtree_gap values must be consistent prior to erase, * with the possible exception of the vma being erased. */ - validate_mm_rb(root, vma); + validate_mm_rb(&mm->mm_rb, vma); - __vma_rb_erase(vma, root); + __vma_rb_erase(vma, mm); } /* @@ -567,10 +604,12 @@ void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma, * immediately update the gap to the correct value. Finally we * rebalance the rbtree after all augmented values have been set. */ + mm_rb_write_lock(mm); rb_link_node(&vma->vm_rb, rb_parent, rb_link); vma->rb_subtree_gap = 0; vma_gap_update(vma); - vma_rb_insert(vma, &mm->mm_rb); + vma_rb_insert(vma, mm); + mm_rb_write_unlock(mm); } static void __vma_link_file(struct vm_area_struct *vma) @@ -646,7 +685,7 @@ static __always_inline void __vma_unlink_common(struct mm_struct *mm, { struct vm_area_struct *next; - vma_rb_erase_ignore(vma, &mm->mm_rb, ignore); + vma_rb_erase_ignore(vma, mm, ignore); next = vma->vm_next; if (has_prev) prev->vm_next = next; @@ -923,16 +962,13 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, } if (remove_next) { - if (file) { + if (file) uprobe_munmap(next, next->vm_start, next->vm_end); - fput(file); - } if (next->anon_vma) anon_vma_merge(vma, next); mm->map_count--; - mpol_put(vma_policy(next)); vm_raw_write_end(next); - kmem_cache_free(vm_area_cachep, next); + put_vma(next); /* * In mprotect's case 6 (see comments on vma_merge), * we must remove another next too. It would clutter @@ -2165,15 +2201,11 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, EXPORT_SYMBOL(get_unmapped_area); /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ -struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) +static struct vm_area_struct *__find_vma(struct mm_struct *mm, + unsigned long addr) { struct rb_node *rb_node; - struct vm_area_struct *vma; - - /* Check the cache first. */ - vma = vmacache_find(mm, addr); - if (likely(vma)) - return vma; + struct vm_area_struct *vma = NULL; rb_node = mm->mm_rb.rb_node; @@ -2191,13 +2223,40 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) rb_node = rb_node->rb_right; } + return vma; +} + +struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) +{ + struct vm_area_struct *vma; + + /* Check the cache first. */ + vma = vmacache_find(mm, addr); + if (likely(vma)) + return vma; + + vma = __find_vma(mm, addr); if (vma) vmacache_update(addr, vma); return vma; } - EXPORT_SYMBOL(find_vma); +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT +struct vm_area_struct *get_vma(struct mm_struct *mm, unsigned long addr) +{ + struct vm_area_struct *vma = NULL; + + read_lock(&mm->mm_rb_lock); + vma = __find_vma(mm, addr); + if (vma) + atomic_inc(&vma->vm_ref_count); + read_unlock(&mm->mm_rb_lock); + + return vma; +} +#endif + /* * Same as find_vma, but also return a pointer to the previous VMA in *pprev. */ @@ -2565,7 +2624,7 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, insertion_point = (prev ? &prev->vm_next : &mm->mmap); vma->vm_prev = NULL; do { - vma_rb_erase(vma, &mm->mm_rb); + vma_rb_erase(vma, mm); mm->map_count--; tail_vma = vma; vma = vma->vm_next; -- GitLab From ce37f07c6b6374e48b2ea986359552dcf6d3daf5 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 17 Apr 2018 16:33:24 +0200 Subject: [PATCH 0025/1299] mm: provide speculative fault infrastructure Provide infrastructure to do a speculative fault (not holding mmap_sem). The not holding of mmap_sem means we can race against VMA change/removal and page-table destruction. We use the SRCU VMA freeing to keep the VMA around. We use the VMA seqcount to detect change (including umapping / page-table deletion) and we use gup_fast() style page-table walking to deal with page-table races. Once we've obtained the page and are ready to update the PTE, we validate if the state we started the fault with is still valid, if not, we'll fail the fault with VM_FAULT_RETRY, otherwise we update the PTE and we're done. Signed-off-by: Peter Zijlstra (Intel) [Manage the newly introduced pte_spinlock() for speculative page fault to fail if the VMA is touched in our back] [Rename vma_is_dead() to vma_has_changed() and declare it here] [Fetch p4d and pud] [Set vmd.sequence in __handle_mm_fault()] [Abort speculative path when handle_userfault() has to be called] [Add additional VMA's flags checks in handle_speculative_fault()] [Clear FAULT_FLAG_ALLOW_RETRY in handle_speculative_fault()] [Don't set vmf->pte and vmf->ptl if pte_map_lock() failed] [Remove warning comment about waiting for !seq&1 since we don't want to wait] [Remove warning about no huge page support, mention it explictly] [Don't call do_fault() in the speculative path as __do_fault() calls vma->vm_ops->fault() which may want to release mmap_sem] [Only vm_fault pointer argument for vma_has_changed()] [Fix check against huge page, calling pmd_trans_huge()] [Use READ_ONCE() when reading VMA's fields in the speculative path] [Explicitly check for __HAVE_ARCH_PTE_SPECIAL as we can't support for processing done in vm_normal_page()] [Check that vma->anon_vma is already set when starting the speculative path] [Check for memory policy as we can't support MPOL_INTERLEAVE case due to the processing done in mpol_misplaced()] [Don't support VMA growing up or down] [Move check on vm_sequence just before calling handle_pte_fault()] [Don't build SPF services if !CONFIG_SPECULATIVE_PAGE_FAULT] [Add mem cgroup oom check] [Use READ_ONCE to access p*d entries] [Replace deprecated ACCESS_ONCE() by READ_ONCE() in vma_has_changed()] [Don't fetch pte again in handle_pte_fault() when running the speculative path] [Check PMD against concurrent collapsing operation] [Try spin lock the pte during the speculative path to avoid deadlock with other CPU's invalidating the TLB and requiring this CPU to catch the inter processor's interrupt] [Move define of FAULT_FLAG_SPECULATIVE here] [Introduce __handle_speculative_fault() and add a check against mm->mm_users in handle_speculative_fault() defined in mm.h] Signed-off-by: Laurent Dufour Change-Id: I45cbe79a96c7aa234cace421a36550e7fb0b9368 Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:24 [vinmenon@codeaurora.org: fix !CONFIG_NUMA build + checkpatch fixes] Signed-off-by: Vinayak Menon --- include/linux/hugetlb_inline.h | 2 +- include/linux/mm.h | 31 +++ include/linux/pagemap.h | 4 +- mm/internal.h | 16 +- mm/memory.c | 342 ++++++++++++++++++++++++++++++++- 5 files changed, 388 insertions(+), 7 deletions(-) diff --git a/include/linux/hugetlb_inline.h b/include/linux/hugetlb_inline.h index 0660a03d37d9..9e25283d6fc9 100644 --- a/include/linux/hugetlb_inline.h +++ b/include/linux/hugetlb_inline.h @@ -8,7 +8,7 @@ static inline bool is_vm_hugetlb_page(struct vm_area_struct *vma) { - return !!(vma->vm_flags & VM_HUGETLB); + return !!(READ_ONCE(vma->vm_flags) & VM_HUGETLB); } #else diff --git a/include/linux/mm.h b/include/linux/mm.h index b44e0b2f9975..eafaf4739277 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -292,6 +292,8 @@ extern pgprot_t protection_map[16]; #define FAULT_FLAG_USER 0x40 /* The fault originated in userspace */ #define FAULT_FLAG_REMOTE 0x80 /* faulting for non current tsk/mm */ #define FAULT_FLAG_INSTRUCTION 0x100 /* The fault was during an instruction fetch */ +/* Speculative fault, not holding mmap_sem */ +#define FAULT_FLAG_SPECULATIVE 0x200 #define FAULT_FLAG_TRACE \ { FAULT_FLAG_WRITE, "WRITE" }, \ @@ -320,6 +322,10 @@ struct vm_fault { gfp_t gfp_mask; /* gfp mask to be used for allocations */ pgoff_t pgoff; /* Logical page offset based on vma */ unsigned long address; /* Faulting virtual address */ +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + unsigned int sequence; + pmd_t orig_pmd; /* value of PMD at the time of fault */ +#endif pmd_t *pmd; /* Pointer to pmd entry matching * the 'address' */ pud_t *pud; /* Pointer to pud entry matching @@ -1401,6 +1407,31 @@ int invalidate_inode_page(struct page *page); #ifdef CONFIG_MMU extern int handle_mm_fault(struct vm_area_struct *vma, unsigned long address, unsigned int flags); + +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT +extern int __handle_speculative_fault(struct mm_struct *mm, + unsigned long address, + unsigned int flags); +static inline int handle_speculative_fault(struct mm_struct *mm, + unsigned long address, + unsigned int flags) +{ + /* + * Try speculative page fault for multithreaded user space task only. + */ + if (!(flags & FAULT_FLAG_USER) || atomic_read(&mm->mm_users) == 1) + return VM_FAULT_RETRY; + return __handle_speculative_fault(mm, address, flags); +} +#else +static inline int handle_speculative_fault(struct mm_struct *mm, + unsigned long address, + unsigned int flags) +{ + return VM_FAULT_RETRY; +} +#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */ + extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm, unsigned long address, unsigned int fault_flags, bool *unlocked); diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 9369e9cea295..51a9a0af3281 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -452,8 +452,8 @@ static inline pgoff_t linear_page_index(struct vm_area_struct *vma, pgoff_t pgoff; if (unlikely(is_vm_hugetlb_page(vma))) return linear_hugepage_index(vma, address); - pgoff = (address - vma->vm_start) >> PAGE_SHIFT; - pgoff += vma->vm_pgoff; + pgoff = (address - READ_ONCE(vma->vm_start)) >> PAGE_SHIFT; + pgoff += READ_ONCE(vma->vm_pgoff); return pgoff; } diff --git a/mm/internal.h b/mm/internal.h index 7a2d10376775..7cc2c6e787bf 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -44,7 +44,21 @@ int do_swap_page(struct vm_fault *vmf); extern struct vm_area_struct *get_vma(struct mm_struct *mm, unsigned long addr); extern void put_vma(struct vm_area_struct *vma); -#endif + +static inline bool vma_has_changed(struct vm_fault *vmf) +{ + int ret = RB_EMPTY_NODE(&vmf->vma->vm_rb); + unsigned int seq = READ_ONCE(vmf->vma->vm_sequence.sequence); + + /* + * Matches both the wmb in write_seqlock_{begin,end}() and + * the wmb in vma_rb_erase(). + */ + smp_rmb(); + + return ret || seq != vmf->sequence; +} +#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma, unsigned long floor, unsigned long ceiling); diff --git a/mm/memory.c b/mm/memory.c index f8efb3efe2e9..81ef2d146dac 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -762,7 +762,8 @@ static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr, if (page) dump_page(page, "bad pte"); pr_alert("addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n", - (void *)addr, vma->vm_flags, vma->anon_vma, mapping, index); + (void *)addr, READ_ONCE(vma->vm_flags), vma->anon_vma, + mapping, index); /* * Choose text because data symbols depend on CONFIG_KALLSYMS_ALL=y */ @@ -2282,6 +2283,113 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr, } EXPORT_SYMBOL_GPL(apply_to_page_range); +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT +static bool pte_spinlock(struct vm_fault *vmf) +{ + bool ret = false; +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + pmd_t pmdval; +#endif + + /* Check if vma is still valid */ + if (!(vmf->flags & FAULT_FLAG_SPECULATIVE)) { + vmf->ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd); + spin_lock(vmf->ptl); + return true; + } + + local_irq_disable(); + if (vma_has_changed(vmf)) + goto out; + +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + /* + * We check if the pmd value is still the same to ensure that there + * is not a huge collapse operation in progress in our back. + */ + pmdval = READ_ONCE(*vmf->pmd); + if (!pmd_same(pmdval, vmf->orig_pmd)) + goto out; +#endif + + vmf->ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd); + if (unlikely(!spin_trylock(vmf->ptl))) + goto out; + + if (vma_has_changed(vmf)) { + spin_unlock(vmf->ptl); + goto out; + } + + ret = true; +out: + local_irq_enable(); + return ret; +} + +static bool pte_map_lock(struct vm_fault *vmf) +{ + bool ret = false; + pte_t *pte; + spinlock_t *ptl; +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + pmd_t pmdval; +#endif + + if (!(vmf->flags & FAULT_FLAG_SPECULATIVE)) { + vmf->pte = pte_offset_map_lock(vmf->vma->vm_mm, vmf->pmd, + vmf->address, &vmf->ptl); + return true; + } + + /* + * The first vma_has_changed() guarantees the page-tables are still + * valid, having IRQs disabled ensures they stay around, hence the + * second vma_has_changed() to make sure they are still valid once + * we've got the lock. After that a concurrent zap_pte_range() will + * block on the PTL and thus we're safe. + */ + local_irq_disable(); + if (vma_has_changed(vmf)) + goto out; + +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + /* + * We check if the pmd value is still the same to ensure that there + * is not a huge collapse operation in progress in our back. + */ + pmdval = READ_ONCE(*vmf->pmd); + if (!pmd_same(pmdval, vmf->orig_pmd)) + goto out; +#endif + + /* + * Same as pte_offset_map_lock() except that we call + * spin_trylock() in place of spin_lock() to avoid race with + * unmap path which may have the lock and wait for this CPU + * to invalidate TLB but this CPU has irq disabled. + * Since we are in a speculative patch, accept it could fail + */ + ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd); + pte = pte_offset_map(vmf->pmd, vmf->address); + if (unlikely(!spin_trylock(ptl))) { + pte_unmap(pte); + goto out; + } + + if (vma_has_changed(vmf)) { + pte_unmap_unlock(pte, ptl); + goto out; + } + + vmf->pte = pte; + vmf->ptl = ptl; + ret = true; +out: + local_irq_enable(); + return ret; +} +#else static inline bool pte_spinlock(struct vm_fault *vmf) { vmf->ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd); @@ -2295,6 +2403,7 @@ static inline bool pte_map_lock(struct vm_fault *vmf) vmf->address, &vmf->ptl); return true; } +#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */ /* * handle_pte_fault chooses page fault handler according to an entry which was @@ -3161,6 +3270,14 @@ static int do_anonymous_page(struct vm_fault *vmf) ret = check_stable_address_space(vma->vm_mm); if (ret) goto unlock; + /* + * Don't call the userfaultfd during the speculative path. + * We already checked for the VMA to not be managed through + * userfaultfd, but it may be set in our back once we have lock + * the pte. In such a case we can ignore it this time. + */ + if (vmf->flags & FAULT_FLAG_SPECULATIVE) + goto setpte; /* Deliver the page fault to userland, check inside PT lock */ if (userfaultfd_missing(vma)) { pte_unmap_unlock(vmf->pte, vmf->ptl); @@ -3202,7 +3319,8 @@ static int do_anonymous_page(struct vm_fault *vmf) goto unlock_and_release; /* Deliver the page fault to userland, check inside PT lock */ - if (userfaultfd_missing(vma)) { + if (!(vmf->flags & FAULT_FLAG_SPECULATIVE) && + userfaultfd_missing(vma)) { pte_unmap_unlock(vmf->pte, vmf->ptl); mem_cgroup_cancel_charge(page, memcg, false); put_page(page); @@ -3945,6 +4063,15 @@ static int handle_pte_fault(struct vm_fault *vmf) pte_t entry; if (unlikely(pmd_none(*vmf->pmd))) { + /* + * In the case of the speculative page fault handler we abort + * the speculative path immediately as the pmd is probably + * in the way to be converted in a huge one. We will try + * again holding the mmap_sem (which implies that the collapse + * operation is done). + */ + if (vmf->flags & FAULT_FLAG_SPECULATIVE) + return VM_FAULT_RETRY; /* * Leave __pte_alloc() until later: because vm_ops->fault may * want to allocate huge page, and if we expose page table @@ -3952,7 +4079,7 @@ static int handle_pte_fault(struct vm_fault *vmf) * concurrent faults and from rmap lookups. */ vmf->pte = NULL; - } else { + } else if (!(vmf->flags & FAULT_FLAG_SPECULATIVE)) { /* See comment in pte_alloc_one_map() */ if (pmd_devmap_trans_unstable(vmf->pmd)) return 0; @@ -3961,6 +4088,9 @@ static int handle_pte_fault(struct vm_fault *vmf) * pmd from under us anymore at this point because we hold the * mmap_sem read mode and khugepaged takes it in write mode. * So now it's safe to run pte_offset_map(). + * This is not applicable to the speculative page fault handler + * but in that case, the pte is fetched earlier in + * handle_speculative_fault(). */ vmf->pte = pte_offset_map(vmf->pmd, vmf->address); vmf->orig_pte = *vmf->pte; @@ -3983,6 +4113,8 @@ static int handle_pte_fault(struct vm_fault *vmf) if (!vmf->pte) { if (vma_is_anonymous(vmf->vma)) return do_anonymous_page(vmf); + else if (vmf->flags & FAULT_FLAG_SPECULATIVE) + return VM_FAULT_RETRY; else return do_fault(vmf); } @@ -4080,6 +4212,9 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address, vmf.pmd = pmd_alloc(mm, vmf.pud, address); if (!vmf.pmd) return VM_FAULT_OOM; +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + vmf.sequence = raw_read_seqcount(&vma->vm_sequence); +#endif if (pmd_none(*vmf.pmd) && transparent_hugepage_enabled(vma)) { ret = create_huge_pmd(&vmf); if (!(ret & VM_FAULT_FALLBACK)) @@ -4113,6 +4248,207 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address, return handle_pte_fault(&vmf); } +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + +#ifndef __HAVE_ARCH_PTE_SPECIAL +/* This is required by vm_normal_page() */ +#error "Speculative page fault handler requires __HAVE_ARCH_PTE_SPECIAL" +#endif + +/* + * vm_normal_page() adds some processing which should be done while + * hodling the mmap_sem. + */ +int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, + unsigned int flags) +{ + struct vm_fault vmf = { + .address = address, + }; + pgd_t *pgd, pgdval; + p4d_t *p4d, p4dval; + pud_t pudval; + int seq, ret = VM_FAULT_RETRY; + struct vm_area_struct *vma; + + /* Clear flags that may lead to release the mmap_sem to retry */ + flags &= ~(FAULT_FLAG_ALLOW_RETRY|FAULT_FLAG_KILLABLE); + flags |= FAULT_FLAG_SPECULATIVE; + + vma = get_vma(mm, address); + if (!vma) + return ret; + + /* rmb <-> seqlock,vma_rb_erase() */ + seq = raw_read_seqcount(&vma->vm_sequence); + if (seq & 1) + goto out_put; + + /* + * Can't call vm_ops service has we don't know what they would do + * with the VMA. + * This include huge page from hugetlbfs. + */ + if (vma->vm_ops) + goto out_put; + + /* + * __anon_vma_prepare() requires the mmap_sem to be held + * because vm_next and vm_prev must be safe. This can't be guaranteed + * in the speculative path. + */ + if (unlikely(!vma->anon_vma)) + goto out_put; + + vmf.vma_flags = READ_ONCE(vma->vm_flags); + vmf.vma_page_prot = READ_ONCE(vma->vm_page_prot); + + /* Can't call userland page fault handler in the speculative path */ + if (unlikely(vmf.vma_flags & VM_UFFD_MISSING)) + goto out_put; + + if (vmf.vma_flags & VM_GROWSDOWN || vmf.vma_flags & VM_GROWSUP) + /* + * This could be detected by the check address against VMA's + * boundaries but we want to trace it as not supported instead + * of changed. + */ + goto out_put; + + if (address < READ_ONCE(vma->vm_start) + || READ_ONCE(vma->vm_end) <= address) + goto out_put; + + if (!arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE, + flags & FAULT_FLAG_INSTRUCTION, + flags & FAULT_FLAG_REMOTE)) { + ret = VM_FAULT_SIGSEGV; + goto out_put; + } + + /* This is one is required to check that the VMA has write access set */ + if (flags & FAULT_FLAG_WRITE) { + if (unlikely(!(vmf.vma_flags & VM_WRITE))) { + ret = VM_FAULT_SIGSEGV; + goto out_put; + } + } else if (unlikely(!(vmf.vma_flags & (VM_READ|VM_EXEC|VM_WRITE)))) { + ret = VM_FAULT_SIGSEGV; + goto out_put; + } + +#ifdef CONFIG_NUMA + struct mempolicy *pol; + + /* + * MPOL_INTERLEAVE implies additional checks in + * mpol_misplaced() which are not compatible with the + *speculative page fault processing. + */ + pol = __get_vma_policy(vma, address); + if (!pol) + pol = get_task_policy(current); + if (pol && pol->mode == MPOL_INTERLEAVE) + goto out_put; +#endif + + /* + * Do a speculative lookup of the PTE entry. + */ + local_irq_disable(); + pgd = pgd_offset(mm, address); + pgdval = READ_ONCE(*pgd); + if (pgd_none(pgdval) || unlikely(pgd_bad(pgdval))) + goto out_walk; + + p4d = p4d_offset(pgd, address); + p4dval = READ_ONCE(*p4d); + if (p4d_none(p4dval) || unlikely(p4d_bad(p4dval))) + goto out_walk; + + vmf.pud = pud_offset(p4d, address); + pudval = READ_ONCE(*vmf.pud); + if (pud_none(pudval) || unlikely(pud_bad(pudval))) + goto out_walk; + + /* Huge pages at PUD level are not supported. */ + if (unlikely(pud_trans_huge(pudval))) + goto out_walk; + + vmf.pmd = pmd_offset(vmf.pud, address); + vmf.orig_pmd = READ_ONCE(*vmf.pmd); + /* + * pmd_none could mean that a hugepage collapse is in progress + * in our back as collapse_huge_page() mark it before + * invalidating the pte (which is done once the IPI is catched + * by all CPU and we have interrupt disabled). + * For this reason we cannot handle THP in a speculative way since we + * can't safely indentify an in progress collapse operation done in our + * back on that PMD. + * Regarding the order of the following checks, see comment in + * pmd_devmap_trans_unstable() + */ + if (unlikely(pmd_devmap(vmf.orig_pmd) || + pmd_none(vmf.orig_pmd) || pmd_trans_huge(vmf.orig_pmd) || + is_swap_pmd(vmf.orig_pmd))) + goto out_walk; + + /* + * The above does not allocate/instantiate page-tables because doing so + * would lead to the possibility of instantiating page-tables after + * free_pgtables() -- and consequently leaking them. + * + * The result is that we take at least one !speculative fault per PMD + * in order to instantiate it. + */ + + vmf.pte = pte_offset_map(vmf.pmd, address); + vmf.orig_pte = READ_ONCE(*vmf.pte); + barrier(); /* See comment in handle_pte_fault() */ + if (pte_none(vmf.orig_pte)) { + pte_unmap(vmf.pte); + vmf.pte = NULL; + } + + vmf.vma = vma; + vmf.pgoff = linear_page_index(vma, address); + vmf.gfp_mask = __get_fault_gfp_mask(vma); + vmf.sequence = seq; + vmf.flags = flags; + + local_irq_enable(); + + /* + * We need to re-validate the VMA after checking the bounds, otherwise + * we might have a false positive on the bounds. + */ + if (read_seqcount_retry(&vma->vm_sequence, seq)) + goto out_put; + + mem_cgroup_oom_enable(); + ret = handle_pte_fault(&vmf); + mem_cgroup_oom_disable(); + + put_vma(vma); + + /* + * The task may have entered a memcg OOM situation but + * if the allocation error was handled gracefully (no + * VM_FAULT_OOM), there is no need to kill anything. + * Just clean up the OOM state peacefully. + */ + if (task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM)) + mem_cgroup_oom_synchronize(false); + return ret; + +out_walk: + local_irq_enable(); +out_put: + put_vma(vma); + return ret; +} +#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */ + /* * By the time we get here, we already hold the mm semaphore * -- GitLab From 9a54b720861bc9e1891b9e979bc1fd35688ebde9 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:25 +0200 Subject: [PATCH 0026/1299] mm: adding speculative page fault failure trace events This patch a set of new trace events to collect the speculative page fault event failures. Signed-off-by: Laurent Dufour Change-Id: I9dafba293edf40bdad4ae241d105ecdfb42579c1 Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:25 [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- include/trace/events/pagefault.h | 88 ++++++++++++++++++++++++++++++++ mm/memory.c | 65 ++++++++++++++++++----- 2 files changed, 139 insertions(+), 14 deletions(-) create mode 100644 include/trace/events/pagefault.h diff --git a/include/trace/events/pagefault.h b/include/trace/events/pagefault.h new file mode 100644 index 000000000000..a9643b3759f2 --- /dev/null +++ b/include/trace/events/pagefault.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM pagefault + +#if !defined(_TRACE_PAGEFAULT_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_PAGEFAULT_H + +#include +#include + +DECLARE_EVENT_CLASS(spf, + + TP_PROTO(unsigned long caller, + struct vm_area_struct *vma, unsigned long address), + + TP_ARGS(caller, vma, address), + + TP_STRUCT__entry( + __field(unsigned long, caller) + __field(unsigned long, vm_start) + __field(unsigned long, vm_end) + __field(unsigned long, address) + ), + + TP_fast_assign( + __entry->caller = caller; + __entry->vm_start = vma->vm_start; + __entry->vm_end = vma->vm_end; + __entry->address = address; + ), + + TP_printk("ip:%lx vma:%lx-%lx address:%lx", + __entry->caller, __entry->vm_start, __entry->vm_end, + __entry->address) +); + +DEFINE_EVENT(spf, spf_pte_lock, + + TP_PROTO(unsigned long caller, + struct vm_area_struct *vma, unsigned long address), + + TP_ARGS(caller, vma, address) +); + +DEFINE_EVENT(spf, spf_vma_changed, + + TP_PROTO(unsigned long caller, + struct vm_area_struct *vma, unsigned long address), + + TP_ARGS(caller, vma, address) +); + +DEFINE_EVENT(spf, spf_vma_noanon, + + TP_PROTO(unsigned long caller, + struct vm_area_struct *vma, unsigned long address), + + TP_ARGS(caller, vma, address) +); + +DEFINE_EVENT(spf, spf_vma_notsup, + + TP_PROTO(unsigned long caller, + struct vm_area_struct *vma, unsigned long address), + + TP_ARGS(caller, vma, address) +); + +DEFINE_EVENT(spf, spf_vma_access, + + TP_PROTO(unsigned long caller, + struct vm_area_struct *vma, unsigned long address), + + TP_ARGS(caller, vma, address) +); + +DEFINE_EVENT(spf, spf_pmd_changed, + + TP_PROTO(unsigned long caller, + struct vm_area_struct *vma, unsigned long address), + + TP_ARGS(caller, vma, address) +); + +#endif /* _TRACE_PAGEFAULT_H */ + +/* This part must be outside protection */ +#include diff --git a/mm/memory.c b/mm/memory.c index 81ef2d146dac..2bcf8169f3b9 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -81,6 +81,9 @@ #include "internal.h" +#define CREATE_TRACE_POINTS +#include + #if defined(LAST_CPUPID_NOT_IN_PAGE_FLAGS) && !defined(CONFIG_COMPILE_TEST) #warning Unfortunate NUMA and NUMA Balancing config, growing page-frame for last_cpupid. #endif @@ -2299,8 +2302,10 @@ static bool pte_spinlock(struct vm_fault *vmf) } local_irq_disable(); - if (vma_has_changed(vmf)) + if (vma_has_changed(vmf)) { + trace_spf_vma_changed(_RET_IP_, vmf->vma, vmf->address); goto out; + } #ifdef CONFIG_TRANSPARENT_HUGEPAGE /* @@ -2308,16 +2313,21 @@ static bool pte_spinlock(struct vm_fault *vmf) * is not a huge collapse operation in progress in our back. */ pmdval = READ_ONCE(*vmf->pmd); - if (!pmd_same(pmdval, vmf->orig_pmd)) + if (!pmd_same(pmdval, vmf->orig_pmd)) { + trace_spf_pmd_changed(_RET_IP_, vmf->vma, vmf->address); goto out; + } #endif vmf->ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd); - if (unlikely(!spin_trylock(vmf->ptl))) + if (unlikely(!spin_trylock(vmf->ptl))) { + trace_spf_pte_lock(_RET_IP_, vmf->vma, vmf->address); goto out; + } if (vma_has_changed(vmf)) { spin_unlock(vmf->ptl); + trace_spf_vma_changed(_RET_IP_, vmf->vma, vmf->address); goto out; } @@ -2350,8 +2360,10 @@ static bool pte_map_lock(struct vm_fault *vmf) * block on the PTL and thus we're safe. */ local_irq_disable(); - if (vma_has_changed(vmf)) + if (vma_has_changed(vmf)) { + trace_spf_vma_changed(_RET_IP_, vmf->vma, vmf->address); goto out; + } #ifdef CONFIG_TRANSPARENT_HUGEPAGE /* @@ -2359,8 +2371,10 @@ static bool pte_map_lock(struct vm_fault *vmf) * is not a huge collapse operation in progress in our back. */ pmdval = READ_ONCE(*vmf->pmd); - if (!pmd_same(pmdval, vmf->orig_pmd)) + if (!pmd_same(pmdval, vmf->orig_pmd)) { + trace_spf_pmd_changed(_RET_IP_, vmf->vma, vmf->address); goto out; + } #endif /* @@ -2374,11 +2388,13 @@ static bool pte_map_lock(struct vm_fault *vmf) pte = pte_offset_map(vmf->pmd, vmf->address); if (unlikely(!spin_trylock(ptl))) { pte_unmap(pte); + trace_spf_pte_lock(_RET_IP_, vmf->vma, vmf->address); goto out; } if (vma_has_changed(vmf)) { pte_unmap_unlock(pte, ptl); + trace_spf_vma_changed(_RET_IP_, vmf->vma, vmf->address); goto out; } @@ -4281,47 +4297,60 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, /* rmb <-> seqlock,vma_rb_erase() */ seq = raw_read_seqcount(&vma->vm_sequence); - if (seq & 1) + if (seq & 1) { + trace_spf_vma_changed(_RET_IP_, vma, address); goto out_put; + } /* * Can't call vm_ops service has we don't know what they would do * with the VMA. * This include huge page from hugetlbfs. */ - if (vma->vm_ops) + if (vma->vm_ops) { + trace_spf_vma_notsup(_RET_IP_, vma, address); goto out_put; + } /* * __anon_vma_prepare() requires the mmap_sem to be held * because vm_next and vm_prev must be safe. This can't be guaranteed * in the speculative path. */ - if (unlikely(!vma->anon_vma)) + if (unlikely(!vma->anon_vma)) { + trace_spf_vma_notsup(_RET_IP_, vma, address); goto out_put; + } vmf.vma_flags = READ_ONCE(vma->vm_flags); vmf.vma_page_prot = READ_ONCE(vma->vm_page_prot); /* Can't call userland page fault handler in the speculative path */ - if (unlikely(vmf.vma_flags & VM_UFFD_MISSING)) + if (unlikely(vmf.vma_flags & VM_UFFD_MISSING)) { + trace_spf_vma_notsup(_RET_IP_, vma, address); goto out_put; + } - if (vmf.vma_flags & VM_GROWSDOWN || vmf.vma_flags & VM_GROWSUP) + if (vmf.vma_flags & VM_GROWSDOWN || vmf.vma_flags & VM_GROWSUP) { /* * This could be detected by the check address against VMA's * boundaries but we want to trace it as not supported instead * of changed. */ + trace_spf_vma_notsup(_RET_IP_, vma, address); goto out_put; + } if (address < READ_ONCE(vma->vm_start) - || READ_ONCE(vma->vm_end) <= address) + || READ_ONCE(vma->vm_end) <= address) { + trace_spf_vma_changed(_RET_IP_, vma, address); goto out_put; + } if (!arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE, flags & FAULT_FLAG_INSTRUCTION, flags & FAULT_FLAG_REMOTE)) { + trace_spf_vma_access(_RET_IP_, vma, address); ret = VM_FAULT_SIGSEGV; goto out_put; } @@ -4329,10 +4358,12 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, /* This is one is required to check that the VMA has write access set */ if (flags & FAULT_FLAG_WRITE) { if (unlikely(!(vmf.vma_flags & VM_WRITE))) { + trace_spf_vma_access(_RET_IP_, vma, address); ret = VM_FAULT_SIGSEGV; goto out_put; } } else if (unlikely(!(vmf.vma_flags & (VM_READ|VM_EXEC|VM_WRITE)))) { + trace_spf_vma_access(_RET_IP_, vma, address); ret = VM_FAULT_SIGSEGV; goto out_put; } @@ -4348,8 +4379,11 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, pol = __get_vma_policy(vma, address); if (!pol) pol = get_task_policy(current); - if (pol && pol->mode == MPOL_INTERLEAVE) - goto out_put; + if (!pol) + if (pol && pol->mode == MPOL_INTERLEAVE) { + trace_spf_vma_notsup(_RET_IP_, vma, address); + goto out_put; + } #endif /* @@ -4422,8 +4456,10 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, * We need to re-validate the VMA after checking the bounds, otherwise * we might have a false positive on the bounds. */ - if (read_seqcount_retry(&vma->vm_sequence, seq)) + if (read_seqcount_retry(&vma->vm_sequence, seq)) { + trace_spf_vma_changed(_RET_IP_, vma, address); goto out_put; + } mem_cgroup_oom_enable(); ret = handle_pte_fault(&vmf); @@ -4442,6 +4478,7 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, return ret; out_walk: + trace_spf_vma_notsup(_RET_IP_, vma, address); local_irq_enable(); out_put: put_vma(vma); -- GitLab From 697615066a8ec2bf53c24cb88476c75c4861eac7 Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:28 +0200 Subject: [PATCH 0027/1299] mm: speculative page fault handler return VMA When the speculative page fault handler is returning VM_RETRY, there is a chance that VMA fetched without grabbing the mmap_sem can be reused by the legacy page fault handler. By reusing it, we avoid calling find_vma() again. To achieve, that we must ensure that the VMA structure will not be freed in our back. This is done by getting the reference on it (get_vma()) and by assuming that the caller will call the new service can_reuse_spf_vma() once it has grabbed the mmap_sem. can_reuse_spf_vma() is first checking that the VMA is still in the RB tree , and then that the VMA's boundaries matched the passed address and release the reference on the VMA so that it can be freed if needed. In the case the VMA is freed, can_reuse_spf_vma() will have returned false as the VMA is no more in the RB tree. In the architecture page fault handler, the call to the new service reuse_spf_or_find_vma() should be made in place of find_vma(), this will handle the check on the spf_vma and if needed call find_vma(). Signed-off-by: Laurent Dufour Change-Id: Ia56dcf807e8bddf6788fd696dd80372db35476f0 Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:28 [vinmenon@codeaurora.org: trivial merge conflicts] Signed-off-by: Vinayak Menon --- include/linux/mm.h | 22 +++++-- mm/memory.c | 139 +++++++++++++++++++++++++++------------------ 2 files changed, 102 insertions(+), 59 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index eafaf4739277..fc7e143892bb 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1411,25 +1411,37 @@ extern int handle_mm_fault(struct vm_area_struct *vma, unsigned long address, #ifdef CONFIG_SPECULATIVE_PAGE_FAULT extern int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, - unsigned int flags); + unsigned int flags, + struct vm_area_struct **vma); static inline int handle_speculative_fault(struct mm_struct *mm, unsigned long address, - unsigned int flags) + unsigned int flags, + struct vm_area_struct **vma) { /* * Try speculative page fault for multithreaded user space task only. */ - if (!(flags & FAULT_FLAG_USER) || atomic_read(&mm->mm_users) == 1) + if (!(flags & FAULT_FLAG_USER) || atomic_read(&mm->mm_users) == 1) { + *vma = NULL; return VM_FAULT_RETRY; - return __handle_speculative_fault(mm, address, flags); + } + return __handle_speculative_fault(mm, address, flags, vma); } +extern bool can_reuse_spf_vma(struct vm_area_struct *vma, + unsigned long address); #else static inline int handle_speculative_fault(struct mm_struct *mm, unsigned long address, - unsigned int flags) + unsigned int flags, + struct vm_area_struct **vma) { return VM_FAULT_RETRY; } +static inline bool can_reuse_spf_vma(struct vm_area_struct *vma, + unsigned long address) +{ + return false; +} #endif /* CONFIG_SPECULATIVE_PAGE_FAULT */ extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm, diff --git a/mm/memory.c b/mm/memory.c index 2bcf8169f3b9..137ae04fb7b1 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4270,13 +4270,22 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address, /* This is required by vm_normal_page() */ #error "Speculative page fault handler requires __HAVE_ARCH_PTE_SPECIAL" #endif - /* * vm_normal_page() adds some processing which should be done while * hodling the mmap_sem. */ + +/* + * Tries to handle the page fault in a speculative way, without grabbing the + * mmap_sem. + * When VM_FAULT_RETRY is returned, the vma pointer is valid and this vma must + * be checked later when the mmap_sem has been grabbed by calling + * can_reuse_spf_vma(). + * This is needed as the returned vma is kept in memory until the call to + * can_reuse_spf_vma() is made. + */ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, - unsigned int flags) + unsigned int flags, struct vm_area_struct **vma) { struct vm_fault vmf = { .address = address, @@ -4284,22 +4293,22 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, pgd_t *pgd, pgdval; p4d_t *p4d, p4dval; pud_t pudval; - int seq, ret = VM_FAULT_RETRY; - struct vm_area_struct *vma; + int seq, ret; /* Clear flags that may lead to release the mmap_sem to retry */ flags &= ~(FAULT_FLAG_ALLOW_RETRY|FAULT_FLAG_KILLABLE); flags |= FAULT_FLAG_SPECULATIVE; - vma = get_vma(mm, address); - if (!vma) - return ret; + *vma = get_vma(mm, address); + if (!*vma) + return VM_FAULT_RETRY; + vmf.vma = *vma; /* rmb <-> seqlock,vma_rb_erase() */ - seq = raw_read_seqcount(&vma->vm_sequence); + seq = raw_read_seqcount(&vmf.vma->vm_sequence); if (seq & 1) { - trace_spf_vma_changed(_RET_IP_, vma, address); - goto out_put; + trace_spf_vma_changed(_RET_IP_, vmf.vma, address); + return VM_FAULT_RETRY; } /* @@ -4307,9 +4316,9 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, * with the VMA. * This include huge page from hugetlbfs. */ - if (vma->vm_ops) { - trace_spf_vma_notsup(_RET_IP_, vma, address); - goto out_put; + if (vmf.vma->vm_ops) { + trace_spf_vma_notsup(_RET_IP_, vmf.vma, address); + return VM_FAULT_RETRY; } /* @@ -4317,18 +4326,18 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, * because vm_next and vm_prev must be safe. This can't be guaranteed * in the speculative path. */ - if (unlikely(!vma->anon_vma)) { - trace_spf_vma_notsup(_RET_IP_, vma, address); - goto out_put; + if (unlikely(!vmf.vma->anon_vma)) { + trace_spf_vma_notsup(_RET_IP_, vmf.vma, address); + return VM_FAULT_RETRY; } - vmf.vma_flags = READ_ONCE(vma->vm_flags); - vmf.vma_page_prot = READ_ONCE(vma->vm_page_prot); + vmf.vma_flags = READ_ONCE(vmf.vma->vm_flags); + vmf.vma_page_prot = READ_ONCE(vmf.vma->vm_page_prot); /* Can't call userland page fault handler in the speculative path */ if (unlikely(vmf.vma_flags & VM_UFFD_MISSING)) { - trace_spf_vma_notsup(_RET_IP_, vma, address); - goto out_put; + trace_spf_vma_notsup(_RET_IP_, vmf.vma, address); + return VM_FAULT_RETRY; } if (vmf.vma_flags & VM_GROWSDOWN || vmf.vma_flags & VM_GROWSUP) { @@ -4337,36 +4346,27 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, * boundaries but we want to trace it as not supported instead * of changed. */ - trace_spf_vma_notsup(_RET_IP_, vma, address); - goto out_put; + trace_spf_vma_notsup(_RET_IP_, vmf.vma, address); + return VM_FAULT_RETRY; } - if (address < READ_ONCE(vma->vm_start) - || READ_ONCE(vma->vm_end) <= address) { - trace_spf_vma_changed(_RET_IP_, vma, address); - goto out_put; + if (address < READ_ONCE(vmf.vma->vm_start) + || READ_ONCE(vmf.vma->vm_end) <= address) { + trace_spf_vma_changed(_RET_IP_, vmf.vma, address); + return VM_FAULT_RETRY; } - if (!arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE, + if (!arch_vma_access_permitted(vmf.vma, flags & FAULT_FLAG_WRITE, flags & FAULT_FLAG_INSTRUCTION, - flags & FAULT_FLAG_REMOTE)) { - trace_spf_vma_access(_RET_IP_, vma, address); - ret = VM_FAULT_SIGSEGV; - goto out_put; - } + flags & FAULT_FLAG_REMOTE)) + goto out_segv; /* This is one is required to check that the VMA has write access set */ if (flags & FAULT_FLAG_WRITE) { - if (unlikely(!(vmf.vma_flags & VM_WRITE))) { - trace_spf_vma_access(_RET_IP_, vma, address); - ret = VM_FAULT_SIGSEGV; - goto out_put; - } - } else if (unlikely(!(vmf.vma_flags & (VM_READ|VM_EXEC|VM_WRITE)))) { - trace_spf_vma_access(_RET_IP_, vma, address); - ret = VM_FAULT_SIGSEGV; - goto out_put; - } + if (unlikely(!(vmf.vma_flags & VM_WRITE))) + goto out_segv; + } else if (unlikely(!(vmf.vma_flags & (VM_READ|VM_EXEC|VM_WRITE)))) + goto out_segv; #ifdef CONFIG_NUMA struct mempolicy *pol; @@ -4376,13 +4376,13 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, * mpol_misplaced() which are not compatible with the *speculative page fault processing. */ - pol = __get_vma_policy(vma, address); + pol = __get_vma_policy(vmf.vma, address); if (!pol) pol = get_task_policy(current); if (!pol) if (pol && pol->mode == MPOL_INTERLEAVE) { - trace_spf_vma_notsup(_RET_IP_, vma, address); - goto out_put; + trace_spf_vma_notsup(_RET_IP_, vmf.vma, address); + return VM_FAULT_RETRY; } #endif @@ -4444,9 +4444,8 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, vmf.pte = NULL; } - vmf.vma = vma; - vmf.pgoff = linear_page_index(vma, address); - vmf.gfp_mask = __get_fault_gfp_mask(vma); + vmf.pgoff = linear_page_index(vmf.vma, address); + vmf.gfp_mask = __get_fault_gfp_mask(vmf.vma); vmf.sequence = seq; vmf.flags = flags; @@ -4456,16 +4455,22 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, * We need to re-validate the VMA after checking the bounds, otherwise * we might have a false positive on the bounds. */ - if (read_seqcount_retry(&vma->vm_sequence, seq)) { - trace_spf_vma_changed(_RET_IP_, vma, address); - goto out_put; + if (read_seqcount_retry(&vmf.vma->vm_sequence, seq)) { + trace_spf_vma_changed(_RET_IP_, vmf.vma, address); + return VM_FAULT_RETRY; } mem_cgroup_oom_enable(); ret = handle_pte_fault(&vmf); mem_cgroup_oom_disable(); - put_vma(vma); + /* + * If there is no need to retry, don't return the vma to the caller. + */ + if (ret != VM_FAULT_RETRY) { + put_vma(vmf.vma); + *vma = NULL; + } /* * The task may have entered a memcg OOM situation but @@ -4478,9 +4483,35 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, return ret; out_walk: - trace_spf_vma_notsup(_RET_IP_, vma, address); + trace_spf_vma_notsup(_RET_IP_, vmf.vma, address); local_irq_enable(); -out_put: + return VM_FAULT_RETRY; + +out_segv: + trace_spf_vma_access(_RET_IP_, vmf.vma, address); + /* + * We don't return VM_FAULT_RETRY so the caller is not expected to + * retrieve the fetched VMA. + */ + put_vma(vmf.vma); + *vma = NULL; + return VM_FAULT_SIGSEGV; +} + +/* + * This is used to know if the vma fetch in the speculative page fault handler + * is still valid when trying the regular fault path while holding the + * mmap_sem. + * The call to put_vma(vma) must be made after checking the vma's fields, as + * the vma may be freed by put_vma(). In such a case it is expected that false + * is returned. + */ +bool can_reuse_spf_vma(struct vm_area_struct *vma, unsigned long address) +{ + bool ret; + + ret = !RB_EMPTY_NODE(&vma->vm_rb) && + vma->vm_start <= address && address < vma->vm_end; put_vma(vma); return ret; } -- GitLab From 726581778c6072ce5e9b2210e3075d8b9034fbda Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Tue, 17 Apr 2018 16:33:29 +0200 Subject: [PATCH 0028/1299] mm: add speculative page fault vmstats Add speculative_pgfault vmstat counter to count successful speculative page fault handling. Also fixing a minor typo in include/linux/vm_event_item.h. Change-Id: I0d3f3dc5195e1156d4b8edf83aff9d8d85904e8e Signed-off-by: Laurent Dufour Patch-mainline: linux-mm @ Tue, 17 Apr 2018 16:33:29 Signed-off-by: Vinayak Menon --- include/linux/vm_event_item.h | 3 +++ mm/memory.c | 1 + mm/vmstat.c | 5 ++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h index d3a8dbee8038..ffd92cc5a039 100644 --- a/include/linux/vm_event_item.h +++ b/include/linux/vm_event_item.h @@ -110,6 +110,9 @@ enum vm_event_item { PGPGIN, PGPGOUT, PGPGOUTCLEAN, PSWPIN, PSWPOUT, #ifdef CONFIG_SWAP SWAP_RA, SWAP_RA_HIT, +#endif +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + SPECULATIVE_PGFAULT, #endif NR_VM_EVENT_ITEMS }; diff --git a/mm/memory.c b/mm/memory.c index 137ae04fb7b1..36f74787fd2c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4468,6 +4468,7 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, * If there is no need to retry, don't return the vma to the caller. */ if (ret != VM_FAULT_RETRY) { + count_vm_event(SPECULATIVE_PGFAULT); put_vma(vmf.vma); *vma = NULL; } diff --git a/mm/vmstat.c b/mm/vmstat.c index e35d6d77ad68..c90f44e5d66a 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1219,7 +1219,10 @@ const char * const vmstat_text[] = { "swap_ra", "swap_ra_hit", #endif -#endif /* CONFIG_VM_EVENTS_COUNTERS */ +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + "speculative_pgfault" +#endif +#endif /* CONFIG_VM_EVENT_COUNTERS */ }; #endif /* CONFIG_PROC_FS || CONFIG_SYSFS || CONFIG_NUMA */ -- GitLab From 8bbf585224c12c60417e2f8ef0fa4e8f4242d39b Mon Sep 17 00:00:00 2001 From: Mahendran Ganesh Date: Fri, 4 May 2018 14:57:48 +0800 Subject: [PATCH 0029/1299] arm64/mm: define ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT Set ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT for arm64. This enables Speculative Page Fault handler. Change-Id: Ic55bd1993b3af78ddac25867c5f422861079bb27 Signed-off-by: Ganesh Mahendran Patch-mainline: linux-mm @ Wed, 2 May 2018 15:54:31 Signed-off-by: Vinayak Menon --- arch/arm64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 18015fe1d39b..e697f990411f 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -140,6 +140,7 @@ config ARM64 select SPARSE_IRQ select SYSCTL_EXCEPTION_TRACE select THREAD_INFO_IN_TASK + select ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT help ARM 64-bit (AArch64) Linux support. -- GitLab From 4e07353086b4ded25c4db6be62c8bcb8c6617f93 Mon Sep 17 00:00:00 2001 From: Mahendran Ganesh Date: Fri, 4 May 2018 14:57:49 +0800 Subject: [PATCH 0030/1299] arm64/mm: add speculative page fault This patch enables the speculative page fault on the arm64 architecture. I completed spf porting in 4.9. From the test result, we can see app launching time improved by about 10% in average. For the apps which have more than 50 threads, 15% or even more improvement can be got. Signed-off-by: Ganesh Mahendran Change-Id: Ib7c8b2e354800b5023e6c6400448a6d40aaf89c8 Patch-mainline: linux-mm @ Wed, 2 May 2018 15:54:32 [vinmenon@codeaurora.org: remove the speculative fault perf counter] Signed-off-by: Vinayak Menon --- arch/arm64/mm/fault.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index a3e6e81d6d63..9e493cab40a9 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -358,14 +358,12 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re #define VM_FAULT_BADMAP 0x010000 #define VM_FAULT_BADACCESS 0x020000 -static int __do_page_fault(struct mm_struct *mm, unsigned long addr, +static int __do_page_fault(struct vm_area_struct *vma, unsigned long addr, unsigned int mm_flags, unsigned long vm_flags, struct task_struct *tsk) { - struct vm_area_struct *vma; int fault; - vma = find_vma(mm, addr); fault = VM_FAULT_BADMAP; if (unlikely(!vma)) goto out; @@ -408,6 +406,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, int fault, sig, code, major = 0; unsigned long vm_flags = VM_READ | VM_WRITE; unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; + struct vm_area_struct *vma = NULL; if (notify_page_fault(regs, esr)) return 0; @@ -446,6 +445,14 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr); + /* + * let's try a speculative page fault without grabbing the + * mmap_sem. + */ + fault = handle_speculative_fault(mm, addr, mm_flags, &vma); + if (fault != VM_FAULT_RETRY) + goto done; + /* * As per x86, we may deadlock here. However, since the kernel only * validly references user space from well defined areas of the code, @@ -468,7 +475,10 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, #endif } - fault = __do_page_fault(mm, addr, mm_flags, vm_flags, tsk); + if (!vma || !can_reuse_spf_vma(vma, addr)) + vma = find_vma(mm, addr); + + fault = __do_page_fault(vma, addr, mm_flags, vm_flags, tsk); major |= fault & VM_FAULT_MAJOR; if (fault & VM_FAULT_RETRY) { @@ -491,11 +501,20 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, if (mm_flags & FAULT_FLAG_ALLOW_RETRY) { mm_flags &= ~FAULT_FLAG_ALLOW_RETRY; mm_flags |= FAULT_FLAG_TRIED; + + /* + * Do not try to reuse this vma and fetch it + * again since we will release the mmap_sem. + */ + vma = NULL; + goto retry; } } up_read(&mm->mmap_sem); +done: + /* * Handle the "normal" (no error) case first. */ -- GitLab From 397ac326813c443ec339cbd79bcfc82550732680 Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Wed, 28 Mar 2018 16:15:58 +0530 Subject: [PATCH 0031/1299] drm/msm/sde: Set the rotator dev state to active on resume Set the rotator dev state to active in pm resume as the dev state is used by generic pm driver for on/off operations. Change-Id: I0cde97f2ec2094d7374101719a9efb019bbaa5d8 Signed-off-by: Kalyan Thota --- drivers/media/platform/msm/sde/rotator/sde_rotator_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c index 585582deeee9..30ffcfc89746 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c @@ -3342,6 +3342,7 @@ int sde_rotator_pm_resume(struct device *dev) */ pm_runtime_disable(dev); pm_runtime_set_suspended(dev); + pm_runtime_set_active(dev); pm_runtime_enable(dev); sde_rot_mgr_lock(mgr); -- GitLab From 909f7878eda9700c5f329a608ffb542cd7e6daed Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Thu, 24 May 2018 10:05:54 -0700 Subject: [PATCH 0032/1299] drm/msm: track msm_gem_obj in active_list with a boolean The active_list is maintained to keep track of the unmapped buffers during the detach of a context-bank, so that it can be re-mapped during the re-attach process. Add a boolean to track if the msm_obj is part of active_list to avoid adding it twice. In addition, set the aspace domain_attached flag before the re-mapping of buffers during the re-attach process. This is required to re-map the buffers for which the domains were removed during detach of the context-bank. Change-Id: Ic4daa020dbed2faaffd609ceb369a2fbd36af4cf Signed-off-by: Veera Sundaram Sankaran --- drivers/gpu/drm/msm/msm_gem.c | 3 ++- drivers/gpu/drm/msm/msm_gem.h | 1 + drivers/gpu/drm/msm/msm_gem_vma.c | 2 ++ drivers/gpu/drm/msm/sde/sde_kms.c | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 766221196c32..9839cbe6368c 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -490,7 +490,7 @@ int msm_gem_get_iova(struct drm_gem_object *obj, *iova = vma->iova; - if (aspace && aspace->domain_attached) { + if (aspace && !msm_obj->in_active_list) { mutex_lock(&aspace->list_lock); msm_gem_add_obj_to_aspace_active_list(aspace, obj); mutex_unlock(&aspace->list_lock); @@ -1035,6 +1035,7 @@ static int msm_gem_new_impl(struct drm_device *dev, INIT_LIST_HEAD(&msm_obj->vmas); INIT_LIST_HEAD(&msm_obj->iova_list); msm_obj->aspace = NULL; + msm_obj->in_active_list = false; if (struct_mutex_locked) { WARN_ON(!mutex_is_locked(&dev->struct_mutex)); diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 903a53b42777..d3a0c97613d5 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -134,6 +134,7 @@ struct msm_gem_object { struct list_head iova_list; struct msm_gem_address_space *aspace; + bool in_active_list; }; #define to_msm_bo(x) container_of(x, struct msm_gem_object, base) diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 58fe9bc328d6..62c2233616eb 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -68,6 +68,7 @@ static void smmu_aspace_add_to_active( { WARN_ON(!mutex_is_locked(&aspace->list_lock)); list_move_tail(&msm_obj->iova_list, &aspace->active_list); + msm_obj->in_active_list = true; } static void smmu_aspace_remove_from_active( @@ -81,6 +82,7 @@ static void smmu_aspace_remove_from_active( list_for_each_entry_safe(msm_obj, next, &aspace->active_list, iova_list) { if (msm_obj == obj) { + msm_obj->in_active_list = false; list_del(&msm_obj->iova_list); break; } diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index bc88f929373b..08b0957dc67e 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -1799,8 +1799,8 @@ int sde_kms_mmu_attach(struct sde_kms *sde_kms, bool secure_only) aspace->mmu->funcs->attach(mmu, (const char **)iommu_ports, ARRAY_SIZE(iommu_ports)); - msm_gem_aspace_domain_attach_detach_update(aspace, false); aspace->domain_attached = true; + msm_gem_aspace_domain_attach_detach_update(aspace, false); } return 0; -- GitLab From fc01aee17f62972ad588d67033d380277877abc3 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Tue, 5 Jun 2018 13:02:10 +0530 Subject: [PATCH 0033/1299] msm: kgsl: Trigger GMU recovery on OOB set failures Currently, GMU recovery for preemption and performance counter OOB set failures is not getting triggered. Enable this to make sure GMU snapshot is dumped and recovery happens for these failures. Change-Id: Ie4084c236957538d396cfb504f50d7b325a5743d Signed-off-by: Deepak Kumar --- drivers/gpu/msm/adreno.h | 5 ++++- drivers/gpu/msm/adreno_a6xx_preempt.c | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index e2b848753e56..fb43f0ae7cd4 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -1862,8 +1862,11 @@ static inline int adreno_perfcntr_active_oob_get( if (gmu_dev_ops->oob_set) { ret = gmu_dev_ops->oob_set(adreno_dev, oob_perfcntr); - if (ret) + if (ret) { + adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT); + adreno_dispatcher_schedule(KGSL_DEVICE(adreno_dev)); kgsl_active_count_put(KGSL_DEVICE(adreno_dev)); + } } return ret; diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c index 0c308edea824..f71839ff6e74 100644 --- a/drivers/gpu/msm/adreno_a6xx_preempt.c +++ b/drivers/gpu/msm/adreno_a6xx_preempt.c @@ -48,8 +48,13 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer) if (gmu_dev_ops->oob_set) { status = gmu_dev_ops->oob_set(adreno_dev, oob_preempt); - if (status) + if (status) { + adreno_set_gpu_fault(adreno_dev, + ADRENO_GMU_FAULT); + adreno_dispatcher_schedule( + KGSL_DEVICE(adreno_dev)); return; + } } } -- GitLab From fab4419c92328117faeecfd55349735750ee9194 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Thu, 31 May 2018 11:41:03 +0530 Subject: [PATCH 0034/1299] msm: ADSPRPC: handle 32 bit support Handle 32 bit support without any truncation. Add IOCTL calls for map and unmap for 64 bit separately. Change-Id: I077a0b4345a6c21a88d7a500aa5c9faf7193f620 Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 22 +++++++ drivers/char/adsprpc_compat.c | 106 ++++++++++++++++++++++++++++++++++ drivers/char/adsprpc_shared.h | 15 +++++ 3 files changed, 143 insertions(+) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 5ecd690c9770..0970488d41f7 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2863,6 +2863,28 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, if (err) goto bail; break; + case FASTRPC_IOCTL_MMAP_64: + K_COPY_FROM_USER(err, 0, &p.mmap, param, + sizeof(p.mmap)); + if (err) + goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &p.mmap))); + if (err) + goto bail; + K_COPY_TO_USER(err, 0, param, &p.mmap, sizeof(p.mmap)); + if (err) + goto bail; + break; + case FASTRPC_IOCTL_MUNMAP_64: + K_COPY_FROM_USER(err, 0, &p.munmap, param, + sizeof(p.munmap)); + if (err) + goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, + &p.munmap))); + if (err) + goto bail; + break; case FASTRPC_IOCTL_MUNMAP_FD: K_COPY_FROM_USER(err, 0, &p.munmap_fd, param, sizeof(p.munmap_fd)); diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c index e7d50451440f..804cedade655 100644 --- a/drivers/char/adsprpc_compat.c +++ b/drivers/char/adsprpc_compat.c @@ -39,6 +39,10 @@ _IOWR('R', 11, struct compat_fastrpc_ioctl_invoke_crc) #define COMPAT_FASTRPC_IOCTL_CONTROL \ _IOWR('R', 12, struct compat_fastrpc_ioctl_control) +#define COMPAT_FASTRPC_IOCTL_MMAP_64 \ + _IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64) +#define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \ + _IOWR('R', 15, struct compat_fastrpc_ioctl_munmap_64) struct compat_remote_buf { compat_uptr_t pv; /* buffer pointer */ @@ -82,11 +86,24 @@ struct compat_fastrpc_ioctl_mmap { compat_uptr_t vaddrout; /* dsps virtual address */ }; +struct compat_fastrpc_ioctl_mmap_64 { + compat_int_t fd; /* ion fd */ + compat_uint_t flags; /* flags for dsp to map with */ + compat_u64 vaddrin; /* optional virtual address */ + compat_size_t size; /* size */ + compat_u64 vaddrout; /* dsps virtual address */ +}; + struct compat_fastrpc_ioctl_munmap { compat_uptr_t vaddrout; /* address to unmap */ compat_size_t size; /* size */ }; +struct compat_fastrpc_ioctl_munmap_64 { + compat_u64 vaddrout; /* address to unmap */ + compat_size_t size; /* size */ +}; + struct compat_fastrpc_ioctl_init { compat_uint_t flags; /* one of FASTRPC_INIT_* macros */ compat_uptr_t file; /* pointer to elf file */ @@ -206,6 +223,28 @@ static int compat_get_fastrpc_ioctl_mmap( return err; } +static int compat_get_fastrpc_ioctl_mmap_64( + struct compat_fastrpc_ioctl_mmap_64 __user *map32, + struct fastrpc_ioctl_mmap __user *map) +{ + compat_uint_t u; + compat_int_t i; + compat_size_t s; + compat_u64 p; + int err; + + err = get_user(i, &map32->fd); + err |= put_user(i, &map->fd); + err |= get_user(u, &map32->flags); + err |= put_user(u, &map->flags); + err |= get_user(p, &map32->vaddrin); + err |= put_user(p, &map->vaddrin); + err |= get_user(s, &map32->size); + err |= put_user(s, &map->size); + + return err; +} + static int compat_put_fastrpc_ioctl_mmap( struct compat_fastrpc_ioctl_mmap __user *map32, struct fastrpc_ioctl_mmap __user *map) @@ -219,6 +258,19 @@ static int compat_put_fastrpc_ioctl_mmap( return err; } +static int compat_put_fastrpc_ioctl_mmap_64( + struct compat_fastrpc_ioctl_mmap_64 __user *map32, + struct fastrpc_ioctl_mmap __user *map) +{ + compat_u64 p; + int err; + + err = get_user(p, &map->vaddrout); + err |= put_user(p, &map32->vaddrout); + + return err; +} + static int compat_get_fastrpc_ioctl_munmap( struct compat_fastrpc_ioctl_munmap __user *unmap32, struct fastrpc_ioctl_munmap __user *unmap) @@ -235,6 +287,22 @@ static int compat_get_fastrpc_ioctl_munmap( return err; } +static int compat_get_fastrpc_ioctl_munmap_64( + struct compat_fastrpc_ioctl_munmap_64 __user *unmap32, + struct fastrpc_ioctl_munmap __user *unmap) +{ + compat_u64 p; + compat_size_t s; + int err; + + err = get_user(p, &unmap32->vaddrout); + err |= put_user(p, &unmap->vaddrout); + err |= get_user(s, &unmap32->size); + err |= put_user(s, &unmap->size); + + return err; +} + static int compat_get_fastrpc_ioctl_perf( struct compat_fastrpc_ioctl_perf __user *perf32, struct fastrpc_ioctl_perf __user *perf) @@ -355,6 +423,27 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map)); return err; } + case COMPAT_FASTRPC_IOCTL_MMAP_64: + { + struct compat_fastrpc_ioctl_mmap_64 __user *map32; + struct fastrpc_ioctl_mmap __user *map; + long ret; + + map32 = compat_ptr(arg); + VERIFY(err, NULL != (map = compat_alloc_user_space( + sizeof(*map)))); + if (err) + return -EFAULT; + VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap_64(map32, map)); + if (err) + return err; + ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MMAP_64, + (unsigned long)map); + if (ret) + return ret; + VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap_64(map32, map)); + return err; + } case COMPAT_FASTRPC_IOCTL_MUNMAP: { struct compat_fastrpc_ioctl_munmap __user *unmap32; @@ -372,6 +461,23 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP, (unsigned long)unmap); } + case COMPAT_FASTRPC_IOCTL_MUNMAP_64: + { + struct compat_fastrpc_ioctl_munmap_64 __user *unmap32; + struct fastrpc_ioctl_munmap __user *unmap; + + unmap32 = compat_ptr(arg); + VERIFY(err, NULL != (unmap = compat_alloc_user_space( + sizeof(*unmap)))); + if (err) + return -EFAULT; + VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap_64(unmap32, + unmap)); + if (err) + return err; + return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP_64, + (unsigned long)unmap); + } case COMPAT_FASTRPC_IOCTL_INIT: /* fall through */ case COMPAT_FASTRPC_IOCTL_INIT_ATTRS: diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h index 207e1ab08e21..d7120a2f00ae 100644 --- a/drivers/char/adsprpc_shared.h +++ b/drivers/char/adsprpc_shared.h @@ -19,6 +19,8 @@ #define FASTRPC_IOCTL_INVOKE _IOWR('R', 1, struct fastrpc_ioctl_invoke) #define FASTRPC_IOCTL_MMAP _IOWR('R', 2, struct fastrpc_ioctl_mmap) #define FASTRPC_IOCTL_MUNMAP _IOWR('R', 3, struct fastrpc_ioctl_munmap) +#define FASTRPC_IOCTL_MMAP_64 _IOWR('R', 14, struct fastrpc_ioctl_mmap_64) +#define FASTRPC_IOCTL_MUNMAP_64 _IOWR('R', 15, struct fastrpc_ioctl_munmap_64) #define FASTRPC_IOCTL_INVOKE_FD _IOWR('R', 4, struct fastrpc_ioctl_invoke_fd) #define FASTRPC_IOCTL_SETMODE _IOWR('R', 5, uint32_t) #define FASTRPC_IOCTL_INIT _IOWR('R', 6, struct fastrpc_ioctl_init) @@ -203,6 +205,11 @@ struct fastrpc_ioctl_munmap { size_t size; /* size */ }; +struct fastrpc_ioctl_munmap_64 { + uint64_t vaddrout; /* address to unmap */ + size_t size; /* size */ +}; + struct fastrpc_ioctl_mmap { int fd; /* ion fd */ uint32_t flags; /* flags for dsp to map with */ @@ -211,6 +218,14 @@ struct fastrpc_ioctl_mmap { uintptr_t vaddrout; /* dsps virtual address */ }; +struct fastrpc_ioctl_mmap_64 { + int fd; /* ion fd */ + uint32_t flags; /* flags for dsp to map with */ + uint64_t vaddrin; /* optional virtual address */ + size_t size; /* size */ + uint64_t vaddrout; /* dsps virtual address */ +}; + struct fastrpc_ioctl_munmap_fd { int fd; /* fd */ uint32_t flags; /* control flags */ -- GitLab From 56283068ccc971f92f398df2d7dea65ea06bc24c Mon Sep 17 00:00:00 2001 From: David Collins Date: Tue, 29 May 2018 15:06:13 -0700 Subject: [PATCH 0035/1299] ARM: dts: msm: add PM8150 LDO 18 regulator device for SM8150 Add an rpmh-regulator device for PMIC PM8150 LDO 18. This regulator may be used to power USB. Change-Id: I642a73015c8374557b9433ad8cedeea3d85cd8e1 Signed-off-by: David Collins --- arch/arm64/boot/dts/qcom/sm8150-regulator.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-regulator.dtsi b/arch/arm64/boot/dts/qcom/sm8150-regulator.dtsi index 56a5f3435b10..40a4ab37f02a 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-regulator.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-regulator.dtsi @@ -475,6 +475,24 @@ }; }; + rpmh-regulator-ldoa18 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa18"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 30000>; + L18A: pm8150_l18: regulator-pm8150-l18 { + regulator-name = "pm8150_l18"; + qcom,set = ; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + qcom,init-voltage = <880000>; + }; + }; + rpmh-regulator-smpc1 { compatible = "qcom,rpmh-vrm-regulator"; mboxes = <&apps_rsc 0>; -- GitLab From 62c30af186965bc5bde73223b6c24cb2638c4b5c Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 31 May 2018 10:20:48 -0700 Subject: [PATCH 0036/1299] FROMLIST: f2fs: run fstrim asynchronously if runtime discard is on Cherry-picked from: origin/upstream-f2fs-stable-linux-4.14.y We don't need to wait for whole bunch of discard candidates in fstrim, since runtime discard will issue them in idle time. Change-Id: Ibdee2d7d6451b8c24a7506d53317dfb128bf9580 Signed-off-by: Jaegeuk Kim --- fs/f2fs/segment.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index bef74d628f66..b1e58b10425f 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2439,9 +2439,18 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) __init_discard_policy(sbi, &dpolicy, DPOLICY_FSTRIM, cpc.trim_minlen); __issue_discard_cmd_range(sbi, &dpolicy, start_block, end_block); - trimmed = __wait_discard_cmd_range(sbi, &dpolicy, + + /* + * We filed discard candidates, but actually we don't need to wait for + * all of them, since they'll be issued in idle time along with runtime + * discard option. User configuration looks like using runtime discard + * or periodic fstrim instead of it. + */ + if (!test_opt(sbi, DISCARD)) { + trimmed = __wait_discard_cmd_range(sbi, &dpolicy, start_block, end_block); - range->len = F2FS_BLK_TO_BYTES(trimmed); + range->len = F2FS_BLK_TO_BYTES(trimmed); + } out: return err; } -- GitLab From 3f81a442f01b7746f6c6ef2b761f2c44daf1532f Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Wed, 30 May 2018 13:23:15 -0700 Subject: [PATCH 0037/1299] drivers/misc/hdcp: load HDCP SRM app Load the HDCP SRM app together with the HDCP 2.2 app as its functionality is needed to validate the downstream client list. Change-Id: I5be85464a49215934cc109f575231f1c70b7f955 Signed-off-by: Tatenda Chipeperekwa --- drivers/misc/hdcp_qseecom.c | 204 ++++++++++++++++++++---------------- 1 file changed, 111 insertions(+), 93 deletions(-) diff --git a/drivers/misc/hdcp_qseecom.c b/drivers/misc/hdcp_qseecom.c index 87f1b338106c..671d06b6f157 100644 --- a/drivers/misc/hdcp_qseecom.c +++ b/drivers/misc/hdcp_qseecom.c @@ -33,8 +33,9 @@ #include "qseecom_kernel.h" -#define TZAPP_NAME "hdcp2p2" +#define HDCP2P2_APP_NAME "hdcp2p2" #define HDCP1_APP_NAME "hdcp1" +#define HDCPSRM_APP_NAME "hdcpsrm" #define QSEECOM_SBUFF_SIZE 0x1000 #define MAX_TX_MESSAGE_SIZE 129 @@ -141,7 +142,8 @@ struct hdcp_##x##_rsp *rsp_buf = NULL; \ if (!handle->qseecom_handle) { \ pr_err("invalid qseecom_handle while processing %s\n", #x); \ - return -EINVAL; \ + rc = -EINVAL; \ + goto error; \ } \ req_buf = (struct hdcp_##x##_req *) handle->qseecom_handle->sbuf; \ rsp_buf = (struct hdcp_##x##_rsp *) (handle->qseecom_handle->sbuf + \ @@ -454,6 +456,7 @@ struct hdcp2_handle { bool feature_supported; enum hdcp_state hdcp_state; struct qseecom_handle *qseecom_handle; + struct qseecom_handle *hdcpsrm_qseecom_handle; uint32_t session_id; bool legacy_app; uint32_t device_type; @@ -566,12 +569,12 @@ static int hdcp_get_version(struct hdcp2_handle *handle) if (handle->hdcp_state & HDCP_STATE_APP_LOADED) { pr_err("library already loaded\n"); - return rc; + goto error; } rc = hdcp2_app_process_cmd(version); if (rc) - goto exit; + goto error; app_major_version = HCDP_TXMTR_GET_MAJOR_VERSION(rsp_buf->appversion); @@ -580,7 +583,7 @@ static int hdcp_get_version(struct hdcp2_handle *handle) if (app_major_version == 1) handle->legacy_app = true; -exit: +error: return rc; } @@ -592,20 +595,21 @@ static int hdcp2_app_init_legacy(struct hdcp2_handle *handle) if (!handle->legacy_app) { pr_err("wrong init function\n"); - goto exit; + rc = -EINVAL; + goto error; } if (handle->hdcp_state & HDCP_STATE_APP_LOADED) { pr_err("library already loaded\n"); - goto exit; + goto error; } rc = hdcp2_app_process_cmd(init_v1); if (rc) - goto exit; + goto error; pr_debug("success\n"); -exit: +error: return rc; } @@ -618,12 +622,13 @@ static int hdcp2_app_init(struct hdcp2_handle *handle) if (handle->legacy_app) { pr_err("wrong init function\n"); - goto exit; + rc = -EINVAL; + goto error; } if (handle->hdcp_state & HDCP_STATE_APP_LOADED) { pr_err("library already loaded\n"); - goto exit; + goto error; } req_buf->clientversion = @@ -633,7 +638,7 @@ static int hdcp2_app_init(struct hdcp2_handle *handle) rc = hdcp2_app_process_cmd(init); if (rc) - goto exit; + goto error; app_minor_version = HCDP_TXMTR_GET_MINOR_VERSION(rsp_buf->appversion); if (app_minor_version != HDCP_CLIENT_MINOR_VERSION) { @@ -641,7 +646,7 @@ static int hdcp2_app_init(struct hdcp2_handle *handle) ("client-app minor version mismatch app(%d), client(%d)\n", app_minor_version, HDCP_CLIENT_MINOR_VERSION); rc = -1; - goto exit; + goto error; } pr_debug("success\n"); @@ -654,7 +659,7 @@ static int hdcp2_app_init(struct hdcp2_handle *handle) HCDP_TXMTR_GET_MAJOR_VERSION(rsp_buf->appversion), HCDP_TXMTR_GET_MINOR_VERSION(rsp_buf->appversion), HCDP_TXMTR_GET_PATCH_VERSION(rsp_buf->appversion)); -exit: +error: return rc; } @@ -666,25 +671,26 @@ static int hdcp2_app_tx_init(struct hdcp2_handle *handle) if (!(handle->hdcp_state & HDCP_STATE_SESSION_INIT)) { pr_err("session not initialized\n"); - goto exit; + rc = -EINVAL; + goto error; } if (handle->hdcp_state & HDCP_STATE_TXMTR_INIT) { pr_err("txmtr already initialized\n"); - goto exit; + goto error; } req_buf->sessionid = handle->session_id; rc = hdcp2_app_process_cmd(tx_init); if (rc) - goto exit; + goto error; handle->tz_ctxhandle = rsp_buf->ctxhandle; handle->hdcp_state |= HDCP_STATE_TXMTR_INIT; pr_debug("success\n"); -exit: +error: return rc; } @@ -696,17 +702,18 @@ static int hdcp2_app_tx_init_legacy(struct hdcp2_handle *handle) if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { pr_err("app not loaded\n"); - goto exit; + rc = -EINVAL; + goto error; } if (handle->hdcp_state & HDCP_STATE_TXMTR_INIT) { pr_err("txmtr already initialized\n"); - goto exit; + goto error; } rc = hdcp2_app_process_cmd(tx_init_v1); if (rc) - goto exit; + goto error; handle->app_data.response.data = rsp_buf->message; handle->app_data.response.length = rsp_buf->msglen; @@ -716,7 +723,7 @@ static int hdcp2_app_tx_init_legacy(struct hdcp2_handle *handle) handle->hdcp_state |= HDCP_STATE_TXMTR_INIT; pr_debug("success\n"); -exit: +error: return rc; } @@ -726,19 +733,27 @@ static int hdcp2_app_load(struct hdcp2_handle *handle) if (!handle) { pr_err("invalid input\n"); - goto exit; + rc = -EINVAL; + goto error; } if (handle->hdcp_state & HDCP_STATE_APP_LOADED) { pr_err("library already loaded\n"); - goto exit; + goto error; } rc = qseecom_start_app(&handle->qseecom_handle, - TZAPP_NAME, QSEECOM_SBUFF_SIZE); + HDCP2P2_APP_NAME, QSEECOM_SBUFF_SIZE); if (rc) { - pr_err("qseecom_start_app failed %d\n", rc); - goto exit; + pr_err("qseecom_start_app failed for HDCP2P2 (%d)\n", rc); + goto error; + } + + rc = qseecom_start_app(&handle->hdcpsrm_qseecom_handle, + HDCPSRM_APP_NAME, QSEECOM_SBUFF_SIZE); + if (rc) { + pr_err("qseecom_start_app failed for HDCPSRM (%d)\n", rc); + goto hdcpsrm_error; } pr_debug("qseecom_start_app success\n"); @@ -746,7 +761,7 @@ static int hdcp2_app_load(struct hdcp2_handle *handle) rc = hdcp_get_version(handle); if (rc) { pr_err("library get version failed\n"); - goto exit; + goto get_version_error; } if (handle->legacy_app) { @@ -757,19 +772,20 @@ static int hdcp2_app_load(struct hdcp2_handle *handle) handle->tx_init = hdcp2_app_tx_init; } - if (handle->app_init == NULL) { - pr_err("invalid app init function pointer\n"); - goto exit; - } - rc = handle->app_init(handle); if (rc) { pr_err("app init failed\n"); - goto exit; + goto get_version_error; } handle->hdcp_state |= HDCP_STATE_APP_LOADED; -exit: + + return rc; +get_version_error: + qseecom_shutdown_app(&handle->hdcpsrm_qseecom_handle); +hdcpsrm_error: + qseecom_shutdown_app(&handle->qseecom_handle); +error: return rc; } @@ -779,20 +795,26 @@ static int hdcp2_app_unload(struct hdcp2_handle *handle) hdcp2_app_init_var(deinit); - rc = hdcp2_app_process_cmd(deinit); + hdcp2_app_process_cmd(deinit); + + /* deallocate the resources for qseecom HDCPSRM handle */ + rc = qseecom_shutdown_app(&handle->hdcpsrm_qseecom_handle); if (rc) - goto exit; + pr_err("qseecom_shutdown_app failed for HDCPSRM (%d)\n", rc); - /* deallocate the resources for qseecom handle */ + /* deallocate the resources for qseecom HDCP2P2 handle */ rc = qseecom_shutdown_app(&handle->qseecom_handle); if (rc) { - pr_err("qseecom_shutdown_app failed err: %d\n", rc); - goto exit; + pr_err("qseecom_shutdown_app failed for HDCP2P2 (%d)\n", rc); + return rc; } handle->hdcp_state &= ~HDCP_STATE_APP_LOADED; pr_debug("success\n"); -exit: + + return rc; +error: + qseecom_shutdown_app(&handle->hdcpsrm_qseecom_handle); return rc; } @@ -804,12 +826,13 @@ bool hdcp2_feature_supported(void *data) if (!handle) { pr_err("invalid input\n"); - goto exit; + rc = -EINVAL; + goto error; } if (handle->feature_supported) { supported = true; - goto exit; + goto error; } rc = hdcp2_app_load(handle); @@ -821,7 +844,7 @@ bool hdcp2_feature_supported(void *data) hdcp2_app_unload(handle); supported = true; } -exit: +error: return supported; } @@ -834,25 +857,25 @@ static int hdcp2_app_session_init(struct hdcp2_handle *handle) if (!handle->qseecom_handle || !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); rc = -EINVAL; - goto exit; + goto error; } if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { pr_err("app not loaded\n"); rc = -EINVAL; - goto exit; + goto error; } if (handle->hdcp_state & HDCP_STATE_SESSION_INIT) { pr_err("session already initialized\n"); - goto exit; + goto error; } req_buf->deviceid = handle->device_type; rc = hdcp2_app_process_cmd(session_init); if (rc) - goto exit; + goto error; pr_debug("session id %d\n", rsp_buf->sessionid); @@ -860,7 +883,7 @@ static int hdcp2_app_session_init(struct hdcp2_handle *handle) handle->hdcp_state |= HDCP_STATE_SESSION_INIT; pr_debug("success\n"); -exit: +error: return rc; } @@ -873,25 +896,24 @@ static int hdcp2_app_session_deinit(struct hdcp2_handle *handle) if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { pr_err("app not loaded\n"); rc = -EINVAL; - goto exit; + goto error; } if (!(handle->hdcp_state & HDCP_STATE_SESSION_INIT)) { - /* unload library here */ pr_err("session not initialized\n"); rc = -EINVAL; - goto exit; + goto error; } req_buf->sessionid = handle->session_id; rc = hdcp2_app_process_cmd(session_deinit); if (rc) - goto exit; + goto error; handle->hdcp_state &= ~HDCP_STATE_SESSION_INIT; pr_debug("success\n"); -exit: +error: return rc; } @@ -904,25 +926,24 @@ static int hdcp2_app_tx_deinit(struct hdcp2_handle *handle) if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { pr_err("app not loaded\n"); rc = -EINVAL; - goto exit; + goto error; } if (!(handle->hdcp_state & HDCP_STATE_TXMTR_INIT)) { - /* unload library here */ pr_err("txmtr not initialized\n"); rc = -EINVAL; - goto exit; + goto error; } req_buf->ctxhandle = handle->tz_ctxhandle; rc = hdcp2_app_process_cmd(tx_deinit); if (rc) - goto exit; + goto error; handle->hdcp_state &= ~HDCP_STATE_TXMTR_INIT; pr_debug("success\n"); -exit: +error: return rc; } @@ -935,20 +956,20 @@ static int hdcp2_app_start_auth(struct hdcp2_handle *handle) if (!(handle->hdcp_state & HDCP_STATE_SESSION_INIT)) { pr_err("session not initialized\n"); rc = -EINVAL; - goto exit; + goto error; } if (!(handle->hdcp_state & HDCP_STATE_TXMTR_INIT)) { pr_err("txmtr not initialized\n"); rc = -EINVAL; - goto exit; + goto error; } req_buf->ctxHandle = handle->tz_ctxhandle; rc = hdcp2_app_process_cmd(start_auth); if (rc) - goto exit; + goto error; handle->app_data.response.data = rsp_buf->message; handle->app_data.response.length = rsp_buf->msglen; @@ -957,7 +978,7 @@ static int hdcp2_app_start_auth(struct hdcp2_handle *handle) handle->tz_ctxhandle = rsp_buf->ctxhandle; pr_debug("success\n"); -exit: +error: return rc; } @@ -967,30 +988,27 @@ static int hdcp2_app_start(struct hdcp2_handle *handle) rc = hdcp2_app_load(handle); if (rc) - goto exit; + goto error; if (!handle->legacy_app) { rc = hdcp2_app_session_init(handle); if (rc) - goto exit; + goto error; } if (handle->tx_init == NULL) { pr_err("invalid txmtr init function pointer\n"); rc = -EINVAL; - goto exit; + goto error; } rc = handle->tx_init(handle); if (rc) - goto exit; + goto error; - if (!handle->legacy_app) { + if (!handle->legacy_app) rc = hdcp2_app_start_auth(handle); - if (rc) - goto exit; - } -exit: +error: return rc; } @@ -1021,7 +1039,8 @@ static int hdcp2_app_process_msg(struct hdcp2_handle *handle) if (!handle->app_data.request.data) { pr_err("invalid request buffer\n"); - return -EINVAL; + rc = -EINVAL; + goto error; } req_buf->msglen = handle->app_data.request.length; @@ -1029,7 +1048,7 @@ static int hdcp2_app_process_msg(struct hdcp2_handle *handle) rc = hdcp2_app_process_cmd(rcvd_msg); if (rc) - goto exit; + goto error; /* check if it's a repeater */ if (rsp_buf->flag == HDCP_TXMTR_SUBSTATE_WAITING_FOR_RECIEVERID_LIST) @@ -1040,7 +1059,7 @@ static int hdcp2_app_process_msg(struct hdcp2_handle *handle) handle->app_data.response.data = rsp_buf->msg; handle->app_data.response.length = rsp_buf->msglen; handle->app_data.timeout = rsp_buf->timeout; -exit: +error: return rc; } @@ -1052,12 +1071,12 @@ static int hdcp2_app_timeout(struct hdcp2_handle *handle) rc = hdcp2_app_process_cmd(send_timeout); if (rc) - goto exit; + goto error; handle->app_data.response.data = rsp_buf->message; handle->app_data.response.length = rsp_buf->msglen; handle->app_data.timeout = rsp_buf->timeout; -exit: +error: return rc; } @@ -1069,7 +1088,7 @@ static int hdcp2_app_enable_encryption(struct hdcp2_handle *handle) /* * wait at least 200ms before enabling encryption - * as per hdcp2p2 sepcifications. + * as per hdcp2p2 specifications. */ msleep(SLEEP_SET_HW_KEY_MS); @@ -1077,14 +1096,13 @@ static int hdcp2_app_enable_encryption(struct hdcp2_handle *handle) rc = hdcp2_app_process_cmd(set_hw_key); if (rc) - goto exit; + goto error; handle->hdcp_state |= HDCP_STATE_AUTHENTICATED; pr_debug("success\n"); - return 0; -exit: - pr_err("failed, rc=%d\n", rc); + return rc; +error: return rc; } @@ -1098,12 +1116,12 @@ static int hdcp2_app_query_stream(struct hdcp2_handle *handle) rc = hdcp2_app_process_cmd(query_stream_type); if (rc) - goto exit; + goto error; handle->app_data.response.data = rsp_buf->msg; handle->app_data.response.length = rsp_buf->msglen; handle->app_data.timeout = rsp_buf->timeout; -exit: +error: return rc; } @@ -1150,11 +1168,11 @@ int hdcp2_app_comm(void *ctx, enum hdcp2_app_cmd cmd, case HDCP2_CMD_STOP: rc = hdcp2_app_stop(handle); default: - goto exit; + goto error; } if (rc) - goto exit; + goto error; handle->app_data.request.data = hdcp2_get_recv_buf(handle); @@ -1164,7 +1182,7 @@ int hdcp2_app_comm(void *ctx, enum hdcp2_app_cmd cmd, app_data->response.length = handle->app_data.response.length; app_data->timeout = handle->app_data.timeout; app_data->repeater_flag = handle->app_data.repeater_flag; -exit: +error: return rc; } @@ -1174,10 +1192,10 @@ void *hdcp2_init(u32 device_type) handle = kzalloc(sizeof(struct hdcp2_handle), GFP_KERNEL); if (!handle) - goto exit; + goto error; handle->device_type = device_type; -exit: +error: return handle; } @@ -1208,25 +1226,25 @@ bool hdcp1_feature_supported(void *data) if (!handle) { pr_err("invalid input\n"); - goto exit; + goto error; } if (handle->feature_supported) { supported = true; - goto exit; + goto error; } rc = qseecom_start_app(&handle->qseecom_handle, HDCP1_APP_NAME, QSEECOM_SBUFF_SIZE); if (rc) { pr_err("qseecom_start_app failed %d\n", rc); - goto exit; + goto error; } pr_debug("HDCP 1.x supported\n"); handle->feature_supported = true; supported = true; -exit: +error: return supported; } -- GitLab From 8560d726e89b20bac68baa2117edf7dda1088c46 Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Fri, 25 May 2018 19:18:39 +0800 Subject: [PATCH 0038/1299] usb: dwc3-msm: Add sysfs node that can change USB bus vote Add min and max USB bus vote support which can be set by adb command. Change-Id: Ia57c32053b6c2d5083e894883c5e38860f14f6ad Signed-off-by: Liangliang Lu --- drivers/usb/dwc3/dwc3-msm.c | 128 +++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 40 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 85142b7e5d7e..596482242e0f 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -148,6 +148,14 @@ enum msm_usb_irq { USB_MAX_IRQ }; +enum bus_vote { + BUS_VOTE_NONE, + BUS_VOTE_NOMINAL, + BUS_VOTE_SVS, + BUS_VOTE_MIN, + BUS_VOTE_MAX +}; + struct usb_irq { char *name; int irq; @@ -224,6 +232,7 @@ struct dwc3_msm { unsigned int max_power; bool charging_disabled; enum usb_otg_state otg_state; + enum bus_vote override_bus_vote; u32 bus_perf_client; struct msm_bus_scale_pdata *bus_scale_table; struct power_supply *usb_psy; @@ -2113,60 +2122,39 @@ static void configure_nonpdc_usb_interrupt(struct dwc3_msm *mdwc, } } -enum bus_vote { - BUS_VOTE_INVALID, - BUS_VOTE_SUSPEND, - BUS_VOTE_NOMINAL, - BUS_VOTE_SVS -}; - static int dwc3_msm_update_bus_bw(struct dwc3_msm *mdwc, enum bus_vote bv) { int ret = 0; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); + unsigned int bv_index = mdwc->override_bus_vote ?: bv; if (!mdwc->bus_perf_client) return 0; dbg_event(0xFF, "bus_vote_start", bv); - switch (bv) { - case BUS_VOTE_SVS: - /* On some platforms SVS does not have separate vote. Vote for - * nominal if svs usecase does not exist - */ - if (mdwc->bus_scale_table->num_usecases == 2) - goto nominal_vote; + /* On some platforms SVS does not have separate vote. + * Vote for nominal if svs usecase does not exist. + * If the request is to set the bus_vote to _NONE, + * set it to _NONE irrespective of the requested vote + * from userspace. + */ + if (bv >= mdwc->bus_scale_table->num_usecases) + bv_index = BUS_VOTE_NOMINAL; + else if (bv == BUS_VOTE_NONE) + bv_index = BUS_VOTE_NONE; - /* index starts from zero */ - ret = msm_bus_scale_client_update_request( - mdwc->bus_perf_client, 2); - if (ret) - dev_err(mdwc->dev, "bus bw voting failed %d\n", ret); - break; - case BUS_VOTE_NOMINAL: -nominal_vote: - ret = msm_bus_scale_client_update_request( - mdwc->bus_perf_client, 1); - if (ret) - dev_err(mdwc->dev, "bus bw voting failed %d\n", ret); - break; - case BUS_VOTE_SUSPEND: - ret = msm_bus_scale_client_update_request( - mdwc->bus_perf_client, 0); - if (ret) - dev_err(mdwc->dev, "bus bw voting failed %d\n", ret); - break; - default: - dev_err(mdwc->dev, "Unsupported bus vote:%d\n", bv); - ret = -EINVAL; - } + ret = msm_bus_scale_client_update_request( + mdwc->bus_perf_client, bv_index); + if (ret) + dev_err(mdwc->dev, "bus bw voting %d failed %d\n", + bv_index, ret); - dbg_event(0xFF, "bus_vote_end", bv); + dbg_event(0xFF, "bus_vote_end", bv_index); return ret; - } + static int dwc3_msm_suspend(struct dwc3_msm *mdwc) { int ret; @@ -2298,7 +2286,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) } } - dwc3_msm_update_bus_bw(mdwc, BUS_VOTE_SUSPEND); + dwc3_msm_update_bus_bw(mdwc, BUS_VOTE_NONE); /* * release wakeup source with timeout to defer system suspend to @@ -3146,6 +3134,65 @@ static ssize_t usb_compliance_mode_store(struct device *dev, } static DEVICE_ATTR_RW(usb_compliance_mode); +static ssize_t bus_vote_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dwc3_msm *mdwc = dev_get_drvdata(dev); + + if (mdwc->override_bus_vote == BUS_VOTE_MIN) + return snprintf(buf, PAGE_SIZE, "%s\n", + "Fixed bus vote: min"); + else if (mdwc->override_bus_vote == BUS_VOTE_MAX) + return snprintf(buf, PAGE_SIZE, "%s\n", + "Fixed bus vote: max"); + else + return snprintf(buf, PAGE_SIZE, "%s\n", + "Do not have fixed bus vote"); +} + +static ssize_t bus_vote_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct dwc3_msm *mdwc = dev_get_drvdata(dev); + struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); + bool bv_fixed = false; + enum bus_vote bv; + + if (sysfs_streq(buf, "min") + && (mdwc->bus_scale_table->num_usecases + >= (BUS_VOTE_MIN + 1))) { + bv_fixed = true; + mdwc->override_bus_vote = BUS_VOTE_MIN; + } else if (sysfs_streq(buf, "max") + && (mdwc->bus_scale_table->num_usecases + >= (BUS_VOTE_MAX + 1))) { + bv_fixed = true; + mdwc->override_bus_vote = BUS_VOTE_MAX; + } else if (sysfs_streq(buf, "cancel")) { + bv_fixed = false; + mdwc->override_bus_vote = BUS_VOTE_NONE; + } else { + dev_err(dev, "min/max/cancel only.\n"); + return -EINVAL; + } + + /* Update bus vote value only when not suspend */ + if (!atomic_read(&dwc->in_lpm)) { + if (bv_fixed) + bv = mdwc->override_bus_vote; + else if (mdwc->in_host_mode + && (mdwc->max_rh_port_speed == USB_SPEED_HIGH)) + bv = BUS_VOTE_SVS; + else + bv = BUS_VOTE_NOMINAL; + + dwc3_msm_update_bus_bw(mdwc, bv); + } + + return count; +} +static DEVICE_ATTR_RW(bus_vote); static int dwc3_msm_probe(struct platform_device *pdev) { @@ -3411,6 +3458,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) device_create_file(&pdev->dev, &dev_attr_mode); device_create_file(&pdev->dev, &dev_attr_speed); device_create_file(&pdev->dev, &dev_attr_usb_compliance_mode); + device_create_file(&pdev->dev, &dev_attr_bus_vote); host_mode = usb_get_dr_mode(&mdwc->dwc3->dev) == USB_DR_MODE_HOST; if (host_mode) { -- GitLab From ab446c03bcb710e34cfbe703d1f0c871a5cfc001 Mon Sep 17 00:00:00 2001 From: Yuan Zhao Date: Thu, 7 Jun 2018 15:56:52 +0800 Subject: [PATCH 0039/1299] ARM: dts: msm: Modify panel porch settings for QRD SM8150 Reduce the HFP and HBP settings for this command mode panel, otherwise will see flickers when device booting up. Change-Id: I44a24430e4ab5242baaa7203a478f25dc06461b8 Signed-off-by: Yuan Zhao --- .../dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi | 6 +++--- arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi index c7e17b531b90..a39150e4112f 100644 --- a/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi +++ b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi @@ -46,9 +46,9 @@ qcom,mdss-dsi-panel-framerate = <60>; qcom,mdss-dsi-panel-width = <1440>; qcom,mdss-dsi-panel-height = <2880>; - qcom,mdss-dsi-h-front-porch = <160>; - qcom,mdss-dsi-h-back-porch = <72>; - qcom,mdss-dsi-h-pulse-width = <16>; + qcom,mdss-dsi-h-front-porch = <60>; + qcom,mdss-dsi-h-back-porch = <30>; + qcom,mdss-dsi-h-pulse-width = <12>; qcom,mdss-dsi-h-sync-skew = <0>; qcom,mdss-dsi-v-back-porch = <8>; qcom,mdss-dsi-v-front-porch = <8>; diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi index cd99f6a12e60..0e829c2b1af9 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi @@ -671,9 +671,9 @@ qcom,mdss-dsi-t-clk-pre = <0x16>; qcom,mdss-dsi-display-timings { timing@0 { - qcom,mdss-dsi-panel-phy-timings = [00 1a 07 06 22 21 07 - 07 04 03 04 00 16 16]; - qcom,display-topology = <2 1 1>; + qcom,mdss-dsi-panel-phy-timings = [00 16 05 05 20 1f 06 + 06 03 03 04 00 13 15]; + qcom,display-topology = <2 2 1>; qcom,default-topology-index = <0>; }; }; -- GitLab From c1864002afcf6d15680fcd99b49d23f29e324eec Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Wed, 6 Jun 2018 14:16:27 -0700 Subject: [PATCH 0040/1299] drivers: qcom: cmd-db: Initialize resource name Resource name must be initialized otherwise it will contain a garbage value which will cause a crash when it is dereferenced, such as when a user calls 'cat /proc/iomem'. Initialize to name to NULL and let the devm_ioremap_resource call assign the device name as the name. Change-Id: I4667a288bc6dcf68aeb46c62fc4be86788fd8887 Signed-off-by: Liam Mark --- drivers/soc/qcom/cmd-db.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c index 252bd2108681..22b44648a402 100644 --- a/drivers/soc/qcom/cmd-db.c +++ b/drivers/soc/qcom/cmd-db.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -362,6 +362,7 @@ static int cmd_db_dev_probe(struct platform_device *pdev) res.start = readl_relaxed(dict); res.end = res.start + readl_relaxed(dict + 0x4); res.flags = IORESOURCE_MEM; + res.name = NULL; iounmap(dict); start_addr = devm_ioremap_resource(&pdev->dev, &res); -- GitLab From 9854146b81b5916bca9f21174f12b156c9484504 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Wed, 6 Jun 2018 17:21:49 -0700 Subject: [PATCH 0041/1299] usb_bam: Get source bam size to map into USB CB For USB QDSS BAM2BAM usecase when USB is using SMMU S1 functionality, it is required to map QDSS BAM device register address space into USB context bank. Currently USB BAM device register address space is used instead of QDSS BAM device which results into garbage data with this usecase although QDSS is not generating any data. Fix this issue by mapping QDSS BAM device register address space. Change-Id: I66c46513865a0acf21c28bba242845e52fbd7d67 Signed-off-by: Mayank Rana --- drivers/platform/msm/usb_bam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c index ab877f296520..c51d4b2990b4 100644 --- a/drivers/platform/msm/usb_bam.c +++ b/drivers/platform/msm/usb_bam.c @@ -632,7 +632,7 @@ int get_qdss_bam_info(enum usb_ctrl cur_bam, u8 idx, &ctx->usb_bam_connections[idx]; unsigned long peer_bam_handle; - ret = sps_phy2h(pipe_connect->dst_phy_addr, &peer_bam_handle); + ret = sps_phy2h(pipe_connect->src_phy_addr, &peer_bam_handle); if (ret) { log_event_err("%s: sps_phy2h failed (src BAM) %d\n", __func__, ret); -- GitLab From eeebcdff745368834dc038664cace6f7899f7dd5 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Samavedam Date: Tue, 8 May 2018 23:39:51 -0700 Subject: [PATCH 0042/1299] dwc3: gadget: Set TXFRAMNUM_N while resizing TXFIFO for ISOC eps Set TXFRAMNUM_N per synopsys programming guide recommendation for isoc endpoints. Change-Id: I8a433e8e6198f0374e13c75619bfffc8238432ea Signed-off-by: Vamsi Krishna Samavedam --- drivers/usb/dwc3/core.c | 1 + drivers/usb/dwc3/core.h | 5 +++++ drivers/usb/dwc3/ep0.c | 6 ------ drivers/usb/dwc3/gadget.c | 5 +++++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index a6e2a21e5089..08928b19a995 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -660,6 +660,7 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc) /* Detected DWC_usb31 IP */ dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); dwc->revision |= DWC3_REVISION_IS_DWC31; + dwc->versiontype = dwc3_readl(dwc->regs, DWC3_VER_TYPE); } else { return false; } diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 64e0fd0b33cf..4dd6f34064fe 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1061,6 +1061,11 @@ struct dwc3 { #define DWC3_REVISION_IS_DWC31 0x80000000 #define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_DWC31) #define DWC3_USB31_REVISION_120A (0x3132302a | DWC3_REVISION_IS_DWC31) +#define DWC3_USB31_REVISION_170A (0x3137302a | DWC3_REVISION_IS_DWC31) + + /* valid only for dwc31 configuraitons */ + u32 versiontype; +#define DWC3_USB31_VER_TYPE_EA06 0x65613036 enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index e4b82bdcd006..00cd200665f6 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -682,12 +682,6 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) DWC3_ENDPOINTS_NUM); num += 2) { dep = dwc->eps[num]; size = 0; - /* Don't change TXFRAMNUM on usb31 version */ - if (dwc3_is_usb31(dwc)) - size = dwc3_readl(dwc->regs, - DWC3_GTXFIFOSIZ(num >> 1)) & - DWC31_GTXFIFOSIZ_TXFRAMNUM; - dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1), size); dep->fifo_depth = 0; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 94a84547699c..1e0b33ccc4d6 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -270,6 +270,11 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc, struct dwc3_ep *dep) return -ENOMEM; } + if ((dwc->revision == DWC3_USB31_REVISION_170A) && + (dwc->versiontype == DWC3_USB31_VER_TYPE_EA06) && + usb_endpoint_xfer_isoc(dep->endpoint.desc)) + fifo_size |= DWC31_GTXFIFOSIZ_TXFRAMNUM; + dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(dep->endpoint.ep_num), fifo_size); return 0; -- GitLab From 950c769dcb30066481b625c735a3981c41dfe40c Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Samavedam Date: Thu, 24 May 2018 18:58:11 -0700 Subject: [PATCH 0043/1299] usb: dwc3: Improve lfps handshake interop by reducing u3 exit time SNPS star 9001276244:LFPS Handshake Interoperability Issues suggests to reduce U3 exit handshake timer to from 8us to 300ns to increase interoperability with hosts/devices which supports USB 3.1 gen2 speeds. Change-Id: I68c6f5f8a09337c5c3c70c2f0b6940efcba0dab8 Signed-off-by: Vamsi Krishna Samavedam --- drivers/usb/dwc3/core.h | 5 +++++ drivers/usb/dwc3/dwc3-msm.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 4dd6f34064fe..a8100092d469 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -160,6 +160,11 @@ #define DWC3_OSTS 0xcc10 /* DWC 3.1 Link Registers */ +#define DWC31_LINK_LU3LFPSRXTIM(n) (0xd010 + ((n) * 0x80)) +#define GEN2_U3_EXIT_RSP_RX_CLK(n) ((n) << 16) +#define GEN2_U3_EXIT_RSP_RX_CLK_MASK GEN2_U3_EXIT_RSP_RX_CLK(0xff) +#define GEN1_U3_EXIT_RSP_RX_CLK(n) (n) +#define GEN1_U3_EXIT_RSP_RX_CLK_MASK GEN1_U3_EXIT_RSP_RX_CLK(0xff) #define DWC31_LINK_GDBGLTSSM 0xd050 /* Bit fields */ diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 85142b7e5d7e..11e3f3a68928 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -3686,6 +3686,21 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on) mdwc->in_host_mode = true; dwc3_usb3_phy_suspend(dwc, true); + /* Reduce the U3 exit handshake timer from 8us to approximately + * 300ns to avoid lfps handshake interoperability issues + */ + if (dwc->revision == DWC3_USB31_REVISION_170A) { + dwc3_msm_write_reg_field(mdwc->base, + DWC31_LINK_LU3LFPSRXTIM(0), + GEN2_U3_EXIT_RSP_RX_CLK_MASK, 6); + dwc3_msm_write_reg_field(mdwc->base, + DWC31_LINK_LU3LFPSRXTIM(0), + GEN1_U3_EXIT_RSP_RX_CLK_MASK, 5); + dev_dbg(mdwc->dev, "LU3:%08x\n", + dwc3_msm_read_reg(mdwc->base, + DWC31_LINK_LU3LFPSRXTIM(0))); + } + /* xHCI should have incremented child count as necessary */ dbg_event(0xFF, "StrtHost psync", atomic_read(&mdwc->dev->power.usage_count)); @@ -3792,6 +3807,22 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on) dwc3_msm_block_reset(mdwc, false); dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); mdwc->in_device_mode = true; + + /* Reduce the U3 exit handshake timer from 8us to approximately + * 300ns to avoid lfps handshake interoperability issues + */ + if (dwc->revision == DWC3_USB31_REVISION_170A) { + dwc3_msm_write_reg_field(mdwc->base, + DWC31_LINK_LU3LFPSRXTIM(0), + GEN2_U3_EXIT_RSP_RX_CLK_MASK, 6); + dwc3_msm_write_reg_field(mdwc->base, + DWC31_LINK_LU3LFPSRXTIM(0), + GEN1_U3_EXIT_RSP_RX_CLK_MASK, 5); + dev_dbg(mdwc->dev, "LU3:%08x\n", + dwc3_msm_read_reg(mdwc->base, + DWC31_LINK_LU3LFPSRXTIM(0))); + } + usb_gadget_vbus_connect(&dwc->gadget); #ifdef CONFIG_SMP mdwc->pm_qos_req_dma.type = PM_QOS_REQ_AFFINE_IRQ; -- GitLab From 664dc0bd7c0e7300054be6654b82facf15455870 Mon Sep 17 00:00:00 2001 From: Raghavendra Rao Ananta Date: Fri, 25 May 2018 14:27:16 -0700 Subject: [PATCH 0044/1299] esoc: Add module parameters to control driver actions In order to control some parameters while debugging, such as, change the number of PON attempts, change the action to be taken in case the external modem doesn't boot, and so on, add module parameters. Change-Id: I508d795a8684533302d8c9668693b630029cecb4 Signed-off-by: Raghavendra Rao Ananta --- drivers/esoc/esoc-mdm-drv.c | 66 +++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/drivers/esoc/esoc-mdm-drv.c b/drivers/esoc/esoc-mdm-drv.c index cba2128f5295..9afd171fb677 100644 --- a/drivers/esoc/esoc-mdm-drv.c +++ b/drivers/esoc/esoc-mdm-drv.c @@ -19,8 +19,25 @@ #include "esoc-mdm.h" #include "mdm-dbg.h" -/* Maximum number of powerup trial requests per session */ -#define ESOC_MAX_PON_REQ 2 +/* Default number of powerup trial requests per session */ +#define ESOC_DEF_PON_REQ 2 +static unsigned int n_pon_tries = ESOC_DEF_PON_REQ; +module_param(n_pon_tries, uint, 0644); +MODULE_PARM_DESC(n_pon_tries, +"Number of power-on retrials allowed upon boot failure"); + +enum esoc_boot_fail_action { + BOOT_FAIL_ACTION_RETRY, + BOOT_FAIL_ACTION_COLD_RESET, + BOOT_FAIL_ACTION_SHUTDOWN, + BOOT_FAIL_ACTION_PANIC, + BOOT_FAIL_ACTION_NOP, +}; + +static unsigned int boot_fail_action = BOOT_FAIL_ACTION_NOP; +module_param(boot_fail_action, uint, 0644); +MODULE_PARM_DESC(boot_fail_action, +"Actions: 0:Retry PON; 1:Cold reset; 2:Power-down; 3:APQ Panic; 4:No action"); enum esoc_pon_state { PON_INIT, @@ -232,6 +249,41 @@ static void mdm_subsys_retry_powerup_cleanup(struct esoc_clink *esoc_clink) reinit_completion(&mdm_drv->req_eng_wait); } +/* Returns 0 to proceed towards another retry, or an error code to quit */ +static int mdm_handle_boot_fail(struct esoc_clink *esoc_clink, u8 *pon_trial) +{ + struct mdm_ctrl *mdm = get_esoc_clink_data(esoc_clink); + + switch (boot_fail_action) { + case BOOT_FAIL_ACTION_RETRY: + mdm_subsys_retry_powerup_cleanup(esoc_clink); + (*pon_trial)++; + break; + /* + * Issue a shutdown here and rerun the powerup again. + * This way it becomes a cold reset. Else, we end up + * issuing a cold reset & a warm reset back to back. + */ + case BOOT_FAIL_ACTION_COLD_RESET: + mdm_subsys_retry_powerup_cleanup(esoc_clink); + (*pon_trial)++; + mdm_power_down(mdm); + break; + case BOOT_FAIL_ACTION_PANIC: + panic("Panic requested on external modem boot failure\n"); + break; + case BOOT_FAIL_ACTION_NOP: + return -EIO; + case BOOT_FAIL_ACTION_SHUTDOWN: + default: + mdm_subsys_retry_powerup_cleanup(esoc_clink); + mdm_power_down(mdm); + return -EIO; + } + + return 0; +} + static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) { int ret; @@ -240,7 +292,6 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) subsys); struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops; - struct mdm_ctrl *mdm = get_esoc_clink_data(esoc_clink); int timeout = INT_MAX; u8 pon_trial = 1; @@ -288,16 +339,16 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) ret = wait_for_completion_timeout(&mdm_drv->pon_done, timeout); if (mdm_drv->pon_state == PON_FAIL || ret <= 0) { dev_err(&esoc_clink->dev, "booting failed\n"); - mdm_subsys_retry_powerup_cleanup(esoc_clink); - mdm_power_down(mdm); - return -EIO; + ret = mdm_handle_boot_fail(esoc_clink, &pon_trial); + if (ret) + return ret; } else if (mdm_drv->pon_state == PON_RETRY) { pon_trial++; mdm_subsys_retry_powerup_cleanup(esoc_clink); } else if (mdm_drv->pon_state == PON_SUCCESS) { break; } - } while (pon_trial <= ESOC_MAX_PON_REQ); + } while (pon_trial <= n_pon_tries); return 0; } @@ -375,6 +426,7 @@ int esoc_ssr_probe(struct esoc_clink *esoc_clink, struct esoc_drv *drv) dev_dbg(&esoc_clink->dev, "dbg engine initialized\n"); debug_init_done = true; } + return 0; queue_err: esoc_clink_unregister_ssr(esoc_clink); -- GitLab From b030b3b85de29bccc53c7bc35e08cba0764ad08e Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Fri, 25 May 2018 19:36:51 +0530 Subject: [PATCH 0045/1299] ARM: dts: msm: Enable clocks for sm6150 kgsl SMMU Enable gcc_gpu_memnoc_gfx_clk, gcc_gpu_snoc_dvm_gfx_clk and gpu_cc_ahb_clk clocks which are required by kgsl SMMU for sm6150. Change-Id: Ib8b8523a6fd4427c6e801807665947cbec2b577d Signed-off-by: Vijayanand Jitta --- arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi index fca527cf14cf..2db42735c717 100644 --- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi @@ -24,6 +24,12 @@ #global-interrupts = <1>; qcom,regulator-names = "vdd"; vdd-supply = <&gpu_cx_gdsc>; + clocks = <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&clock_gcc GCC_GPU_SNOC_DVM_GFX_CLK>, + <&clock_gpucc GPU_CC_AHB_CLK>; + clock-names = "gcc_gpu_memnoc_gfx_clk", + "gcc_gpu_snoc_dvm_gfx_clk", + "gpu_cc_ahb_clk"; #size-cells = <1>; #address-cells = <1>; ranges; -- GitLab From ac85d9878621cab16e8a589fc4265d5a0a6012a6 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Wed, 23 May 2018 13:09:59 -0700 Subject: [PATCH 0046/1299] power: fg-memif: Modify FG SRAM access configuration over DMA Currently, when SRAM access over DMA is requested, low latency is set and it is cleared after SRAM access is done and DMA is released. Instead of this, keep low latency set always as per the hardware recommendation. With this, memory arbitration request is made when SRAM is accessed by software and released when SRAM access is completed without changing the latency configuration. Also, change the order of register writes for DMA request and release as following: DMA request: - Memory arbiter request - Memory interface request DMA release: - Memory interface release - Memory arbiter release While at it, clear the DMA error log bit during initialization. Change-Id: I3ddbe9ca6053673c3dc7b1620bed472546278547 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-memif.c | 76 ++++++++++++++++------------ drivers/power/supply/qcom/fg-reg.h | 1 + 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/drivers/power/supply/qcom/fg-memif.c b/drivers/power/supply/qcom/fg-memif.c index 049639e0548a..4e4589a24960 100644 --- a/drivers/power/supply/qcom/fg-memif.c +++ b/drivers/power/supply/qcom/fg-memif.c @@ -793,36 +793,52 @@ int fg_interleaved_mem_write(struct fg_dev *fg, u16 address, u8 offset, return rc; } -#define MEM_GNT_WAIT_TIME_US 10000 -#define MEM_GNT_RETRIES 50 -static int fg_direct_mem_request(struct fg_dev *fg, bool request) +static int fg_direct_mem_release(struct fg_dev *fg) { - int rc, ret, i = 0; - u8 val, mask, poll_bit; + int rc; + u8 val = 0, mask; mask = MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT; - val = request ? MEM_ACCESS_REQ_BIT : 0; rc = fg_masked_write(fg, MEM_IF_MEM_INTF_CFG(fg), mask, val); if (rc < 0) { pr_err("failed to configure mem_if_mem_intf_cfg rc=%d\n", rc); return rc; } - mask = MEM_ARB_LO_LATENCY_EN_BIT | MEM_ARB_REQ_BIT; - val = request ? mask : 0; + mask = MEM_ARB_REQ_BIT; rc = fg_masked_write(fg, MEM_IF_MEM_ARB_CFG(fg), mask, val); if (rc < 0) { pr_err("failed to configure mem_if_mem_arb_cfg rc:%d\n", rc); - goto release; + return rc; } - if (request) - pr_debug("requesting access\n"); - else - pr_debug("releasing access\n"); + pr_debug("released access\n"); + return rc; +} - if (!request) - return 0; +#define MEM_GNT_WAIT_TIME_US 10000 +#define MEM_GNT_RETRIES 50 +static int fg_direct_mem_request(struct fg_dev *fg) +{ + int rc, ret, i = 0; + u8 val, mask, poll_bit; + + val = mask = MEM_ARB_REQ_BIT; + rc = fg_masked_write(fg, MEM_IF_MEM_ARB_CFG(fg), mask, val); + if (rc < 0) { + pr_err("failed to configure mem_if_mem_arb_cfg rc:%d\n", rc); + return rc; + } + + mask = MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT; + val = MEM_ACCESS_REQ_BIT; + rc = fg_masked_write(fg, MEM_IF_MEM_INTF_CFG(fg), mask, val); + if (rc < 0) { + pr_err("failed to configure mem_if_mem_intf_cfg rc=%d\n", rc); + goto release; + } + + pr_debug("requesting access\n"); /* * HW takes 5 cycles (200 KHz clock) to grant access after requesting @@ -858,20 +874,9 @@ static int fg_direct_mem_request(struct fg_dev *fg, bool request) fg_dump_regs(fg); release: - val = 0; - mask = MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT; - ret = fg_masked_write(fg, MEM_IF_MEM_INTF_CFG(fg), mask, val); - if (ret < 0) { - pr_err("failed to configure mem_if_mem_intf_cfg rc=%d\n", rc); + ret = fg_direct_mem_release(fg); + if (ret < 0) return ret; - } - - mask = MEM_ARB_LO_LATENCY_EN_BIT | MEM_ARB_REQ_BIT; - ret = fg_masked_write(fg, MEM_IF_MEM_ARB_CFG(fg), mask, val); - if (ret < 0) { - pr_err("failed to configure mem_if_mem_arb_cfg rc:%d\n", rc); - return ret; - } return rc; } @@ -987,7 +992,7 @@ static int __fg_direct_mem_rw(struct fg_dev *fg, u16 sram_addr, u8 offset, pr_debug("number of partitions: %d\n", num_partitions); - rc = fg_direct_mem_request(fg, true); + rc = fg_direct_mem_request(fg); if (rc < 0) { pr_err("Error in requesting direct_mem access rc=%d\n", rc); return rc; @@ -1032,7 +1037,7 @@ static int __fg_direct_mem_rw(struct fg_dev *fg, u16 sram_addr, u8 offset, offset = 0; } - ret = fg_direct_mem_request(fg, false); + rc = fg_direct_mem_release(fg); if (ret < 0) { pr_err("Error in releasing direct_mem access rc=%d\n", rc); return ret; @@ -1196,13 +1201,22 @@ static int fg_dma_init(struct fg_dev *fg) } /* Release the DMA initially so that request can happen */ - rc = fg_direct_mem_request(fg, false); + rc = fg_direct_mem_release(fg); if (rc < 0) { pr_err("Error in releasing direct_mem access rc=%d\n", rc); return rc; } + /* Set low latency always and clear log bit */ + rc = fg_masked_write(fg, MEM_IF_MEM_ARB_CFG(fg), + MEM_ARB_LO_LATENCY_EN_BIT | MEM_CLR_LOG_BIT, + MEM_ARB_LO_LATENCY_EN_BIT); + if (rc < 0) { + pr_err("failed to configure mem_if_mem_arb_cfg rc:%d\n", rc); + return rc; + } + return 0; } diff --git a/drivers/power/supply/qcom/fg-reg.h b/drivers/power/supply/qcom/fg-reg.h index aa30626d9427..5c20fb13bb4a 100644 --- a/drivers/power/supply/qcom/fg-reg.h +++ b/drivers/power/supply/qcom/fg-reg.h @@ -284,6 +284,7 @@ #define GEN4_MEM_ATTN_BIT BIT(4) #define MEM_IF_MEM_ARB_CFG(chip) ((chip->mem_if_base) + 0x40) +#define MEM_CLR_LOG_BIT BIT(2) #define MEM_ARB_LO_LATENCY_EN_BIT BIT(1) #define MEM_ARB_REQ_BIT BIT(0) -- GitLab From 31f8a9f89f8ede5c9dc6433274239296aa11df09 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Thu, 22 Feb 2018 10:16:04 +0530 Subject: [PATCH 0047/1299] usb: phy: Add Synopsys High Speed Femto PHY driver Add Synopsys High Speed 28 nm Femto driver that can be interfaced with PHY framework. Change-Id: Ic1fb76fc0087f7f6bd14b5399bde94a98d4e42b2 Signed-off-by: Sriharsha Allenki --- .../bindings/phy/qcom,snps-28nm-hs-usb.txt | 76 +++ drivers/usb/phy/Kconfig | 10 + drivers/usb/phy/Makefile | 1 + drivers/usb/phy/phy-qcom-snps-28nm-hs.c | 617 ++++++++++++++++++ include/linux/usb/msm_hsusb_hw.h | 26 + 5 files changed, 730 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/qcom,snps-28nm-hs-usb.txt create mode 100644 drivers/usb/phy/phy-qcom-snps-28nm-hs.c diff --git a/Documentation/devicetree/bindings/phy/qcom,snps-28nm-hs-usb.txt b/Documentation/devicetree/bindings/phy/qcom,snps-28nm-hs-usb.txt new file mode 100644 index 000000000000..3505c7fb96ef --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom,snps-28nm-hs-usb.txt @@ -0,0 +1,76 @@ +Qualcomm Synopsys 28nm Femto phy controller +=========================================== + +Synopsys 28nm femto phy controller supports LS/FS/HS usb connectivity on +Qualcomm chipsets. + +Required properties: +- compatible: + Value type: + Definition: Should contain "qcom,usb-snps-hsphy". + +- reg: + Value type: + Definition: USB PHY base address and length of the register map + +- reg-names: + Value type: + Definition: Names of the reg bases in 1-1 correspondence with the + "reg" property. "phy_csr" is a mandatory reg base. + +- clocks: + Value type: + Definition: See clock-bindings.txt section "consumers". List of + two clock specifiers for interface and core controller + clocks. + +- clock-names: + Value type: + Definition: Names of the clocks in 1-1 correspondence with the "clocks" + property. Must contain "phy_csr_clk" and "ref_clk" clocks. + +- vdd-supply: + Value type: + Definition: phandle to the regulator VDD supply node. + +- vdda18-supply: + Value type: + Definition: phandle to the regulator 1.8V supply node. + +- vdda33-supply: + Value type: + Definition: phandle to the regulator 3.3V supply node. + +- qcom,vdd-voltage-level: + Value type: + Definition: This is a list of three integer values (no, min, max) where + each value corresponding to voltage corner. + +- resets: + Value type: + Definition: See reset.txt section "consumers". PHY reset specifier. + +- reset-names: + Value type: + Definition: Must contain "phy_por_reset" and "phy_reset" strings. + +Example: + usb_phy: phy@78d9000 { + compatible = "qcom,usb-snps-hsphy"; + reg = <0x78d9000 0x400>; + reg-names = "phy_csr"; + + vdd-supply = <&pm8916_s1_corner>; + vdda18-supply = <&pm8916_l7>; + vdda33-supply = <&pm8916_l13>; + + clocks = <&gcc GCC_USB_HS_AHB_CLK>, + <&gcc GCC_USB_HS_SYSTEM_CLK>; + clock-names = "phy_csr_clk", "ref_clk"; + + resets = <&gcc GCC_QUSB2_PHY_BCR>, + <&gcc GCC_USB2_HS_PHY_ONLY_BCR>; + reset-names = "phy_por_reset", "phy_reset"; + + }; + diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 6c7f082406dc..6181449a2726 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -145,6 +145,16 @@ config USB_ISP1301 To compile this driver as a module, choose M here: the module will be called phy-isp1301. +config MSM_SNPS_FEMTO_PHY + tristate "MSM SNPS HSUSB PHY Driver" + depends on ARCH_QCOM + select USB_PHY + help + Enable this to support the 28nm HSUSB PHY on MSM chips. This driver + supports the high-speed PHY which is usually paired with either + the ChipIdea or Synopsys DWC3 USB IPs on MSM SOCs. This driver expects + to configure the PHY with a dedicated register I/O memory region. + config USB_MSM_OTG tristate "Qualcomm on-chip USB OTG controller support" depends on (USB || USB_GADGET) && (ARCH_QCOM || COMPILE_TEST) diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 444fa5c5d0be..5b625a692b74 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o obj-$(CONFIG_KEYSTONE_USB_PHY) += phy-keystone.o obj-$(CONFIG_USB_MSM_SSPHY_QMP) += phy-msm-ssusb-qmp.o obj-$(CONFIG_MSM_HSUSB_PHY) += phy-msm-snps-hs.o +obj-$(CONFIG_MSM_SNPS_FEMTO_PHY) += phy-qcom-snps-28nm-hs.o diff --git a/drivers/usb/phy/phy-qcom-snps-28nm-hs.c b/drivers/usb/phy/phy-qcom-snps-28nm-hs.c new file mode 100644 index 000000000000..3aeca1f72679 --- /dev/null +++ b/drivers/usb/phy/phy-qcom-snps-28nm-hs.c @@ -0,0 +1,617 @@ +/* Copyright (c) 2009-2018, Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MSM_USB_PHY_CSR_BASE phy->phy_csr_regs +#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ +#define USB_HSPHY_3P3_VOL_MAX 3300000 /* uV */ +#define USB_HSPHY_3P3_HPM_LOAD 16000 /* uA */ + +#define USB_HSPHY_1P8_VOL_MIN 1704000 /* uV */ +#define USB_HSPHY_1P8_VOL_MAX 1800000 /* uV */ +#define USB_HSPHY_1P8_HPM_LOAD 19000 /* uA */ + +#define USB_HSPHY_MAX_REGULATORS 3 + +enum regulators { + MSM_HSPHY_DVDD_REGULATOR, + MSM_HSPHY_1P8_REGULATOR, + MSM_HSPHY_3P3_REGULATOR, + MSM_HSPHY_MAX_REGULATORS = USB_HSPHY_MAX_REGULATORS +}; + +struct msm_snps_hsphy { + struct usb_phy phy; + void __iomem *phy_csr_regs; + + struct clk *phy_csr_clk; + struct clk *ref_clk; + struct reset_control *phy_reset; + struct reset_control *phy_por_reset; + + bool dpdm_enable; + struct regulator_dev *dpdm_rdev; + struct regulator_desc dpdm_rdesc; + + int *phy_init_seq; + + bool suspended; + bool cable_connected; + bool clocks_enabled; + + int voltage_levels[USB_HSPHY_MAX_REGULATORS][3]; + struct regulator_bulk_data regulator[USB_HSPHY_MAX_REGULATORS]; + + struct mutex phy_lock; +}; + +static void msm_snps_hsphy_disable_clocks(struct msm_snps_hsphy *phy) +{ + dev_dbg(phy->phy.dev, "%s: clocks_enabled:%d\n", + __func__, phy->clocks_enabled); + + if (!phy->clocks_enabled) + return; + + clk_disable_unprepare(phy->phy_csr_clk); + clk_disable_unprepare(phy->ref_clk); + + phy->clocks_enabled = false; +} + +static void msm_snps_hsphy_enable_clocks(struct msm_snps_hsphy *phy) +{ + dev_dbg(phy->phy.dev, "%s: clocks_enabled:%d\n", + __func__, phy->clocks_enabled); + + if (phy->clocks_enabled) + return; + + clk_prepare_enable(phy->ref_clk); + clk_prepare_enable(phy->phy_csr_clk); + + phy->clocks_enabled = true; +} + +static int msm_snps_hsphy_config_regulators(struct msm_snps_hsphy *phy, + int high) +{ + int min, ret, i; + + min = high ? 1 : 0; /* low or none? */ + + for (i = 0; i < USB_HSPHY_MAX_REGULATORS; i++) { + ret = regulator_set_voltage(phy->regulator[i].consumer, + phy->voltage_levels[i][min], + phy->voltage_levels[i][2]); + if (ret) { + dev_err(phy->phy.dev, "%s: unable to set voltage for hsusb %s regulator\n", + __func__, phy->regulator[i].supply); + return ret; + } + dev_dbg(phy->phy.dev, "%s: min_vol:%d max_vol:%d\n", + phy->regulator[i].supply, + phy->voltage_levels[i][min], + phy->voltage_levels[i][2]); + } + + return 0; +} +static int msm_snps_hsphy_disable_regulators(struct msm_snps_hsphy *phy) +{ + int ret = 0; + + dev_dbg(phy->phy.dev, "%s turn off regulators\n", __func__); + + mutex_lock(&phy->phy_lock); + ret = regulator_bulk_disable(USB_HSPHY_MAX_REGULATORS, phy->regulator); + + ret = regulator_set_load( + phy->regulator[MSM_HSPHY_1P8_REGULATOR].consumer, 0); + if (ret) + dev_err(phy->phy.dev, "Unable to set (0) HPM for vdda18\n"); + + ret = regulator_set_load( + phy->regulator[MSM_HSPHY_3P3_REGULATOR].consumer, 0); + if (ret) + dev_err(phy->phy.dev, "Unable to set (0) HPM for vdda33\n"); + + ret = msm_snps_hsphy_config_regulators(phy, 0); + + mutex_unlock(&phy->phy_lock); + + return ret; +} + +static int msm_snps_hsphy_enable_regulators(struct msm_snps_hsphy *phy) +{ + int ret = 0; + + dev_dbg(phy->phy.dev, "%s turn on regulators.\n", __func__); + + mutex_lock(&phy->phy_lock); + ret = msm_snps_hsphy_config_regulators(phy, 1); + if (ret) { + mutex_unlock(&phy->phy_lock); + return ret; + } + + ret = regulator_set_load( + phy->regulator[MSM_HSPHY_1P8_REGULATOR].consumer, + USB_HSPHY_1P8_HPM_LOAD); + if (ret < 0) { + dev_err(phy->phy.dev, "Unable to set HPM of vdda18:%d\n", ret); + goto unconfig_regulators; + } + + ret = regulator_set_load( + phy->regulator[MSM_HSPHY_3P3_REGULATOR].consumer, + USB_HSPHY_3P3_HPM_LOAD); + if (ret < 0) { + dev_err(phy->phy.dev, "Unable to set HPM of vdda33:%d\n", ret); + goto unset_1p8_load; + } + + ret = regulator_bulk_enable(USB_HSPHY_MAX_REGULATORS, phy->regulator); + if (ret) + goto unset_3p3_load; + + mutex_unlock(&phy->phy_lock); + + dev_dbg(phy->phy.dev, "%s(): HSUSB PHY's regulators are turned ON.\n", + __func__); + return 0; + +unset_3p3_load: + regulator_set_load(phy->regulator[MSM_HSPHY_3P3_REGULATOR].consumer, 0); +unset_1p8_load: + regulator_set_load(phy->regulator[MSM_HSPHY_1P8_REGULATOR].consumer, 0); +unconfig_regulators: + msm_snps_hsphy_config_regulators(phy, 0); + mutex_unlock(&phy->phy_lock); + + return ret; +} + +static void msm_snps_hsphy_enter_retention(struct msm_snps_hsphy *phy) +{ + u32 val; + + val = readb_relaxed(USB_PHY_CSR_PHY_CTRL_COMMON0); + val |= SIDDQ; + writeb_relaxed(val, USB_PHY_CSR_PHY_CTRL_COMMON0); + + dev_dbg(phy->phy.dev, "PHY is in retention"); +} + +static void msm_snps_hsphy_exit_retention(struct msm_snps_hsphy *phy) +{ + u32 val; + + val = readb_relaxed(USB_PHY_CSR_PHY_CTRL_COMMON0); + val &= ~SIDDQ; + writeb_relaxed(val, USB_PHY_CSR_PHY_CTRL_COMMON0); + + dev_dbg(phy->phy.dev, "PHY is out of retention"); +} + +static int msm_snps_phy_block_reset(struct msm_snps_hsphy *phy) +{ + int ret; + + msm_snps_hsphy_disable_clocks(phy); + + ret = reset_control_assert(phy->phy_reset); + if (ret) { + dev_err(phy->phy.dev, "phy_reset_clk assert failed %d\n", + ret); + return ret; + } + + usleep_range(10, 15); + + ret = reset_control_deassert(phy->phy_reset); + if (ret) { + dev_err(phy->phy.dev, "phy_reset_clk deassert failed %d\n", + ret); + return ret; + } + + usleep_range(80, 100); + + msm_snps_hsphy_enable_clocks(phy); + + return 0; +} + +static int msm_snps_hsphy_reset(struct msm_snps_hsphy *phy) +{ + int ret; + + ret = reset_control_assert(phy->phy_por_reset); + if (ret) { + dev_err(phy->phy.dev, "phy_por_clk assert failed %d\n", ret); + return ret; + } + /* + * The Femto PHY is POR reset in the following scenarios. + * + * 1. After overriding the parameter registers. + * 2. Low power mode exit from PHY retention. + * + * Ensure that SIDDQ is cleared before bringing the PHY + * out of reset. + * + */ + msm_snps_hsphy_exit_retention(phy); + + /* + * As per databook, 10 usec delay is required between + * PHY POR assert and de-assert. + */ + usleep_range(10, 20); + ret = reset_control_deassert(phy->phy_por_reset); + if (ret) { + pr_err("phy_por_clk de-assert failed %d\n", ret); + return ret; + } + /* + * As per databook, it takes 75 usec for PHY to stabilize + * after the reset. + */ + usleep_range(80, 100); + + /* Ensure that RESET operation is completed. */ + mb(); + + return 0; +} + +static int msm_snps_hsphy_init(struct usb_phy *uphy) +{ + struct msm_snps_hsphy *phy = + container_of(uphy, struct msm_snps_hsphy, phy); + int ret; + + dev_dbg(phy->phy.dev, "%s: Initialize HS PHY\n", __func__); + ret = msm_snps_hsphy_enable_regulators(phy); + if (ret) + return ret; + + ret = msm_snps_phy_block_reset(phy); + if (ret) + return ret; + + ret = msm_snps_hsphy_reset(phy); + + return ret; +} + +static void msm_snps_hsphy_enable_hv_interrupts(struct msm_snps_hsphy *phy) +{ + u32 val; + + dev_dbg(phy->phy.dev, "%s\n", __func__); + val = readl_relaxed(USB_PHY_CSR_PHY_CTRL3); + val |= CLAMP_MPM_DPSE_DMSE_EN_N; + writeb_relaxed(val, USB_PHY_CSR_PHY_CTRL3); +} + +static void msm_snps_hsphy_disable_hv_interrupts(struct msm_snps_hsphy *phy) +{ + u32 val; + + dev_dbg(phy->phy.dev, "%s\n", __func__); + val = readl_relaxed(USB_PHY_CSR_PHY_CTRL3); + val &= ~CLAMP_MPM_DPSE_DMSE_EN_N; + writeb_relaxed(val, USB_PHY_CSR_PHY_CTRL3); +} + +static int msm_snps_hsphy_set_suspend(struct usb_phy *uphy, int suspend) +{ + struct msm_snps_hsphy *phy = container_of(uphy, + struct msm_snps_hsphy, phy); + + dev_dbg(phy->phy.dev, "%s: suspend:%d with phy->suspended:%d\n", + __func__, suspend, phy->suspended); + if (phy->suspended == suspend) { + dev_info(phy->phy.dev, "PHY is already suspended\n"); + return 0; + } + + if (suspend) { + if (phy->cable_connected) { + msm_snps_hsphy_enable_hv_interrupts(phy); + msm_snps_hsphy_disable_clocks(phy); + } else { + msm_snps_hsphy_enter_retention(phy); + msm_snps_hsphy_disable_clocks(phy); + msm_snps_hsphy_disable_regulators(phy); + } + + phy->suspended = true; + } else { + if (phy->cable_connected) { + msm_snps_hsphy_enable_clocks(phy); + msm_snps_hsphy_disable_hv_interrupts(phy); + } else { + msm_snps_hsphy_enable_regulators(phy); + msm_snps_hsphy_enable_clocks(phy); + msm_snps_hsphy_exit_retention(phy); + } + + phy->suspended = false; + } + + return 0; +} + +static int msm_snps_dpdm_regulator_enable(struct regulator_dev *rdev) +{ + int ret = 0; + struct msm_snps_hsphy *phy = rdev_get_drvdata(rdev); + + mutex_lock(&phy->phy_lock); + if (phy->dpdm_enable) { + dev_dbg(phy->phy.dev, "%s: DP DM regulator already enabled\n", + __func__); + mutex_unlock(&phy->phy_lock); + return 0; + } + + msm_snps_hsphy_enable_regulators(phy); + phy->dpdm_enable = true; + mutex_unlock(&phy->phy_lock); + + return ret; +} + +static int msm_snps_dpdm_regulator_disable(struct regulator_dev *rdev) +{ + int ret = 0; + struct msm_snps_hsphy *phy = rdev_get_drvdata(rdev); + + mutex_lock(&phy->phy_lock); + if (!phy->dpdm_enable) { + dev_dbg(phy->phy.dev, "%s: DP DM regulator already enabled\n", + __func__); + mutex_unlock(&phy->phy_lock); + return 0; + } + + msm_snps_hsphy_disable_regulators(phy); + phy->dpdm_enable = false; + mutex_unlock(&phy->phy_lock); + + return ret; +} + +static int msm_snps_dpdm_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct msm_snps_hsphy *phy = rdev_get_drvdata(rdev); + + return phy->dpdm_enable; +} + +static struct regulator_ops msm_snps_dpdm_regulator_ops = { + .enable = msm_snps_dpdm_regulator_enable, + .disable = msm_snps_dpdm_regulator_disable, + .is_enabled = msm_snps_dpdm_regulator_is_enabled, +}; + +static int msm_snps_dpdm_regulator_register(struct msm_snps_hsphy *phy) +{ + struct device *dev = phy->phy.dev; + struct regulator_config cfg = {}; + struct regulator_init_data *init_data; + + init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); + if (!init_data) + return -ENOMEM; + + init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS; + phy->dpdm_rdesc.owner = THIS_MODULE; + phy->dpdm_rdesc.type = REGULATOR_VOLTAGE; + phy->dpdm_rdesc.ops = &msm_snps_dpdm_regulator_ops; + phy->dpdm_rdesc.name = kbasename(dev->of_node->full_name); + + cfg.dev = dev; + cfg.init_data = init_data; + cfg.driver_data = phy; + cfg.of_node = dev->of_node; + + phy->dpdm_rdev = devm_regulator_register(dev, &phy->dpdm_rdesc, &cfg); + if (IS_ERR(phy->dpdm_rdev)) + return PTR_ERR(phy->dpdm_rdev); + + return 0; +} + +static int msm_snps_hsphy_notify_connect(struct usb_phy *uphy, + enum usb_device_speed speed) +{ + struct msm_snps_hsphy *phy = container_of(uphy, + struct msm_snps_hsphy, phy); + + phy->cable_connected = true; + + dev_dbg(phy->phy.dev, "PHY: connect notification cable_connected=%d\n", + phy->cable_connected); + return 0; +} + +static int msm_snps_hsphy_notify_disconnect(struct usb_phy *uphy, + enum usb_device_speed speed) +{ + struct msm_snps_hsphy *phy = container_of(uphy, + struct msm_snps_hsphy, phy); + + phy->cable_connected = false; + + dev_dbg(phy->phy.dev, "PHY: connect notification cable_connected=%d\n", + phy->cable_connected); + return 0; +} + +static int msm_snps_hsphy_probe(struct platform_device *pdev) +{ + struct msm_snps_hsphy *phy; + struct device *dev = &pdev->dev; + struct resource *res; + int ret = 0; + int len = 0; + + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + dev_dbg(dev, "%s: probe\n", __func__); + phy->phy_reset = devm_reset_control_get(dev, "phy_reset"); + if (IS_ERR(phy->phy_reset)) { + dev_err(dev, "%s failed to get phy_reset %d\n", + __func__, ret); + return PTR_ERR(phy->phy_reset); + } + + phy->phy_por_reset = devm_reset_control_get(dev, "phy_por_reset"); + if (IS_ERR(phy->phy_por_reset)) { + dev_err(dev, "%s failed to get phy_por_reset %d\n", + __func__, ret); + return PTR_ERR(phy->phy_por_reset); + } + + phy->ref_clk = devm_clk_get(dev, "ref_clk"); + if (IS_ERR(phy->ref_clk)) { + dev_err(dev, "%s failed to get ref_clk %d\n", + __func__, ret); + return PTR_ERR(phy->ref_clk); + } + + phy->phy_csr_clk = devm_clk_get(dev, "phy_csr_clk"); + if (IS_ERR(phy->phy_csr_clk)) { + dev_err(dev, "%s failed to get phy_csr_clk %d\n", + __func__, ret); + return PTR_ERR(phy->phy_csr_clk); + } + + res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "phy_csr"); + + phy->phy_csr_regs = devm_ioremap_resource(dev, res); + if (IS_ERR(phy->phy_csr_regs)) { + dev_err(dev, "%s: PHY CSR ioremap failed!\n", __func__); + return PTR_ERR(phy->phy_csr_regs); + } + + of_get_property(dev->of_node, "qcom,snps-hs-phy-init-seq", &len); + if (len) { + phy->phy_init_seq = devm_kzalloc(dev, len, GFP_KERNEL); + if (!phy->phy_init_seq) + return -ENOMEM; + of_property_read_u32_array(dev->of_node, + "qcom,snps-hs-phy-init-seq", phy->phy_init_seq, + (len/sizeof(*phy->phy_init_seq))); + } + + phy->regulator[MSM_HSPHY_DVDD_REGULATOR].supply = "vdd"; + phy->regulator[MSM_HSPHY_1P8_REGULATOR].supply = "vdda18"; + phy->regulator[MSM_HSPHY_3P3_REGULATOR].supply = "vdda33"; + + ret = devm_regulator_bulk_get(dev, USB_HSPHY_MAX_REGULATORS, + phy->regulator); + if (ret) + return ret; + + ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level", + (u32 *) phy->voltage_levels[MSM_HSPHY_DVDD_REGULATOR], + ARRAY_SIZE(phy->voltage_levels[MSM_HSPHY_DVDD_REGULATOR])); + if (ret) { + dev_err(dev, "%s: error reading qcom,vdd-voltage-level property\n", + __func__); + return ret; + } + + phy->voltage_levels[MSM_HSPHY_1P8_REGULATOR][0] = 0; + phy->voltage_levels[MSM_HSPHY_1P8_REGULATOR][1] = USB_HSPHY_1P8_VOL_MIN; + phy->voltage_levels[MSM_HSPHY_1P8_REGULATOR][2] = USB_HSPHY_1P8_VOL_MAX; + + phy->voltage_levels[MSM_HSPHY_3P3_REGULATOR][0] = 0; + phy->voltage_levels[MSM_HSPHY_3P3_REGULATOR][1] = USB_HSPHY_3P3_VOL_MIN; + phy->voltage_levels[MSM_HSPHY_3P3_REGULATOR][2] = USB_HSPHY_3P3_VOL_MAX; + + platform_set_drvdata(pdev, phy); + + phy->phy.dev = dev; + phy->phy.init = msm_snps_hsphy_init; + phy->phy.set_suspend = msm_snps_hsphy_set_suspend; + phy->phy.notify_connect = msm_snps_hsphy_notify_connect; + phy->phy.notify_disconnect = msm_snps_hsphy_notify_disconnect; + + mutex_init(&phy->phy_lock); + ret = msm_snps_dpdm_regulator_register(phy); + if (ret) + return ret; + + ret = usb_add_phy_dev(&phy->phy); + + return ret; +} + +static int msm_snps_hsphy_remove(struct platform_device *pdev) +{ + struct msm_snps_hsphy *phy = platform_get_drvdata(pdev); + + usb_remove_phy(&phy->phy); + + msm_snps_hsphy_disable_clocks(phy); + msm_snps_hsphy_disable_regulators(phy); + + return 0; +} + +static const struct of_device_id msm_usb_hsphy_match[] = { + { + .compatible = "qcom,usb-snps-hsphy", + }, + { }, +}; + +static struct platform_driver msm_snps_hsphy_driver = { + .probe = msm_snps_hsphy_probe, + .remove = msm_snps_hsphy_remove, + .driver = { + .name = "msm-usb-snps-hsphy", + .of_match_table = msm_usb_hsphy_match, + }, +}; + +module_platform_driver(msm_snps_hsphy_driver); + +MODULE_DESCRIPTION("MSM USB SNPS HS PHY driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h index 974c3796a23f..5d9b02a90421 100644 --- a/include/linux/usb/msm_hsusb_hw.h +++ b/include/linux/usb/msm_hsusb_hw.h @@ -64,6 +64,7 @@ #define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */ #define PHY_RETEN (1 << 1) /* PHY retention enable/disable */ #define PHY_POR_ASSERT (1 << 0) /* USB2 28nm PHY POR ASSERT */ +#define PHY_CLAMP_DPDMSE_EN (1 << 21) /* PHY mpm DP DM clamp enable */ /* OTG definitions */ #define OTGSC_INTSTS_MASK (0x7f << 16) @@ -74,4 +75,29 @@ #define OTGSC_IDIE (1 << 24) #define OTGSC_BSVIE (1 << 27) +/* USB PHY CSR registers and bit definitions */ + +#define USB_PHY_CSR_PHY_CTRL_COMMON0 (MSM_USB_PHY_CSR_BASE + 0x078) +#define SIDDQ BIT(2) + +#define USB_PHY_CSR_PHY_CTRL1 (MSM_USB_PHY_CSR_BASE + 0x08C) +#define ID_HV_CLAMP_EN_N BIT(1) + +#define USB_PHY_CSR_PHY_CTRL3 (MSM_USB_PHY_CSR_BASE + 0x094) +#define CLAMP_MPM_DPSE_DMSE_EN_N BIT(2) + +#define USB2_PHY_USB_PHY_IRQ_CMD (MSM_USB_PHY_CSR_BASE + 0x0D0) +#define USB2_PHY_USB_PHY_INTERRUPT_SRC_STATUS (MSM_USB_PHY_CSR_BASE + 0x05C) + +#define USB2_PHY_USB_PHY_INTERRUPT_CLEAR0 (MSM_USB_PHY_CSR_BASE + 0x0DC) +#define USB2_PHY_USB_PHY_INTERRUPT_CLEAR1 (MSM_USB_PHY_CSR_BASE + 0x0E0) + +#define USB2_PHY_USB_PHY_INTERRUPT_MASK1 (MSM_USB_PHY_CSR_BASE + 0x0D8) + +#define USB_PHY_IDDIG_1_0 BIT(7) + +#define USB_PHY_IDDIG_RISE_MASK BIT(0) +#define USB_PHY_IDDIG_FALL_MASK BIT(1) +#define USB_PHY_ID_MASK (USB_PHY_IDDIG_RISE_MASK | USB_PHY_IDDIG_FALL_MASK) + #endif /* __LINUX_USB_GADGET_MSM72K_UDC_H__ */ -- GitLab From 03b297f4e718cc3e47d118a36c264cdec2a90d0f Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Fri, 8 Jun 2018 11:51:24 +0530 Subject: [PATCH 0048/1299] defconfig: Enable CPU clock driver for QCS405 Enable CPU clock controller driver support. Change-Id: I58c45c5f41987bf77ff0a46fb44137dab23f63aa Signed-off-by: Shefali Jain --- arch/arm/configs/qcs405_defconfig | 1 + arch/arm64/configs/qcs405_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/qcs405_defconfig b/arch/arm/configs/qcs405_defconfig index 1fd8d9d2d78e..73f4976cf3a5 100644 --- a/arch/arm/configs/qcs405_defconfig +++ b/arch/arm/configs/qcs405_defconfig @@ -368,6 +368,7 @@ CONFIG_COMMON_CLK_QCOM=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_MDM_GCC_QCS405=y CONFIG_MDM_DEBUGCC_QCS405=y +CONFIG_CLOCK_CPU_QCS405=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_MAILBOX=y diff --git a/arch/arm64/configs/qcs405_defconfig b/arch/arm64/configs/qcs405_defconfig index 0f438beb743e..571382c01496 100644 --- a/arch/arm64/configs/qcs405_defconfig +++ b/arch/arm64/configs/qcs405_defconfig @@ -369,6 +369,7 @@ CONFIG_SPS_SUPPORT_NDP_BAM=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_MDM_GCC_QCS405=y CONFIG_MDM_DEBUGCC_QCS405=y +CONFIG_CLOCK_CPU_QCS405=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_MAILBOX=y -- GitLab From b65909d1d9daefc7fffe2a3efae469d33b3658b5 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Thu, 7 Jun 2018 14:12:42 +0530 Subject: [PATCH 0049/1299] ARM: dts: msm: Add uart clocks to enable serial console for qcs405 Enable serial console support. Change-Id: I38e34d33124746e4652c891e4a06344e5a2745a8 Signed-off-by: Avaneesh Kumar Dwivedi --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index d866a8c275e5..aaf6e8bb982f 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -318,11 +318,15 @@ status = "disabled"; }; - blsp1_uart2: serial@78b0000 { + blsp1_uart1: serial@78b0000 { compatible = "qcom,msm-uartdm", "qcom,msm-uartdm-v1.4"; reg = <0x78b0000 0x200>; interrupts = <0 108 0>; + clocks = <&clock_gcc GCC_BLSP1_UART1_APPS_CLK>, + <&clock_gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + status = "okay"; }; dcc: dcc_v2@b2000 { -- GitLab From 4158139dfd054462b768b2db6d7adad6bfad5902 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Thu, 7 Jun 2018 13:01:07 +0530 Subject: [PATCH 0050/1299] ARM: dts: msm: Restrict access to hyp calls in SM6150 Define a flag for restrict access to hyp assign calls. Change-Id: Iae1eed9f8246bdce520a673ef0464dd2de372be4 Signed-off-by: Tharun Kumar Merugu --- arch/arm64/boot/dts/qcom/sm6150.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index e384dd622a7c..15301849fb3c 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -1126,6 +1126,7 @@ qcom,msm-adsprpc-mem { compatible = "qcom,msm-adsprpc-mem-region"; memory-region = <&adsp_mem>; + restrict-access; }; qcom,msm_fastrpc { -- GitLab From df8425d2ae44847c79104ff8cfb6db77d5c2511e Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Wed, 23 May 2018 02:52:46 +0530 Subject: [PATCH 0051/1299] msm: kgsl: Move some helper functions out of gmu Some of the gmu functions have common functionality across A6xx GPUs. Move out these helper function from gmu so that it can be reusable. Change-Id: Idf623544854329a27ecbe52f28bbd2e90941fcba Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno.c | 43 ++++++++- drivers/gpu/msm/adreno.h | 3 +- drivers/gpu/msm/adreno_a6xx.c | 44 ++++++++- drivers/gpu/msm/adreno_a6xx.h | 64 ++++++++++++- drivers/gpu/msm/adreno_a6xx_gmu.c | 109 ++++++++------------- drivers/gpu/msm/adreno_a6xx_snapshot.c | 5 +- drivers/gpu/msm/adreno_snapshot.c | 1 - drivers/gpu/msm/kgsl_gmu.c | 127 +++---------------------- drivers/gpu/msm/kgsl_gmu.h | 33 ++----- drivers/gpu/msm/kgsl_gmu_core.c | 9 -- drivers/gpu/msm/kgsl_gmu_core.h | 35 ++++--- drivers/gpu/msm/kgsl_hfi.c | 30 ++++++ drivers/gpu/msm/kgsl_hfi.h | 1 + drivers/gpu/msm/kgsl_pwrctrl.c | 29 ++++++ drivers/gpu/msm/kgsl_pwrctrl.h | 1 + 15 files changed, 296 insertions(+), 238 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 70e51e50187c..9bae4f19be21 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -3111,9 +3111,50 @@ static void adreno_regwrite(struct kgsl_device *device, __raw_writel(value, reg); } +/** + * adreno_gmu_clear_and_unmask_irqs() - Clear pending IRQs and Unmask IRQs + * @adreno_dev: Pointer to the Adreno device that owns the GMU + */ +void adreno_gmu_clear_and_unmask_irqs(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); + + /* Clear any pending IRQs before unmasking on GMU */ + adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR, + 0xFFFFFFFF); + adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, + 0xFFFFFFFF); + + /* Unmask needed IRQs on GMU */ + adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, + (unsigned int) ~(gmu_dev_ops->gmu2host_intr_mask)); + adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, + (unsigned int) ~(gmu_dev_ops->gmu_ao_intr_mask)); +} + +/** + * adreno_gmu_mask_and_clear_irqs() - Mask all IRQs and clear pending IRQs + * @adreno_dev: Pointer to the Adreno device that owns the GMU + */ +void adreno_gmu_mask_and_clear_irqs(struct adreno_device *adreno_dev) +{ + /* Mask all IRQs on GMU */ + adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, + 0xFFFFFFFF); + adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, + 0xFFFFFFFF); + + /* Clear any pending IRQs before disabling */ + adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, + 0xFFFFFFFF); + adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR, + 0xFFFFFFFF); +} + /* * adreno_gmu_fenced_write() - Check if there is a GMU and it is enabled - * @adreno_dev: Pointer to the Adreno device device that owns the GMU + * @adreno_dev: Pointer to the Adreno device that owns the GMU * @offset: 32bit register enum that is to be written * @val: The value to be written to the register * @fence_mask: The value to poll the fence status register diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 952e48b53006..99ba7b01493b 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -1935,7 +1935,8 @@ static inline void adreno_deassert_gbif_halt(struct adreno_device *adreno_dev) if (adreno_has_gbif(adreno_dev)) adreno_writereg(adreno_dev, ADRENO_REG_GBIF_HALT, 0x0); } - +void adreno_gmu_clear_and_unmask_irqs(struct adreno_device *adreno_dev); +void adreno_gmu_mask_and_clear_irqs(struct adreno_device *adreno_dev); int adreno_gmu_fenced_write(struct adreno_device *adreno_dev, enum adreno_regs offset, unsigned int val, unsigned int fence_mask); diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index c38dff8d2046..b537c97777bc 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -1123,6 +1123,44 @@ static int a6xx_rb_start(struct adreno_device *adreno_dev, return a6xx_post_start(adreno_dev); } +/* + * a6xx_sptprac_enable() - Power on SPTPRAC + * @adreno_dev: Pointer to Adreno device + */ +static int a6xx_sptprac_enable(struct adreno_device *adreno_dev) +{ + if (!adreno_has_sptprac_gdsc(adreno_dev)) + return 0; + + return a6xx_gmu_sptprac_enable(adreno_dev); +} + +/* + * a6xx_sptprac_disable() - Power off SPTPRAC + * @adreno_dev: Pointer to Adreno device + */ +static void a6xx_sptprac_disable(struct adreno_device *adreno_dev) +{ + if (!adreno_has_sptprac_gdsc(adreno_dev)) + return; + + a6xx_gmu_sptprac_disable(adreno_dev); +} + +/* + * a6xx_sptprac_is_on() - Check if SPTP is on using pwr status register + * @adreno_dev - Pointer to adreno_device + * This check should only be performed if the keepalive bit is set or it + * can be guaranteed that the power state of the GPU will remain unchanged + */ +bool a6xx_sptprac_is_on(struct adreno_device *adreno_dev) +{ + if (!adreno_has_sptprac_gdsc(adreno_dev)) + return true; + + return a6xx_gmu_sptprac_is_on(adreno_dev); +} + unsigned int a6xx_set_marker( unsigned int *cmds, enum adreno_cp_marker_type type) { @@ -2813,8 +2851,8 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .platform_setup = a6xx_platform_setup, .init = a6xx_init, .rb_start = a6xx_rb_start, - .regulator_enable = a6xx_gmu_sptprac_enable, - .regulator_disable = a6xx_gmu_sptprac_disable, + .regulator_enable = a6xx_sptprac_enable, + .regulator_disable = a6xx_sptprac_disable, .perfcounters = &a6xx_perfcounters, .enable_pwr_counters = a6xx_enable_pwr_counters, .count_throttles = a6xx_count_throttles, @@ -2836,7 +2874,7 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .preemption_context_init = a6xx_preemption_context_init, .preemption_context_destroy = a6xx_preemption_context_destroy, .gx_is_on = a6xx_gmu_gx_is_on, - .sptprac_is_on = a6xx_gmu_sptprac_is_on, + .sptprac_is_on = a6xx_sptprac_is_on, .ccu_invalidate = a6xx_ccu_invalidate, .perfcounter_update = a6xx_perfcounter_update, .coresight = {&a6xx_coresight, &a6xx_coresight_cx}, diff --git a/drivers/gpu/msm/adreno_a6xx.h b/drivers/gpu/msm/adreno_a6xx.h index c40dcccf0bf8..7d4f9b895c4d 100644 --- a/drivers/gpu/msm/adreno_a6xx.h +++ b/drivers/gpu/msm/adreno_a6xx.h @@ -106,6 +106,68 @@ struct cpu_gpu_lock { #define A6XX_CP_RB_CNTL_DEFAULT (((ilog2(4) << 8) & 0x1F00) | \ (ilog2(KGSL_RB_DWORDS >> 1) & 0x3F)) +/* + * timed_poll_check() - polling *gmu* register at given offset until + * its value changed to match expected value. The function times + * out and returns after given duration if register is not updated + * as expected. + * + * @device: Pointer to KGSL device + * @offset: Register offset + * @expected_ret: expected register value that stops polling + * @timout: number of jiffies to abort the polling + * @mask: bitmask to filter register value to match expected_ret + */ +static inline int timed_poll_check(struct kgsl_device *device, + unsigned int offset, unsigned int expected_ret, + unsigned int timeout, unsigned int mask) +{ + unsigned long t; + unsigned int value; + + t = jiffies + msecs_to_jiffies(timeout); + + do { + gmu_core_regread(device, offset, &value); + if ((value & mask) == expected_ret) + return 0; + /* Wait 100us to reduce unnecessary AHB bus traffic */ + usleep_range(10, 100); + } while (!time_after(jiffies, t)); + + /* Double check one last time */ + gmu_core_regread(device, offset, &value); + if ((value & mask) == expected_ret) + return 0; + + return -ETIMEDOUT; +} + +/* + * read_AO_counter() - Returns the 64bit always on counter value + * + * @device: Pointer to KGSL device + */ +static inline uint64_t read_AO_counter(struct kgsl_device *device) +{ + unsigned int l, h, h1; + + gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h); + gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); + gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1); + + /* + * If there's no change in COUNTER_H we have no overflow so return, + * otherwise read COUNTER_L again + */ + + if (h == h1) + return (uint64_t) l | ((uint64_t) h << 32); + + gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); + return (uint64_t) l | ((uint64_t) h1 << 32); +} + /* Preemption functions */ void a6xx_preemption_trigger(struct adreno_device *adreno_dev); void a6xx_preemption_schedule(struct adreno_device *adreno_dev); @@ -131,8 +193,6 @@ void a6xx_snapshot(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot); void a6xx_snapshot_debugbus(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot); -void a6xx_gmu_snapshot(struct adreno_device *adreno_dev, - struct kgsl_snapshot *snapshot); void a6xx_crashdump_init(struct adreno_device *adreno_dev); int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev); void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev); diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index d3f36cfe7c69..b4fcdbd60e9d 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -11,9 +11,8 @@ * */ #include -#include -#include #include +#include #include "kgsl_gmu_core.h" #include "kgsl_gmu.h" @@ -171,48 +170,13 @@ static void _load_gmu_rpmh_ucode(struct kgsl_device *device) wmb(); } +/* GMU timeouts */ +#define GMU_IDLE_TIMEOUT 100 /* ms */ #define GMU_START_TIMEOUT 100 /* ms */ #define GPU_START_TIMEOUT 100 /* ms */ #define GPU_RESET_TIMEOUT 1 /* ms */ #define GPU_RESET_TIMEOUT_US 10 /* us */ -/* - * timed_poll_check() - polling *gmu* register at given offset until - * its value changed to match expected value. The function times - * out and returns after given duration if register is not updated - * as expected. - * - * @device: Pointer to KGSL device - * @offset: Register offset - * @expected_ret: expected register value that stops polling - * @timout: number of jiffies to abort the polling - * @mask: bitmask to filter register value to match expected_ret - */ -static int timed_poll_check(struct kgsl_device *device, - unsigned int offset, unsigned int expected_ret, - unsigned int timeout, unsigned int mask) -{ - unsigned long t; - unsigned int value; - - t = jiffies + msecs_to_jiffies(timeout); - - do { - gmu_core_regread(device, offset, &value); - if ((value & mask) == expected_ret) - return 0; - /* Wait 100us to reduce unnecessary AHB bus traffic */ - usleep_range(10, 100); - } while (!time_after(jiffies, t)); - - /* Double check one last time */ - gmu_core_regread(device, offset, &value); - if ((value & mask) == expected_ret) - return 0; - - return -EINVAL; -} - /* * The lowest 16 bits of this value are the number of XO clock cycles * for main hysteresis. This is the first hysteresis. Here we set it @@ -334,26 +298,6 @@ static int a6xx_gmu_hfi_start(struct kgsl_device *device) return 0; } -static uint64_t read_AO_counter(struct kgsl_device *device) -{ - unsigned int l, h, h1; - - gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h); - gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); - gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1); - - /* - * If there's no change in COUNTER_H we have no overflow so return, - * otherwise read COUNTER_L again - */ - - if (h == h1) - return (uint64_t) l | ((uint64_t) h << 32); - - gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l); - return (uint64_t) l | ((uint64_t) h1 << 32); -} - static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); @@ -621,6 +565,32 @@ static inline void a6xx_gmu_oob_clear(struct adreno_device *adreno_dev, trace_kgsl_gmu_oob_clear(clear); } +static void a6xx_gmu_irq_enable(struct kgsl_device *device) +{ + struct gmu_device *gmu = KGSL_GMU_DEVICE(device); + struct kgsl_hfi *hfi = &gmu->hfi; + + /* Clear pending IRQs and Unmask needed IRQs */ + adreno_gmu_clear_and_unmask_irqs(ADRENO_DEVICE(device)); + + /* Enable all IRQs on host */ + enable_irq(hfi->hfi_interrupt_num); + enable_irq(gmu->gmu_interrupt_num); +} + +static void a6xx_gmu_irq_disable(struct kgsl_device *device) +{ + struct gmu_device *gmu = KGSL_GMU_DEVICE(device); + struct kgsl_hfi *hfi = &gmu->hfi; + + /* Disable all IRQs on host */ + disable_irq(gmu->gmu_interrupt_num); + disable_irq(hfi->hfi_interrupt_num); + + /* Mask all IRQs and clear pending IRQs */ + adreno_gmu_mask_and_clear_irqs(ADRENO_DEVICE(device)); +} + static int a6xx_gmu_hfi_start_msg(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -704,9 +674,6 @@ int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev) if (!gmu_core_gpmu_isenabled(device)) return -EINVAL; - if (!adreno_has_sptprac_gdsc(adreno_dev)) - return 0; - gmu_core_regwrite(device, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, SPTPRAC_POWERON_CTRL_MASK); @@ -731,9 +698,6 @@ void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - if (!adreno_has_sptprac_gdsc(adreno_dev)) - return; - if (!gmu_core_gpmu_isenabled(device)) return; @@ -786,7 +750,7 @@ bool a6xx_gmu_sptprac_is_on(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); unsigned int val; - if (!gmu_core_isenabled(device) || !adreno_has_sptprac_gdsc(adreno_dev)) + if (!gmu_core_isenabled(device)) return true; gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val); @@ -901,6 +865,9 @@ static int a6xx_gmu_wait_for_idle(struct adreno_device *adreno_dev) return 0; } +/* A6xx GMU FENCE RANGE MASK */ +#define GMU_FENCE_RANGE_MASK ((0x1 << 31) | ((0xA << 2) << 18) | (0x8A0)) + /* * a6xx_gmu_fw_start() - set up GMU and start FW * @device: Pointer to KGSL device @@ -958,7 +925,7 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device, gmu_core_regwrite(device, A6XX_GMU_HFI_QTBL_INFO, 1); gmu_core_regwrite(device, A6XX_GMU_AHB_FENCE_RANGE_0, - FENCE_RANGE_MASK); + GMU_FENCE_RANGE_MASK); /* Pass chipid to GMU FW, must happen before starting GMU */ @@ -1389,7 +1356,7 @@ static size_t a6xx_snapshot_gmu_mem(struct kgsl_device *device, * This is where all of the A6XX GMU specific bits and pieces are grabbed * into the snapshot memory */ -void a6xx_gmu_snapshot(struct adreno_device *adreno_dev, +static void a6xx_gmu_snapshot(struct adreno_device *adreno_dev, struct kgsl_snapshot *snapshot) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -1432,14 +1399,16 @@ struct gmu_dev_ops adreno_a6xx_gmudev = { .load_firmware = a6xx_gmu_load_firmware, .oob_set = a6xx_gmu_oob_set, .oob_clear = a6xx_gmu_oob_clear, + .irq_enable = a6xx_gmu_irq_enable, + .irq_disable = a6xx_gmu_irq_disable, .hfi_start_msg = a6xx_gmu_hfi_start_msg, .enable_lm = a6xx_gmu_enable_lm, .rpmh_gpu_pwrctrl = a6xx_gmu_rpmh_gpu_pwrctrl, .wait_for_lowest_idle = a6xx_gmu_wait_for_lowest_idle, .wait_for_gmu_idle = a6xx_gmu_wait_for_idle, - .sptprac_enable = a6xx_gmu_sptprac_enable, - .sptprac_disable = a6xx_gmu_sptprac_disable, .ifpc_store = a6xx_gmu_ifpc_store, .ifpc_show = a6xx_gmu_ifpc_show, .snapshot = a6xx_gmu_snapshot, + .gmu2host_intr_mask = HFI_IRQ_MASK, + .gmu_ao_intr_mask = GMU_AO_INT_MASK, }; diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c index 6b92c077367f..4b26b7d50b15 100644 --- a/drivers/gpu/msm/adreno_a6xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c @@ -18,6 +18,7 @@ #include "adreno_snapshot.h" #include "a6xx_reg.h" #include "adreno_a6xx.h" +#include "kgsl_gmu_core.h" #define A6XX_NUM_CTXTS 2 #define A6XX_NUM_AXI_ARB_BLOCKS 2 @@ -1491,12 +1492,14 @@ void a6xx_snapshot(struct adreno_device *adreno_dev, { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); + struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); struct adreno_snapshot_data *snap_data = gpudev->snapshot_data; bool sptprac_on; unsigned int i; /* GMU TCM data dumped through AHB */ - a6xx_gmu_snapshot(adreno_dev, snapshot); + if (gmu_dev_ops->snapshot) + gmu_dev_ops->snapshot(adreno_dev, snapshot); sptprac_on = gpudev->sptprac_is_on(adreno_dev); diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c index df55407564f9..6cd503e8c0bd 100644 --- a/drivers/gpu/msm/adreno_snapshot.c +++ b/drivers/gpu/msm/adreno_snapshot.c @@ -13,7 +13,6 @@ #include "kgsl.h" #include "kgsl_sharedmem.h" #include "kgsl_snapshot.h" -#include "kgsl_gmu_core.h" #include "adreno.h" #include "adreno_pm4types.h" diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index c27aa2dcd368..adcb51a163c4 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -10,16 +10,14 @@ * GNU General Public License for more details. * */ -#include -#include #include #include +#include #include #include #include #include #include -#include #include #include @@ -1033,35 +1031,6 @@ static irqreturn_t gmu_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static irqreturn_t hfi_irq_handler(int irq, void *data) -{ - struct kgsl_device *device = data; - struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - struct kgsl_hfi *hfi = &gmu->hfi; - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - unsigned int status = 0; - - adreno_read_gmureg(ADRENO_DEVICE(device), - ADRENO_REG_GMU_GMU2HOST_INTR_INFO, &status); - adreno_write_gmureg(ADRENO_DEVICE(device), - ADRENO_REG_GMU_GMU2HOST_INTR_CLR, status); - - if (status & HFI_IRQ_MSGQ_MASK) - tasklet_hi_schedule(&hfi->tasklet); - if (status & HFI_IRQ_CM3_FAULT_MASK) { - dev_err_ratelimited(&gmu->pdev->dev, - "GMU CM3 fault interrupt received\n"); - adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT); - adreno_dispatcher_schedule(device); - } - if (status & ~HFI_IRQ_MASK) - dev_err_ratelimited(&gmu->pdev->dev, - "Unhandled HFI interrupts 0x%lx\n", - status & ~HFI_IRQ_MASK); - - return IRQ_HANDLED; -} - static int gmu_pwrlevel_probe(struct gmu_device *gmu, struct device_node *node) { int ret; @@ -1306,52 +1275,6 @@ static int gmu_irq_probe(struct kgsl_device *device, struct gmu_device *gmu) return ret; } -static void gmu_irq_enable(struct kgsl_device *device) -{ - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - struct kgsl_hfi *hfi = &gmu->hfi; - - /* Clear any pending IRQs before unmasking on GMU */ - adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR, - 0xFFFFFFFF); - adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, - 0xFFFFFFFF); - - /* Unmask needed IRQs on GMU */ - adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, - (unsigned int) ~HFI_IRQ_MASK); - adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, - (unsigned int) ~GMU_AO_INT_MASK); - - /* Enable all IRQs on host */ - enable_irq(hfi->hfi_interrupt_num); - enable_irq(gmu->gmu_interrupt_num); -} - -static void gmu_irq_disable(struct kgsl_device *device) -{ - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - struct kgsl_hfi *hfi = &gmu->hfi; - - /* Disable all IRQs on host */ - disable_irq(gmu->gmu_interrupt_num); - disable_irq(hfi->hfi_interrupt_num); - - /* Mask all IRQs on GMU */ - adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, - 0xFFFFFFFF); - adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, - 0xFFFFFFFF); - - /* Clear any pending IRQs before disabling */ - adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, - 0xFFFFFFFF); - adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR, - 0xFFFFFFFF); -} - /* Do not access any GMU registers in GMU probe function */ static int gmu_probe(struct kgsl_device *device, struct device_node *node, unsigned long flags) @@ -1412,7 +1335,7 @@ static int gmu_probe(struct kgsl_device *device, goto error; /* Don't enable GMU interrupts until GMU started */ - /* We cannot use gmu_irq_disable because it writes registers */ + /* We cannot use irq_disable because it writes registers */ disable_irq(gmu->gmu_interrupt_num); disable_irq(hfi->hfi_interrupt_num); @@ -1587,7 +1510,7 @@ static int gmu_suspend(struct kgsl_device *device) /* Pending message in all queues are abandoned */ hfi_stop(gmu); clear_bit(GMU_HFI_ON, &gmu->flags); - gmu_irq_disable(device); + gmu_dev_ops->irq_disable(device); if (gmu_dev_ops->rpmh_gpu_pwrctrl(adreno_dev, GMU_SUSPEND, 0, 0)) return -EINVAL; @@ -1601,6 +1524,7 @@ static int gmu_suspend(struct kgsl_device *device) static void gmu_snapshot(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); /* Mask so there's no interrupt caused by NMI */ @@ -1623,37 +1547,11 @@ static void gmu_snapshot(struct kgsl_device *device) ADRENO_REG_GMU_GMU2HOST_INTR_CLR, 0xFFFFFFFF); adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, - (unsigned int) ~HFI_IRQ_MASK); + ~(gmu_dev_ops->gmu2host_intr_mask)); gmu->fault_count++; } -static void gmu_change_gpu_pwrlevel(struct kgsl_device *device, - unsigned int new_level) -{ - - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - unsigned int old_level = pwr->active_pwrlevel; - - /* - * Update the level according to any thermal, - * max/min, or power constraints. - */ - new_level = kgsl_pwrctrl_adjust_pwrlevel(device, new_level); - - /* - * If thermal cycling is required and the new level hits the - * thermal limit, kick off the cycling. - */ - kgsl_pwrctrl_set_thermal_cycle(device, new_level); - - pwr->active_pwrlevel = new_level; - pwr->previous_pwrlevel = old_level; - - /* Request adjusted DCVS level */ - kgsl_clk_set_rate(device, pwr->active_pwrlevel); -} - /* To be called to power on both GPU and GMU */ static int gmu_start(struct kgsl_device *device) { @@ -1669,7 +1567,7 @@ static int gmu_start(struct kgsl_device *device) WARN_ON(test_bit(GMU_CLK_ON, &gmu->flags)); gmu_enable_gdsc(gmu); gmu_enable_clks(gmu); - gmu_irq_enable(device); + gmu_dev_ops->irq_enable(device); /* Vote for 300MHz DDR for GMU to init */ ret = msm_bus_scale_client_update_request(gmu->pcl, @@ -1688,7 +1586,7 @@ static int gmu_start(struct kgsl_device *device) goto error_gmu; /* Request default DCVS level */ - gmu_change_gpu_pwrlevel(device, pwr->default_pwrlevel); + kgsl_pwrctrl_set_default_gpu_pwrlevel(device); msm_bus_scale_client_update_request(gmu->pcl, 0); break; @@ -1696,7 +1594,7 @@ static int gmu_start(struct kgsl_device *device) WARN_ON(test_bit(GMU_CLK_ON, &gmu->flags)); gmu_enable_gdsc(gmu); gmu_enable_clks(gmu); - gmu_irq_enable(device); + gmu_dev_ops->irq_enable(device); ret = gmu_dev_ops->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START, GMU_COLD_BOOT, 0); @@ -1707,7 +1605,7 @@ static int gmu_start(struct kgsl_device *device) if (ret) goto error_gmu; - gmu_change_gpu_pwrlevel(device, pwr->default_pwrlevel); + kgsl_pwrctrl_set_default_gpu_pwrlevel(device); break; case KGSL_STATE_RESET: @@ -1716,7 +1614,7 @@ static int gmu_start(struct kgsl_device *device) gmu_suspend(device); gmu_enable_gdsc(gmu); gmu_enable_clks(gmu); - gmu_irq_enable(device); + gmu_dev_ops->irq_enable(device); ret = gmu_dev_ops->rpmh_gpu_pwrctrl( adreno_dev, GMU_FW_START, GMU_COLD_BOOT, 0); @@ -1729,8 +1627,7 @@ static int gmu_start(struct kgsl_device *device) goto error_gmu; /* Send DCVS level prior to reset*/ - gmu_change_gpu_pwrlevel(device, - pwr->default_pwrlevel); + kgsl_pwrctrl_set_default_gpu_pwrlevel(device); } else { /* GMU fast boot */ hfi_stop(gmu); @@ -1786,7 +1683,7 @@ static void gmu_stop(struct kgsl_device *device) /* Pending message in all queues are abandoned */ hfi_stop(gmu); clear_bit(GMU_HFI_ON, &gmu->flags); - gmu_irq_disable(device); + gmu_dev_ops->irq_disable(device); gmu_dev_ops->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_STOP, 0, 0); gmu_disable_clks(gmu); diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h index 33605c8a0432..efbe5f7ad846 100644 --- a/drivers/gpu/msm/kgsl_gmu.h +++ b/drivers/gpu/msm/kgsl_gmu.h @@ -16,10 +16,19 @@ #include "kgsl_hfi.h" #define MAX_GMUFW_SIZE 0x2000 /* in bytes */ -#define FENCE_RANGE_MASK ((0x1 << 31) | ((0xA << 2) << 18) | (0x8A0)) #define BWMEM_SIZE (12 + (4 * NUM_BW_LEVELS)) /*in bytes*/ +#define GMU_INT_WDOG_BITE BIT(0) +#define GMU_INT_RSCC_COMP BIT(1) +#define GMU_INT_FENCE_ERR BIT(3) +#define GMU_INT_DBD_WAKEUP BIT(4) +#define GMU_INT_HOST_AHB_BUS_ERR BIT(5) +#define GMU_AO_INT_MASK \ + (GMU_INT_WDOG_BITE | \ + GMU_INT_FENCE_ERR | \ + GMU_INT_HOST_AHB_BUS_ERR) + /* Bitmask for GPU low power mode enabling and hysterisis*/ #define SPTP_ENABLE_MASK (BIT(2) | BIT(0)) #define IFPC_ENABLE_MASK (BIT(1) | BIT(0)) @@ -41,9 +50,6 @@ CX_VOTE_ENABLE | \ GFX_VOTE_ENABLE) -/* GMU timeouts */ -#define GMU_IDLE_TIMEOUT 100 /* ms */ - /* Constants for GMU OOBs */ #define OOB_BOOT_OPTION 0 #define OOB_SLUMBER_OPTION 1 @@ -92,25 +98,6 @@ enum gmu_load_mode { INVALID_LOAD }; -enum gmu_pwrctrl_mode { - GMU_FW_START, - GMU_FW_STOP, - GMU_SUSPEND, - GMU_DCVS_NOHFI, - GMU_NOTIFY_SLUMBER, - INVALID_POWER_CTRL -}; - -enum gpu_idle_level { - GPU_HW_ACTIVE = 0x0, - GPU_HW_SPTP_PC = 0x2, - GPU_HW_IFPC = 0x3, - GPU_HW_NAP = 0x4, - GPU_HW_MIN_VOLT = 0x5, - GPU_HW_MIN_DDR = 0x6, - GPU_HW_SLUMBER = 0xF -}; - /** * struct gmu_device - GMU device structure * @ver: GMU FW version, read from GMU diff --git a/drivers/gpu/msm/kgsl_gmu_core.c b/drivers/gpu/msm/kgsl_gmu_core.c index 37a9d3178e8e..06887ecd8f3a 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.c +++ b/drivers/gpu/msm/kgsl_gmu_core.c @@ -12,15 +12,6 @@ */ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "kgsl_device.h" #include "kgsl_gmu_core.h" diff --git a/drivers/gpu/msm/kgsl_gmu_core.h b/drivers/gpu/msm/kgsl_gmu_core.h index 9d8b65818af8..b3ff2130d807 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.h +++ b/drivers/gpu/msm/kgsl_gmu_core.h @@ -13,16 +13,6 @@ #ifndef __KGSL_GMU_CORE_H #define __KGSL_GMU_CORE_H -#define GMU_INT_WDOG_BITE BIT(0) -#define GMU_INT_RSCC_COMP BIT(1) -#define GMU_INT_FENCE_ERR BIT(3) -#define GMU_INT_DBD_WAKEUP BIT(4) -#define GMU_INT_HOST_AHB_BUS_ERR BIT(5) -#define GMU_AO_INT_MASK \ - (GMU_INT_WDOG_BITE | \ - GMU_INT_HOST_AHB_BUS_ERR | \ - GMU_INT_FENCE_ERR) - /* GMU_DEVICE - Given an KGSL device return the GMU specific struct */ #define GMU_DEVICE_OPS(_a) ((_a)->gmu_core.dev_ops) #define GMU_CORE_OPS(_a) ((_a)->gmu_core.core_ops) @@ -80,6 +70,25 @@ enum oob_request { oob_dcvs = 7, /* reserved special case */ }; +enum gmu_pwrctrl_mode { + GMU_FW_START, + GMU_FW_STOP, + GMU_SUSPEND, + GMU_DCVS_NOHFI, + GMU_NOTIFY_SLUMBER, + INVALID_POWER_CTRL +}; + +enum gpu_idle_level { + GPU_HW_ACTIVE = 0x0, + GPU_HW_SPTP_PC = 0x2, + GPU_HW_IFPC = 0x3, + GPU_HW_NAP = 0x4, + GPU_HW_MIN_VOLT = 0x5, + GPU_HW_MIN_DDR = 0x6, + GPU_HW_SLUMBER = 0xF +}; + /* * Wait time before trying to write the register again. * Hopefully the GMU has finished waking up during this delay. @@ -127,18 +136,20 @@ struct gmu_dev_ops { enum oob_request req); void (*oob_clear)(struct adreno_device *adreno_dev, enum oob_request req); + void (*irq_enable)(struct kgsl_device *device); + void (*irq_disable)(struct kgsl_device *device); int (*hfi_start_msg)(struct adreno_device *adreno_dev); void (*enable_lm)(struct kgsl_device *device); int (*rpmh_gpu_pwrctrl)(struct adreno_device *, unsigned int ops, unsigned int arg1, unsigned int arg2); int (*wait_for_lowest_idle)(struct adreno_device *); int (*wait_for_gmu_idle)(struct adreno_device *); - int (*sptprac_enable)(struct adreno_device *adreno_dev); - void (*sptprac_disable)(struct adreno_device *adreno_dev); int (*ifpc_store)(struct adreno_device *adreno_dev, unsigned int val); unsigned int (*ifpc_show)(struct adreno_device *adreno_dev); void (*snapshot)(struct adreno_device *, struct kgsl_snapshot *); + const unsigned int gmu2host_intr_mask; + const unsigned int gmu_ao_intr_mask; }; /** diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c index bec11d672aa2..c54e19504ed9 100644 --- a/drivers/gpu/msm/kgsl_hfi.c +++ b/drivers/gpu/msm/kgsl_hfi.c @@ -720,3 +720,33 @@ int hfi_send_req(struct gmu_device *gmu, unsigned int id, void *data) return -EINVAL; } + +/* HFI interrupt handler */ +irqreturn_t hfi_irq_handler(int irq, void *data) +{ + struct kgsl_device *device = data; + struct gmu_device *gmu = KGSL_GMU_DEVICE(device); + struct kgsl_hfi *hfi = &gmu->hfi; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + unsigned int status = 0; + + adreno_read_gmureg(ADRENO_DEVICE(device), + ADRENO_REG_GMU_GMU2HOST_INTR_INFO, &status); + adreno_write_gmureg(ADRENO_DEVICE(device), + ADRENO_REG_GMU_GMU2HOST_INTR_CLR, status); + + if (status & HFI_IRQ_MSGQ_MASK) + tasklet_hi_schedule(&hfi->tasklet); + if (status & HFI_IRQ_CM3_FAULT_MASK) { + dev_err_ratelimited(&gmu->pdev->dev, + "GMU CM3 fault interrupt received\n"); + adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT); + adreno_dispatcher_schedule(device); + } + if (status & ~HFI_IRQ_MASK) + dev_err_ratelimited(&gmu->pdev->dev, + "Unhandled HFI interrupts 0x%lx\n", + status & ~HFI_IRQ_MASK); + + return IRQ_HANDLED; +} diff --git a/drivers/gpu/msm/kgsl_hfi.h b/drivers/gpu/msm/kgsl_hfi.h index 372b45a3cf9d..a3013225b60c 100644 --- a/drivers/gpu/msm/kgsl_hfi.h +++ b/drivers/gpu/msm/kgsl_hfi.h @@ -615,6 +615,7 @@ struct kgsl_hfi { struct gmu_device; struct gmu_memdesc; +irqreturn_t hfi_irq_handler(int irq, void *data); int hfi_start(struct kgsl_device *device, struct gmu_device *gmu, uint32_t boot_state); void hfi_stop(struct gmu_device *gmu); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 72722618941c..acdc8421de92 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -3361,3 +3361,32 @@ unsigned int kgsl_pwr_limits_get_freq(enum kgsl_deviceid id) return freq; } EXPORT_SYMBOL(kgsl_pwr_limits_get_freq); + +/** + * kgsl_pwrctrl_set_default_gpu_pwrlevel() - Set GPU to default power level + * @device: Pointer to the kgsl_device struct + */ +void kgsl_pwrctrl_set_default_gpu_pwrlevel(struct kgsl_device *device) +{ + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + unsigned int new_level = pwr->default_pwrlevel; + unsigned int old_level = pwr->active_pwrlevel; + + /* + * Update the level according to any thermal, + * max/min, or power constraints. + */ + new_level = kgsl_pwrctrl_adjust_pwrlevel(device, new_level); + + /* + * If thermal cycling is required and the new level hits the + * thermal limit, kick off the cycling. + */ + kgsl_pwrctrl_set_thermal_cycle(device, new_level); + + pwr->active_pwrlevel = new_level; + pwr->previous_pwrlevel = old_level; + + /* Request adjusted DCVS level */ + kgsl_clk_set_rate(device, pwr->active_pwrlevel); +} diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index d3b9c9ccb001..1800d14c389d 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -273,4 +273,5 @@ void kgsl_pwrctrl_set_constraint(struct kgsl_device *device, struct kgsl_pwr_constraint *pwrc, uint32_t id); void kgsl_pwrctrl_update_l2pc(struct kgsl_device *device, unsigned long timeout_us); +void kgsl_pwrctrl_set_default_gpu_pwrlevel(struct kgsl_device *device); #endif /* __KGSL_PWRCTRL_H */ -- GitLab From 0beb76611ede44084dc658654254f722eb60321d Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Thu, 7 Jun 2018 13:40:14 +0530 Subject: [PATCH 0052/1299] ARM: dts: msm: Remove adsp ion heap 22 for SM6150 Remove adsp ion heap 22 as complete adsp heap is reserved to adsp remote heap. Change-Id: I8e6e506b78b8ef68d9c9914775690a36ff2ada0e Acked-by: Himateja Reddy Signed-off-by: Tharun Kumar Merugu --- arch/arm64/boot/dts/qcom/sm6150-ion.dtsi | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm6150-ion.dtsi b/arch/arm64/boot/dts/qcom/sm6150-ion.dtsi index a8bfab8603ec..f89f20ef5c37 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-ion.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-ion.dtsi @@ -21,12 +21,6 @@ qcom,ion-heap-type = "SYSTEM"; }; - qcom,ion-heap@22 { /* ADSP HEAP */ - reg = <22>; - memory-region = <&adsp_mem>; - qcom,ion-heap-type = "DMA"; - }; - qcom,ion-heap@27 { /* QSEECOM HEAP */ reg = <27>; memory-region = <&qseecom_mem>; -- GitLab From fb625d18e697bd746f313a67839889741253dbb6 Mon Sep 17 00:00:00 2001 From: Narender Ankam Date: Fri, 8 Jun 2018 18:33:36 +0530 Subject: [PATCH 0053/1299] msm: mdss: select dss io utility as per supported display subsystem msm-4.14 kernel supports only upstream pll clk driver and either of DRM or FBDEV display subsystems. Select dss io utility as per target's supported DRM or FBDEV display subsystem. Change-Id: Ib90d6990b29bcd06e387a4f7710084012b24e4d8 Signed-off-by: Narender Ankam --- drivers/clk/qcom/mdss/mdss-pll.h | 7 +- drivers/video/fbdev/msm/dsi_host_v2.c | 10 +- drivers/video/fbdev/msm/dsi_io_v2.c | 8 +- drivers/video/fbdev/msm/dsi_io_v2.h | 4 +- drivers/video/fbdev/msm/dsi_v2.c | 6 +- drivers/video/fbdev/msm/mdss.h | 20 +-- drivers/video/fbdev/msm/mdss_debug.h | 2 +- drivers/video/fbdev/msm/mdss_dsi.c | 42 +++--- drivers/video/fbdev/msm/mdss_dsi.h | 14 +- drivers/video/fbdev/msm/mdss_hdmi_audio.c | 6 +- drivers/video/fbdev/msm/mdss_hdmi_audio.h | 2 +- drivers/video/fbdev/msm/mdss_hdmi_cec.c | 8 +- drivers/video/fbdev/msm/mdss_hdmi_cec.h | 2 +- drivers/video/fbdev/msm/mdss_hdmi_hdcp.c | 28 ++-- drivers/video/fbdev/msm/mdss_hdmi_hdcp.h | 6 +- drivers/video/fbdev/msm/mdss_hdmi_panel.c | 10 +- drivers/video/fbdev/msm/mdss_hdmi_panel.h | 2 +- drivers/video/fbdev/msm/mdss_hdmi_tx.c | 120 +++++++++--------- drivers/video/fbdev/msm/mdss_hdmi_tx.h | 4 +- drivers/video/fbdev/msm/mdss_hdmi_util.c | 8 +- drivers/video/fbdev/msm/mdss_hdmi_util.h | 2 +- drivers/video/fbdev/msm/mdss_io_util.c | 96 +++++++------- drivers/video/fbdev/msm/mdss_mdp.c | 8 +- drivers/video/fbdev/msm/mdss_rotator.c | 12 +- .../video/fbdev/msm/mdss_rotator_internal.h | 2 +- drivers/video/fbdev/msm/mdss_smmu.c | 32 ++--- drivers/video/fbdev/msm/mhl_sii8334.c | 14 +- drivers/video/fbdev/msm/msm_dba/adv7533.c | 18 +-- drivers/video/fbdev/msm/msm_mdss_io_8974.c | 4 +- include/linux/mdss_io_util.h | 70 +++++----- 30 files changed, 287 insertions(+), 280 deletions(-) diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h index 2c27ddaa1a31..9652176bd953 100644 --- a/drivers/clk/qcom/mdss/mdss-pll.h +++ b/drivers/clk/qcom/mdss/mdss-pll.h @@ -12,7 +12,7 @@ #ifndef __MDSS_PLL_H #define __MDSS_PLL_H -#include + #include #include #include @@ -22,6 +22,11 @@ #include "../clk-regmap-divider.h" #include "../clk-regmap-mux.h" +#if defined(CONFIG_DRM) +#include +#else +#include +#endif #define MDSS_PLL_REG_W(base, offset, data) \ writel_relaxed((data), (base) + (offset)) diff --git a/drivers/video/fbdev/msm/dsi_host_v2.c b/drivers/video/fbdev/msm/dsi_host_v2.c index 58927a6d26c6..61ce052a365e 100644 --- a/drivers/video/fbdev/msm/dsi_host_v2.c +++ b/drivers/video/fbdev/msm/dsi_host_v2.c @@ -1114,7 +1114,7 @@ static int msm_dsi_on(struct mdss_panel_data *pdata) if (!pdata->panel_info.dynamic_switch_pending) { for (i = 0; !ret && (i < DSI_MAX_PM); i++) { - ret = msm_mdss_enable_vreg( + ret = msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 1); if (ret) { @@ -1215,7 +1215,7 @@ static int msm_dsi_on(struct mdss_panel_data *pdata) error_vreg: if (ret) { for (; i >= 0; i--) - msm_mdss_enable_vreg( + msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 0); } @@ -1250,7 +1250,7 @@ static int msm_dsi_off(struct mdss_panel_data *pdata) if (!pdata->panel_info.dynamic_switch_pending) { for (i = DSI_MAX_PM - 1; i >= 0; i--) { - ret = msm_mdss_enable_vreg( + ret = msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 0); if (ret) @@ -1287,7 +1287,7 @@ static int msm_dsi_cont_on(struct mdss_panel_data *pdata) pinfo = &pdata->panel_info; mutex_lock(&ctrl_pdata->mutex); for (i = 0; !ret && (i < DSI_MAX_PM); i++) { - ret = msm_mdss_enable_vreg( + ret = msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 1); if (ret) { @@ -1314,7 +1314,7 @@ static int msm_dsi_cont_on(struct mdss_panel_data *pdata) error_vreg: if (ret) { for (; i >= 0; i--) - msm_mdss_enable_vreg( + msm_dss_enable_vreg( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, 0); } diff --git a/drivers/video/fbdev/msm/dsi_io_v2.c b/drivers/video/fbdev/msm/dsi_io_v2.c index 71c1d1d7c2a7..a5e36612d570 100644 --- a/drivers/video/fbdev/msm/dsi_io_v2.c +++ b/drivers/video/fbdev/msm/dsi_io_v2.c @@ -50,7 +50,7 @@ void msm_dsi_ahb_ctrl(int enable) } } -int msm_dsi_io_init(struct platform_device *pdev, struct mdss_module_power *mp) +int msm_dsi_io_init(struct platform_device *pdev, struct dss_module_power *mp) { int rc; @@ -67,7 +67,7 @@ int msm_dsi_io_init(struct platform_device *pdev, struct mdss_module_power *mp) return rc; } - rc = msm_mdss_config_vreg(&pdev->dev, mp->vreg_config, + rc = msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, 1); if (rc) { pr_err("fail to initialize DSI regulator\n"); @@ -78,11 +78,11 @@ int msm_dsi_io_init(struct platform_device *pdev, struct mdss_module_power *mp) } void msm_dsi_io_deinit(struct platform_device *pdev, - struct mdss_module_power *mp) + struct dss_module_power *mp) { if (dsi_io_private) { msm_dsi_clk_deinit(); - msm_mdss_config_vreg(&pdev->dev, mp->vreg_config, + msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, 0); kfree(dsi_io_private); dsi_io_private = NULL; diff --git a/drivers/video/fbdev/msm/dsi_io_v2.h b/drivers/video/fbdev/msm/dsi_io_v2.h index d0227ecc7b81..dd9adf90abf3 100644 --- a/drivers/video/fbdev/msm/dsi_io_v2.h +++ b/drivers/video/fbdev/msm/dsi_io_v2.h @@ -18,10 +18,10 @@ void msm_dsi_ahb_ctrl(int enable); int msm_dsi_io_init(struct platform_device *dev, - struct mdss_module_power *mp); + struct dss_module_power *mp); void msm_dsi_io_deinit(struct platform_device *dev, - struct mdss_module_power *mp); + struct dss_module_power *mp); int msm_dsi_clk_init(struct platform_device *dev); diff --git a/drivers/video/fbdev/msm/dsi_v2.c b/drivers/video/fbdev/msm/dsi_v2.c index bfd29416cd1b..60c57e45212d 100644 --- a/drivers/video/fbdev/msm/dsi_v2.c +++ b/drivers/video/fbdev/msm/dsi_v2.c @@ -236,7 +236,7 @@ static int dsi_parse_gpio(struct platform_device *pdev, } static void mdss_dsi_put_dt_vreg_data(struct device *dev, - struct mdss_module_power *module_power) + struct dss_module_power *module_power) { if (!module_power) { pr_err("%s: invalid input\n", __func__); @@ -251,7 +251,7 @@ static void mdss_dsi_put_dt_vreg_data(struct device *dev, } static int mdss_dsi_get_dt_vreg_data(struct device *dev, - struct mdss_module_power *mp, enum dsi_pm_type module) + struct dss_module_power *mp, enum dsi_pm_type module) { int i = 0, rc = 0; u32 tmp = 0; @@ -286,7 +286,7 @@ static int mdss_dsi_get_dt_vreg_data(struct device *dev, pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg); } - mp->vreg_config = devm_kzalloc(dev, sizeof(struct mdss_vreg) * + mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * mp->num_vreg, GFP_KERNEL); if (!mp->vreg_config) { rc = -ENOMEM; diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 22844df4882e..d0b5ddfa2851 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -213,7 +213,7 @@ struct reg_bus_client { struct mdss_smmu_client { struct device *dev; struct dma_iommu_mapping *mmu_mapping; - struct mdss_module_power mp; + struct dss_module_power mp; struct reg_bus_client *reg_bus_clt; bool domain_attached; bool handoff_pending; @@ -295,9 +295,9 @@ struct mdss_data_type { unsigned long mdp_clk_rate; struct platform_device *pdev; - struct mdss_io_data mdss_io; - struct mdss_io_data vbif_io; - struct mdss_io_data vbif_nrt_io; + struct dss_io_data mdss_io; + struct dss_io_data vbif_io; + struct dss_io_data vbif_nrt_io; char __iomem *mdp_base; struct mdss_smmu_client mdss_smmu[MDSS_IOMMU_MAX_DOMAIN]; @@ -604,14 +604,14 @@ static inline bool mdss_has_quirk(struct mdss_data_type *mdata, } #define MDSS_VBIF_WRITE(mdata, offset, value, nrt_vbif) \ - (nrt_vbif ? mdss_reg_w(&mdata->vbif_nrt_io, offset, value, 0) :\ - mdss_reg_w(&mdata->vbif_io, offset, value, 0)) + (nrt_vbif ? dss_reg_w(&mdata->vbif_nrt_io, offset, value, 0) :\ + dss_reg_w(&mdata->vbif_io, offset, value, 0)) #define MDSS_VBIF_READ(mdata, offset, nrt_vbif) \ - (nrt_vbif ? mdss_reg_r(&mdata->vbif_nrt_io, offset, 0) :\ - mdss_reg_r(&mdata->vbif_io, offset, 0)) + (nrt_vbif ? dss_reg_r(&mdata->vbif_nrt_io, offset, 0) :\ + dss_reg_r(&mdata->vbif_io, offset, 0)) #define MDSS_REG_WRITE(mdata, offset, value) \ - mdss_reg_w(&mdata->mdss_io, offset, value, 0) + dss_reg_w(&mdata->mdss_io, offset, value, 0) #define MDSS_REG_READ(mdata, offset) \ - mdss_reg_r(&mdata->mdss_io, offset, 0) + dss_reg_r(&mdata->mdss_io, offset, 0) #endif /* MDSS_H */ diff --git a/drivers/video/fbdev/msm/mdss_debug.h b/drivers/video/fbdev/msm/mdss_debug.h index 8858209ad35e..c920418eb977 100644 --- a/drivers/video/fbdev/msm/mdss_debug.h +++ b/drivers/video/fbdev/msm/mdss_debug.h @@ -227,7 +227,7 @@ void mdss_mdp_debug_mid(u32 mid); int mdss_dump_misr_data(char **buf, u32 size); static inline int mdss_debug_register_io(const char *name, - struct mdss_io_data *io_data, struct mdss_debug_base **dbg_blk) + struct dss_io_data *io_data, struct mdss_debug_base **dbg_blk) { return mdss_debug_register_base(name, io_data->base, io_data->len, dbg_blk); diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 47aa2c433fe9..5bb6575bd053 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -253,14 +253,14 @@ static int mdss_dsi_regulator_init(struct platform_device *pdev, } for (i = DSI_CORE_PM; !rc && (i < DSI_MAX_PM); i++) { - rc = msm_mdss_config_vreg(&pdev->dev, + rc = msm_dss_config_vreg(&pdev->dev, sdata->power_data[i].vreg_config, sdata->power_data[i].num_vreg, 1); if (rc) { pr_err("%s: failed to init vregs for %s\n", __func__, __mdss_dsi_pm_name(i)); for (j = i-1; j >= DSI_CORE_PM; j--) { - msm_mdss_config_vreg(&pdev->dev, + msm_dss_config_vreg(&pdev->dev, sdata->power_data[j].vreg_config, sdata->power_data[j].num_vreg, 0); } @@ -293,7 +293,7 @@ static int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) if (mdss_dsi_pinctrl_set_state(ctrl_pdata, false)) pr_debug("reset disable: pinctrl not enabled\n"); - ret = msm_mdss_enable_vreg( + ret = msm_dss_enable_vreg( ctrl_pdata->panel_power_data.vreg_config, ctrl_pdata->panel_power_data.num_vreg, 0); if (ret) @@ -317,7 +317,7 @@ static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata) ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); - ret = msm_mdss_enable_vreg( + ret = msm_dss_enable_vreg( ctrl_pdata->panel_power_data.vreg_config, ctrl_pdata->panel_power_data.num_vreg, 1); if (ret) { @@ -378,11 +378,11 @@ static int mdss_dsi_panel_power_ulp(struct mdss_panel_data *pdata, if (i == DSI_CORE_PM) continue; if (i == DSI_PANEL_PM) - ret = msm_mdss_config_vreg_opt_mode( + ret = msm_dss_config_vreg_opt_mode( ctrl_pdata->panel_power_data.vreg_config, ctrl_pdata->panel_power_data.num_vreg, mode); else - ret = msm_mdss_config_vreg_opt_mode( + ret = msm_dss_config_vreg_opt_mode( sdata->power_data[i].vreg_config, sdata->power_data[i].num_vreg, mode); if (ret) { @@ -395,7 +395,7 @@ static int mdss_dsi_panel_power_ulp(struct mdss_panel_data *pdata, if (ret) { mode = enable ? DSS_REG_MODE_ENABLE : DSS_REG_MODE_ULP; for (; i >= 0; i--) - msm_mdss_config_vreg_opt_mode( + msm_dss_config_vreg_opt_mode( ctrl_pdata->power_data[i].vreg_config, ctrl_pdata->power_data[i].num_vreg, mode); } @@ -478,7 +478,7 @@ int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata, } static void mdss_dsi_put_dt_vreg_data(struct device *dev, - struct mdss_module_power *module_power) + struct dss_module_power *module_power) { if (!module_power) { pr_err("%s: invalid input\n", __func__); @@ -493,7 +493,7 @@ static void mdss_dsi_put_dt_vreg_data(struct device *dev, } static int mdss_dsi_get_dt_vreg_data(struct device *dev, - struct device_node *of_node, struct mdss_module_power *mp, + struct device_node *of_node, struct dss_module_power *mp, enum dsi_pm_type module) { int i = 0, rc = 0; @@ -535,7 +535,7 @@ static int mdss_dsi_get_dt_vreg_data(struct device *dev, pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg); } - mp->vreg_config = devm_kzalloc(dev, sizeof(struct mdss_vreg) * + mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * mp->num_vreg, GFP_KERNEL); if (!mp->vreg_config) { rc = -ENOMEM; @@ -3451,7 +3451,7 @@ static void mdss_dsi_res_deinit(struct platform_device *pdev) goto res_release; for (i = (DSI_MAX_PM - 1); i >= DSI_CORE_PM; i--) { - if (msm_mdss_config_vreg(&pdev->dev, + if (msm_dss_config_vreg(&pdev->dev, sdata->power_data[i].vreg_config, sdata->power_data[i].num_vreg, 1) < 0) pr_err("%s: failed to de-init vregs for %s\n", @@ -3817,7 +3817,7 @@ static int mdss_dsi_ctrl_remove(struct platform_device *pdev) mdss_dsi_pm_qos_remove_request(ctrl_pdata->shared_data); - if (msm_mdss_config_vreg(&pdev->dev, + if (msm_dss_config_vreg(&pdev->dev, ctrl_pdata->panel_power_data.vreg_config, ctrl_pdata->panel_power_data.num_vreg, 1) < 0) pr_err("%s: failed to de-init vregs for %s\n", @@ -3825,9 +3825,9 @@ static int mdss_dsi_ctrl_remove(struct platform_device *pdev) mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->panel_power_data); mfd = platform_get_drvdata(pdev); - msm_mdss_iounmap(&ctrl_pdata->mmss_misc_io); - msm_mdss_iounmap(&ctrl_pdata->phy_io); - msm_mdss_iounmap(&ctrl_pdata->ctrl_io); + msm_dss_iounmap(&ctrl_pdata->mmss_misc_io); + msm_dss_iounmap(&ctrl_pdata->phy_io); + msm_dss_iounmap(&ctrl_pdata->ctrl_io); mdss_dsi_debugfs_cleanup(ctrl_pdata); if (ctrl_pdata->workq) @@ -3870,7 +3870,7 @@ int mdss_dsi_retrieve_ctrl_resources(struct platform_device *pdev, int mode, return -EPERM; } - rc = msm_mdss_ioremap_byname(pdev, &ctrl->ctrl_io, "dsi_ctrl"); + rc = msm_dss_ioremap_byname(pdev, &ctrl->ctrl_io, "dsi_ctrl"); if (rc) { pr_err("%s:%d unable to remap dsi ctrl resources\n", __func__, __LINE__); @@ -3880,14 +3880,14 @@ int mdss_dsi_retrieve_ctrl_resources(struct platform_device *pdev, int mode, ctrl->ctrl_base = ctrl->ctrl_io.base; ctrl->reg_size = ctrl->ctrl_io.len; - rc = msm_mdss_ioremap_byname(pdev, &ctrl->phy_io, "dsi_phy"); + rc = msm_dss_ioremap_byname(pdev, &ctrl->phy_io, "dsi_phy"); if (rc) { pr_err("%s:%d unable to remap dsi phy resources\n", __func__, __LINE__); return rc; } - rc = msm_mdss_ioremap_byname(pdev, &ctrl->phy_regulator_io, + rc = msm_dss_ioremap_byname(pdev, &ctrl->phy_regulator_io, "dsi_phy_regulator"); if (rc) pr_debug("%s:%d unable to remap dsi phy regulator resources\n", @@ -3901,7 +3901,7 @@ int mdss_dsi_retrieve_ctrl_resources(struct platform_device *pdev, int mode, __func__, ctrl->ctrl_base, ctrl->reg_size, ctrl->phy_io.base, ctrl->phy_io.len); - rc = msm_mdss_ioremap_byname(pdev, &ctrl->mmss_misc_io, + rc = msm_dss_ioremap_byname(pdev, &ctrl->mmss_misc_io, "mmss_misc_phys"); if (rc) { pr_debug("%s:%d mmss_misc IO remap failed\n", @@ -4171,7 +4171,7 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, return rc; } - rc = msm_mdss_config_vreg(&ctrl_pdev->dev, + rc = msm_dss_config_vreg(&ctrl_pdev->dev, ctrl_pdata->panel_power_data.vreg_config, ctrl_pdata->panel_power_data.num_vreg, 1); if (rc) { @@ -4253,7 +4253,7 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, sdata = ctrl_pdata->shared_data; if (pinfo->ulps_suspend_enabled) { - rc = msm_mdss_enable_vreg( + rc = msm_dss_enable_vreg( sdata->power_data[DSI_PHY_PM].vreg_config, sdata->power_data[DSI_PHY_PM].num_vreg, 1); if (rc) { diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 058c27a61130..9eb3bc8b87f8 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -272,7 +272,7 @@ struct dsi_shared_data { struct clk *pixel1_parent; /* DSI core regulators */ - struct mdss_module_power power_data[DSI_MAX_PM]; + struct dss_module_power power_data[DSI_MAX_PM]; /* Shared mutex for DSI PHY regulator */ struct mutex phy_reg_lock; @@ -408,10 +408,10 @@ struct mdss_dsi_ctrl_pdata { void (*switch_mode)(struct mdss_panel_data *pdata, int mode); struct mdss_panel_data panel_data; unsigned char *ctrl_base; - struct mdss_io_data ctrl_io; - struct mdss_io_data mmss_misc_io; - struct mdss_io_data phy_io; - struct mdss_io_data phy_regulator_io; + struct dss_io_data ctrl_io; + struct dss_io_data mmss_misc_io; + struct dss_io_data phy_io; + struct dss_io_data phy_regulator_io; int reg_size; u32 flags; struct clk *byte_clk; @@ -460,8 +460,8 @@ struct mdss_dsi_ctrl_pdata { u32 pclk_rate_bkp; u32 byte_clk_rate_bkp; bool refresh_clk_rate; /* flag to recalculate clk_rate */ - struct mdss_module_power panel_power_data; - struct mdss_module_power power_data[DSI_MAX_PM]; /* for 8x10 */ + struct dss_module_power panel_power_data; + struct dss_module_power power_data[DSI_MAX_PM]; /* for 8x10 */ u32 dsi_irq_mask; struct mdss_hw *dsi_hw; struct mdss_intf_recovery *recovery; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_audio.c b/drivers/video/fbdev/msm/mdss_hdmi_audio.c index 446e8b4921b6..0effbcb00a6b 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_audio.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_audio.c @@ -63,7 +63,7 @@ enum hdmi_audio_sample_rates { }; struct hdmi_audio { - struct mdss_io_data *io; + struct dss_io_data *io; struct msm_hdmi_audio_setup_params params; struct extcon_dev sdev; u32 pclk; @@ -143,7 +143,7 @@ static void hdmi_audio_get_acr_param(u32 pclk, u32 fs, static void hdmi_audio_acr_enable(struct hdmi_audio *audio) { - struct mdss_io_data *io; + struct dss_io_data *io; struct hdmi_audio_acr acr; struct msm_hdmi_audio_setup_params *params; u32 pclk, layout, multiplier = 1, sample_rate; @@ -260,7 +260,7 @@ static void hdmi_audio_acr_setup(struct hdmi_audio *audio, bool on) static void hdmi_audio_infoframe_setup(struct hdmi_audio *audio, bool enabled) { - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; u32 channels, channel_allocation, level_shift, down_mix, layout; u32 hdmi_debug_reg = 0, audio_info_0_reg = 0, audio_info_1_reg = 0; u32 audio_info_ctrl_reg, aud_pck_ctrl_2_reg; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_audio.h b/drivers/video/fbdev/msm/mdss_hdmi_audio.h index 2449123922c7..7b33cb8d5954 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_audio.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_audio.h @@ -62,7 +62,7 @@ struct hdmi_audio_ops { * Defines the data needed to be provided while initializing audio module */ struct hdmi_audio_init_data { - struct mdss_io_data *io; + struct dss_io_data *io; struct hdmi_audio_ops *ops; }; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_cec.c b/drivers/video/fbdev/msm/mdss_hdmi_cec.c index f15272e8a5ea..f1be3132b607 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_cec.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_cec.c @@ -52,7 +52,7 @@ static int hdmi_cec_msg_send(void *data, struct cec_msg *msg) u32 frame_retransmit = RETRANSMIT_MAX_NUM; bool frame_type; unsigned long flags; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)data; if (!cec_ctrl || !cec_ctrl->init_data.io || !msg) { @@ -169,7 +169,7 @@ static void hdmi_cec_msg_recv(struct work_struct *work) int i; u32 data; struct hdmi_cec_ctrl *cec_ctrl = NULL; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; struct cec_msg msg; struct cec_cbs *cbs; @@ -262,7 +262,7 @@ int hdmi_cec_isr(void *input) int rc = 0; u32 cec_intr, cec_status; unsigned long flags; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input; if (!cec_ctrl || !cec_ctrl->init_data.io) { @@ -368,7 +368,7 @@ static int hdmi_cec_enable(void *input, bool enable) { int ret = 0; u32 hdmi_hw_version, reg_val; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; struct hdmi_cec_ctrl *cec_ctrl = (struct hdmi_cec_ctrl *)input; struct mdss_panel_info *pinfo; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_cec.h b/drivers/video/fbdev/msm/mdss_hdmi_cec.h index de4bb356c9e1..57a76645e806 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_cec.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_cec.h @@ -30,7 +30,7 @@ */ struct hdmi_cec_init_data { struct workqueue_struct *workq; - struct mdss_io_data *io; + struct dss_io_data *io; struct mdss_panel_info *pinfo; struct cec_cbs *cbs; struct cec_ops *ops; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c index 17b1f60e29a6..0c76ad4e91bf 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c @@ -87,7 +87,7 @@ static void reset_hdcp_ddc_failures(struct hdmi_hdcp_ctrl *hdcp_ctrl) int hdcp_ddc_status; int failure; int nack0; - struct mdss_io_data *io; + struct dss_io_data *io; if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) { DEV_ERR("%s: invalid input\n", __func__); @@ -166,7 +166,7 @@ static void reset_hdcp_ddc_failures(struct hdmi_hdcp_ctrl *hdcp_ctrl) static void hdmi_hdcp_hw_ddc_clean(struct hdmi_hdcp_ctrl *hdcp_ctrl) { - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; u32 hdcp_ddc_status, ddc_hw_status; u32 ddc_xfer_done, ddc_xfer_req; u32 ddc_hw_req, ddc_hw_not_idle; @@ -254,8 +254,8 @@ static int hdmi_hdcp_load_keys(void *input) u32 ksv_lsb_addr, ksv_msb_addr; u32 aksv_lsb, aksv_msb; u8 aksv[5]; - struct mdss_io_data *io; - struct mdss_io_data *qfprom_io; + struct dss_io_data *io; + struct dss_io_data *qfprom_io; struct hdmi_hdcp_ctrl *hdcp_ctrl = input; if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io || @@ -352,8 +352,8 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) u32 link0_an_0, link0_an_1; u32 timeout_count; bool is_match; - struct mdss_io_data *io; - struct mdss_io_data *hdcp_io; + struct dss_io_data *io; + struct dss_io_data *hdcp_io; u8 aksv[5], *bksv = NULL; u8 an[8]; u8 bcaps = 0; @@ -678,7 +678,7 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl) static int read_write_v_h(struct hdmi_hdcp_ctrl *hdcp_ctrl, struct hdmi_tx_ddc_data ddc_data, - struct mdss_io_data *io, int off, char *name, + struct dss_io_data *io, int off, char *name, u32 reg, bool wr) { int rc = 0; @@ -715,7 +715,7 @@ static int hdmi_hdcp_transfer_v_h(struct hdmi_hdcp_ctrl *hdcp_ctrl) int rc = 0; u8 buf[4]; struct hdmi_tx_ddc_data ddc_data; - struct mdss_io_data *io; + struct dss_io_data *io; struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG]; u32 phy_addr; @@ -774,7 +774,7 @@ static int hdmi_hdcp_transfer_v_h(struct hdmi_hdcp_ctrl *hdcp_ctrl) goto error; } } else if (hdcp_ctrl->hdmi_tx_ver_4) { - struct mdss_io_data *hdcp_io = hdcp_ctrl->init_data.hdcp_io; + struct dss_io_data *hdcp_io = hdcp_ctrl->init_data.hdcp_io; /* Read V'.HO 4 Byte at offset 0x20 */ if (read_write_v_h(hdcp_ctrl, ddc_data, hdcp_io, 0x20, "V' H0", @@ -843,7 +843,7 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl) u16 bstatus, max_devs_exceeded = 0, max_cascade_exceeded = 0; u32 link0_status; u32 ksv_bytes; - struct mdss_io_data *io; + struct dss_io_data *io; struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG]; u32 phy_addr; @@ -1247,7 +1247,7 @@ static void hdmi_hdcp_auth_work(struct work_struct *work) struct delayed_work *dw = to_delayed_work(work); struct hdmi_hdcp_ctrl *hdcp_ctrl = container_of(dw, struct hdmi_hdcp_ctrl, hdcp_auth_work); - struct mdss_io_data *io; + struct dss_io_data *io; if (!hdcp_ctrl) { DEV_ERR("%s: invalid input\n", __func__); @@ -1353,7 +1353,7 @@ int hdmi_hdcp_authenticate(void *input) int hdmi_hdcp_reauthenticate(void *input) { struct hdmi_hdcp_ctrl *hdcp_ctrl = (struct hdmi_hdcp_ctrl *)input; - struct mdss_io_data *io; + struct dss_io_data *io; u32 hdmi_hw_version; u32 ret = 0; @@ -1400,7 +1400,7 @@ int hdmi_hdcp_reauthenticate(void *input) void hdmi_hdcp_off(void *input) { struct hdmi_hdcp_ctrl *hdcp_ctrl = (struct hdmi_hdcp_ctrl *)input; - struct mdss_io_data *io; + struct dss_io_data *io; int rc = 0; if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) { @@ -1453,7 +1453,7 @@ int hdmi_hdcp_isr(void *input) { struct hdmi_hdcp_ctrl *hdcp_ctrl = (struct hdmi_hdcp_ctrl *)input; int rc = 0; - struct mdss_io_data *io; + struct dss_io_data *io; u32 hdcp_int_val; if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) { diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h index 2276009133f2..2098943f4dd7 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h @@ -28,9 +28,9 @@ enum hdmi_hdcp_state { }; struct hdmi_hdcp_init_data { - struct mdss_io_data *core_io; - struct mdss_io_data *qfprom_io; - struct mdss_io_data *hdcp_io; + struct dss_io_data *core_io; + struct dss_io_data *qfprom_io; + struct dss_io_data *hdcp_io; struct mutex *mutex; struct kobject *sysfs_kobj; struct workqueue_struct *workq; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.c b/drivers/video/fbdev/msm/mdss_hdmi_panel.c index 3823d3be27f2..9e082b3a0e24 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_panel.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.c @@ -108,7 +108,7 @@ struct hdmi_video_config { }; struct hdmi_panel { - struct mdss_io_data *io; + struct dss_io_data *io; struct hdmi_util_ds_data *ds_data; struct hdmi_panel_data *data; struct hdmi_video_config vid_cfg; @@ -275,7 +275,7 @@ static int hdmi_panel_setup_video(struct hdmi_panel *panel) u32 total_h, start_h, end_h; u32 total_v, start_v, end_v; u32 div = 0; - struct mdss_io_data *io = panel->io; + struct dss_io_data *io = panel->io; struct msm_hdmi_mode_timing_info *timing; timing = panel->vid_cfg.timing; @@ -342,7 +342,7 @@ static void hdmi_panel_set_avi_infoframe(struct hdmi_panel *panel) u8 avi_iframe[AVI_MAX_DATA_BYTES] = {0}; u8 checksum; u32 sum, reg_val; - struct mdss_io_data *io = panel->io; + struct dss_io_data *io = panel->io; struct hdmi_avi_infoframe_config *avi; struct msm_hdmi_mode_timing_info *timing; @@ -477,7 +477,7 @@ static void hdmi_panel_set_vendor_specific_infoframe(void *input) u32 sum, reg_val; u32 hdmi_vic, hdmi_video_format, s3d_struct = 0; struct hdmi_panel *panel = input; - struct mdss_io_data *io = panel->io; + struct dss_io_data *io = panel->io; /* HDMI Spec 1.4a Table 8-10 */ vs_iframe[0] = 0x81; /* type */ @@ -564,7 +564,7 @@ static void hdmi_panel_set_spd_infoframe(struct hdmi_panel *panel) u32 packet_control = 0; u8 *vendor_name = NULL; u8 *product_description = NULL; - struct mdss_io_data *io = panel->io; + struct dss_io_data *io = panel->io; vendor_name = panel->spd_vendor_name; product_description = panel->spd_product_description; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.h b/drivers/video/fbdev/msm/mdss_hdmi_panel.h index 50e168af0d07..4685b4ee7444 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_panel.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.h @@ -73,7 +73,7 @@ struct hdmi_panel_ops { * @version: hardware version of the hdmi tx */ struct hdmi_panel_init_data { - struct mdss_io_data *io; + struct dss_io_data *io; struct hdmi_util_ds_data *ds_data; struct hdmi_panel_data *panel_data; struct hdmi_tx_ddc_ctrl *ddc; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c index 42e2181c22c9..bfb5cd9cb06b 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c @@ -119,23 +119,23 @@ static struct mdss_hw hdmi_tx_hw = { .irq_handler = hdmi_tx_isr, }; -static struct mdss_gpio hpd_gpio_config[] = { +static struct dss_gpio hpd_gpio_config[] = { {0, 1, COMPATIBLE_NAME "-hpd"}, {0, 1, COMPATIBLE_NAME "-mux-en"}, {0, 0, COMPATIBLE_NAME "-mux-sel"}, {0, 1, COMPATIBLE_NAME "-mux-lpm"} }; -static struct mdss_gpio ddc_gpio_config[] = { +static struct dss_gpio ddc_gpio_config[] = { {0, 1, COMPATIBLE_NAME "-ddc-mux-sel"}, {0, 1, COMPATIBLE_NAME "-ddc-clk"}, {0, 1, COMPATIBLE_NAME "-ddc-data"} }; -static struct mdss_gpio core_gpio_config[] = { +static struct dss_gpio core_gpio_config[] = { }; -static struct mdss_gpio cec_gpio_config[] = { +static struct dss_gpio cec_gpio_config[] = { {0, 1, COMPATIBLE_NAME "-cec"} }; @@ -154,7 +154,7 @@ static int hdmi_tx_get_version(struct hdmi_tx_ctrl *hdmi_ctrl) { int rc; int reg_val; - struct mdss_io_data *io; + struct dss_io_data *io; rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, true); if (rc) { @@ -394,7 +394,7 @@ static void hdmi_tx_wait_for_audio_engine(struct hdmi_tx_ctrl *hdmi_ctrl) { u64 status = 0; u32 wait_for_vote = 50; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); @@ -485,7 +485,7 @@ EXPORT_SYMBOL(hdmi_get_featuredata_from_sysfs_dev); static int hdmi_tx_config_5v(struct hdmi_tx_ctrl *hdmi_ctrl, bool enable) { - struct mdss_module_power *pd = NULL; + struct dss_module_power *pd = NULL; int ret = 0; if (!hdmi_ctrl) { @@ -646,7 +646,7 @@ static ssize_t hdmi_tx_sysfs_wta_audio_cb(struct device *dev, static int hdmi_tx_update_pixel_clk(struct hdmi_tx_ctrl *hdmi_ctrl) { - struct mdss_module_power *power_data = NULL; + struct dss_module_power *power_data = NULL; struct mdss_panel_info *pinfo; int rc = 0; @@ -677,7 +677,7 @@ static int hdmi_tx_update_pixel_clk(struct hdmi_tx_ctrl *hdmi_ctrl) DEV_DBG("%s: rate %ld\n", __func__, power_data->clk_config->rate); - msm_mdss_clk_set_rate(power_data->clk_config, power_data->num_clk); + msm_dss_clk_set_rate(power_data->clk_config, power_data->num_clk); end: return rc; } @@ -738,7 +738,7 @@ static ssize_t hdmi_tx_sysfs_wta_sim_mode(struct device *dev, { int sim_mode, rc; struct hdmi_tx_ctrl *hdmi_ctrl = NULL; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev); @@ -1224,7 +1224,7 @@ static ssize_t hdmi_tx_sysfs_wta_5v(struct device *dev, { int read, ret; struct hdmi_tx_ctrl *hdmi_ctrl = NULL; - struct mdss_module_power *pd = NULL; + struct dss_module_power *pd = NULL; hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev); if (!hdmi_ctrl) { @@ -1335,7 +1335,7 @@ static void hdmi_tx_sysfs_remove(struct hdmi_tx_ctrl *hdmi_ctrl) static int hdmi_tx_config_avmute(struct hdmi_tx_ctrl *hdmi_ctrl, bool set) { - struct mdss_io_data *io; + struct dss_io_data *io; u32 av_mute_status; bool av_pkt_en = false; @@ -1376,7 +1376,7 @@ static int hdmi_tx_config_avmute(struct hdmi_tx_ctrl *hdmi_ctrl, bool set) static bool hdmi_tx_is_encryption_set(struct hdmi_tx_ctrl *hdmi_ctrl) { - struct mdss_io_data *io; + struct dss_io_data *io; bool enc_en = true; u32 reg_val; @@ -1962,7 +1962,7 @@ static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl, static inline u32 hdmi_tx_is_controller_on(struct hdmi_tx_ctrl *hdmi_ctrl) { - struct mdss_io_data *io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO]; + struct dss_io_data *io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO]; return DSS_REG_R_ND(io, HDMI_CTRL) & BIT(0); } /* hdmi_tx_is_controller_on */ @@ -2098,7 +2098,7 @@ static void hdmi_tx_update_hdcp_info(struct hdmi_tx_ctrl *hdmi_ctrl) static void hdmi_tx_hpd_int_work(struct work_struct *work) { struct hdmi_tx_ctrl *hdmi_ctrl = NULL; - struct mdss_io_data *io; + struct dss_io_data *io; int rc = -EINVAL; int retry = MAX_EDID_READ_RETRY; @@ -2151,7 +2151,7 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work) static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl) { u32 hdmi_disabled, hdcp_disabled, reg_val; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; int ret = 0; if (!hdmi_ctrl) { @@ -2210,7 +2210,7 @@ static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl) static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on) { - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; /* Defaults: Disable block, HDMI mode */ u32 reg_val = BIT(1); @@ -2262,7 +2262,7 @@ static int hdmi_tx_pinctrl_set_state(struct hdmi_tx_ctrl *hdmi_ctrl, { struct pinctrl_state *pin_state = NULL; int rc = -EFAULT; - struct mdss_module_power *power_data = NULL; + struct dss_module_power *power_data = NULL; u64 cur_pin_states; if (!hdmi_ctrl) { @@ -2359,7 +2359,7 @@ static int hdmi_tx_config_power(struct hdmi_tx_ctrl *hdmi_ctrl, enum hdmi_tx_power_module_type module, int config) { int rc = 0; - struct mdss_module_power *power_data = NULL; + struct dss_module_power *power_data = NULL; char name[MAX_CLIENT_NAME_LEN]; if (!hdmi_ctrl || module >= HDMI_TX_MAX_PM) { @@ -2376,7 +2376,7 @@ static int hdmi_tx_config_power(struct hdmi_tx_ctrl *hdmi_ctrl, } if (config) { - rc = msm_mdss_config_vreg(&hdmi_ctrl->pdev->dev, + rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev, power_data->vreg_config, power_data->num_vreg, 1); if (rc) { DEV_ERR("%s: Failed to config %s vreg. Err=%d\n", @@ -2389,13 +2389,13 @@ static int hdmi_tx_config_power(struct hdmi_tx_ctrl *hdmi_ctrl, mdss_reg_bus_vote_client_create(name); if (IS_ERR(hdmi_ctrl->pdata.reg_bus_clt[module])) { pr_err("reg bus client create failed\n"); - msm_mdss_config_vreg(&hdmi_ctrl->pdev->dev, + msm_dss_config_vreg(&hdmi_ctrl->pdev->dev, power_data->vreg_config, power_data->num_vreg, 0); rc = PTR_ERR(hdmi_ctrl->pdata.reg_bus_clt[module]); goto exit; } - rc = msm_mdss_get_clk(&hdmi_ctrl->pdev->dev, + rc = msm_dss_get_clk(&hdmi_ctrl->pdev->dev, power_data->clk_config, power_data->num_clk); if (rc) { DEV_ERR("%s: Failed to get %s clk. Err=%d\n", @@ -2404,16 +2404,16 @@ static int hdmi_tx_config_power(struct hdmi_tx_ctrl *hdmi_ctrl, mdss_reg_bus_vote_client_destroy( hdmi_ctrl->pdata.reg_bus_clt[module]); hdmi_ctrl->pdata.reg_bus_clt[module] = NULL; - msm_mdss_config_vreg(&hdmi_ctrl->pdev->dev, + msm_dss_config_vreg(&hdmi_ctrl->pdev->dev, power_data->vreg_config, power_data->num_vreg, 0); } } else { - msm_mdss_put_clk(power_data->clk_config, power_data->num_clk); + msm_dss_put_clk(power_data->clk_config, power_data->num_clk); mdss_reg_bus_vote_client_destroy( hdmi_ctrl->pdata.reg_bus_clt[module]); hdmi_ctrl->pdata.reg_bus_clt[module] = NULL; - rc = msm_mdss_config_vreg(&hdmi_ctrl->pdev->dev, + rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev, power_data->vreg_config, power_data->num_vreg, 0); if (rc) DEV_ERR("%s: Fail to deconfig %s vreg. Err=%d\n", @@ -2429,7 +2429,7 @@ static int hdmi_tx_check_clk_state(struct hdmi_tx_ctrl *hdmi_ctrl, { int i; int rc = 0; - struct mdss_module_power *pd = NULL; + struct dss_module_power *pd = NULL; if (!hdmi_ctrl || module >= HDMI_TX_MAX_PM) { DEV_ERR("%s: Error: invalid input\n", __func__); @@ -2475,7 +2475,7 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl, enum hdmi_tx_power_module_type module, int enable) { int rc = 0; - struct mdss_module_power *power_data = NULL; + struct dss_module_power *power_data = NULL; if (!hdmi_ctrl || module >= HDMI_TX_MAX_PM) { DEV_ERR("%s: Error: invalid input\n", __func__); @@ -2497,7 +2497,7 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl, } if (enable && !hdmi_ctrl->power_data_enable[module]) { - rc = msm_mdss_enable_vreg(power_data->vreg_config, + rc = msm_dss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 1); if (rc) { DEV_ERR("%s: Failed to enable %s vreg. Error=%d\n", @@ -2512,7 +2512,7 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl, goto error; } - rc = msm_mdss_enable_gpio(power_data->gpio_config, + rc = msm_dss_enable_gpio(power_data->gpio_config, power_data->num_gpio, 1); if (rc) { DEV_ERR("%s: Failed to enable %s gpio. Error=%d\n", @@ -2522,7 +2522,7 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl, mdss_update_reg_bus_vote(hdmi_ctrl->pdata.reg_bus_clt[module], VOTE_INDEX_LOW); - rc = msm_mdss_clk_set_rate(power_data->clk_config, + rc = msm_dss_clk_set_rate(power_data->clk_config, power_data->num_clk); if (rc) { DEV_ERR("%s: failed to set clks rate for %s. err=%d\n", @@ -2530,7 +2530,7 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl, goto disable_gpio; } - rc = msm_mdss_enable_clk(power_data->clk_config, + rc = msm_dss_enable_clk(power_data->clk_config, power_data->num_clk, 1); if (rc) { DEV_ERR("%s: Failed to enable clks for %s. Error=%d\n", @@ -2541,14 +2541,14 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl, } else if (!enable && hdmi_ctrl->power_data_enable[module] && (!hdmi_tx_is_cec_wakeup_en(hdmi_ctrl) || ((module != HDMI_TX_HPD_PM) && (module != HDMI_TX_CEC_PM)))) { - msm_mdss_enable_clk(power_data->clk_config, + msm_dss_enable_clk(power_data->clk_config, power_data->num_clk, 0); mdss_update_reg_bus_vote(hdmi_ctrl->pdata.reg_bus_clt[module], VOTE_INDEX_DISABLE); - msm_mdss_enable_gpio(power_data->gpio_config, + msm_dss_enable_gpio(power_data->gpio_config, power_data->num_gpio, 0); hdmi_tx_pinctrl_set_state(hdmi_ctrl, module, 0); - msm_mdss_enable_vreg(power_data->vreg_config, + msm_dss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 0); hdmi_ctrl->power_data_enable[module] = false; } @@ -2558,9 +2558,9 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl, disable_gpio: mdss_update_reg_bus_vote(hdmi_ctrl->pdata.reg_bus_clt[module], VOTE_INDEX_DISABLE); - msm_mdss_enable_gpio(power_data->gpio_config, power_data->num_gpio, 0); + msm_dss_enable_gpio(power_data->gpio_config, power_data->num_gpio, 0); disable_vreg: - msm_mdss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 0); + msm_dss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 0); error: return rc; } /* hdmi_tx_enable_power */ @@ -2609,7 +2609,7 @@ static void hdmi_tx_phy_reset(struct hdmi_tx_ctrl *hdmi_ctrl) unsigned int phy_reset_polarity = 0x0; unsigned int pll_reset_polarity = 0x0; unsigned int val; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); @@ -2867,7 +2867,7 @@ static inline bool hdmi_tx_hw_is_cable_connected(struct hdmi_tx_ctrl *hdmi_ctrl) static void hdmi_tx_hpd_polarity_setup(struct hdmi_tx_ctrl *hdmi_ctrl, bool polarity) { - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; bool cable_sense; if (!hdmi_ctrl) { @@ -2915,7 +2915,7 @@ static inline void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl) static int hdmi_tx_power_off(struct hdmi_tx_ctrl *hdmi_ctrl) { - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; void *pdata = NULL; if (!hdmi_ctrl) { @@ -3043,7 +3043,7 @@ static int hdmi_tx_power_on(struct hdmi_tx_ctrl *hdmi_ctrl) static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl) { int rc = 0; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; unsigned long flags; if (!hdmi_ctrl) { @@ -3093,7 +3093,7 @@ static int hdmi_tx_hpd_on(struct hdmi_tx_ctrl *hdmi_ctrl) { u32 reg_val; int rc = 0; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); @@ -3116,7 +3116,7 @@ static int hdmi_tx_hpd_on(struct hdmi_tx_ctrl *hdmi_ctrl) return rc; } - mdss_reg_dump(io->base, io->len, "HDMI-INIT: ", REG_DUMP); + dss_reg_dump(io->base, io->len, "HDMI-INIT: ", REG_DUMP); if (!hdmi_ctrl->panel_data.panel_info.cont_splash_enabled) { hdmi_tx_set_mode(hdmi_ctrl, false); @@ -3215,7 +3215,7 @@ static int hdmi_tx_set_mhl_hpd(struct platform_device *pdev, uint8_t on) static irqreturn_t hdmi_tx_isr(int irq, void *data) { - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)data; unsigned long flags; u32 hpd_current_state; @@ -3856,7 +3856,7 @@ static void hdmi_tx_deinit_resource(struct hdmi_tx_ctrl *hdmi_ctrl) /* IO */ for (i = HDMI_TX_MAX_IO - 1; i >= 0; i--) { if (hdmi_ctrl->pdata.io[i].base) - msm_mdss_iounmap(&hdmi_ctrl->pdata.io[i]); + msm_dss_iounmap(&hdmi_ctrl->pdata.io[i]); } } /* hdmi_tx_deinit_resource */ @@ -3876,7 +3876,7 @@ static int hdmi_tx_init_resource(struct hdmi_tx_ctrl *hdmi_ctrl) /* IO */ for (i = 0; i < HDMI_TX_MAX_IO; i++) { - rc = msm_mdss_ioremap_byname(hdmi_ctrl->pdev, &pdata->io[i], + rc = msm_dss_ioremap_byname(hdmi_ctrl->pdev, &pdata->io[i], hdmi_tx_io_name(i)); if (rc) { DEV_DBG("%s: '%s' remap failed or not available\n", @@ -3905,7 +3905,7 @@ static int hdmi_tx_init_resource(struct hdmi_tx_ctrl *hdmi_ctrl) } /* hdmi_tx_init_resource */ static void hdmi_tx_put_dt_clk_data(struct device *dev, - struct mdss_module_power *module_power) + struct dss_module_power *module_power) { if (!module_power) { DEV_ERR("%s: invalid input\n", __func__); @@ -3921,7 +3921,7 @@ static void hdmi_tx_put_dt_clk_data(struct device *dev, /* todo: once clk are moved to device tree then change this implementation */ static int hdmi_tx_get_dt_clk_data(struct device *dev, - struct mdss_module_power *mp, u32 module_type) + struct dss_module_power *mp, u32 module_type) { int rc = 0; @@ -3935,7 +3935,7 @@ static int hdmi_tx_get_dt_clk_data(struct device *dev, switch (module_type) { case HDMI_TX_HPD_PM: mp->num_clk = 4; - mp->clk_config = devm_kzalloc(dev, sizeof(struct mdss_clk) * + mp->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) * mp->num_clk, GFP_KERNEL); if (!mp->clk_config) { DEV_ERR("%s: can't alloc '%s' clk mem\n", __func__, @@ -3968,7 +3968,7 @@ static int hdmi_tx_get_dt_clk_data(struct device *dev, case HDMI_TX_CORE_PM: mp->num_clk = 1; - mp->clk_config = devm_kzalloc(dev, sizeof(struct mdss_clk) * + mp->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) * mp->num_clk, GFP_KERNEL); if (!mp->clk_config) { DEV_ERR("%s: can't alloc '%s' clk mem\n", __func__, @@ -4007,7 +4007,7 @@ static int hdmi_tx_get_dt_clk_data(struct device *dev, } /* hdmi_tx_get_dt_clk_data */ static void hdmi_tx_put_dt_vreg_data(struct device *dev, - struct mdss_module_power *module_power) + struct dss_module_power *module_power) { if (!module_power) { DEV_ERR("%s: invalid input\n", __func__); @@ -4022,7 +4022,7 @@ static void hdmi_tx_put_dt_vreg_data(struct device *dev, } /* hdmi_tx_put_dt_vreg_data */ static int hdmi_tx_get_dt_vreg_data(struct device *dev, - struct mdss_module_power *mp, u32 module_type) + struct dss_module_power *mp, u32 module_type) { int i, j, rc = 0; int dt_vreg_total = 0, mod_vreg_total = 0; @@ -4087,7 +4087,7 @@ static int hdmi_tx_get_dt_vreg_data(struct device *dev, if (mod_vreg_total > 0) { mp->num_vreg = mod_vreg_total; - mp->vreg_config = devm_kzalloc(dev, sizeof(struct mdss_vreg) * + mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * mod_vreg_total, GFP_KERNEL); if (!mp->vreg_config) { DEV_ERR("%s: can't alloc '%s' vreg mem\n", __func__, @@ -4200,7 +4200,7 @@ static int hdmi_tx_get_dt_vreg_data(struct device *dev, } /* hdmi_tx_get_dt_vreg_data */ static void hdmi_tx_put_dt_gpio_data(struct device *dev, - struct mdss_module_power *module_power) + struct dss_module_power *module_power) { if (!module_power) { DEV_ERR("%s: invalid input\n", __func__); @@ -4215,11 +4215,11 @@ static void hdmi_tx_put_dt_gpio_data(struct device *dev, } /* hdmi_tx_put_dt_gpio_data */ static int hdmi_tx_get_dt_gpio_data(struct device *dev, - struct mdss_module_power *mp, u32 module_type) + struct dss_module_power *mp, u32 module_type) { int i, j; int mp_gpio_cnt = 0, gpio_list_size = 0; - struct mdss_gpio *gpio_list = NULL; + struct dss_gpio *gpio_list = NULL; struct device_node *of_node = NULL; DEV_DBG("%s: module: '%s'\n", __func__, hdmi_tx_pm_name(module_type)); @@ -4266,7 +4266,7 @@ static int hdmi_tx_get_dt_gpio_data(struct device *dev, DEV_DBG("%s: mp_gpio_cnt = %d\n", __func__, mp_gpio_cnt); mp->num_gpio = mp_gpio_cnt; - mp->gpio_config = devm_kzalloc(dev, sizeof(struct mdss_gpio) * + mp->gpio_config = devm_kzalloc(dev, sizeof(struct dss_gpio) * mp_gpio_cnt, GFP_KERNEL); if (!mp->gpio_config) { DEV_ERR("%s: can't alloc '%s' gpio mem\n", __func__, @@ -4285,7 +4285,7 @@ static int hdmi_tx_get_dt_gpio_data(struct device *dev, continue; } memcpy(&mp->gpio_config[j], &gpio_list[i], - sizeof(struct mdss_gpio)); + sizeof(struct dss_gpio)); mp->gpio_config[j].gpio = (unsigned int)gpio; @@ -4533,17 +4533,17 @@ static int hdmi_tx_probe(struct platform_device *pdev) if (hdmi_ctrl->panel_data.panel_info.cont_splash_enabled) { for (i = 0; i < HDMI_TX_MAX_PM; i++) { - msm_mdss_enable_vreg( + msm_dss_enable_vreg( hdmi_ctrl->pdata.power_data[i].vreg_config, hdmi_ctrl->pdata.power_data[i].num_vreg, 1); hdmi_tx_pinctrl_set_state(hdmi_ctrl, i, 1); - msm_mdss_enable_gpio( + msm_dss_enable_gpio( hdmi_ctrl->pdata.power_data[i].gpio_config, hdmi_ctrl->pdata.power_data[i].num_gpio, 1); - msm_mdss_enable_clk( + msm_dss_enable_clk( hdmi_ctrl->pdata.power_data[i].clk_config, hdmi_ctrl->pdata.power_data[i].num_clk, 1); diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.h b/drivers/video/fbdev/msm/mdss_hdmi_tx.h index 6a13c7529580..d09ca3c1b958 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.h @@ -41,8 +41,8 @@ struct hdmi_tx_platform_data { bool primary; bool cont_splash_enabled; bool cond_power_on; - struct mdss_io_data io[HDMI_TX_MAX_IO]; - struct mdss_module_power power_data[HDMI_TX_MAX_PM]; + struct dss_io_data io[HDMI_TX_MAX_IO]; + struct dss_module_power power_data[HDMI_TX_MAX_PM]; struct reg_bus_client *reg_bus_clt[HDMI_TX_MAX_PM]; /* bitfield representing each module's pin state */ u64 pin_states; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.c b/drivers/video/fbdev/msm/mdss_hdmi_util.c index 834cc6ffce9b..734b3dab36b6 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.c @@ -186,7 +186,7 @@ static int hdmi_scrambler_status_timer_setup(struct hdmi_tx_ddc_ctrl *ctrl, { u32 reg_val; int rc; - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; if (!ctrl || !ctrl->io) { pr_err("invalid input\n"); @@ -655,7 +655,7 @@ static void hdmi_ddc_trigger(struct hdmi_tx_ddc_ctrl *ddc_ctrl, enum trigger_mode mode, bool seg) { struct hdmi_tx_ddc_data *ddc_data = &ddc_ctrl->ddc_data; - struct mdss_io_data *io = ddc_ctrl->io; + struct dss_io_data *io = ddc_ctrl->io; u32 const seg_addr = 0x60, seg_num = 0x01; u32 ddc_ctrl_reg_val; @@ -886,7 +886,7 @@ static void hdmi_hdcp2p2_ddc_clear_status(struct hdmi_tx_ddc_ctrl *ctrl) static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) { - struct mdss_io_data *io = NULL; + struct dss_io_data *io = NULL; struct hdmi_tx_hdcp2p2_ddc_data *data; u32 intr0, intr2, intr5; u32 msg_size; @@ -1022,7 +1022,7 @@ static int hdmi_ddc_hdcp2p2_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) static int hdmi_ddc_scrambling_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl) { - struct mdss_io_data *io; + struct dss_io_data *io; bool scrambler_timer_off = false; u32 intr2, intr5; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.h b/drivers/video/fbdev/msm/mdss_hdmi_util.h index ecab9d5f6702..d26be9997a7c 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.h @@ -447,7 +447,7 @@ struct hdmi_tx_ddc_ctrl { atomic_t write_busy_wait_done; atomic_t read_busy_wait_done; atomic_t rxstatus_busy_wait_done; - struct mdss_io_data *io; + struct dss_io_data *io; struct completion ddc_sw_done; struct hdmi_tx_ddc_data ddc_data; struct hdmi_tx_hdcp2p2_ddc_data hdcp2p2_ddc_data; diff --git a/drivers/video/fbdev/msm/mdss_io_util.c b/drivers/video/fbdev/msm/mdss_io_util.c index 311779347e08..5d344bdd8222 100644 --- a/drivers/video/fbdev/msm/mdss_io_util.c +++ b/drivers/video/fbdev/msm/mdss_io_util.c @@ -17,7 +17,7 @@ #include #define MAX_I2C_CMDS 16 -void mdss_reg_w(struct mdss_io_data *io, u32 offset, u32 value, u32 debug) +void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug) { u32 in_val; @@ -41,10 +41,10 @@ void mdss_reg_w(struct mdss_io_data *io, u32 offset, u32 value, u32 debug) value, in_val); } -} /* mdss_reg_w */ -EXPORT_SYMBOL(mdss_reg_w); +} /* dss_reg_w */ +EXPORT_SYMBOL(dss_reg_w); -u32 mdss_reg_r(struct mdss_io_data *io, u32 offset, u32 debug) +u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug) { u32 value; @@ -66,17 +66,17 @@ u32 mdss_reg_r(struct mdss_io_data *io, u32 offset, u32 debug) (u32)(unsigned long)(io->base + offset), value); return value; -} /* mdss_reg_r */ -EXPORT_SYMBOL(mdss_reg_r); +} /* dss_reg_r */ +EXPORT_SYMBOL(dss_reg_r); -void mdss_reg_dump(void __iomem *base, u32 length, const char *prefix, +void dss_reg_dump(void __iomem *base, u32 length, const char *prefix, u32 debug) { if (debug) print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 32, 4, (void *)base, length, false); -} /* mdss_reg_dump */ -EXPORT_SYMBOL(mdss_reg_dump); +} /* dss_reg_dump */ +EXPORT_SYMBOL(dss_reg_dump); static struct resource *msm_mdss_get_res_byname(struct platform_device *pdev, unsigned int type, const char *name) @@ -91,8 +91,8 @@ static struct resource *msm_mdss_get_res_byname(struct platform_device *pdev, } /* msm_mdss_get_res_byname */ EXPORT_SYMBOL(msm_mdss_get_res_byname); -int msm_mdss_ioremap_byname(struct platform_device *pdev, - struct mdss_io_data *io_data, const char *name) +int msm_dss_ioremap_byname(struct platform_device *pdev, + struct dss_io_data *io_data, const char *name) { struct resource *res = NULL; @@ -118,10 +118,10 @@ int msm_mdss_ioremap_byname(struct platform_device *pdev, } return 0; -} /* msm_mdss_ioremap_byname */ -EXPORT_SYMBOL(msm_mdss_ioremap_byname); +} /* msm_dss_ioremap_byname */ +EXPORT_SYMBOL(msm_dss_ioremap_byname); -void msm_mdss_iounmap(struct mdss_io_data *io_data) +void msm_dss_iounmap(struct dss_io_data *io_data) { if (!io_data) { DEV_ERR("%pS->%s: invalid input\n", @@ -134,15 +134,15 @@ void msm_mdss_iounmap(struct mdss_io_data *io_data) io_data->base = NULL; } io_data->len = 0; -} /* msm_mdss_iounmap */ -EXPORT_SYMBOL(msm_mdss_iounmap); +} /* msm_dss_iounmap */ +EXPORT_SYMBOL(msm_dss_iounmap); -int msm_mdss_config_vreg(struct device *dev, struct mdss_vreg *in_vreg, +int msm_dss_config_vreg(struct device *dev, struct dss_vreg *in_vreg, int num_vreg, int config) { int i = 0, rc = 0; - struct mdss_vreg *curr_vreg = NULL; - enum mdss_vreg_type type; + struct dss_vreg *curr_vreg = NULL; + enum dss_vreg_type type; if (!in_vreg || !num_vreg) return rc; @@ -210,11 +210,11 @@ if (type == DSS_REG_LDO) goto vreg_unconfig; } return rc; -} /* msm_mdss_config_vreg */ -EXPORT_SYMBOL(msm_mdss_config_vreg); +} /* msm_dss_config_vreg */ +EXPORT_SYMBOL(msm_dss_config_vreg); -int msm_mdss_config_vreg_opt_mode(struct mdss_vreg *in_vreg, int num_vreg, - enum mdss_vreg_mode mode) +int msm_dss_config_vreg_opt_mode(struct dss_vreg *in_vreg, int num_vreg, + enum dss_vreg_mode mode) { int i = 0, rc = 0; @@ -257,9 +257,9 @@ int msm_mdss_config_vreg_opt_mode(struct mdss_vreg *in_vreg, int num_vreg, error: return rc; } -EXPORT_SYMBOL(msm_mdss_config_vreg_opt_mode); +EXPORT_SYMBOL(msm_dss_config_vreg_opt_mode); -int msm_mdss_enable_vreg(struct mdss_vreg *in_vreg, int num_vreg, int enable) +int msm_dss_enable_vreg(struct dss_vreg *in_vreg, int num_vreg, int enable) { int i = 0, rc = 0; bool need_sleep; @@ -332,10 +332,10 @@ int msm_mdss_enable_vreg(struct mdss_vreg *in_vreg, int num_vreg, int enable) } return rc; -} /* msm_mdss_enable_vreg */ -EXPORT_SYMBOL(msm_mdss_enable_vreg); +} /* msm_dss_enable_vreg */ +EXPORT_SYMBOL(msm_dss_enable_vreg); -int msm_mdss_enable_gpio(struct mdss_gpio *in_gpio, int num_gpio, int enable) +int msm_dss_enable_gpio(struct dss_gpio *in_gpio, int num_gpio, int enable) { int i = 0, rc = 0; @@ -372,10 +372,10 @@ int msm_mdss_enable_gpio(struct mdss_gpio *in_gpio, int num_gpio, int enable) gpio_free(in_gpio[i].gpio); return rc; -} /* msm_mdss_enable_gpio */ -EXPORT_SYMBOL(msm_mdss_enable_gpio); +} /* msm_dss_enable_gpio */ +EXPORT_SYMBOL(msm_dss_enable_gpio); -void msm_mdss_put_clk(struct mdss_clk *clk_arry, int num_clk) +void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk) { int i; @@ -384,10 +384,10 @@ void msm_mdss_put_clk(struct mdss_clk *clk_arry, int num_clk) clk_put(clk_arry[i].clk); clk_arry[i].clk = NULL; } -} /* msm_mdss_put_clk */ -EXPORT_SYMBOL(msm_mdss_put_clk); +} /* msm_dss_put_clk */ +EXPORT_SYMBOL(msm_dss_put_clk); -int msm_mdss_get_clk(struct device *dev, struct mdss_clk *clk_arry, int num_clk) +int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk) { int i, rc = 0; @@ -405,13 +405,13 @@ int msm_mdss_get_clk(struct device *dev, struct mdss_clk *clk_arry, int num_clk) return rc; error: - msm_mdss_put_clk(clk_arry, num_clk); + msm_dss_put_clk(clk_arry, num_clk); return rc; -} /* msm_mdss_get_clk */ -EXPORT_SYMBOL(msm_mdss_get_clk); +} /* msm_dss_get_clk */ +EXPORT_SYMBOL(msm_dss_get_clk); -int msm_mdss_clk_set_rate(struct mdss_clk *clk_arry, int num_clk) +int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk) { int i, rc = 0; @@ -442,10 +442,10 @@ int msm_mdss_clk_set_rate(struct mdss_clk *clk_arry, int num_clk) } return rc; -} /* msm_mdss_clk_set_rate */ -EXPORT_SYMBOL(msm_mdss_clk_set_rate); +} /* msm_dss_clk_set_rate */ +EXPORT_SYMBOL(msm_dss_clk_set_rate); -int msm_mdss_enable_clk(struct mdss_clk *clk_arry, int num_clk, int enable) +int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable) { int i, rc = 0; @@ -469,7 +469,7 @@ int msm_mdss_enable_clk(struct mdss_clk *clk_arry, int num_clk, int enable) } if (rc) { - msm_mdss_enable_clk(&clk_arry[i], + msm_dss_enable_clk(&clk_arry[i], i, false); break; } @@ -490,11 +490,11 @@ int msm_mdss_enable_clk(struct mdss_clk *clk_arry, int num_clk, int enable) } return rc; -} /* msm_mdss_enable_clk */ -EXPORT_SYMBOL(msm_mdss_enable_clk); +} /* msm_dss_enable_clk */ +EXPORT_SYMBOL(msm_dss_enable_clk); -int mdss_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr, +int dss_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr, uint8_t reg_offset, uint8_t *read_buf) { struct i2c_msg msgs[2]; @@ -521,9 +521,9 @@ int mdss_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr, pr_debug("%s: i2c buf is [%x]\n", __func__, *read_buf); return 0; } -EXPORT_SYMBOL(mdss_i2c_byte_read); +EXPORT_SYMBOL(dss_i2c_byte_read); -int mdss_i2c_byte_write(struct i2c_client *client, uint8_t slave_addr, +int dss_i2c_byte_write(struct i2c_client *client, uint8_t slave_addr, uint8_t reg_offset, uint8_t *value) { struct i2c_msg msgs[1]; @@ -549,4 +549,4 @@ int mdss_i2c_byte_write(struct i2c_client *client, uint8_t slave_addr, pr_debug("%s: I2C write status=%x\n", __func__, status); return status; } -EXPORT_SYMBOL(mdss_i2c_byte_write); +EXPORT_SYMBOL(dss_i2c_byte_write); diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index ad87a5eb425b..993446d8fab9 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -2745,7 +2745,7 @@ static int mdss_mdp_probe(struct platform_device *pdev) mdss_res->mdss_util->panel_intf_type = mdss_panel_intf_type; mdss_res->mdss_util->panel_intf_status = mdss_panel_get_intf_status; - rc = msm_mdss_ioremap_byname(pdev, &mdata->mdss_io, "mdp_phys"); + rc = msm_dss_ioremap_byname(pdev, &mdata->mdss_io, "mdp_phys"); if (rc) { pr_err("unable to map MDP base\n"); goto probe_done; @@ -2754,7 +2754,7 @@ static int mdss_mdp_probe(struct platform_device *pdev) (int) (unsigned long) mdata->mdss_io.base, mdata->mdss_io.len); - rc = msm_mdss_ioremap_byname(pdev, &mdata->vbif_io, "vbif_phys"); + rc = msm_dss_ioremap_byname(pdev, &mdata->vbif_io, "vbif_phys"); if (rc) { pr_err("unable to map MDSS VBIF base\n"); goto probe_done; @@ -2763,7 +2763,7 @@ static int mdss_mdp_probe(struct platform_device *pdev) (int) (unsigned long) mdata->vbif_io.base, mdata->vbif_io.len); - rc = msm_mdss_ioremap_byname(pdev, &mdata->vbif_nrt_io, + rc = msm_dss_ioremap_byname(pdev, &mdata->vbif_nrt_io, "vbif_nrt_phys"); if (rc) pr_debug("unable to map MDSS VBIF non-realtime base\n"); @@ -2965,7 +2965,7 @@ static int mdss_mdp_probe(struct platform_device *pdev) } static void mdss_mdp_parse_dt_regs_array(const u32 *arr, - struct mdss_io_data *io, struct mdss_hw_settings *hws, int count) + struct dss_io_data *io, struct mdss_hw_settings *hws, int count) { u32 len, reg; int i; diff --git a/drivers/video/fbdev/msm/mdss_rotator.c b/drivers/video/fbdev/msm/mdss_rotator.c index 3223e7432e3f..f285d793d520 100644 --- a/drivers/video/fbdev/msm/mdss_rotator.c +++ b/drivers/video/fbdev/msm/mdss_rotator.c @@ -254,7 +254,7 @@ static void mdss_rotator_footswitch_ctrl(struct mdss_rot_mgr *mgr, bool on) } pr_debug("%s: rotator regulators", on ? "Enable" : "Disable"); - ret = msm_mdss_enable_vreg(mgr->module_power.vreg_config, + ret = msm_dss_enable_vreg(mgr->module_power.vreg_config, mgr->module_power.num_vreg, on); if (ret) { pr_warn("Rotator regulator failed to %s\n", @@ -2658,14 +2658,14 @@ static int mdss_rotator_parse_dt(struct mdss_rot_mgr *mgr, } static void mdss_rotator_put_dt_vreg_data(struct device *dev, - struct mdss_module_power *mp) + struct dss_module_power *mp) { if (!mp) { DEV_ERR("%s: invalid input\n", __func__); return; } - msm_mdss_config_vreg(dev, mp->vreg_config, mp->num_vreg, 0); + msm_dss_config_vreg(dev, mp->vreg_config, mp->num_vreg, 0); if (mp->vreg_config) { devm_kfree(dev, mp->vreg_config); mp->vreg_config = NULL; @@ -2674,7 +2674,7 @@ static void mdss_rotator_put_dt_vreg_data(struct device *dev, } static int mdss_rotator_get_dt_vreg_data(struct device *dev, - struct mdss_module_power *mp) + struct dss_module_power *mp) { const char *st = NULL; struct device_node *of_node = NULL; @@ -2696,7 +2696,7 @@ static int mdss_rotator_get_dt_vreg_data(struct device *dev, return 0; } mp->num_vreg = dt_vreg_total; - mp->vreg_config = devm_kzalloc(dev, sizeof(struct mdss_vreg) * + mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * dt_vreg_total, GFP_KERNEL); if (!mp->vreg_config) { DEV_ERR("%s: can't alloc vreg mem\n", __func__); @@ -2714,7 +2714,7 @@ static int mdss_rotator_get_dt_vreg_data(struct device *dev, } snprintf(mp->vreg_config[i].vreg_name, 32, "%s", st); } - msm_mdss_config_vreg(dev, mp->vreg_config, mp->num_vreg, 1); + msm_dss_config_vreg(dev, mp->vreg_config, mp->num_vreg, 1); for (i = 0; i < dt_vreg_total; i++) { DEV_DBG("%s: %s min=%d, max=%d, enable=%d disable=%d\n", diff --git a/drivers/video/fbdev/msm/mdss_rotator_internal.h b/drivers/video/fbdev/msm/mdss_rotator_internal.h index 88f530addf26..6330582ba768 100644 --- a/drivers/video/fbdev/msm/mdss_rotator_internal.h +++ b/drivers/video/fbdev/msm/mdss_rotator_internal.h @@ -172,7 +172,7 @@ struct mdss_rot_mgr { struct mdss_rot_bus_data_type reg_bus; /* Module power is only used for regulator management */ - struct mdss_module_power module_power; + struct dss_module_power module_power; bool regulator_enable; struct mutex clk_lock; diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c index f7923e1868e4..78c7ca31a7e0 100644 --- a/drivers/video/fbdev/msm/mdss_smmu.c +++ b/drivers/video/fbdev/msm/mdss_smmu.c @@ -58,7 +58,7 @@ void mdss_iommu_unlock(void) } static int mdss_smmu_util_parse_dt_clock(struct platform_device *pdev, - struct mdss_module_power *mp) + struct dss_module_power *mp) { u32 i = 0, rc = 0; const char *clock_name; @@ -74,7 +74,7 @@ static int mdss_smmu_util_parse_dt_clock(struct platform_device *pdev, mp->num_clk = num_clk; mp->clk_config = devm_kzalloc(&pdev->dev, - sizeof(struct mdss_clk) * mp->num_clk, GFP_KERNEL); + sizeof(struct dss_clk) * mp->num_clk, GFP_KERNEL); if (!mp->clk_config) { rc = -ENOMEM; mp->num_clk = 0; @@ -102,7 +102,7 @@ static int mdss_smmu_util_parse_dt_clock(struct platform_device *pdev, } static int mdss_smmu_clk_register(struct platform_device *pdev, - struct mdss_module_power *mp) + struct dss_module_power *mp) { int i, ret; struct clk *clk; @@ -130,7 +130,7 @@ static int mdss_smmu_enable_power(struct mdss_smmu_client *mdss_smmu, bool enable) { int rc = 0; - struct mdss_module_power *mp; + struct dss_module_power *mp; if (!mdss_smmu) return -EINVAL; @@ -141,27 +141,27 @@ static int mdss_smmu_enable_power(struct mdss_smmu_client *mdss_smmu, return 0; if (enable) { - rc = msm_mdss_enable_vreg(mp->vreg_config, mp->num_vreg, true); + rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, true); if (rc) { pr_err("vreg enable failed - rc:%d\n", rc); goto end; } mdss_update_reg_bus_vote(mdss_smmu->reg_bus_clt, VOTE_INDEX_LOW); - rc = msm_mdss_enable_clk(mp->clk_config, mp->num_clk, true); + rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true); if (rc) { pr_err("clock enable failed - rc:%d\n", rc); mdss_update_reg_bus_vote(mdss_smmu->reg_bus_clt, VOTE_INDEX_DISABLE); - msm_mdss_enable_vreg(mp->vreg_config, mp->num_vreg, + msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, false); goto end; } } else { - msm_mdss_enable_clk(mp->clk_config, mp->num_clk, false); + msm_dss_enable_clk(mp->clk_config, mp->num_clk, false); mdss_update_reg_bus_vote(mdss_smmu->reg_bus_clt, VOTE_INDEX_DISABLE); - msm_mdss_enable_vreg(mp->vreg_config, mp->num_vreg, false); + msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, false); } end: return rc; @@ -721,7 +721,7 @@ int mdss_smmu_probe(struct platform_device *pdev) int rc = 0; struct mdss_smmu_domain smmu_domain; const struct of_device_id *match; - struct mdss_module_power *mp; + struct dss_module_power *mp; char name[MAX_CLIENT_NAME_LEN]; const __be32 *address = NULL, *size = NULL; @@ -759,13 +759,13 @@ int mdss_smmu_probe(struct platform_device *pdev) mdss_smmu = &mdata->mdss_smmu[smmu_domain.domain]; mp = &mdss_smmu->mp; - memset(mp, 0, sizeof(struct mdss_module_power)); + memset(mp, 0, sizeof(struct dss_module_power)); if (of_find_property(pdev->dev.of_node, "gdsc-mmagic-mdss-supply", NULL)) { mp->vreg_config = devm_kzalloc(&pdev->dev, - sizeof(struct mdss_vreg), GFP_KERNEL); + sizeof(struct dss_vreg), GFP_KERNEL); if (!mp->vreg_config) return -ENOMEM; @@ -774,7 +774,7 @@ int mdss_smmu_probe(struct platform_device *pdev) mp->num_vreg = 1; } - rc = msm_mdss_config_vreg(&pdev->dev, mp->vreg_config, + rc = msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, true); if (rc) { pr_err("vreg config failed rc=%d\n", rc); @@ -785,7 +785,7 @@ int mdss_smmu_probe(struct platform_device *pdev) if (rc) { pr_err("smmu clk register failed for domain[%d] with err:%d\n", smmu_domain.domain, rc); - msm_mdss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, + msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, false); return rc; } @@ -794,7 +794,7 @@ int mdss_smmu_probe(struct platform_device *pdev) mdss_smmu->reg_bus_clt = mdss_reg_bus_vote_client_create(name); if (IS_ERR(mdss_smmu->reg_bus_clt)) { pr_err("mdss bus client register failed\n"); - msm_mdss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, + msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, false); return PTR_ERR(mdss_smmu->reg_bus_clt); } @@ -856,7 +856,7 @@ int mdss_smmu_probe(struct platform_device *pdev) bus_client_destroy: mdss_reg_bus_vote_client_destroy(mdss_smmu->reg_bus_clt); mdss_smmu->reg_bus_clt = NULL; - msm_mdss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, + msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, false); return rc; } diff --git a/drivers/video/fbdev/msm/mhl_sii8334.c b/drivers/video/fbdev/msm/mhl_sii8334.c index cf45eb6fcda9..4133b76c6284 100644 --- a/drivers/video/fbdev/msm/mhl_sii8334.c +++ b/drivers/video/fbdev/msm/mhl_sii8334.c @@ -203,7 +203,7 @@ int mhl_i2c_reg_read(struct i2c_client *client, int rc = -1; uint8_t buffer = 0; - rc = mdss_i2c_byte_read(client, slave_addrs[slave_addr_index], + rc = dss_i2c_byte_read(client, slave_addrs[slave_addr_index], reg_offset, &buffer); if (rc) { pr_err("%s: slave=%x, off=%x\n", @@ -218,7 +218,7 @@ int mhl_i2c_reg_write(struct i2c_client *client, uint8_t slave_addr_index, uint8_t reg_offset, uint8_t value) { - return mdss_i2c_byte_write(client, slave_addrs[slave_addr_index], + return dss_i2c_byte_write(client, slave_addrs[slave_addr_index], reg_offset, &value); } @@ -240,7 +240,7 @@ static int mhl_tx_get_dt_data(struct device *dev, { int i, rc = 0; struct device_node *of_node = NULL; - struct mdss_gpio *temp_gpio = NULL; + struct dss_gpio *temp_gpio = NULL; struct platform_device *hdmi_pdev = NULL; struct device_node *hdmi_tx_node = NULL; int dt_gpio; @@ -262,7 +262,7 @@ static int mhl_tx_get_dt_data(struct device *dev, /* GPIOs */ temp_gpio = NULL; - temp_gpio = devm_kzalloc(dev, sizeof(struct mdss_gpio), GFP_KERNEL); + temp_gpio = devm_kzalloc(dev, sizeof(struct dss_gpio), GFP_KERNEL); pr_debug("%s: gpios allocd\n", __func__); if (!(temp_gpio)) { pr_err("%s: can't alloc %d gpio mem\n", __func__, i); @@ -283,7 +283,7 @@ static int mhl_tx_get_dt_data(struct device *dev, /* PWR */ temp_gpio = NULL; - temp_gpio = devm_kzalloc(dev, sizeof(struct mdss_gpio), GFP_KERNEL); + temp_gpio = devm_kzalloc(dev, sizeof(struct dss_gpio), GFP_KERNEL); pr_debug("%s: gpios allocd\n", __func__); if (!(temp_gpio)) { pr_err("%s: can't alloc %d gpio mem\n", __func__, i); @@ -303,7 +303,7 @@ static int mhl_tx_get_dt_data(struct device *dev, /* INTR */ temp_gpio = NULL; - temp_gpio = devm_kzalloc(dev, sizeof(struct mdss_gpio), GFP_KERNEL); + temp_gpio = devm_kzalloc(dev, sizeof(struct dss_gpio), GFP_KERNEL); pr_debug("%s: gpios allocd\n", __func__); if (!(temp_gpio)) { pr_err("%s: can't alloc %d gpio mem\n", __func__, i); @@ -1716,7 +1716,7 @@ static int mhl_vreg_config(struct mhl_tx_ctrl *mhl_ctrl, uint8_t on) static int mhl_gpio_config(struct mhl_tx_ctrl *mhl_ctrl, int on) { int ret; - struct mdss_gpio *temp_reset_gpio, *temp_intr_gpio; + struct dss_gpio *temp_reset_gpio, *temp_intr_gpio; /* caused too many line spills */ temp_reset_gpio = mhl_ctrl->pdata->gpios[MHL_TX_RESET_GPIO]; diff --git a/drivers/video/fbdev/msm/msm_dba/adv7533.c b/drivers/video/fbdev/msm/msm_dba/adv7533.c index 3f189d5fbd79..49303625c3d9 100644 --- a/drivers/video/fbdev/msm/msm_dba/adv7533.c +++ b/drivers/video/fbdev/msm/msm_dba/adv7533.c @@ -125,7 +125,7 @@ struct adv7533 { struct pinctrl_state *pinctrl_state_suspend; bool audio; bool disable_gpios; - struct mdss_module_power power_data; + struct dss_module_power power_data; bool hdcp_enabled; bool cec_enabled; bool is_power_on; @@ -433,7 +433,7 @@ static int adv7533_program_i2c_addr(struct adv7533 *pdata) } static void adv7533_parse_vreg_dt(struct device *dev, - struct mdss_module_power *mp) + struct dss_module_power *mp) { int i, rc = 0; int dt_vreg_total = 0; @@ -449,7 +449,7 @@ static void adv7533_parse_vreg_dt(struct device *dev, goto end; } mp->num_vreg = dt_vreg_total; - mp->vreg_config = devm_kzalloc(dev, sizeof(struct mdss_vreg) * + mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * dt_vreg_total, GFP_KERNEL); if (!mp->vreg_config) goto end; @@ -1471,7 +1471,7 @@ static void adv7533_video_setup(struct adv7533 *pdata, static int adv7533_config_vreg(struct adv7533 *pdata, int enable) { int rc = 0; - struct mdss_module_power *power_data = NULL; + struct dss_module_power *power_data = NULL; if (!pdata) { pr_err("invalid input\n"); @@ -1486,7 +1486,7 @@ static int adv7533_config_vreg(struct adv7533 *pdata, int enable) } if (enable) { - rc = msm_mdss_config_vreg(&pdata->i2c_client->dev, + rc = msm_dss_config_vreg(&pdata->i2c_client->dev, power_data->vreg_config, power_data->num_vreg, 1); if (rc) { @@ -1495,7 +1495,7 @@ static int adv7533_config_vreg(struct adv7533 *pdata, int enable) goto exit; } } else { - rc = msm_mdss_config_vreg(&pdata->i2c_client->dev, + rc = msm_dss_config_vreg(&pdata->i2c_client->dev, power_data->vreg_config, power_data->num_vreg, 0); if (rc) { @@ -1512,7 +1512,7 @@ static int adv7533_config_vreg(struct adv7533 *pdata, int enable) static int adv7533_enable_vreg(struct adv7533 *pdata, int enable) { int rc = 0; - struct mdss_module_power *power_data = NULL; + struct dss_module_power *power_data = NULL; if (!pdata) { pr_err("invalid input\n"); @@ -1527,7 +1527,7 @@ static int adv7533_enable_vreg(struct adv7533 *pdata, int enable) } if (enable) { - rc = msm_mdss_enable_vreg(power_data->vreg_config, + rc = msm_dss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 1); if (rc) { pr_err("%s: Failed to enable vreg. Err=%d\n", @@ -1535,7 +1535,7 @@ static int adv7533_enable_vreg(struct adv7533 *pdata, int enable) goto exit; } } else { - rc = msm_mdss_enable_vreg(power_data->vreg_config, + rc = msm_dss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 0); if (rc) { pr_err("%s: Failed to disable vreg. Err=%d\n", diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index 5051d1290d3e..5736e09b32cb 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -2343,7 +2343,7 @@ int mdss_dsi_post_clkoff_cb(void *priv, if ((ctrl->ctrl_state & CTRL_STATE_DSI_ACTIVE) && (i != DSI_CORE_PM)) continue; - rc = msm_mdss_enable_vreg( + rc = msm_dss_enable_vreg( sdata->power_data[i].vreg_config, sdata->power_data[i].num_vreg, 0); if (rc) { @@ -2404,7 +2404,7 @@ int mdss_dsi_pre_clkon_cb(void *priv, (!pdata->panel_info.cont_splash_enabled) && (i != DSI_CORE_PM)) continue; - rc = msm_mdss_enable_vreg( + rc = msm_dss_enable_vreg( sdata->power_data[i].vreg_config, sdata->power_data[i].num_vreg, 1); if (rc) { diff --git a/include/linux/mdss_io_util.h b/include/linux/mdss_io_util.h index dd0b17cc555d..ad706baa9d08 100644 --- a/include/linux/mdss_io_util.h +++ b/include/linux/mdss_io_util.h @@ -28,26 +28,26 @@ #define DEV_WARN(fmt, args...) pr_warn(fmt, ##args) #define DEV_ERR(fmt, args...) pr_err(fmt, ##args) -struct mdss_io_data { +struct dss_io_data { u32 len; void __iomem *base; }; -void mdss_reg_w(struct mdss_io_data *io, u32 offset, u32 value, u32 debug); -u32 mdss_reg_r(struct mdss_io_data *io, u32 offset, u32 debug); -void mdss_reg_dump(void __iomem *base, u32 len, const char *prefix, u32 debug); +void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug); +u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug); +void dss_reg_dump(void __iomem *base, u32 len, const char *prefix, u32 debug); -#define DSS_REG_W_ND(io, offset, val) mdss_reg_w(io, offset, val, false) -#define DSS_REG_W(io, offset, val) mdss_reg_w(io, offset, val, true) -#define DSS_REG_R_ND(io, offset) mdss_reg_r(io, offset, false) -#define DSS_REG_R(io, offset) mdss_reg_r(io, offset, true) +#define DSS_REG_W_ND(io, offset, val) dss_reg_w(io, offset, val, false) +#define DSS_REG_W(io, offset, val) dss_reg_w(io, offset, val, true) +#define DSS_REG_R_ND(io, offset) dss_reg_r(io, offset, false) +#define DSS_REG_R(io, offset) dss_reg_r(io, offset, true) -enum mdss_vreg_type { +enum dss_vreg_type { DSS_REG_LDO, DSS_REG_VS, }; -enum mdss_vreg_mode { +enum dss_vreg_mode { DSS_REG_MODE_ENABLE, DSS_REG_MODE_DISABLE, DSS_REG_MODE_LP, @@ -55,68 +55,70 @@ enum mdss_vreg_mode { DSS_REG_MODE_MAX, }; -struct mdss_vreg { +struct dss_vreg { struct regulator *vreg; /* vreg handle */ char vreg_name[32]; int min_voltage; int max_voltage; u32 load[DSS_REG_MODE_MAX]; + int enable_load; + int disable_load; int pre_on_sleep; int post_on_sleep; int pre_off_sleep; int post_off_sleep; }; -struct mdss_gpio { +struct dss_gpio { unsigned int gpio; unsigned int value; char gpio_name[32]; }; -enum mdss_clk_type { +enum dss_clk_type { DSS_CLK_AHB, /* no set rate. rate controlled through rpm */ DSS_CLK_PCLK, DSS_CLK_OTHER, }; -struct mdss_clk { +struct dss_clk { struct clk *clk; /* clk handle */ char clk_name[32]; - enum mdss_clk_type type; + enum dss_clk_type type; unsigned long rate; }; -struct mdss_module_power { +struct dss_module_power { unsigned int num_vreg; - struct mdss_vreg *vreg_config; + struct dss_vreg *vreg_config; unsigned int num_gpio; - struct mdss_gpio *gpio_config; + struct dss_gpio *gpio_config; unsigned int num_clk; - struct mdss_clk *clk_config; + struct dss_clk *clk_config; }; -int msm_mdss_ioremap_byname(struct platform_device *pdev, - struct mdss_io_data *io_data, const char *name); -void msm_mdss_iounmap(struct mdss_io_data *io_data); +int msm_dss_ioremap_byname(struct platform_device *pdev, + struct dss_io_data *io_data, const char *name); +void msm_dss_iounmap(struct dss_io_data *io_data); -int msm_mdss_enable_gpio(struct mdss_gpio *in_gpio, int num_gpio, int enable); -int msm_mdss_gpio_enable(struct mdss_gpio *in_gpio, int num_gpio, int enable); +int msm_dss_enable_gpio(struct dss_gpio *in_gpio, int num_gpio, int enable); +int msm_dss_gpio_enable(struct dss_gpio *in_gpio, int num_gpio, int enable); -int msm_mdss_config_vreg(struct device *dev, struct mdss_vreg *in_vreg, +int msm_dss_config_vreg(struct device *dev, struct dss_vreg *in_vreg, int num_vreg, int config); -int msm_mdss_enable_vreg(struct mdss_vreg *in_vreg, int num_vreg, int enable); -int msm_mdss_config_vreg_opt_mode(struct mdss_vreg *in_vreg, int num_vreg, - enum mdss_vreg_mode mode); +int msm_dss_enable_vreg(struct dss_vreg *in_vreg, int num_vreg, int enable); +int msm_dss_config_vreg_opt_mode(struct dss_vreg *in_vreg, int num_vreg, + enum dss_vreg_mode mode); -int msm_mdss_get_clk(struct device *dev, struct mdss_clk *clk_arry, +int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk); -void msm_mdss_put_clk(struct mdss_clk *clk_arry, int num_clk); -int msm_mdss_clk_set_rate(struct mdss_clk *clk_arry, int num_clk); -int msm_mdss_enable_clk(struct mdss_clk *clk_arry, int num_clk, int enable); +void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk); +int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk); +int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable); -int mdss_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr, +int dss_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr, uint8_t reg_offset, uint8_t *read_buf); -int mdss_i2c_byte_write(struct i2c_client *client, uint8_t slave_addr, +int dss_i2c_byte_write(struct i2c_client *client, uint8_t slave_addr, uint8_t reg_offset, uint8_t *value); #endif /* __MDSS_IO_UTIL_H__ */ -- GitLab From d29c9082fd915ac16a28f6aecf7a5ca873f262f2 Mon Sep 17 00:00:00 2001 From: Prasad Sodagudi Date: Thu, 7 Jun 2018 19:53:32 -0700 Subject: [PATCH 0054/1299] defconfig: arm64: Enable DEBUG_PREEMPT for sm8150 SoC Enable DEBUG_PREEMPT for sm8150 SoC, So that this feature provides "Preemption disabled at:" print information for debugging. Change-Id: I9cccfe1ef064bd3c55c9179aa5d1387320c3f87d Signed-off-by: Prasad Sodagudi --- arch/arm64/configs/sm8150_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/sm8150_defconfig b/arch/arm64/configs/sm8150_defconfig index 26255237ae9c..b1879eeb3978 100644 --- a/arch/arm64/configs/sm8150_defconfig +++ b/arch/arm64/configs/sm8150_defconfig @@ -645,7 +645,6 @@ CONFIG_PANIC_ON_SCHED_BUG=y CONFIG_PANIC_ON_RT_THROTTLING=y CONFIG_SCHEDSTATS=y CONFIG_SCHED_STACK_END_CHECK=y -# CONFIG_DEBUG_PREEMPT is not set CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_ATOMIC_SLEEP=y -- GitLab From 52cf7a400335982b069d078469b95755c6a0a6b2 Mon Sep 17 00:00:00 2001 From: Raghavendra Rao Ananta Date: Tue, 3 Apr 2018 20:32:23 -0700 Subject: [PATCH 0055/1299] esoc: Add IPC logging support Add IPC logging support for detailed tracking of events that the esoc driver would be handling. Change-Id: Iadb63dc946efc355de2e68d6c4890aade1a04b0c Signed-off-by: Raghavendra Rao Ananta --- drivers/esoc/esoc-mdm-4x.c | 112 ++++++++++++++++++++++++++++++++++-- drivers/esoc/esoc-mdm-drv.c | 74 +++++++++++++++++++++++- drivers/esoc/esoc-mdm-pon.c | 20 ++++++- drivers/esoc/esoc.h | 12 ++++ drivers/esoc/esoc_dev.c | 66 ++++++++++++++++++--- 5 files changed, 268 insertions(+), 16 deletions(-) diff --git a/drivers/esoc/esoc-mdm-4x.c b/drivers/esoc/esoc-mdm-4x.c index 0fa9a0a090bc..6132c9a4a1a9 100644 --- a/drivers/esoc/esoc-mdm-4x.c +++ b/drivers/esoc/esoc-mdm-4x.c @@ -55,6 +55,8 @@ static const int required_gpios[] = { AP2MDM_STATUS, }; +void *ipc_log; + static void mdm_debug_gpio_show(struct mdm_ctrl *mdm) { struct device *dev = mdm->dev; @@ -83,10 +85,25 @@ static void mdm_debug_gpio_show(struct mdm_ctrl *mdm) __func__, MDM_GPIO(mdm, MDM2AP_VDDMIN)); } +static void mdm_debug_gpio_ipc_log(struct mdm_ctrl *mdm) +{ + esoc_mdm_log("MDM2AP_ERRFATAL gpio = %d\n", + MDM_GPIO(mdm, MDM2AP_ERRFATAL)); + esoc_mdm_log("AP2MDM_ERRFATAL gpio = %d\n", + MDM_GPIO(mdm, AP2MDM_ERRFATAL)); + esoc_mdm_log("MDM2AP_STATUS gpio = %d\n", + MDM_GPIO(mdm, MDM2AP_STATUS)); + esoc_mdm_log("AP2MDM_STATUS gpio = %d\n", + MDM_GPIO(mdm, AP2MDM_STATUS)); + esoc_mdm_log("AP2MDM_SOFT_RESET gpio = %d\n", + MDM_GPIO(mdm, AP2MDM_SOFT_RESET)); +} + static void mdm_enable_irqs(struct mdm_ctrl *mdm) { if (!mdm) return; + esoc_mdm_log("Enabling the interrupts\n"); if (mdm->irq_mask & IRQ_ERRFATAL) { enable_irq(mdm->errfatal_irq); mdm->irq_mask &= ~IRQ_ERRFATAL; @@ -105,6 +122,7 @@ void mdm_disable_irqs(struct mdm_ctrl *mdm) { if (!mdm) return; + esoc_mdm_log("Disabling the interrupts\n"); if (!(mdm->irq_mask & IRQ_ERRFATAL)) { disable_irq_nosync(mdm->errfatal_irq); mdm->irq_mask |= IRQ_ERRFATAL; @@ -192,6 +210,7 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc) esoc->clink_ops->notify(ESOC_BOOT_DONE, esoc); } } + esoc_mdm_log("ESOC_PWR_ON: Setting AP2MDM_ERRFATAL = 0\n"); gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0); mdm->init = 1; mdm_do_first_power_on(mdm); @@ -206,11 +225,17 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc) break; graceful_shutdown = true; if (!esoc->userspace_handle_shutdown) { + esoc_mdm_log( + "ESOC_PWR_OFF: sending sysmon-shutdown to modem\n"); ret = sysmon_send_shutdown(&esoc->subsys); if (ret) { + esoc_mdm_log( + "ESOC_PWR_OFF: sysmon-shutdown failed: %d\n", ret); dev_err(mdm->dev, "sysmon shutdown fail, ret = %d\n", ret); graceful_shutdown = false; + esoc_mdm_log( + "ESOC_PWR_OFF: forcefully powering-off modem\n"); } } else { esoc_clink_queue_request(ESOC_REQ_SEND_SHUTDOWN, esoc); @@ -236,13 +261,19 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc) * monitored by multiple mdms(might be wrongly interpreted as * a primary crash). */ - if (esoc->statusline_not_a_powersource == false) + if (esoc->statusline_not_a_powersource == false) { + esoc_mdm_log( + "ESOC_FORCE_PWR_OFF: setting AP2MDM_STATUS = 0\n"); gpio_set_value(MDM_GPIO(mdm, AP2MDM_STATUS), 0); + } + esoc_mdm_log( + "ESOC_FORCE_PWR_OFF: Queueing request: ESOC_REQ_SHUTDOWN\n"); esoc_clink_queue_request(ESOC_REQ_SHUTDOWN, esoc); mdm_power_down(mdm); mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG); break; case ESOC_RESET: + esoc_mdm_log("ESOC_RESET: Resetting the modem\n"); mdm_toggle_soft_reset(mdm, false); break; case ESOC_PREPARE_DEBUG: @@ -252,8 +283,12 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc) * an APQ crash, wait till mdm is ready for ramdumps. */ mdm->ready = false; + esoc_mdm_log( + "ESOC_PREPARE_DEBUG: Cancelling the status check work\n"); cancel_delayed_work(&mdm->mdm2ap_status_check_work); if (!mdm->esoc->auto_boot) { + esoc_mdm_log( + "ESOC_PREPARE_DEBUG: setting AP2MDM_ERRFATAL = 1\n"); gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1); dev_dbg(mdm->dev, "set ap2mdm errfatal to force reset\n"); @@ -266,6 +301,7 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc) if (mdm->skip_restart_for_mdm_crash) break; + esoc_mdm_log("ESOC_EXE_DEBUG: Resetting the modem\n"); mdm->debug = 1; mdm_toggle_soft_reset(mdm, false); /* @@ -273,8 +309,12 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc) * then power down the mdm and switch gpios to booting * config */ + esoc_mdm_log( + "ESOC_EXE_DEBUG: Waiting for ramdumps to be collected\n"); wait_for_completion(&mdm->debug_done); if (mdm->debug_fail) { + esoc_mdm_log( + "ESOC_EXE_DEBUG: Failed to collect the ramdumps\n"); dev_err(mdm->dev, "unable to collect ramdumps\n"); mdm->debug = 0; return -EIO; @@ -288,11 +328,13 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc) * Deassert APQ to mdm err fatal * Power on the mdm */ + esoc_mdm_log("ESOC_EXIT_DEBUG: Setting AP2MDM_ERRFATAL = 0\n"); gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 0); dev_dbg(mdm->dev, "exiting debug state after power on\n"); mdm->get_restart_reason = true; break; default: + esoc_mdm_log("Invalid command\n"); return -EINVAL; }; return 0; @@ -306,7 +348,11 @@ static void mdm2ap_status_check(struct work_struct *work) struct device *dev = mdm->dev; struct esoc_clink *esoc = mdm->esoc; + esoc_mdm_log( + "Powerup timer expired after images are transferred to modem\n"); + if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) == 0) { + esoc_mdm_log("MDM2AP_STATUS did not go high\n"); dev_dbg(dev, "MDM2AP_STATUS did not go high\n"); esoc_clink_evt_notify(ESOC_UNEXPECTED_RESET, esoc); } @@ -336,14 +382,17 @@ static void mdm_get_restart_reason(struct work_struct *work) ret = sysmon_get_reason(&mdm->esoc->subsys, sfr_buf, sizeof(sfr_buf)); if (!ret) { + esoc_mdm_log("restart reason is %s\n", sfr_buf); dev_err(dev, "mdm restart reason is %s\n", sfr_buf); break; } msleep(SFR_RETRY_INTERVAL); } while (++ntries < SFR_MAX_RETRIES); - if (ntries == SFR_MAX_RETRIES) + if (ntries == SFR_MAX_RETRIES) { + esoc_mdm_log("restart reason not obtained. err: %d\n", ret); dev_dbg(dev, "%s: Error retrieving restart reason: %d\n", __func__, ret); + } mdm->get_restart_reason = false; } @@ -355,36 +404,53 @@ static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc) struct mdm_ctrl *mdm = get_esoc_clink_data(esoc); struct device *dev = mdm->dev; + esoc_mdm_log("Notification: %d\n", notify); + switch (notify) { case ESOC_IMG_XFER_DONE: - if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) == 0) + if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)) == 0) { + esoc_mdm_log( + "ESOC_IMG_XFER_DONE: Begin timeout of %lu ms for modem_status\n", + MDM2AP_STATUS_TIMEOUT_MS); schedule_delayed_work(&mdm->mdm2ap_status_check_work, msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS)); + } break; case ESOC_BOOT_DONE: + esoc_mdm_log( + "ESOC_BOOT_DONE: Sending the notification: ESOC_RUN_STATE\n"); esoc_clink_evt_notify(ESOC_RUN_STATE, esoc); break; case ESOC_IMG_XFER_RETRY: + esoc_mdm_log("ESOC_IMG_XFER_RETRY: Resetting the device\n"); mdm->init = 1; mdm_toggle_soft_reset(mdm, false); break; case ESOC_IMG_XFER_FAIL: + esoc_mdm_log( + "ESOC_IMG_XFER_FAIL: Send notification: ESOC_INVALID_STATE\n"); esoc_clink_evt_notify(ESOC_INVALID_STATE, esoc); break; case ESOC_BOOT_FAIL: + esoc_mdm_log( + "ESOC_BOOT_FAIL: Send notification: ESOC_INVALID_STATE\n"); esoc_clink_evt_notify(ESOC_INVALID_STATE, esoc); break; case ESOC_PON_RETRY: + esoc_mdm_log( + "ESOC_PON_RETRY: Send notification: ESOC_RETRY_PON_EVT\n"); esoc_clink_evt_notify(ESOC_RETRY_PON_EVT, esoc); break; case ESOC_UPGRADE_AVAILABLE: break; case ESOC_DEBUG_DONE: + esoc_mdm_log("ESOC_DEBUG_DONE: Ramdumps collection done\n"); mdm->debug_fail = false; mdm_update_gpio_configs(mdm, GPIO_UPDATE_BOOTING_CONFIG); complete(&mdm->debug_done); break; case ESOC_DEBUG_FAIL: + esoc_mdm_log("ESOC_DEBUG_FAIL: Ramdumps collection failed\n"); mdm->debug_fail = true; complete(&mdm->debug_done); break; @@ -392,9 +458,13 @@ static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc) mdm_disable_irqs(mdm); status_down = false; dev_dbg(dev, "signal apq err fatal for graceful restart\n"); + esoc_mdm_log( + "ESOC_PRIMARY_CRASH: Setting AP2MDM_ERRFATAL = 1\n"); gpio_set_value(MDM_GPIO(mdm, AP2MDM_ERRFATAL), 1); if (esoc->primary) break; + esoc_mdm_log( + "ESOC_PRIMARY_CRASH: Waiting for MDM2AP_STATUS to go LOW\n"); timeout = local_clock(); do_div(timeout, NSEC_PER_MSEC); timeout += MDM_MODEM_TIMEOUT; @@ -409,6 +479,8 @@ static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc) } while (!time_after64(now, timeout)); if (!status_down) { + esoc_mdm_log( + "ESOC_PRIMARY_CRASH: MDM2AP_STATUS didn't go LOW. Resetting modem\n"); dev_err(mdm->dev, "%s MDM2AP status did not go low\n", __func__); mdm_toggle_soft_reset(mdm, true); @@ -418,6 +490,8 @@ static void mdm_notify(enum esoc_notify notify, struct esoc_clink *esoc) mdm_disable_irqs(mdm); mdm->debug = 0; mdm->ready = false; + esoc_mdm_log( + "ESOC_PRIMARY_REBOOT: Powering down the modem\n"); mdm_power_down(mdm); break; }; @@ -435,6 +509,7 @@ static irqreturn_t mdm_errfatal(int irq, void *dev_id) if (!mdm->ready) goto mdm_pwroff_irq; esoc = mdm->esoc; + esoc_mdm_log("MDM2AP_ERRFATAL IRQ received!\n"); dev_err(dev, "%s: mdm sent errfatal interrupt\n", __func__); subsys_set_crash_status(esoc->subsys_dev, true); @@ -442,6 +517,8 @@ static irqreturn_t mdm_errfatal(int irq, void *dev_id) esoc_clink_evt_notify(ESOC_ERR_FATAL, esoc); return IRQ_HANDLED; mdm_pwroff_irq: + esoc_mdm_log( + "MDM2AP_ERRFATAL IRQ received before modem booted. Ignoring.\n"); dev_info(dev, "errfatal irq when in pwroff\n"); no_mdm_irq: return IRQ_HANDLED; @@ -458,15 +535,19 @@ static irqreturn_t mdm_status_change(int irq, void *dev_id) return IRQ_HANDLED; dev = mdm->dev; esoc = mdm->esoc; + esoc_mdm_log("MDM2AP_STATUS IRQ received!\n"); /* * On auto boot devices, there is a possibility of receiving * status change interrupt before esoc_clink structure is * initialized. Ignore them. */ - if (!esoc) + if (!esoc) { + esoc_mdm_log("Unexpected IRQ. Ignoring.\n"); return IRQ_HANDLED; + } value = gpio_get_value(MDM_GPIO(mdm, MDM2AP_STATUS)); if (value == 0 && mdm->ready) { + esoc_mdm_log("Unexpected reset of external modem\n"); dev_err(dev, "unexpected reset external modem\n"); subsys_set_crash_status(esoc->subsys_dev, true); esoc_clink_evt_notify(ESOC_UNEXPECTED_RESET, esoc); @@ -478,6 +559,8 @@ static irqreturn_t mdm_status_change(int irq, void *dev_id) if (esoc->auto_boot && mdm->ready) return IRQ_HANDLED; + esoc_mdm_log( + "Modem ready. Cancelling the the status_check work\n"); cancel_delayed_work(&mdm->mdm2ap_status_check_work); dev_dbg(dev, "status = 1: mdm is now ready\n"); mdm->ready = true; @@ -887,30 +970,35 @@ static int sdx50m_setup_hw(struct mdm_ctrl *mdm, ret = mdm_dt_parse_gpios(mdm); if (ret) { + esoc_mdm_log("Failed to parse DT gpios\n"); dev_err(mdm->dev, "Failed to parse DT gpios\n"); goto err_destroy_wrkq; } ret = mdm_pon_dt_init(mdm); if (ret) { + esoc_mdm_log("Failed to parse PON DT gpios\n"); dev_err(mdm->dev, "Failed to parse PON DT gpio\n"); goto err_destroy_wrkq; } ret = mdm_pinctrl_init(mdm); if (ret) { + esoc_mdm_log("Failed to init pinctrl\n"); dev_err(mdm->dev, "Failed to init pinctrl\n"); goto err_destroy_wrkq; } ret = mdm_pon_setup(mdm); if (ret) { + esoc_mdm_log("Failed to setup PON\n"); dev_err(mdm->dev, "Failed to setup PON\n"); goto err_destroy_wrkq; } ret = mdm_configure_ipc(mdm, pdev); if (ret) { + esoc_mdm_log("Failed to configure the ipc\n"); dev_err(mdm->dev, "Failed to configure the ipc\n"); goto err_release_ipc; } @@ -935,10 +1023,12 @@ static int sdx50m_setup_hw(struct mdm_ctrl *mdm, ret = esoc_clink_register(esoc); if (ret) { + esoc_mdm_log("esoc registration failed\n"); dev_err(mdm->dev, "esoc registration failed\n"); goto err_free_irq; } dev_dbg(mdm->dev, "esoc registration done\n"); + esoc_mdm_log("Done configuring the GPIOs and esoc registration\n"); init_completion(&mdm->debug_done); INIT_WORK(&mdm->mdm_status_work, mdm_status_fn); @@ -949,6 +1039,8 @@ static int sdx50m_setup_hw(struct mdm_ctrl *mdm, mdm->esoc = esoc; mdm->init = 0; + mdm_debug_gpio_ipc_log(mdm); + return 0; err_free_irq: @@ -994,6 +1086,7 @@ static int mdm_probe(struct platform_device *pdev) const struct mdm_ops *mdm_ops; struct device_node *node = pdev->dev.of_node; struct mdm_ctrl *mdm; + int ret; match = of_match_node(mdm_dt_match, node); if (IS_ERR_OR_NULL(match)) @@ -1002,7 +1095,16 @@ static int mdm_probe(struct platform_device *pdev) mdm = devm_kzalloc(&pdev->dev, sizeof(*mdm), GFP_KERNEL); if (IS_ERR_OR_NULL(mdm)) return PTR_ERR(mdm); - return mdm_ops->config_hw(mdm, mdm_ops, pdev); + + ipc_log = ipc_log_context_create(ESOC_MDM_IPC_PAGES, "esoc-mdm", 0); + if (!ipc_log) + dev_err(&pdev->dev, "Failed to setup IPC logging\n"); + + ret = mdm_ops->config_hw(mdm, mdm_ops, pdev); + if (ret) + ipc_log_context_destroy(ipc_log); + + return ret; } static struct platform_driver mdm_driver = { diff --git a/drivers/esoc/esoc-mdm-drv.c b/drivers/esoc/esoc-mdm-drv.c index 9afd171fb677..7d477f325c28 100644 --- a/drivers/esoc/esoc-mdm-drv.c +++ b/drivers/esoc/esoc-mdm-drv.c @@ -82,6 +82,8 @@ static int esoc_msm_restart_handler(struct notifier_block *nb, if (action == SYS_RESTART) { if (mdm_dbg_stall_notify(ESOC_PRIMARY_REBOOT)) return NOTIFY_OK; + esoc_mdm_log( + "Reboot notifier: Notifying esoc of cold reboot\n"); dev_dbg(&esoc_clink->dev, "Notifying esoc of cold reboot\n"); clink_ops->notify(ESOC_PRIMARY_REBOOT, esoc_clink); } @@ -91,23 +93,35 @@ static void mdm_handle_clink_evt(enum esoc_evt evt, struct esoc_eng *eng) { struct mdm_drv *mdm_drv = to_mdm_drv(eng); + bool unexpected_state = false; switch (evt) { case ESOC_INVALID_STATE: + esoc_mdm_log( + "ESOC_INVALID_STATE: Calling complete with state: PON_FAIL\n"); mdm_drv->pon_state = PON_FAIL; complete(&mdm_drv->pon_done); break; case ESOC_RUN_STATE: + esoc_mdm_log( + "ESOC_RUN_STATE: Calling complete with state: PON_SUCCESS\n"); mdm_drv->pon_state = PON_SUCCESS; mdm_drv->mode = RUN, complete(&mdm_drv->pon_done); break; case ESOC_RETRY_PON_EVT: + esoc_mdm_log( + "ESOC_RETRY_PON_EVT: Calling complete with state: PON_RETRY\n"); mdm_drv->pon_state = PON_RETRY; complete(&mdm_drv->pon_done); break; case ESOC_UNEXPECTED_RESET: + esoc_mdm_log("evt_state: ESOC_UNEXPECTED_RESET\n"); + unexpected_state = true; case ESOC_ERR_FATAL: + if (!unexpected_state) + esoc_mdm_log("evt_state: ESOC_ERR_FATAL\n"); + /* * Modem can crash while we are waiting for pon_done during * a subsystem_get(). Setting mode to CRASH will prevent a @@ -115,12 +129,20 @@ static void mdm_handle_clink_evt(enum esoc_evt evt, * this by seting mode to CRASH only if device was up and * running. */ + if (mdm_drv->mode == CRASH) + esoc_mdm_log( + "Modem in crash state already. Ignoring.\n"); + if (mdm_drv->mode != RUN) + esoc_mdm_log("Modem not up. Ignoring.\n"); if (mdm_drv->mode == CRASH || mdm_drv->mode != RUN) return; mdm_drv->mode = CRASH; + esoc_mdm_log("Starting SSR work\n"); queue_work(mdm_drv->mdm_queue, &mdm_drv->ssr_work); break; case ESOC_REQ_ENG_ON: + esoc_mdm_log( + "evt_state: ESOC_REQ_ENG_ON; Registered a req engine\n"); complete(&mdm_drv->req_eng_wait); break; default: @@ -145,6 +167,8 @@ static void esoc_client_link_power_on(struct esoc_clink *esoc_clink, struct esoc_client_hook *client_hook; dev_dbg(&esoc_clink->dev, "Calling power_on hooks\n"); + esoc_mdm_log( + "Calling power_on hooks with crash state: %d\n", mdm_crashed); for (i = 0; i < ESOC_MAX_HOOKS; i++) { client_hook = esoc_clink->client_hook[i]; @@ -161,6 +185,8 @@ static void esoc_client_link_power_off(struct esoc_clink *esoc_clink, struct esoc_client_hook *client_hook; dev_dbg(&esoc_clink->dev, "Calling power_off hooks\n"); + esoc_mdm_log( + "Calling power_off hooks with crash state: %d\n", mdm_crashed); for (i = 0; i < ESOC_MAX_HOOKS; i++) { client_hook = esoc_clink->client_hook[i]; @@ -179,6 +205,8 @@ static void mdm_crash_shutdown(const struct subsys_desc *mdm_subsys) subsys); const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops; + esoc_mdm_log("MDM crashed notification from SSR\n"); + if (mdm_dbg_stall_notify(ESOC_PRIMARY_CRASH)) return; clink_ops->notify(ESOC_PRIMARY_CRASH, esoc_clink); @@ -193,7 +221,10 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys, struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops; + esoc_mdm_log("Shutdown request from SSR\n"); + if (mdm_drv->mode == CRASH || mdm_drv->mode == PEER_CRASH) { + esoc_mdm_log("Shutdown in crash mode\n"); if (mdm_dbg_stall_cmd(ESOC_PREPARE_DEBUG)) /* We want to mask debug command. * In this case return success @@ -204,18 +235,23 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys, esoc_clink_queue_request(ESOC_REQ_CRASH_SHUTDOWN, esoc_clink); esoc_client_link_power_off(esoc_clink, true); + esoc_mdm_log("Executing the ESOC_PREPARE_DEBUG command\n"); ret = clink_ops->cmd_exe(ESOC_PREPARE_DEBUG, esoc_clink); if (ret) { + esoc_mdm_log("ESOC_PREPARE_DEBUG command failed\n"); dev_err(&esoc_clink->dev, "failed to enter debug\n"); return ret; } mdm_drv->mode = IN_DEBUG; } else if (!force_stop) { - if (esoc_clink->subsys.sysmon_shutdown_ret) + esoc_mdm_log("Graceful shutdown mode\n"); + if (esoc_clink->subsys.sysmon_shutdown_ret) { + esoc_mdm_log( + "Executing the ESOC_FORCE_PWR_OFF command\n"); ret = clink_ops->cmd_exe(ESOC_FORCE_PWR_OFF, esoc_clink); - else { + } else { if (mdm_dbg_stall_cmd(ESOC_PWR_OFF)) /* Since power off command is masked * we return success, and leave the state @@ -223,9 +259,12 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys, */ return 0; dev_dbg(&esoc_clink->dev, "Sending sysmon-shutdown\n"); + esoc_mdm_log("Executing the ESOC_PWR_OFF command\n"); ret = clink_ops->cmd_exe(ESOC_PWR_OFF, esoc_clink); } if (ret) { + esoc_mdm_log( + "Executing the ESOC_PWR_OFF command failed\n"); dev_err(&esoc_clink->dev, "failed to exe power off\n"); return ret; } @@ -234,6 +273,7 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys, clink_ops->cmd_exe(ESOC_FORCE_PWR_OFF, esoc_clink); mdm_drv->mode = PWR_OFF; } + esoc_mdm_log("Shutdown completed\n"); return 0; } @@ -242,6 +282,8 @@ static void mdm_subsys_retry_powerup_cleanup(struct esoc_clink *esoc_clink) struct mdm_ctrl *mdm = get_esoc_clink_data(esoc_clink); struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); + esoc_mdm_log("Doing cleanup\n"); + esoc_client_link_power_off(esoc_clink, false); mdm_disable_irqs(mdm); mdm_drv->pon_state = PON_INIT; @@ -257,6 +299,7 @@ static int mdm_handle_boot_fail(struct esoc_clink *esoc_clink, u8 *pon_trial) switch (boot_fail_action) { case BOOT_FAIL_ACTION_RETRY: mdm_subsys_retry_powerup_cleanup(esoc_clink); + esoc_mdm_log("Request to retry a warm reset\n"); (*pon_trial)++; break; /* @@ -266,17 +309,21 @@ static int mdm_handle_boot_fail(struct esoc_clink *esoc_clink, u8 *pon_trial) */ case BOOT_FAIL_ACTION_COLD_RESET: mdm_subsys_retry_powerup_cleanup(esoc_clink); + esoc_mdm_log("Doing cold reset by power-down and warm reset\n"); (*pon_trial)++; mdm_power_down(mdm); break; case BOOT_FAIL_ACTION_PANIC: + esoc_mdm_log("Calling panic!!\n"); panic("Panic requested on external modem boot failure\n"); break; case BOOT_FAIL_ACTION_NOP: + esoc_mdm_log("Leaving the modem in its curent state\n"); return -EIO; case BOOT_FAIL_ACTION_SHUTDOWN: default: mdm_subsys_retry_powerup_cleanup(esoc_clink); + esoc_mdm_log("Shutdown the modem and quit\n"); mdm_power_down(mdm); return -EIO; } @@ -295,30 +342,43 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) int timeout = INT_MAX; u8 pon_trial = 1; + esoc_mdm_log("Powerup request from SSR\n"); + do { + esoc_mdm_log("Boot trial: %d\n", pon_trial); if (!esoc_clink->auto_boot && !esoc_req_eng_enabled(esoc_clink)) { + esoc_mdm_log("Wait for req eng registration\n"); dev_dbg(&esoc_clink->dev, "Wait for req eng registration\n"); wait_for_completion(&mdm_drv->req_eng_wait); } + esoc_mdm_log("Req eng available\n"); if (mdm_drv->mode == PWR_OFF) { + esoc_mdm_log("In normal power-on mode\n"); if (mdm_dbg_stall_cmd(ESOC_PWR_ON)) return -EBUSY; + esoc_mdm_log("Executing the ESOC_PWR_ON command\n"); ret = clink_ops->cmd_exe(ESOC_PWR_ON, esoc_clink); if (ret) { + esoc_mdm_log("ESOC_PWR_ON command failed\n"); dev_err(&esoc_clink->dev, "pwr on fail\n"); return ret; } esoc_client_link_power_on(esoc_clink, false); } else if (mdm_drv->mode == IN_DEBUG) { + esoc_mdm_log("In SSR power-on mode\n"); + esoc_mdm_log("Executing the ESOC_EXIT_DEBUG command\n"); ret = clink_ops->cmd_exe(ESOC_EXIT_DEBUG, esoc_clink); if (ret) { + esoc_mdm_log( + "ESOC_EXIT_DEBUG command failed\n"); dev_err(&esoc_clink->dev, "cannot exit debug mode\n"); return ret; } mdm_drv->mode = PWR_OFF; + esoc_mdm_log("Executing the ESOC_PWR_ON command\n"); ret = clink_ops->cmd_exe(ESOC_PWR_ON, esoc_clink); if (ret) { dev_err(&esoc_clink->dev, "pwr on fail\n"); @@ -336,13 +396,18 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) */ if (esoc_clink->auto_boot) timeout = 10 * HZ; + esoc_mdm_log( + "Modem turned-on. Waiting for pon_done notification..\n"); ret = wait_for_completion_timeout(&mdm_drv->pon_done, timeout); if (mdm_drv->pon_state == PON_FAIL || ret <= 0) { dev_err(&esoc_clink->dev, "booting failed\n"); + esoc_mdm_log("booting failed\n"); ret = mdm_handle_boot_fail(esoc_clink, &pon_trial); if (ret) return ret; } else if (mdm_drv->pon_state == PON_RETRY) { + esoc_mdm_log( + "Boot failed. Doing cleanup and attempting to retry\n"); pon_trial++; mdm_subsys_retry_powerup_cleanup(esoc_clink); } else if (mdm_drv->pon_state == PON_SUCCESS) { @@ -362,9 +427,14 @@ static int mdm_subsys_ramdumps(int want_dumps, subsys); const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops; + esoc_mdm_log("Ramdumps called from SSR\n"); + if (want_dumps) { + esoc_mdm_log("Executing the ESOC_EXE_DEBUG command\n"); ret = clink_ops->cmd_exe(ESOC_EXE_DEBUG, esoc_clink); if (ret) { + esoc_mdm_log( + "Failed executing the ESOC_EXE_DEBUG command\n"); dev_err(&esoc_clink->dev, "debugging failed\n"); return ret; } diff --git a/drivers/esoc/esoc-mdm-pon.c b/drivers/esoc/esoc-mdm-pon.c index 3f73364c2fed..e1e335226867 100644 --- a/drivers/esoc/esoc-mdm-pon.c +++ b/drivers/esoc/esoc-mdm-pon.c @@ -51,6 +51,11 @@ static int sdx50m_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic) soft_reset_direction_assert = 1; soft_reset_direction_de_assert = 0; } + + esoc_mdm_log("RESET GPIO value (before doing a reset): %d\n", + gpio_get_value(MDM_GPIO(mdm, AP2MDM_SOFT_RESET))); + esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n", + soft_reset_direction_assert); gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET), soft_reset_direction_assert); /* @@ -64,6 +69,9 @@ static int sdx50m_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic) * panic handler, which has to executed atomically. */ mdelay(100); + + esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n", + soft_reset_direction_de_assert); gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET), soft_reset_direction_de_assert); return 0; @@ -75,6 +83,7 @@ static int mdm4x_do_first_power_on(struct mdm_ctrl *mdm) int pblrdy; struct device *dev = mdm->dev; + esoc_mdm_log("Powering on modem for the first time\n"); dev_dbg(dev, "Powering on modem for the first time\n"); if (mdm->esoc->auto_boot) return 0; @@ -82,6 +91,7 @@ static int mdm4x_do_first_power_on(struct mdm_ctrl *mdm) mdm_toggle_soft_reset(mdm, false); /* Add a delay to allow PON sequence to complete*/ msleep(150); + esoc_mdm_log("Setting AP2MDM_STATUS = 1\n"); gpio_direction_output(MDM_GPIO(mdm, AP2MDM_STATUS), 1); if (gpio_is_valid(MDM_GPIO(mdm, MDM2AP_PBLRDY))) { for (i = 0; i < MDM_PBLRDY_CNT; i++) { @@ -98,8 +108,10 @@ static int mdm4x_do_first_power_on(struct mdm_ctrl *mdm) * Send request for image. Let userspace confirm establishment of * link to external modem. */ - else + else { + esoc_mdm_log("Queueing the request: ESOC_REQ_IMG\n"); esoc_clink_queue_request(ESOC_REQ_IMG, mdm->esoc); + } return 0; } @@ -134,6 +146,7 @@ static int sdx50m_power_down(struct mdm_ctrl *mdm) struct device *dev = mdm->dev; int soft_reset_direction = mdm->soft_reset_inverted ? 1 : 0; /* Assert the soft reset line whether mdm2ap_status went low or not */ + esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n", soft_reset_direction); gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET), soft_reset_direction); dev_dbg(dev, "Doing a hard reset\n"); @@ -152,6 +165,7 @@ static int sdx50m_power_down(struct mdm_ctrl *mdm) static void mdm9x55_cold_reset(struct mdm_ctrl *mdm) { dev_dbg(mdm->dev, "Triggering mdm cold reset"); + gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET), !!mdm->soft_reset_inverted); @@ -168,6 +182,8 @@ static void mdm9x55_cold_reset(struct mdm_ctrl *mdm) static void sdx50m_cold_reset(struct mdm_ctrl *mdm) { dev_dbg(mdm->dev, "Triggering mdm cold reset"); + esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n", + !!mdm->soft_reset_inverted); gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET), !!mdm->soft_reset_inverted); @@ -177,6 +193,8 @@ static void sdx50m_cold_reset(struct mdm_ctrl *mdm) */ mdelay(600); + esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n", + !!mdm->soft_reset_inverted); gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET), !mdm->soft_reset_inverted); } diff --git a/drivers/esoc/esoc.h b/drivers/esoc/esoc.h index ca96ce291ae4..81dd0dfe1cad 100644 --- a/drivers/esoc/esoc.h +++ b/drivers/esoc/esoc.h @@ -23,6 +23,18 @@ #include #include #include +#include + +#define ESOC_MDM_IPC_PAGES 10 + +extern void *ipc_log; + +#define esoc_mdm_log(__msg, ...) \ +do { \ + if (ipc_log) \ + ipc_log_string(ipc_log, \ + "[%s]: "__msg, __func__, ##__VA_ARGS__); \ +} while (0) #define ESOC_DEV_MAX 4 #define ESOC_NAME_LEN 20 diff --git a/drivers/esoc/esoc_dev.c b/drivers/esoc/esoc_dev.c index 214a48883c37..6777627daee5 100644 --- a/drivers/esoc/esoc_dev.c +++ b/drivers/esoc/esoc_dev.c @@ -140,13 +140,16 @@ void esoc_udev_handle_clink_req(enum esoc_req req, struct esoc_eng *eng) struct esoc_clink *esoc_clink = eng->esoc_clink; struct esoc_udev *esoc_udev = esoc_udev_get_by_minor(esoc_clink->id); - if (!esoc_udev) + if (!esoc_udev) { + esoc_mdm_log("esoc_udev not found\n"); return; + } clink_req = (u32)req; err = kfifo_in_spinlocked(&esoc_udev->req_fifo, &clink_req, sizeof(clink_req), &esoc_udev->req_fifo_lock); if (err != sizeof(clink_req)) { + esoc_mdm_log("Unable to queue request %d; err: %d\n", req, err); pr_err("unable to queue request for %s\n", esoc_clink->name); return; } @@ -160,13 +163,16 @@ void esoc_udev_handle_clink_evt(enum esoc_evt evt, struct esoc_eng *eng) struct esoc_clink *esoc_clink = eng->esoc_clink; struct esoc_udev *esoc_udev = esoc_udev_get_by_minor(esoc_clink->id); - if (!esoc_udev) + if (!esoc_udev) { + esoc_mdm_log("esoc_udev not found\n"); return; + } clink_evt = (u32)evt; err = kfifo_in_spinlocked(&esoc_udev->evt_fifo, &clink_evt, sizeof(clink_evt), &esoc_udev->evt_fifo_lock); if (err != sizeof(clink_evt)) { + esoc_mdm_log("Unable to queue event %d; err: %d\n", evt, err); pr_err("unable to queue event for %s\n", esoc_clink->name); return; } @@ -230,25 +236,39 @@ static long esoc_dev_ioctl(struct file *file, unsigned int cmd, switch (cmd) { case ESOC_REG_REQ_ENG: + esoc_mdm_log("ESOC_REG_REQ_ENG\n"); err = esoc_clink_register_req_eng(esoc_clink, &uhandle->eng); - if (err) + if (err) { + esoc_mdm_log("ESOC_REG_REQ_ENG failed: %d\n", err); return err; + } uhandle->req_eng_reg = true; break; case ESOC_REG_CMD_ENG: + esoc_mdm_log("ESOC_REG_CMD_ENG\n"); err = esoc_clink_register_cmd_eng(esoc_clink, &uhandle->eng); - if (err) + if (err) { + esoc_mdm_log("ESOC_REG_CMD_ENG failed: %d\n", err); return err; + } uhandle->cmd_eng_reg = true; break; case ESOC_CMD_EXE: - if (esoc_clink->cmd_eng != &uhandle->eng) + if (esoc_clink->cmd_eng != &uhandle->eng) { + esoc_mdm_log("ESOC_CMD_EXE failed to access\n"); return -EACCES; + } get_user(esoc_cmd, (u32 __user *)arg); + esoc_mdm_log("ESOC_CMD_EXE: Executing esoc command: %u\n", + esoc_cmd); return clink_ops->cmd_exe(esoc_cmd, esoc_clink); case ESOC_WAIT_FOR_REQ: - if (esoc_clink->req_eng != &uhandle->eng) + if (esoc_clink->req_eng != &uhandle->eng) { + esoc_mdm_log("ESOC_WAIT_FOR_REQ: Failed to access\n"); return -EACCES; + } + esoc_mdm_log( + "ESOC_WAIT_FOR_REQ: Waiting for req event to arrive.\n"); err = wait_event_interruptible(esoc_udev->req_wait, !kfifo_is_empty(&esoc_udev->req_fifo)); if (!err) { @@ -256,27 +276,40 @@ static long esoc_dev_ioctl(struct file *file, unsigned int cmd, sizeof(req), &esoc_udev->req_fifo_lock); if (err != sizeof(req)) { + esoc_mdm_log( + "ESOC_WAIT_FOR_REQ: Failed to read the event\n"); pr_err("read from clink %s req q failed\n", esoc_clink->name); return -EIO; } put_user(req, (unsigned int __user *)uarg); + esoc_mdm_log( + "ESOC_WAIT_FOR_REQ: Event arrived: %u\n", req); } return err; case ESOC_NOTIFY: get_user(esoc_cmd, (u32 __user *)arg); + esoc_mdm_log("ESOC_NOTIFY: Notifying esoc about cmd: %u\n", + esoc_cmd); clink_ops->notify(esoc_cmd, esoc_clink); break; case ESOC_GET_STATUS: clink_ops->get_status(&status, esoc_clink); + esoc_mdm_log( + "ESOC_GET_STATUS: Sending the status from esoc: %u\n", status); put_user(status, (unsigned int __user *)uarg); break; case ESOC_GET_ERR_FATAL: clink_ops->get_err_fatal(&status, esoc_clink); + esoc_mdm_log( + "ESOC_GET_ERR_FATAL: Sending err_fatal status from esoc: %u\n", + status); put_user(status, (unsigned int __user *)uarg); break; case ESOC_WAIT_FOR_CRASH: + esoc_mdm_log( + "ESOC_WAIT_FOR_CRASH: Waiting for evt to arrive..\n"); err = wait_event_interruptible(esoc_udev->evt_wait, !kfifo_is_empty(&esoc_udev->evt_fifo)); if (!err) { @@ -284,11 +317,15 @@ static long esoc_dev_ioctl(struct file *file, unsigned int cmd, sizeof(evt), &esoc_udev->evt_fifo_lock); if (err != sizeof(evt)) { + esoc_mdm_log( + "ESOC_WAIT_FOR_CRASH: Failed to read event\n"); pr_err("read from clink %s evt q failed\n", esoc_clink->name); return -EIO; } put_user(evt, (unsigned int __user *)uarg); + esoc_mdm_log("ESOC_WAIT_FOR_CRASH: Event arrived: %u\n", + req); } return err; case ESOC_GET_LINK_ID: @@ -309,12 +346,14 @@ static int esoc_dev_open(struct inode *inode, struct file *file) esoc_udev = esoc_udev_get_by_minor(minor); if (!esoc_udev) { + esoc_mdm_log("failed to get udev\n"); pr_err("failed to get udev\n"); return -ENOMEM; } esoc_clink = get_esoc_clink(esoc_udev->clink->id); if (!esoc_clink) { + esoc_mdm_log("failed to get clink\n"); pr_err("failed to get clink\n"); return -ENOMEM; } @@ -330,6 +369,8 @@ static int esoc_dev_open(struct inode *inode, struct file *file) eng->handle_clink_req = esoc_udev_handle_clink_req; eng->handle_clink_evt = esoc_udev_handle_clink_evt; file->private_data = uhandle; + esoc_mdm_log( + "%s successfully attached to esoc driver\n", current->comm); return 0; } @@ -339,14 +380,23 @@ static int esoc_dev_release(struct inode *inode, struct file *file) struct esoc_uhandle *uhandle = file->private_data; esoc_clink = uhandle->esoc_clink; - if (uhandle->req_eng_reg) + if (uhandle->req_eng_reg) { + esoc_mdm_log("Unregistering req_eng\n"); esoc_clink_unregister_req_eng(esoc_clink, &uhandle->eng); - if (uhandle->cmd_eng_reg) + } else { + esoc_mdm_log("No req_eng to unregister\n"); + } + if (uhandle->cmd_eng_reg) { + esoc_mdm_log("Unregistering cmd_eng\n"); esoc_clink_unregister_cmd_eng(esoc_clink, &uhandle->eng); + } else { + esoc_mdm_log("No cmd_eng to unregister\n"); + } uhandle->req_eng_reg = false; uhandle->cmd_eng_reg = false; put_esoc_clink(esoc_clink); kfree(uhandle); + esoc_mdm_log("%s Unregistered with esoc\n", current->comm); return 0; } static const struct file_operations esoc_dev_fops = { -- GitLab From ab3ff7ff8bef7d95d6108f9e4acb197859424bc5 Mon Sep 17 00:00:00 2001 From: Kyle Piefer Date: Wed, 11 Apr 2018 11:22:14 -0700 Subject: [PATCH 0056/1299] msm: kgsl: Count inter-frame power collapses It is useful to know how many times inter-frame power collapse happens. Enable the IFPC counters and add a trace and a sysfs node to allow tracking the count. Change-Id: I670126d9e61f3831b6c60b895ba373a3be98a029 Signed-off-by: Kyle Piefer --- drivers/gpu/msm/adreno.c | 23 +++++++++++++++++++++++ drivers/gpu/msm/adreno.h | 5 +++++ drivers/gpu/msm/adreno_sysfs.c | 7 +++++++ drivers/gpu/msm/adreno_trace.h | 15 ++++++++++++++- 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 70e51e50187c..22df3e540ddf 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1967,6 +1967,17 @@ static int _adreno_start(struct adreno_device *adreno_dev) } } + if (gmu_core_isenabled(device) && adreno_dev->perfctr_ifpc_lo == 0) { + ret = adreno_perfcounter_get(adreno_dev, + KGSL_PERFCOUNTER_GROUP_GPMU_PWR, 4, + &adreno_dev->perfctr_ifpc_lo, NULL, + PERFCOUNTER_FLAG_KERNEL); + if (ret) { + WARN_ONCE(1, "Unable to get perf counter for IFPC\n"); + adreno_dev->perfctr_ifpc_lo = 0; + } + } + /* Clear the busy_data stats - we're starting over from scratch */ adreno_dev->busy_data.gpu_busy = 0; adreno_dev->busy_data.bif_ram_cycles = 0; @@ -1975,6 +1986,7 @@ static int _adreno_start(struct adreno_device *adreno_dev) adreno_dev->busy_data.bif_ram_cycles_write_ch1 = 0; adreno_dev->busy_data.bif_starved_ram = 0; adreno_dev->busy_data.bif_starved_ram_ch1 = 0; + adreno_dev->busy_data.num_ifpc = 0; /* Restore performance counter registers with saved values */ adreno_perfcounter_restore(adreno_dev); @@ -3456,6 +3468,17 @@ static void adreno_power_stats(struct kgsl_device *device, stats->ram_time = ram_cycles; stats->ram_wait = starved_ram; } + + if (adreno_dev->perfctr_ifpc_lo != 0) { + uint32_t num_ifpc; + + num_ifpc = counter_delta(device, adreno_dev->perfctr_ifpc_lo, + &busy->num_ifpc); + adreno_dev->ifpc_count += num_ifpc; + if (num_ifpc > 0) + trace_adreno_ifpc_count(adreno_dev->ifpc_count); + } + if (adreno_dev->lm_threshold_count && gpudev->count_throttles) gpudev->count_throttles(adreno_dev, adj); diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 952e48b53006..88c74c08fbaf 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -306,6 +306,7 @@ struct adreno_busy_data { unsigned int bif_ram_cycles_write_ch1; unsigned int bif_starved_ram; unsigned int bif_starved_ram_ch1; + unsigned int num_ifpc; unsigned int throttle_cycles[ADRENO_GPMU_THROTTLE_COUNTERS]; }; @@ -443,6 +444,7 @@ enum gpu_coresight_sources { * stall cycles in case of GBIF) * @starved_ram_lo_ch1: Number of cycles GBIF is stalled by DDR channel 1 * @perfctr_pwr_lo: GPU busy cycles + * @perfctr_ifpc_lo: IFPC count * @halt: Atomic variable to check whether the GPU is currently halted * @pending_irq_refcnt: Atomic variable to keep track of running IRQ handlers * @ctx_d_debugfs: Context debugfs node @@ -460,6 +462,7 @@ enum gpu_coresight_sources { * @lm_limit: limiting value for LM * @lm_threshold_count: register value for counter for lm threshold breakin * @lm_threshold_cross: number of current peaks exceeding threshold + * @ifpc_count: Number of times the GPU went into IFPC * @speed_bin: Indicate which power level set to use * @csdev: Pointer to a coresight device (if applicable) * @gpmu_throttle_counters - counteers for number of throttled clocks @@ -509,6 +512,7 @@ struct adreno_device { unsigned int starved_ram_lo; unsigned int starved_ram_lo_ch1; unsigned int perfctr_pwr_lo; + unsigned int perfctr_ifpc_lo; atomic_t halt; atomic_t pending_irq_refcnt; struct dentry *ctx_d_debugfs; @@ -528,6 +532,7 @@ struct adreno_device { uint32_t lm_limit; uint32_t lm_threshold_count; uint32_t lm_threshold_cross; + uint32_t ifpc_count; unsigned int speed_bin; unsigned int quirks; diff --git a/drivers/gpu/msm/adreno_sysfs.c b/drivers/gpu/msm/adreno_sysfs.c index 232770e347e5..a414e553cd7b 100644 --- a/drivers/gpu/msm/adreno_sysfs.c +++ b/drivers/gpu/msm/adreno_sysfs.c @@ -300,6 +300,11 @@ static unsigned int _ifpc_show(struct adreno_device *adreno_dev) return adreno_gmu_ifpc_show(adreno_dev); } +static unsigned int _ifpc_count_show(struct adreno_device *adreno_dev) +{ + return adreno_dev->ifpc_count; +} + static unsigned int _preempt_count_show(struct adreno_device *adreno_dev) { struct adreno_preemption *preempt = &adreno_dev->preempt; @@ -410,6 +415,7 @@ static ADRENO_SYSFS_BOOL(preemption); static ADRENO_SYSFS_BOOL(hwcg); static ADRENO_SYSFS_BOOL(throttling); static ADRENO_SYSFS_BOOL(ifpc); +static ADRENO_SYSFS_RO_U32(ifpc_count); @@ -431,6 +437,7 @@ static const struct device_attribute *_attr_list[] = { &adreno_attr_usesgmem.attr, &adreno_attr_skipsaverestore.attr, &adreno_attr_ifpc.attr, + &adreno_attr_ifpc_count.attr, &adreno_attr_preempt_count.attr, NULL, }; diff --git a/drivers/gpu/msm/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h index de028fad6a02..bf5e798839b0 100644 --- a/drivers/gpu/msm/adreno_trace.h +++ b/drivers/gpu/msm/adreno_trace.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -609,6 +609,19 @@ TRACE_EVENT(adreno_preempt_done, __entry->next->id, __entry->cur->id, __entry->level ) ); + +TRACE_EVENT(adreno_ifpc_count, + TP_PROTO(unsigned int ifpc_count), + TP_ARGS(ifpc_count), + TP_STRUCT__entry( + __field(unsigned int, ifpc_count) + ), + TP_fast_assign( + __entry->ifpc_count = ifpc_count; + ), + TP_printk("total times GMU entered IFPC = %d", __entry->ifpc_count) +); + #endif /* _ADRENO_TRACE_H */ /* This part must be outside protection */ -- GitLab From 9301ce8074f615b0de2d7b4733099e39c2c5a366 Mon Sep 17 00:00:00 2001 From: tharun kumar Date: Wed, 28 Jun 2017 16:56:10 +0530 Subject: [PATCH 0057/1299] msm: rdbg: Add snapshot of remote debugger driver The Remote Debugger driver allows a debugger running on a host PC to communicate with a remotestub running on peripheral subsystems. This snapshot was taken as of msm-3.10 commit ("Merge "msm: msm_bus: Provide valid input pointer argument") Change-Id: I944c298446d3786cb6fde20e4b2edaf02ce8e6f1 Acked-by: Chenna Kesava Raju Signed-off-by: Tharun Kumar Merugu --- Documentation/arm/msm/remote_debug_drv.txt | 468 +++++++ .../bindings/arm/msm/rdbg-smp2p.txt | 15 + drivers/char/Kconfig | 7 + drivers/char/Makefile | 3 +- drivers/char/rdbg.c | 1212 +++++++++++++++++ 5 files changed, 1704 insertions(+), 1 deletion(-) create mode 100644 Documentation/arm/msm/remote_debug_drv.txt create mode 100644 Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt create mode 100644 drivers/char/rdbg.c diff --git a/Documentation/arm/msm/remote_debug_drv.txt b/Documentation/arm/msm/remote_debug_drv.txt new file mode 100644 index 000000000000..13a35f43e86b --- /dev/null +++ b/Documentation/arm/msm/remote_debug_drv.txt @@ -0,0 +1,468 @@ +Introduction +============ + +The goal of this debug feature is to provide a reliable, responsive, +accurate and secure debug capability to developers interested in +debugging MSM subsystem processor images without the use of a hardware +debugger. + +The Debug Agent along with the Remote Debug Driver implements a shared +memory based transport mechanism that allows for a debugger (ex. GDB) +running on a host PC to communicate with a remote stub running on +peripheral subsystems such as the ADSP, MODEM etc. + +The diagram below depicts end to end the components involved to +support remote debugging: + + +: : +: HOST (PC) : MSM +: ,--------, : ,-------, +: | | : | Debug | ,--------, +: |Debugger|<--:-->| Agent | | Remote | +: | | : | App | +----->| Debug | +: `--------` : |-------| ,--------, | | Stub | +: : | Remote| | |<---+ `--------` +: : | Debug |<-->|--------| +: : | Driver| | |<---+ ,--------, +: : `-------` `--------` | | Remote | +: : LA Shared +----->| Debug | +: : Memory | Stub | +: : `--------` +: : Peripheral Subsystems +: : (ADSP, MODEM, ...) + + +Debugger: Debugger application running on the host PC that + communicates with the remote stub. + Examples: GDB, LLDB + +Debug Agent: Software that runs on the Linux Android platform + that provides connectivity from the MSM to the + host PC. This involves two portions: + 1) User mode Debug Agent application that discovers + processes running on the subsystems and creates + TCP/IP sockets for the host to connect to. In addition + to this, it creates an info (or meta) port that + users can connect to discover the various + processes and their corresponding debug ports. + +Remote Debug A character based driver that the Debug +Driver: Agent uses to transport the payload received from the + host to the debug stub running on the subsystem + processor over shared memory and vice versa. + +Shared Memory: Shared memory from the SMEM pool that is accessible + from the Applications Processor (AP) and the + subsystem processors. + +Remote Debug Privileged code that runs in the kernels of the +Stub: subsystem processors that receives debug commands + from the debugger running on the host and + acts on these commands. These commands include reading + and writing to registers and memory belonging to the + subsystem's address space, setting breakpoints, + single stepping etc. + +Hardware description +==================== + +The Remote Debug Driver interfaces with the Remote Debug stubs +running on the subsystem processors and does not drive or +manage any hardware resources. + +Software description +==================== + +The debugger and the remote stubs use Remote Serial Protocol (RSP) +to communicate with each other. This is widely used protocol by both +software and hardware debuggers. RSP is an ASCII based protocol +and used when it is not possible to run GDB server on the target under +debug. + +The Debug Agent application along with the Remote Debug Driver +is responsible for establishing a bi-directional connection from +the debugger application running on the host to the remote debug +stub running on a subsystem. The Debug Agent establishes connectivity +to the host PC via TCP/IP sockets. + +This feature uses ADB port forwarding to establish connectivity +between the debugger running on the host and the target under debug. + +Please note the Debug Agent does not expose HLOS memory to the +remote subsystem processors. + +Design +====== + +Here is the overall flow: + +1) When the Debug Agent application starts up, it opens up a shared memory +based transport channel to the various subsystem processor images. + +2) The Debug Agent application sends messages across to the remote stubs +to discover the various processes that are running on the subsystem and +creates debug sockets for each of them. + +3) Whenever a process running on a subsystem exits, the Debug Agent +is notified by the stub so that the debug port and other resources +can be reclaimed. + +4) The Debug Agent uses the services of the Remote Debug Driver to +transport payload from the host debugger to the remote stub and vice versa. + +5) Communication between the Remote Debug Driver and the Remote Debug stub +running on the subsystem processor is done over shared memory (see figure). +SMEM services are used to allocate the shared memory that will +be readable and writeable by the AP and the subsystem image under debug. + +A separate SMEM allocation takes place for each subsystem processor +involved in remote debugging. The remote stub running on each of the +subsystems allocates a SMEM buffer using a unique identifier so that both +the AP and subsystem get the same physical block of memory. It should be +noted that subsystem images can be restarted at any time. +However, when a subsystem comes back up, its stub uses the same unique +SMEM identifier to allocate the SMEM block. This would not result in a +new allocation rather the same block of memory in the first bootup instance +is provided back to the stub running on the subsystem. + +An 8KB chunk of shared memory is allocated and used for communication +per subsystem. For multi-process capable subsystems, 16KB chunk of shared +memory is allocated to allow for simultaneous debugging of more than one +process running on a single subsystem. + +The shared memory is used as a circular ring buffer in each direction. +Thus we have a bi-directional shared memory channel between the AP +and a subsystem. We call this SMQ. Each memory channel contains a header, +data and a control mechanism that is used to synchronize read and write +of data between the AP and the remote subsystem. + +Overall SMQ memory view: +: +: +------------------------------------------------+ +: | SMEM buffer | +: |-----------------------+------------------------| +: |Producer: LA | Producer: Remote | +: |Consumer: Remote | subsystem | +: | subsystem | Consumer: LA | +: | | | +: | Producer| Consumer| +: +-----------------------+------------------------+ +: | | +: | | +: | +--------------------------------------+ +: | | +: | | +: v v +: +--------------------------------------------------------------+ +: | Header | Data | Control | +: +-----------+---+---+---+-----+----+--+--+-----+---+--+--+-----+ +: | | b | b | b | | S |n |n | | S |n |n | | +: | Producer | l | l | l | | M |o |o | | M |o |o | | +: | Ver | o | o | o | | Q |d |d | | Q |d |d | | +: |-----------| c | c | c | ... | |e |e | ... | |e |e | ... | +: | | k | k | k | | O | | | | I | | | | +: | Consumer | | | | | u |0 |1 | | n |0 |1 | | +: | Ver | 0 | 1 | 2 | | t | | | | | | | | +: +-----------+---+---+---+-----+----+--+--+-----+---+--+--+-----+ +: | | +: + | +: | +: +------------------------+ +: | +: v +: +----+----+----+----+ +: | SMQ Nodes | +: |----|----|----|----| +: Node # | 0 | 1 | 2 | ...| +: |----|----|----|----| +: Starting Block Index # | 0 | 3 | 8 | ...| +: |----|----|----|----| +: # of blocks | 3 | 5 | 1 | ...| +: +----+----+----+----+ +: + +Header: Contains version numbers for software compatibility to ensure +that both producers and consumers on the AP and subsystems know how to +read from and write to the queue. +Both the producer and consumer versions are 1. +: +---------+-------------------+ +: | Size | Field | +: +---------+-------------------+ +: | 1 byte | Producer Version | +: +---------+-------------------+ +: | 1 byte | Consumer Version | +: +---------+-------------------+ + + +Data: The data portion contains multiple blocks [0..N] of a fixed size. +The block size SM_BLOCKSIZE is fixed to 128 bytes for header version #1. +Payload sent from the debug agent app is split (if necessary) and placed +in these blocks. The first data block is placed at the next 8 byte aligned +address after the header. + +The number of blocks for a given SMEM allocation is derived as follows: + Number of Blocks = ((Total Size - Alignment - Size of Header + - Size of SMQIn - Size of SMQOut)/(SM_BLOCKSIZE)) + +The producer maintains a private block map of each of these blocks to +determine which of these blocks in the queue is available and which are free. + +Control: +The control portion contains a list of nodes [0..N] where N is number +of available data blocks. Each node identifies the data +block indexes that contain a particular debug message to be transferred, +and the number of blocks it took to hold the contents of the message. + +Each node has the following structure: +: +---------+-------------------+ +: | Size | Field | +: +---------+-------------------+ +: | 2 bytes |Staring Block Index| +: +---------+-------------------+ +: | 2 bytes |Number of Blocks | +: +---------+-------------------+ + +The producer and the consumer update different parts of the control channel +(SMQOut / SMQIn) respectively. Each of these control data structures contains +information about the last node that was written / read, and the actual nodes +that were written/read. + +SMQOut Structure (R/W by producer, R by consumer): +: +---------+-------------------+ +: | Size | Field | +: +---------+-------------------+ +: | 4 bytes | Magic Init Number | +: +---------+-------------------+ +: | 4 bytes | Reset | +: +---------+-------------------+ +: | 4 bytes | Last Sent Index | +: +---------+-------------------+ +: | 4 bytes | Index Free Read | +: +---------+-------------------+ + +SMQIn Structure (R/W by consumer, R by producer): +: +---------+-------------------+ +: | Size | Field | +: +---------+-------------------+ +: | 4 bytes | Magic Init Number | +: +---------+-------------------+ +: | 4 bytes | Reset ACK | +: +---------+-------------------+ +: | 4 bytes | Last Read Index | +: +---------+-------------------+ +: | 4 bytes | Index Free Write | +: +---------+-------------------+ + +Magic Init Number: +Both SMQ Out and SMQ In initialize this field with a predefined magic +number so as to make sure that both the consumer and producer blocks +have fully initialized and have valid data in the shared memory control area. + Producer Magic #: 0xFF00FF01 + Consumer Magic #: 0xFF00FF02 + +SMQ Out's Last Sent Index and Index Free Read: + Only a producer can write to these indexes and they are updated whenever + there is new payload to be inserted into the SMQ in order to be sent to a + consumer. + + The number of blocks required for the SMQ allocation is determined as: + (payload size + SM_BLOCKSIZE - 1) / SM_BLOCKSIZE + + The private block map is searched for a large enough continuous set of blocks + and the user data is copied into the data blocks. + + The starting index of the free block(s) is updated in the SMQOut's Last Sent + Index. This update keeps track of which index was last written to and the + producer uses it to determine where the the next allocation could be done. + + Every allocation, a producer updates the Index Free Read from its + collaborating consumer's Index Free Write field (if they are unequal). + This index value indicates that the consumer has read all blocks associated + with allocation on the SMQ and that the producer can reuse these blocks for + subsquent allocations since this is a circular queue. + + At cold boot and restart, these indexes are initialized to zero and all + blocks are marked as available for allocation. + +SMQ In's Last Read Index and Index Free Write: + These indexes are written to only by a consumer and are updated whenever + there is new payload to be read from the SMQ. The Last Read Index keeps + track of which index was last read by the consumer and using this, it + determines where the next read should be done. + After completing a read, Last Read Index is incremented to the + next block index. A consumer updates Index Free Write to the starting + index of an allocation whenever it has completed processing the blocks. + This is an optimization that can be used to prevent an additional copy + of data from the queue into a client's data buffer and the data in the queue + itself can be used. + Once Index Free Write is updated, the collaborating producer (on the next + data allocation) reads the updated Index Free Write value and it then + updates its corresponding SMQ Out's Index Free Read and marks the blocks + associated with that index as available for allocation. At cold boot and + restart, these indexes are initialized to zero. + +SMQ Out Reset# and SMQ In Reset ACK #: + Since subsystems can restart at anytime, the data blocks and control channel + can be in an inconsistent state when a producer or consumer comes up. + We use Reset and Reset ACK to manage this. At cold boot, the producer + initializes the Reset# to a known number ex. 1. Every other reset that the + producer undergoes, the Reset#1 is simply incremented by 1. All the producer + indexes are reset. + When the producer notifies the consumer of data availability, the consumer + reads the producers Reset # and copies that into its SMQ In Reset ACK# + field when they differ. When that occurs, the consumer resets its + indexes to 0. + +6) Asynchronous notifications between a producer and consumer are +done using the SMP2P service which is interrupt based. + +Power Management +================ + +None + +SMP/multi-core +============== + +The driver uses completion to wake up the Debug Agent client threads. + +Security +======== + +From the perspective of the subsystem, the AP is untrusted. The remote +stubs consult the secure debug fuses to determine whether or not the +remote debugging will be enabled at the subsystem. + +If the hardware debug fuses indicate that debugging is disabled, the +remote stubs will not be functional on the subsystem. Writes to the +queue will only be done if the driver sees that the remote stub has been +initialized on the subsystem. + +Therefore even if any untrusted software running on the AP requests +the services of the Remote Debug Driver and inject RSP messages +into the shared memory buffer, these RSP messages will be discarded and +an appropriate error code will be sent up to the invoking application. + +Performance +=========== + +During operation, the Remote Debug Driver copies RSP messages +asynchronously sent from the host debugger to the remote stub and vice +versa. The debug messages are ASCII based and relatively short +(<25 bytes) and may once in a while go up to a maximum 700 bytes +depending on the command the user requested. Thus we do not +anticipate any major performance impact. Moreover, in a typical +functional debug scenario performance should not be a concern. + +Interface +========= + +The Remote Debug Driver is a character based device that manages +a piece of shared memory that is used as a bi-directional +single producer/consumer circular queue using a next fit allocator. +Every subsystem, has its own shared memory buffer that is managed +like a separate device. + +The driver distinguishes each subsystem processor's buffer by +registering a node with a different minor number. + +For each subsystem that is supported, the driver exposes a user space +interface through the following node: + - /dev/rdbg- + Ex. /dev/rdbg-adsp (for the ADSP subsystem) + +The standard open(), close(), read() and write() API set is +implemented. + +The open() syscall will fail if a subsystem is not present or supported +by the driver or a shared memory buffer cannot be allocated for the +AP - subsystem communication. It will also fail if the subsytem has +not initialized the queue on its side. Here are the error codes returned +in case a call to open() fails: +ENODEV - memory was not yet allocated for the device +EEXIST - device is already opened +ENOMEM - SMEM allocation failed +ECOMM - Subsytem queue is not yet setup +ENOMEM - Failure to initialize SMQ + +read() is a blocking call that will return with the number of bytes written +by the subsystem whenever the subsystem sends it some payload. Here are the +error codes returned in case a call to read() fails: +EINVAL - Invalid input +ENODEV - Device has not been opened yet +ERESTARTSYS - call to wait_for_completion_interruptible is interrupted +ENODATA - call to smq_receive failed + +write() attempts to send user mode payload out to the subsystem. It can fail +if the SMQ is full. The number of bytes written is returned back to the user. +Here are the error codes returned in case a call to write() fails: +EINVAL - Invalid input +ECOMM - SMQ send failed + +In the close() syscall, the control information state of the SMQ is +initialized to zero thereby preventing any further communication between +the AP and the subsystem. Here is the error code returned in case +a call to close() fails: +ENODEV - device wasn't opened/initialized + +The Remote Debug driver uses SMP2P for bi-directional AP to subsystem +notification. Notifications are sent to indicate that there are new +debug messages available for processing. Each subsystem that is +supported will need to add a device tree entry per the usage +specification of SMP2P driver. + +In case the remote stub becomes non operational or the security configuration +on the subsystem does not permit debugging, any messages put in the SMQ will +not be responded to. It is the responsibility of the Debug Agent app and the +host debugger application such as GDB to timeout and notify the user of the +non availability of remote debugging. + +Driver parameters +================= + +None + +Config options +============== + +The driver is configured with a device tree entry to map an SMP2P entry +to the device. The SMP2P entry name used is "rdbg". Please see +kernel\Documentation\arm\msm\msm_smp2p.txt for information about the +device tree entry required to configure SMP2P. + +The driver uses the SMEM allocation type SMEM_LC_DEBUGGER to allocate memory +for the queue that is used to share data with the subsystems. + +Dependencies +============ + +The Debug Agent driver requires services of SMEM to +allocate shared memory buffers. + +SMP2P is used as a bi-directional notification +mechanism between the AP and a subsystem processor. + +User space utilities +==================== + +This driver is meant to be used in conjunction with the user mode +Remote Debug Agent application. + +Other +===== + +None + +Known issues +============ +For targets with an external subsystem, we cannot use +shared memory for communication and would have to use the prevailing +transport mechanisms that exists between the AP and the external subsystem. + +This driver cannot be leveraged for such targets. + +To do +===== + +None diff --git a/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt b/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt new file mode 100644 index 000000000000..3965ec54dacf --- /dev/null +++ b/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt @@ -0,0 +1,15 @@ +Qualcomm Technologies, Inc. Remote Debugger (RDBG) driver + +Required properties: +-compatible : Should be one of + To communicate with adsp + qcom,smp2p-interrupt-rdbg-2-in (inbound) + qcom,smp2p-interrupt-rdbg-2-out (outbound) + To communicate with cdsp + qcom,smp2p-interrupt-rdbg-5-in (inbound) + qcom,smp2p-interrupt-rdbg-5-out (outbound) + +Example: + qcom,smp2p_interrupt_rdbg_2_in { + compatible = "qcom,smp2p-interrupt-rdbg-2-in"; + }; diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index d96a3842a400..28019ef948d9 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -606,5 +606,12 @@ config MSM_ADSPRPC applications DSP processor. Say M if you want to enable this module. +config MSM_RDBG + tristate "QTI Remote debug driver" + help + Implements a shared memory based transport mechanism that allows + for a debugger running on a host PC to communicate with a remote + stub running on peripheral subsystems such as the ADSP, MODEM etc. + endmenu diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 96ecee7cebc0..f40528c0ac81 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -65,4 +65,5 @@ obj-$(CONFIG_MSM_ADSPRPC) += adsprpc.o ifdef CONFIG_COMPAT obj-$(CONFIG_MSM_ADSPRPC) += adsprpc_compat.o endif -obj-$(CONFIG_MSM_FASTCVPD) += fastcvpd.o \ No newline at end of file +obj-$(CONFIG_MSM_FASTCVPD) += fastcvpd.o +obj-$(CONFIG_MSM_RDBG) += rdbg.o diff --git a/drivers/char/rdbg.c b/drivers/char/rdbg.c new file mode 100644 index 000000000000..0c623221bd1c --- /dev/null +++ b/drivers/char/rdbg.c @@ -0,0 +1,1212 @@ +/* + * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMP2P_NUM_PROCS 16 +#define MAX_RETRIES 20 + +#define SM_VERSION 1 +#define SM_BLOCKSIZE 128 + +#define SMQ_MAGIC_INIT 0xFF00FF00 +#define SMQ_MAGIC_PRODUCER (SMQ_MAGIC_INIT | 0x1) +#define SMQ_MAGIC_CONSUMER (SMQ_MAGIC_INIT | 0x2) + +#define SMEM_LC_DEBUGGER 470 + +enum SMQ_STATUS { + SMQ_SUCCESS = 0, + SMQ_ENOMEMORY = -1, + SMQ_EBADPARM = -2, + SMQ_UNDERFLOW = -3, + SMQ_OVERFLOW = -4 +}; + +enum smq_type { + PRODUCER = 1, + CONSUMER = 2, + INVALID = 3 +}; + +struct smq_block_map { + uint32_t index_read; + uint32_t num_blocks; + uint8_t *map; +}; + +struct smq_node { + uint16_t index_block; + uint16_t num_blocks; +} __attribute__ ((__packed__)); + +struct smq_hdr { + uint8_t producer_version; + uint8_t consumer_version; +} __attribute__ ((__packed__)); + +struct smq_out_state { + uint32_t init; + uint32_t index_check_queue_for_reset; + uint32_t index_sent_write; + uint32_t index_free_read; +} __attribute__ ((__packed__)); + +struct smq_out { + struct smq_out_state s; + struct smq_node sent[1]; +}; + +struct smq_in_state { + uint32_t init; + uint32_t index_check_queue_for_reset_ack; + uint32_t index_sent_read; + uint32_t index_free_write; +} __attribute__ ((__packed__)); + +struct smq_in { + struct smq_in_state s; + struct smq_node free[1]; +}; + +struct smq { + struct smq_hdr *hdr; + struct smq_out *out; + struct smq_in *in; + uint8_t *blocks; + uint32_t num_blocks; + struct mutex *lock; + uint32_t initialized; + struct smq_block_map block_map; + enum smq_type type; +}; + +struct gpio_info { + int gpio_base_id; + int irq_base_id; + unsigned int smem_bit; + struct qcom_smem_state *smem_state; +}; + +struct rdbg_data { + struct device *device; + struct completion work; + struct gpio_info in; + struct gpio_info out; + bool device_initialized; + int gpio_out_offset; + bool device_opened; + void *smem_addr; + size_t smem_size; + struct smq producer_smrb; + struct smq consumer_smrb; + struct mutex write_mutex; +}; + +struct rdbg_device { + struct cdev cdev; + struct class *class; + dev_t dev_no; + int num_devices; + struct rdbg_data *rdbg_data; +}; + + +int registers[32] = {0}; +static struct rdbg_device g_rdbg_instance = { + { {0} }, + NULL, + 0, + SMP2P_NUM_PROCS, + NULL +}; + +struct processor_specific_info { + char *name; + unsigned int smem_buffer_addr; + size_t smem_buffer_size; +}; + +static struct processor_specific_info proc_info[SMP2P_NUM_PROCS] = { + {0}, /*APPS*/ + {"rdbg_modem", 0, 0}, /*MODEM*/ + {"rdbg_adsp", SMEM_LC_DEBUGGER, 16*1024}, /*ADSP*/ + {0}, /*SMP2P_RESERVED_PROC_1*/ + {"rdbg_wcnss", 0, 0}, /*WCNSS*/ + {"rdbg_cdsp", SMEM_LC_DEBUGGER, 16*1024}, /*CDSP*/ + {NULL}, /*SMP2P_POWER_PROC*/ + {NULL}, /*SMP2P_TZ_PROC*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL} /*SMP2P_REMOTE_MOCK_PROC*/ +}; + +static int smq_blockmap_get(struct smq_block_map *block_map, + uint32_t *block_index, uint32_t n) +{ + uint32_t start; + uint32_t mark = 0; + uint32_t found = 0; + uint32_t i = 0; + + start = block_map->index_read; + + if (n == 1) { + do { + if (!block_map->map[block_map->index_read]) { + *block_index = block_map->index_read; + block_map->map[block_map->index_read] = 1; + block_map->index_read++; + block_map->index_read %= block_map->num_blocks; + return SMQ_SUCCESS; + } + block_map->index_read++; + } while (start != (block_map->index_read %= + block_map->num_blocks)); + } else { + mark = block_map->num_blocks; + + do { + if (!block_map->map[block_map->index_read]) { + if (mark > block_map->index_read) { + mark = block_map->index_read; + start = block_map->index_read; + found = 0; + } + + found++; + if (found == n) { + *block_index = mark; + for (i = 0; i < n; i++) + block_map->map[mark + i] = + (uint8_t)(n - i); + block_map->index_read += block_map->map + [block_map->index_read] - 1; + return SMQ_SUCCESS; + } + } else { + found = 0; + block_map->index_read += block_map->map + [block_map->index_read] - 1; + mark = block_map->num_blocks; + } + block_map->index_read++; + } while (start != (block_map->index_read %= + block_map->num_blocks)); + } + + return SMQ_ENOMEMORY; +} + +static void smq_blockmap_put(struct smq_block_map *block_map, uint32_t i) +{ + uint32_t num_blocks = block_map->map[i]; + + while (num_blocks--) { + block_map->map[i] = 0; + i++; + } +} + +static int smq_blockmap_reset(struct smq_block_map *block_map) +{ + if (!block_map->map) + return SMQ_ENOMEMORY; + memset(block_map->map, 0, block_map->num_blocks + 1); + block_map->index_read = 0; + + return SMQ_SUCCESS; +} + +static int smq_blockmap_ctor(struct smq_block_map *block_map, + uint32_t num_blocks) +{ + if (num_blocks <= 1) + return SMQ_ENOMEMORY; + + block_map->map = kcalloc(num_blocks, sizeof(uint8_t), GFP_KERNEL); + if (!block_map->map) + return SMQ_ENOMEMORY; + + block_map->num_blocks = num_blocks - 1; + smq_blockmap_reset(block_map); + + return SMQ_SUCCESS; +} + +static void smq_blockmap_dtor(struct smq_block_map *block_map) +{ + kfree(block_map->map); + block_map->map = NULL; +} + +static int smq_free(struct smq *smq, void *data) +{ + struct smq_node node; + uint32_t index_block; + int err = SMQ_SUCCESS; + + if (smq->lock) + mutex_lock(smq->lock); + + if ((smq->hdr->producer_version != SM_VERSION) && + (smq->out->s.init != SMQ_MAGIC_PRODUCER)) { + err = SMQ_UNDERFLOW; + goto bail; + } + + index_block = ((uint8_t *)data - smq->blocks) / SM_BLOCKSIZE; + if (index_block >= smq->num_blocks) { + err = SMQ_EBADPARM; + goto bail; + } + + node.index_block = (uint16_t)index_block; + node.num_blocks = 0; + *((struct smq_node *)(smq->in->free + + smq->in->s.index_free_write)) = node; + + smq->in->s.index_free_write = (smq->in->s.index_free_write + 1) + % smq->num_blocks; + +bail: + if (smq->lock) + mutex_unlock(smq->lock); + return err; +} + +static int smq_receive(struct smq *smq, void **pp, int *pnsize, int *pbmore) +{ + struct smq_node *node; + int err = SMQ_SUCCESS; + int more = 0; + + if ((smq->hdr->producer_version != SM_VERSION) && + (smq->out->s.init != SMQ_MAGIC_PRODUCER)) + return SMQ_UNDERFLOW; + + if (smq->in->s.index_sent_read == smq->out->s.index_sent_write) { + err = SMQ_UNDERFLOW; + goto bail; + } + + node = (struct smq_node *)(smq->out->sent + smq->in->s.index_sent_read); + if (node->index_block >= smq->num_blocks) { + err = SMQ_EBADPARM; + goto bail; + } + + smq->in->s.index_sent_read = (smq->in->s.index_sent_read + 1) + % smq->num_blocks; + + *pp = smq->blocks + (node->index_block * SM_BLOCKSIZE); + *pnsize = SM_BLOCKSIZE * node->num_blocks; + + /* + * Ensure that the reads and writes are updated in the memory + * when they are done and not cached. Also, ensure that the reads + * and writes are not reordered as they are shared between two cores. + */ + rmb(); + if (smq->in->s.index_sent_read != smq->out->s.index_sent_write) + more = 1; + +bail: + *pbmore = more; + return err; +} + +static int smq_alloc_send(struct smq *smq, const uint8_t *pcb, int nsize) +{ + void *pv = 0; + int num_blocks; + uint32_t index_block = 0; + int err = SMQ_SUCCESS; + struct smq_node *node = NULL; + + mutex_lock(smq->lock); + + if ((smq->in->s.init == SMQ_MAGIC_CONSUMER) && + (smq->hdr->consumer_version == SM_VERSION)) { + if (smq->out->s.index_check_queue_for_reset == + smq->in->s.index_check_queue_for_reset_ack) { + while (smq->out->s.index_free_read != + smq->in->s.index_free_write) { + node = (struct smq_node *)( + smq->in->free + + smq->out->s.index_free_read); + if (node->index_block >= smq->num_blocks) { + err = SMQ_EBADPARM; + goto bail; + } + + smq->out->s.index_free_read = + (smq->out->s.index_free_read + 1) + % smq->num_blocks; + + smq_blockmap_put(&smq->block_map, + node->index_block); + /* + * Ensure that the reads and writes are + * updated in the memory when they are done + * and not cached. Also, ensure that the reads + * and writes are not reordered as they are + * shared between two cores. + */ + rmb(); + } + } + } + + num_blocks = ALIGN(nsize, SM_BLOCKSIZE)/SM_BLOCKSIZE; + err = smq_blockmap_get(&smq->block_map, &index_block, num_blocks); + if (err != SMQ_SUCCESS) + goto bail; + + pv = smq->blocks + (SM_BLOCKSIZE * index_block); + + err = copy_from_user((void *)pv, (void *)pcb, nsize); + if (err != 0) + goto bail; + + ((struct smq_node *)(smq->out->sent + + smq->out->s.index_sent_write))->index_block + = (uint16_t)index_block; + ((struct smq_node *)(smq->out->sent + + smq->out->s.index_sent_write))->num_blocks + = (uint16_t)num_blocks; + + smq->out->s.index_sent_write = (smq->out->s.index_sent_write + 1) + % smq->num_blocks; + +bail: + if (err != SMQ_SUCCESS) { + if (pv) + smq_blockmap_put(&smq->block_map, index_block); + } + mutex_unlock(smq->lock); + return err; +} + +static int smq_reset_producer_queue_internal(struct smq *smq, + uint32_t reset_num) +{ + int retval = 0; + uint32_t i; + + if (smq->type != PRODUCER) + goto bail; + + mutex_lock(smq->lock); + if (smq->out->s.index_check_queue_for_reset != reset_num) { + smq->out->s.index_check_queue_for_reset = reset_num; + for (i = 0; i < smq->num_blocks; i++) + (smq->out->sent + i)->index_block = 0xFFFF; + + smq_blockmap_reset(&smq->block_map); + smq->out->s.index_sent_write = 0; + smq->out->s.index_free_read = 0; + retval = 1; + } + mutex_unlock(smq->lock); + +bail: + return retval; +} + +static int smq_check_queue_reset(struct smq *p_cons, struct smq *p_prod) +{ + int retval = 0; + uint32_t reset_num, i; + + if ((p_cons->type != CONSUMER) || + (p_cons->out->s.init != SMQ_MAGIC_PRODUCER) || + (p_cons->hdr->producer_version != SM_VERSION)) + goto bail; + + reset_num = p_cons->out->s.index_check_queue_for_reset; + if (p_cons->in->s.index_check_queue_for_reset_ack != reset_num) { + p_cons->in->s.index_check_queue_for_reset_ack = reset_num; + for (i = 0; i < p_cons->num_blocks; i++) + (p_cons->in->free + i)->index_block = 0xFFFF; + + p_cons->in->s.index_sent_read = 0; + p_cons->in->s.index_free_write = 0; + + retval = smq_reset_producer_queue_internal(p_prod, reset_num); + } + +bail: + return retval; +} + +static int check_subsystem_debug_enabled(void *base_addr, int size) +{ + int num_blocks; + uint8_t *pb_orig; + uint8_t *pb; + struct smq smq; + int err = 0; + + pb = pb_orig = (uint8_t *)base_addr; + pb += sizeof(struct smq_hdr); + pb = PTR_ALIGN(pb, 8); + size -= pb - (uint8_t *)pb_orig; + num_blocks = (int)((size - sizeof(struct smq_out_state) - + sizeof(struct smq_in_state))/(SM_BLOCKSIZE + + sizeof(struct smq_node) * 2)); + if (num_blocks <= 0) { + err = SMQ_EBADPARM; + goto bail; + } + + pb += num_blocks * SM_BLOCKSIZE; + smq.out = (struct smq_out *)pb; + pb += sizeof(struct smq_out_state) + (num_blocks * + sizeof(struct smq_node)); + smq.in = (struct smq_in *)pb; + + if (smq.in->s.init != SMQ_MAGIC_CONSUMER) { + pr_err("%s, smq in consumer not initialized\n", __func__); + err = -ECOMM; + } + +bail: + return err; +} + +static void smq_dtor(struct smq *smq) +{ + if (smq->initialized == SMQ_MAGIC_INIT) { + switch (smq->type) { + case PRODUCER: + smq->out->s.init = 0; + smq_blockmap_dtor(&smq->block_map); + break; + case CONSUMER: + smq->in->s.init = 0; + break; + default: + case INVALID: + break; + } + + smq->initialized = 0; + } +} + +/* + * The shared memory is used as a circular ring buffer in each direction. + * Thus we have a bi-directional shared memory channel between the AP + * and a subsystem. We call this SMQ. Each memory channel contains a header, + * data and a control mechanism that is used to synchronize read and write + * of data between the AP and the remote subsystem. + * + * Overall SMQ memory view: + * + * +------------------------------------------------+ + * | SMEM buffer | + * |-----------------------+------------------------| + * |Producer: LA | Producer: Remote | + * |Consumer: Remote | subsystem | + * | subsystem | Consumer: LA | + * | | | + * | Producer| Consumer| + * +-----------------------+------------------------+ + * | | + * | | + * | +--------------------------------------+ + * | | + * | | + * v v + * +--------------------------------------------------------------+ + * | Header | Data | Control | + * +-----------+---+---+---+-----+----+--+--+-----+---+--+--+-----+ + * | | b | b | b | | S |n |n | | S |n |n | | + * | Producer | l | l | l | | M |o |o | | M |o |o | | + * | Ver | o | o | o | | Q |d |d | | Q |d |d | | + * |-----------| c | c | c | ... | |e |e | ... | |e |e | ... | + * | | k | k | k | | O | | | | I | | | | + * | Consumer | | | | | u |0 |1 | | n |0 |1 | | + * | Ver | 0 | 1 | 2 | | t | | | | | | | | + * +-----------+---+---+---+-----+----+--+--+-----+---+--+--+-----+ + * | | + * + | + * | + * +------------------------+ + * | + * v + * +----+----+----+----+ + * | SMQ Nodes | + * |----|----|----|----| + * Node # | 0 | 1 | 2 | ...| + * |----|----|----|----| + * Starting Block Index # | 0 | 3 | 8 | ...| + * |----|----|----|----| + * # of blocks | 3 | 5 | 1 | ...| + * +----+----+----+----+ + * + * Header: Contains version numbers for software compatibility to ensure + * that both producers and consumers on the AP and subsystems know how to + * read from and write to the queue. + * Both the producer and consumer versions are 1. + * +---------+-------------------+ + * | Size | Field | + * +---------+-------------------+ + * | 1 byte | Producer Version | + * +---------+-------------------+ + * | 1 byte | Consumer Version | + * +---------+-------------------+ + * + * Data: The data portion contains multiple blocks [0..N] of a fixed size. + * The block size SM_BLOCKSIZE is fixed to 128 bytes for header version #1. + * Payload sent from the debug agent app is split (if necessary) and placed + * in these blocks. The first data block is placed at the next 8 byte aligned + * address after the header. + * + * The number of blocks for a given SMEM allocation is derived as follows: + * Number of Blocks = ((Total Size - Alignment - Size of Header + * - Size of SMQIn - Size of SMQOut)/(SM_BLOCKSIZE)) + * + * The producer maintains a private block map of each of these blocks to + * determine which of these blocks in the queue is available and which are free. + * + * Control: + * The control portion contains a list of nodes [0..N] where N is number + * of available data blocks. Each node identifies the data + * block indexes that contain a particular debug message to be transferred, + * and the number of blocks it took to hold the contents of the message. + * + * Each node has the following structure: + * +---------+-------------------+ + * | Size | Field | + * +---------+-------------------+ + * | 2 bytes |Staring Block Index| + * +---------+-------------------+ + * | 2 bytes |Number of Blocks | + * +---------+-------------------+ + * + * The producer and the consumer update different parts of the control channel + * (SMQOut / SMQIn) respectively. Each of these control data structures contains + * information about the last node that was written / read, and the actual nodes + * that were written/read. + * + * SMQOut Structure (R/W by producer, R by consumer): + * +---------+-------------------+ + * | Size | Field | + * +---------+-------------------+ + * | 4 bytes | Magic Init Number | + * +---------+-------------------+ + * | 4 bytes | Reset | + * +---------+-------------------+ + * | 4 bytes | Last Sent Index | + * +---------+-------------------+ + * | 4 bytes | Index Free Read | + * +---------+-------------------+ + * + * SMQIn Structure (R/W by consumer, R by producer): + * +---------+-------------------+ + * | Size | Field | + * +---------+-------------------+ + * | 4 bytes | Magic Init Number | + * +---------+-------------------+ + * | 4 bytes | Reset ACK | + * +---------+-------------------+ + * | 4 bytes | Last Read Index | + * +---------+-------------------+ + * | 4 bytes | Index Free Write | + * +---------+-------------------+ + * + * Magic Init Number: + * Both SMQ Out and SMQ In initialize this field with a predefined magic + * number so as to make sure that both the consumer and producer blocks + * have fully initialized and have valid data in the shared memory control area. + * Producer Magic #: 0xFF00FF01 + * Consumer Magic #: 0xFF00FF02 + */ +static int smq_ctor(struct smq *smq, void *base_addr, int size, + enum smq_type type, struct mutex *lock_ptr) +{ + int num_blocks; + uint8_t *pb_orig; + uint8_t *pb; + uint32_t i; + int err; + + if (smq->initialized == SMQ_MAGIC_INIT) { + err = SMQ_EBADPARM; + goto bail; + } + + if (!base_addr || !size) { + err = SMQ_EBADPARM; + goto bail; + } + + if (type == PRODUCER) + smq->lock = lock_ptr; + + pb_orig = (uint8_t *)base_addr; + smq->hdr = (struct smq_hdr *)pb_orig; + pb = pb_orig; + pb += sizeof(struct smq_hdr); + pb = PTR_ALIGN(pb, 8); + size -= pb - (uint8_t *)pb_orig; + num_blocks = (int)((size - sizeof(struct smq_out_state) - + sizeof(struct smq_in_state))/(SM_BLOCKSIZE + + sizeof(struct smq_node) * 2)); + if (num_blocks <= 0) { + err = SMQ_ENOMEMORY; + goto bail; + } + + smq->blocks = pb; + smq->num_blocks = num_blocks; + pb += num_blocks * SM_BLOCKSIZE; + smq->out = (struct smq_out *)pb; + pb += sizeof(struct smq_out_state) + (num_blocks * + sizeof(struct smq_node)); + smq->in = (struct smq_in *)pb; + smq->type = type; + if (type == PRODUCER) { + smq->hdr->producer_version = SM_VERSION; + for (i = 0; i < smq->num_blocks; i++) + (smq->out->sent + i)->index_block = 0xFFFF; + + err = smq_blockmap_ctor(&smq->block_map, smq->num_blocks); + if (err != SMQ_SUCCESS) + goto bail; + + smq->out->s.index_sent_write = 0; + smq->out->s.index_free_read = 0; + if (smq->out->s.init == SMQ_MAGIC_PRODUCER) { + smq->out->s.index_check_queue_for_reset += 1; + } else { + smq->out->s.index_check_queue_for_reset = 1; + smq->out->s.init = SMQ_MAGIC_PRODUCER; + } + } else { + smq->hdr->consumer_version = SM_VERSION; + for (i = 0; i < smq->num_blocks; i++) + (smq->in->free + i)->index_block = 0xFFFF; + + smq->in->s.index_sent_read = 0; + smq->in->s.index_free_write = 0; + if (smq->out->s.init == SMQ_MAGIC_PRODUCER) { + smq->in->s.index_check_queue_for_reset_ack = + smq->out->s.index_check_queue_for_reset; + } else { + smq->in->s.index_check_queue_for_reset_ack = 0; + } + + smq->in->s.init = SMQ_MAGIC_CONSUMER; + } + smq->initialized = SMQ_MAGIC_INIT; + err = SMQ_SUCCESS; + +bail: + return err; +} + +static void send_interrupt_to_subsystem(struct rdbg_data *rdbgdata) +{ + unsigned int offset = rdbgdata->gpio_out_offset; + unsigned int val; + + val = (registers[offset]) ^ (BIT(rdbgdata->out.smem_bit+offset)); + qcom_smem_state_update_bits(rdbgdata->out.smem_state, + BIT(rdbgdata->out.smem_bit+offset), val); + registers[offset] = val; + rdbgdata->gpio_out_offset = (offset + 1) % 32; +} + +static irqreturn_t on_interrupt_from(int irq, void *ptr) +{ + struct rdbg_data *rdbgdata = (struct rdbg_data *) ptr; + + dev_dbg(rdbgdata->device, "%s: Received interrupt %d from subsystem\n", + __func__, irq); + complete(&(rdbgdata->work)); + return IRQ_HANDLED; +} + +static int initialize_smq(struct rdbg_data *rdbgdata) +{ + int err = 0; + unsigned char *smem_consumer_buffer = rdbgdata->smem_addr; + + smem_consumer_buffer += (rdbgdata->smem_size/2); + + if (smq_ctor(&(rdbgdata->producer_smrb), (void *)(rdbgdata->smem_addr), + ((rdbgdata->smem_size)/2), PRODUCER, &rdbgdata->write_mutex)) { + dev_err(rdbgdata->device, "%s: smq producer allocation failed\n", + __func__); + err = -ENOMEM; + goto bail; + } + + if (smq_ctor(&(rdbgdata->consumer_smrb), (void *)smem_consumer_buffer, + ((rdbgdata->smem_size)/2), CONSUMER, NULL)) { + dev_err(rdbgdata->device, "%s: smq consumer allocation failed\n", + __func__); + err = -ENOMEM; + } + +bail: + return err; + +} + +static int rdbg_open(struct inode *inode, struct file *filp) +{ + int device_id = -1; + struct rdbg_device *device = &g_rdbg_instance; + struct rdbg_data *rdbgdata = NULL; + int err = 0; + + if (!inode || !device->rdbg_data) { + pr_err("Memory not allocated yet\n"); + err = -ENODEV; + goto bail; + } + + device_id = MINOR(inode->i_rdev); + rdbgdata = &device->rdbg_data[device_id]; + + if (rdbgdata->device_opened) { + dev_err(rdbgdata->device, "%s: Device already opened\n", + __func__); + err = -EEXIST; + goto bail; + } + + rdbgdata->smem_size = proc_info[device_id].smem_buffer_size; + if (!rdbgdata->smem_size) { + dev_err(rdbgdata->device, "%s: smem not initialized\n", + __func__); + err = -ENOMEM; + goto bail; + } + + rdbgdata->smem_addr = qcom_smem_get(QCOM_SMEM_HOST_ANY, + proc_info[device_id].smem_buffer_addr, + &(rdbgdata->smem_size)); + if (!rdbgdata->smem_addr) { + dev_err(rdbgdata->device, "%s: Could not allocate smem memory\n", + __func__); + err = -ENOMEM; + pr_err("rdbg:Could not allocate smem memory\n"); + goto bail; + } + dev_dbg(rdbgdata->device, "%s: SMEM address=0x%lx smem_size=%d\n", + __func__, (unsigned long)rdbgdata->smem_addr, + (unsigned int)rdbgdata->smem_size); + + if (check_subsystem_debug_enabled(rdbgdata->smem_addr, + rdbgdata->smem_size/2)) { + dev_err(rdbgdata->device, "%s: Subsystem %s is not debug enabled\n", + __func__, proc_info[device_id].name); + pr_err("rdbg:Sub system debug is not enabled\n"); + err = -ECOMM; + goto bail; + } + + init_completion(&rdbgdata->work); + + err = request_threaded_irq(rdbgdata->in.irq_base_id, NULL, + on_interrupt_from, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + proc_info[device_id].name, (void *)&device->rdbg_data[device_id]); + if (err) { + dev_err(rdbgdata->device, + "%s: Failed to register interrupt.Err=%d,irqid=%d.\n", + __func__, err, rdbgdata->in.irq_base_id); + pr_err("rdbg : Failed to register interrupt %d\n", err); + goto bail; + } + + mutex_init(&rdbgdata->write_mutex); + + err = initialize_smq(rdbgdata); + if (err) { + dev_err(rdbgdata->device, "Error initializing smq. Err=%d\n", + err); + pr_err("rdbg: initialize_smq() failed with err %d\n", err); + goto smq_bail; + } + + rdbgdata->device_opened = 1; + + filp->private_data = (void *)rdbgdata; + return 0; + +smq_bail: + smq_dtor(&(rdbgdata->producer_smrb)); + smq_dtor(&(rdbgdata->consumer_smrb)); + mutex_destroy(&rdbgdata->write_mutex); +bail: + return err; +} + +static int rdbg_release(struct inode *inode, struct file *filp) +{ + int device_id = -1; + struct rdbg_device *rdbgdevice = &g_rdbg_instance; + struct rdbg_data *rdbgdata = NULL; + int err = 0; + + if (!inode || !rdbgdevice->rdbg_data) { + pr_err("Memory not allocated yet\n"); + err = -ENODEV; + goto bail; + } + + device_id = MINOR(inode->i_rdev); + rdbgdata = &rdbgdevice->rdbg_data[device_id]; + + if (rdbgdata->device_opened == 1) { + dev_dbg(rdbgdata->device, "%s: Destroying %s.\n", __func__, + proc_info[device_id].name); + rdbgdata->device_opened = 0; + complete(&(rdbgdata->work)); + if (rdbgdevice->rdbg_data[device_id].producer_smrb.initialized) + smq_dtor(&( + rdbgdevice->rdbg_data[device_id].producer_smrb)); + if (rdbgdevice->rdbg_data[device_id].consumer_smrb.initialized) + smq_dtor(&( + rdbgdevice->rdbg_data[device_id].consumer_smrb)); + mutex_destroy(&rdbgdata->write_mutex); + } + + filp->private_data = NULL; + +bail: + return err; +} + +static ssize_t rdbg_read(struct file *filp, char __user *buf, size_t size, + loff_t *offset) +{ + int err = 0; + struct rdbg_data *rdbgdata = filp->private_data; + void *p_sent_buffer = NULL; + int nsize = 0; + int more = 0; + + if (!rdbgdata) { + pr_err("Invalid argument"); + err = -EINVAL; + goto bail; + } + + dev_dbg(rdbgdata->device, "%s: In receive\n", __func__); + err = wait_for_completion_interruptible(&(rdbgdata->work)); + if (err) { + dev_err(rdbgdata->device, "%s: Error in wait\n", __func__); + goto bail; + } + + smq_check_queue_reset(&(rdbgdata->consumer_smrb), + &(rdbgdata->producer_smrb)); + if (smq_receive(&(rdbgdata->consumer_smrb), &p_sent_buffer, + &nsize, &more) != SMQ_SUCCESS) { + dev_err(rdbgdata->device, "%s: Error in smq_recv(). Err code = %d\n", + __func__, err); + err = -ENODATA; + goto bail; + } + size = ((size < nsize) ? size : nsize); + err = copy_to_user(buf, p_sent_buffer, size); + if (err != 0) { + dev_err(rdbgdata->device, "%s: Error in copy_to_user(). Err code = %d\n", + __func__, err); + err = -ENODATA; + goto bail; + } + smq_free(&(rdbgdata->consumer_smrb), p_sent_buffer); + err = size; + dev_dbg(rdbgdata->device, "%s: Read data to buffer with address 0x%lx\n", + __func__, (unsigned long) buf); + +bail: + return err; +} + +static ssize_t rdbg_write(struct file *filp, const char __user *buf, + size_t size, loff_t *offset) +{ + int err = 0; + int num_retries = 0; + struct rdbg_data *rdbgdata = filp->private_data; + + if (!rdbgdata) { + pr_err("Invalid argument"); + err = -EINVAL; + goto bail; + } + + do { + err = smq_alloc_send(&(rdbgdata->producer_smrb), buf, size); + dev_dbg(rdbgdata->device, "%s, smq_alloc_send returned %d.\n", + __func__, err); + } while (err != 0 && num_retries++ < MAX_RETRIES); + + if (err != 0) { + pr_err("rdbg: send_interrupt_to_subsystem failed\n"); + err = -ECOMM; + goto bail; + } + + send_interrupt_to_subsystem(rdbgdata); + + err = size; + +bail: + return err; +} + +static const struct file_operations rdbg_fops = { + .open = rdbg_open, + .read = rdbg_read, + .write = rdbg_write, + .release = rdbg_release, +}; + +static int register_smp2p_out(struct device *dev, char *node_name, + struct gpio_info *gpio_info_ptr) +{ + struct device_node *node = dev->of_node; + + if (gpio_info_ptr) { + if (of_find_property(node, "qcom,smem-states", NULL)) { + gpio_info_ptr->smem_state = + qcom_smem_state_get(dev, "rdbg-smp2p-out", + &gpio_info_ptr->smem_bit); + if (IS_ERR_OR_NULL(gpio_info_ptr->smem_state)) + pr_err("rdbg: failed get smem state\n"); + } + return 0; + } + return -EINVAL; +} + +static int register_smp2p_in(struct device *dev, char *node_name, + struct gpio_info *gpio_info_ptr) +{ + int id = 0; + struct device_node *node = dev->of_node; + + if (gpio_info_ptr) { + id = of_irq_get_byname(node, "rdbg-smp2p-in"); + gpio_info_ptr->gpio_base_id = id; + gpio_info_ptr->irq_base_id = id; + return 0; + } + return -EINVAL; +} + +static int rdbg_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rdbg_device *rdbgdevice = &g_rdbg_instance; + int minor = 0; + int err = 0; + char *rdbg_compatible_string = "qcom,smp2p-interrupt-rdbg-"; + int max_len = strlen(rdbg_compatible_string) + strlen("xx-out"); + char *node_name = kcalloc(max_len, sizeof(char), GFP_KERNEL); + + if (!node_name) { + err = -ENOMEM; + goto bail; + } + for (minor = 0; minor < rdbgdevice->num_devices; minor++) { + if (!proc_info[minor].name) + continue; + if (snprintf(node_name, max_len, "%s%d-out", + rdbg_compatible_string, minor) <= 0) { + pr_err("Error in snprintf\n"); + err = -ENOMEM; + goto bail; + } + + if (of_device_is_compatible(dev->of_node, node_name)) { + if (register_smp2p_out(dev, node_name, + &rdbgdevice->rdbg_data[minor].out)) { + pr_err("register_smp2p_out failed for %s\n", + proc_info[minor].name); + err = -EINVAL; + goto bail; + } + } + if (snprintf(node_name, max_len, "%s%d-in", + rdbg_compatible_string, minor) <= 0) { + pr_err("Error in snprintf\n"); + err = -ENOMEM; + goto bail; + } + + if (of_device_is_compatible(dev->of_node, node_name)) { + if (register_smp2p_in(dev, node_name, + &rdbgdevice->rdbg_data[minor].in)) { + pr_err("register_smp2p_in failed for %s\n", + proc_info[minor].name); + } + } + } +bail: + kfree(node_name); + return err; +} + +static const struct of_device_id rdbg_match_table[] = { + { .compatible = "qcom,smp2p-interrupt-rdbg-2-out", }, + { .compatible = "qcom,smp2p-interrupt-rdbg-2-in", }, + { .compatible = "qcom,smp2p-interrupt-rdbg-5-out", }, + { .compatible = "qcom,smp2p-interrupt-rdbg-5-in", }, + {} +}; + +static struct platform_driver rdbg_driver = { + .probe = rdbg_probe, + .driver = { + .name = "rdbg", + .owner = THIS_MODULE, + .of_match_table = rdbg_match_table, + }, +}; + +static int __init rdbg_init(void) +{ + struct rdbg_device *rdbgdevice = &g_rdbg_instance; + int minor = 0; + int major = 0; + int minor_nodes_created = 0; + int err = 0; + + if (rdbgdevice->num_devices < 1 || + rdbgdevice->num_devices > SMP2P_NUM_PROCS) { + pr_err("rgdb: invalid num_devices\n"); + err = -EDOM; + goto bail; + } + rdbgdevice->rdbg_data = kcalloc(rdbgdevice->num_devices, + sizeof(struct rdbg_data), GFP_KERNEL); + if (!rdbgdevice->rdbg_data) { + err = -ENOMEM; + goto bail; + } + err = platform_driver_register(&rdbg_driver); + if (err) + goto bail; + err = alloc_chrdev_region(&rdbgdevice->dev_no, 0, + rdbgdevice->num_devices, "rdbgctl"); + if (err) { + pr_err("Error in alloc_chrdev_region.\n"); + goto data_bail; + } + major = MAJOR(rdbgdevice->dev_no); + + cdev_init(&rdbgdevice->cdev, &rdbg_fops); + rdbgdevice->cdev.owner = THIS_MODULE; + err = cdev_add(&rdbgdevice->cdev, MKDEV(major, 0), + rdbgdevice->num_devices); + if (err) { + pr_err("Error in cdev_add\n"); + goto chrdev_bail; + } + rdbgdevice->class = class_create(THIS_MODULE, "rdbg"); + if (IS_ERR(rdbgdevice->class)) { + err = PTR_ERR(rdbgdevice->class); + pr_err("Error in class_create\n"); + goto cdev_bail; + } + for (minor = 0; minor < rdbgdevice->num_devices; minor++) { + if (!proc_info[minor].name) + continue; + rdbgdevice->rdbg_data[minor].device = device_create( + rdbgdevice->class, NULL, MKDEV(major, minor), + NULL, "%s", proc_info[minor].name); + if (IS_ERR(rdbgdevice->rdbg_data[minor].device)) { + err = PTR_ERR(rdbgdevice->rdbg_data[minor].device); + pr_err("Error in device_create\n"); + goto device_bail; + } + rdbgdevice->rdbg_data[minor].device_initialized = 1; + minor_nodes_created++; + dev_dbg(rdbgdevice->rdbg_data[minor].device, + "%s: created /dev/%s c %d %d'\n", __func__, + proc_info[minor].name, major, minor); + } + if (!minor_nodes_created) { + pr_err("No device tree entries found\n"); + err = -EINVAL; + goto class_bail; + } + + goto bail; + +device_bail: + for (--minor; minor >= 0; minor--) { + if (rdbgdevice->rdbg_data[minor].device_initialized) + device_destroy(rdbgdevice->class, + MKDEV(MAJOR(rdbgdevice->dev_no), minor)); + } +class_bail: + class_destroy(rdbgdevice->class); +cdev_bail: + cdev_del(&rdbgdevice->cdev); +chrdev_bail: + unregister_chrdev_region(rdbgdevice->dev_no, rdbgdevice->num_devices); +data_bail: + kfree(rdbgdevice->rdbg_data); +bail: + return err; +} +module_init(rdbg_init); + +static void __exit rdbg_exit(void) +{ + struct rdbg_device *rdbgdevice = &g_rdbg_instance; + int minor; + + for (minor = 0; minor < rdbgdevice->num_devices; minor++) { + if (rdbgdevice->rdbg_data[minor].device_initialized) { + device_destroy(rdbgdevice->class, + MKDEV(MAJOR(rdbgdevice->dev_no), minor)); + } + } + class_destroy(rdbgdevice->class); + cdev_del(&rdbgdevice->cdev); + unregister_chrdev_region(rdbgdevice->dev_no, 1); + kfree(rdbgdevice->rdbg_data); +} +module_exit(rdbg_exit); + +MODULE_DESCRIPTION("rdbg module"); +MODULE_LICENSE("GPL v2"); -- GitLab From 4f77750070ae916a0f24f3c257817be2a01cee7c Mon Sep 17 00:00:00 2001 From: Lakshmi Narayana Kalavala Date: Thu, 7 Jun 2018 16:35:22 -0700 Subject: [PATCH 0058/1299] ARM: dts: msm: disable esd for video mode panels for sm8150 Disable ESD check for video mode panels for Truly 2k and Sharp 4k panels. Change-Id: I615c2e1c3e25e831f7068d9588832e0bcc91b7a4 Signed-off-by: Lakshmi Narayana Kalavala --- arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi index d50dd42bdbc4..1d49e1b9c58a 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi @@ -400,13 +400,6 @@ /* PHY TIMINGS REVISION P */ &dsi_dual_nt35597_truly_video { - qcom,esd-check-enabled; - qcom,mdss-dsi-panel-status-check-mode = "reg_read"; - qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a]; - qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode"; - qcom,mdss-dsi-panel-status-value = <0x9c>; - qcom,mdss-dsi-panel-on-check-value = <0x9c>; - qcom,mdss-dsi-panel-status-read-length = <1>; qcom,mdss-dsi-display-timings { timing@0{ qcom,mdss-dsi-panel-phy-timings = [00 1c 08 07 23 22 07 @@ -464,13 +457,6 @@ }; &dsi_sharp_4k_dsc_video { - qcom,esd-check-enabled; - qcom,mdss-dsi-panel-status-check-mode = "reg_read"; - qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0c]; - qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode"; - qcom,mdss-dsi-panel-status-value = <0x7>; - qcom,mdss-dsi-panel-on-check-value = <0x7>; - qcom,mdss-dsi-panel-status-read-length = <1>; qcom,mdss-dsi-display-timings { timing@0{ qcom,mdss-dsi-panel-phy-timings = [00 1e 08 07 24 22 08 -- GitLab From 41c1ee57e29436a4685bf3456ad3ecc51d3d4db5 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Fri, 8 Jun 2018 13:28:40 -0700 Subject: [PATCH 0059/1299] backlight: qcom-spmi-wled: Add missing break in wled_flash_led_prepare() Add the missing break statement in wled_flash_led_prepare() without which querying maximum current for flash/torch devices is broken. Change-Id: I79e21f464d677863cb2a6d8c71fe7c8152e536e9 Signed-off-by: Subbaraman Narayanamurthy --- drivers/video/backlight/qcom-spmi-wled.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/backlight/qcom-spmi-wled.c b/drivers/video/backlight/qcom-spmi-wled.c index 46c77a83b6f1..b5123b7c7c32 100644 --- a/drivers/video/backlight/qcom-spmi-wled.c +++ b/drivers/video/backlight/qcom-spmi-wled.c @@ -1527,6 +1527,7 @@ int wled_flash_led_prepare(struct led_trigger *trig, int options, led_cdev->name); return rc; } + break; case QUERY_MAX_AVAIL_CURRENT: rc = wled_get_max_avail_current(led_cdev, max_current); if (rc < 0) { -- GitLab From 9f9a1050d8676339b98c31fd73117adeddf74c7a Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 15 May 2018 13:20:37 -0700 Subject: [PATCH 0060/1299] ARM: dts: msm: Add SW JEITA and step charging config for alium battery Specify the SW JEITA and step charging for alium battery that is used on some SM8150 platforms as per the battery specification. This still needs to be characterized after testing in hardware platforms with different chargers. Change-Id: I4fe93377d05f32cf96f96dcb1aafd57f3dab0960 Signed-off-by: Subbaraman Narayanamurthy Signed-off-by: Guru Das Srinagesh --- .../dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi b/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi index f1a47e24244f..4c79fcd4c6b5 100644 --- a/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi +++ b/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi @@ -14,7 +14,16 @@ qcom,alium_860_89032_0000_3600mah_averaged_masterslave_feb7th2018 { /* #Alium_860_89032_0000_3600mAh_averaged_MasterSlave_Feb7th2018*/ qcom,max-voltage-uv = <4350000>; - qcom,fastchg-current-ma = <3600>; + qcom,fastchg-current-ma = <5400>; + qcom,jeita-fcc-ranges = <0 100 2500000 + 110 400 5400000 + 410 450 2500000>; + qcom,jeita-fv-ranges = <0 100 4250000 + 110 400 4350000 + 410 450 4250000>; + qcom,step-chg-ranges = <3600000 4200000 5400000 + 4201000 4300000 3600000 + 4301000 4350000 2500000>; qcom,batt-id-kohm = <107>; qcom,battery-beta = <4250>; qcom,therm-room-temp = <100000>; -- GitLab From 29c75ea162fc723855e9244e3fbccef62d8e7fba Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 15 May 2018 13:25:24 -0700 Subject: [PATCH 0061/1299] ARM: dts: msm: Enable SW JEITA and step charging in SM8150 MTP Enable SW JEITA and step charging functionality for PM8150B charger on SM8150 MTP platform. Also add battery data phandle to PM8150B charger device which provides the configuration for SW JEITA and step charging algorithms. Change-Id: I815fb2a22504784dd5ae8b653376c6cd3b5ab4eb Signed-off-by: Subbaraman Narayanamurthy Signed-off-by: Guru Das Srinagesh --- arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi index 29b12b28337b..4d83600130eb 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi @@ -574,6 +574,9 @@ io-channel-names = "usb_in_voltage", "usb_in_current", "chg_temp"; + qcom,battery-data = <&mtp_batterydata>; + qcom,step-charging-enable; + qcom,sw-jeita-enable; }; &smb1390 { -- GitLab From dfeab386968c9d92e04d42283533191a809e18dd Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Mon, 4 Jun 2018 10:18:25 +0530 Subject: [PATCH 0062/1299] usb: gadget: f_cdev: Send zero length packets in modem data calls The USB protocol requires zero length packets to be sent when the data transmission ends on a USB packet size boundary. This fix enables sending zero length packets when required. Change-Id: I0269ec7ff25c82000f2a5bc4adb449bc0231c66c Signed-off-by: Pratham Pratap --- drivers/usb/gadget/function/f_cdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c index fbd79142c8a2..09a1430c84a5 100644 --- a/drivers/usb/gadget/function/f_cdev.c +++ b/drivers/usb/gadget/function/f_cdev.c @@ -1251,6 +1251,7 @@ ssize_t f_cdev_write(struct file *file, ret = -EFAULT; } else { req->length = xfer_size; + req->zero = 1; ret = usb_ep_queue(in, req, GFP_KERNEL); if (ret) { pr_err("EP QUEUE failed:%d\n", ret); -- GitLab From f02a6a0f8ebc66c24ba904df9ba2dc53c9e890ba Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Wed, 30 May 2018 00:18:38 -0700 Subject: [PATCH 0063/1299] power: smb5-lib: switch charging in SMB1355 per SMB_EN status Enable/disable charging on parallel charger side when SMB_EN PIN is high/low, per SMB5/SEM1355 spec. Also clean up macro definitions no longer in use. Change-Id: Ib1920c827446791039fda908608952ed579fdf60 Signed-off-by: Harry Yang --- drivers/power/supply/qcom/smb5-lib.c | 8 +++++++- drivers/power/supply/qcom/smb5-lib.h | 10 +--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 2753d72acb0b..204b7ae4dd42 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -126,6 +126,8 @@ static int smblib_select_sec_charger(struct smb_charger *chg, int sec_chg) switch (sec_chg) { case POWER_SUPPLY_CHARGER_SEC_CP: + vote(chg->pl_disable_votable, PL_SMB_EN_VOTER, true, 0); + /* select Charge Pump instead of slave charger */ rc = smblib_masked_write(chg, MISC_SMB_CFG_REG, SMB_EN_SEL_BIT, SMB_EN_SEL_BIT); @@ -158,9 +160,14 @@ static int smblib_select_sec_charger(struct smb_charger *chg, int sec_chg) rc); return rc; } + + vote(chg->pl_disable_votable, PL_SMB_EN_VOTER, false, 0); + break; case POWER_SUPPLY_CHARGER_SEC_NONE: default: + vote(chg->pl_disable_votable, PL_SMB_EN_VOTER, true, 0); + /* SW override, disabling secondary charger(s) */ rc = smblib_write(chg, MISC_SMB_EN_CMD_REG, SMB_EN_OVERRIDE_BIT); @@ -3298,7 +3305,6 @@ static void typec_src_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, PD_VOTER, false, 0); vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); vote(chg->usb_icl_votable, DCP_VOTER, false, 0); - vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0); vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); vote(chg->usb_icl_votable, OTG_VOTER, false, 0); vote(chg->usb_icl_votable, CTM_VOTER, false, 0); diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 7e30c108e7cc..b4467b7af9d6 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -33,22 +33,13 @@ enum print_reason { #define PD_VOTER "PD_VOTER" #define DCP_VOTER "DCP_VOTER" #define QC_VOTER "QC_VOTER" -#define PL_USBIN_USBIN_VOTER "PL_USBIN_USBIN_VOTER" #define USB_PSY_VOTER "USB_PSY_VOTER" #define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER" -#define PL_QNOVO_VOTER "PL_QNOVO_VOTER" #define USBIN_V_VOTER "USBIN_V_VOTER" #define CHG_STATE_VOTER "CHG_STATE_VOTER" -#define TYPEC_SRC_VOTER "TYPEC_SRC_VOTER" #define TAPER_END_VOTER "TAPER_END_VOTER" #define THERMAL_DAEMON_VOTER "THERMAL_DAEMON_VOTER" -#define CC_DETACHED_VOTER "CC_DETACHED_VOTER" -#define APSD_VOTER "APSD_VOTER" -#define PD_DISALLOWED_INDIRECT_VOTER "PD_DISALLOWED_INDIRECT_VOTER" -#define VBUS_CC_SHORT_VOTER "VBUS_CC_SHORT_VOTER" -#define PD_INACTIVE_VOTER "PD_INACTIVE_VOTER" #define BOOST_BACK_VOTER "BOOST_BACK_VOTER" -#define USBIN_USBIN_BOOST_VOTER "USBIN_USBIN_BOOST_VOTER" #define MICRO_USB_VOTER "MICRO_USB_VOTER" #define DEBUG_BOARD_VOTER "DEBUG_BOARD_VOTER" #define PD_SUSPEND_SUPPORTED_VOTER "PD_SUSPEND_SUPPORTED_VOTER" @@ -66,6 +57,7 @@ enum print_reason { #define PL_FCC_LOW_VOTER "PL_FCC_LOW_VOTER" #define WBC_VOTER "WBC_VOTER" #define HW_LIMIT_VOTER "HW_LIMIT_VOTER" +#define PL_SMB_EN_VOTER "PL_SMB_EN_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 -- GitLab From 6594bb37d26d2c3215ff418c5d865ac72d47e488 Mon Sep 17 00:00:00 2001 From: Amir Levy Date: Thu, 7 Jun 2018 13:02:01 +0300 Subject: [PATCH 0064/1299] msm: ipa4: add IOCTL for bridge to vlan mapping IPACM needs info about bridge association with VLANs. Add an IOCTL to send this info to IPACM. Change-Id: Ifeaec348339cd9dd7cf6b507346b61f570861bfc Signed-off-by: Amir Levy --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 89 +++++++++++++------ drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c | 2 + include/uapi/linux/msm_ipa.h | 33 ++++++- 3 files changed, 97 insertions(+), 27 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 92120c009a2c..d5633a179a1b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -619,10 +619,15 @@ static void ipa3_vlan_l2tp_msg_free_cb(void *buff, u32 len, u32 type) return; } - if (type != ADD_VLAN_IFACE && - type != DEL_VLAN_IFACE && - type != ADD_L2TP_VLAN_MAPPING && - type != DEL_L2TP_VLAN_MAPPING) { + switch (type) { + case ADD_VLAN_IFACE: + case DEL_VLAN_IFACE: + case ADD_L2TP_VLAN_MAPPING: + case DEL_L2TP_VLAN_MAPPING: + case ADD_BRIDGE_VLAN_MAPPING: + case DEL_BRIDGE_VLAN_MAPPING: + break; + default: IPAERR("Wrong type given. buff %pK type %d\n", buff, type); return; } @@ -635,10 +640,17 @@ static int ipa3_send_vlan_l2tp_msg(unsigned long usr_param, uint8_t msg_type) int retval; struct ipa_ioc_vlan_iface_info *vlan_info; struct ipa_ioc_l2tp_vlan_mapping_info *mapping_info; + struct ipa_ioc_bridge_vlan_mapping_info *bridge_vlan_info; struct ipa_msg_meta msg_meta; + void *buff; + + IPADBG("type %d\n", msg_type); + + memset(&msg_meta, 0, sizeof(msg_meta)); + msg_meta.msg_type = msg_type; - if (msg_type == ADD_VLAN_IFACE || - msg_type == DEL_VLAN_IFACE) { + if ((msg_type == ADD_VLAN_IFACE) || + (msg_type == DEL_VLAN_IFACE)) { vlan_info = kzalloc(sizeof(struct ipa_ioc_vlan_iface_info), GFP_KERNEL); if (!vlan_info) @@ -650,18 +662,10 @@ static int ipa3_send_vlan_l2tp_msg(unsigned long usr_param, uint8_t msg_type) return -EFAULT; } - memset(&msg_meta, 0, sizeof(msg_meta)); - msg_meta.msg_type = msg_type; msg_meta.msg_len = sizeof(struct ipa_ioc_vlan_iface_info); - retval = ipa3_send_msg(&msg_meta, vlan_info, - ipa3_vlan_l2tp_msg_free_cb); - if (retval) { - IPAERR("ipa3_send_msg failed: %d\n", retval); - kfree(vlan_info); - return retval; - } - } else if (msg_type == ADD_L2TP_VLAN_MAPPING || - msg_type == DEL_L2TP_VLAN_MAPPING) { + buff = vlan_info; + } else if ((msg_type == ADD_L2TP_VLAN_MAPPING) || + (msg_type == DEL_L2TP_VLAN_MAPPING)) { mapping_info = kzalloc(sizeof(struct ipa_ioc_l2tp_vlan_mapping_info), GFP_KERNEL); if (!mapping_info) @@ -674,22 +678,44 @@ static int ipa3_send_vlan_l2tp_msg(unsigned long usr_param, uint8_t msg_type) return -EFAULT; } - memset(&msg_meta, 0, sizeof(msg_meta)); - msg_meta.msg_type = msg_type; msg_meta.msg_len = sizeof(struct ipa_ioc_l2tp_vlan_mapping_info); - retval = ipa3_send_msg(&msg_meta, mapping_info, - ipa3_vlan_l2tp_msg_free_cb); - if (retval) { - IPAERR("ipa3_send_msg failed: %d\n", retval); - kfree(mapping_info); - return retval; + buff = mapping_info; + } else if ((msg_type == ADD_BRIDGE_VLAN_MAPPING) || + (msg_type == DEL_BRIDGE_VLAN_MAPPING)) { + bridge_vlan_info = kzalloc( + sizeof(struct ipa_ioc_bridge_vlan_mapping_info), + GFP_KERNEL); + if (!bridge_vlan_info) + return -ENOMEM; + + if (copy_from_user((u8 *)bridge_vlan_info, + (void __user *)usr_param, + sizeof(struct ipa_ioc_bridge_vlan_mapping_info))) { + kfree(bridge_vlan_info); + IPAERR("copy from user failed\n"); + return -EFAULT; } + + msg_meta.msg_len = sizeof(struct + ipa_ioc_bridge_vlan_mapping_info); + buff = bridge_vlan_info; } else { IPAERR("Unexpected event\n"); return -EFAULT; } + retval = ipa3_send_msg(&msg_meta, buff, + ipa3_vlan_l2tp_msg_free_cb); + if (retval) { + IPAERR("ipa3_send_msg failed: %d, msg_type %d\n", + retval, + msg_type); + kfree(buff); + return retval; + } + IPADBG("exit\n"); + return 0; } @@ -1839,7 +1865,18 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } break; - + case IPA_IOC_ADD_BRIDGE_VLAN_MAPPING: + if (ipa3_send_vlan_l2tp_msg(arg, ADD_BRIDGE_VLAN_MAPPING)) { + retval = -EFAULT; + break; + } + break; + case IPA_IOC_DEL_BRIDGE_VLAN_MAPPING: + if (ipa3_send_vlan_l2tp_msg(arg, DEL_BRIDGE_VLAN_MAPPING)) { + retval = -EFAULT; + break; + } + break; case IPA_IOC_ADD_L2TP_VLAN_MAPPING: if (ipa3_send_vlan_l2tp_msg(arg, ADD_L2TP_VLAN_MAPPING)) { retval = -EFAULT; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index cf0fa50ebb92..7bed9e06a695 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -73,6 +73,8 @@ const char *ipa3_event_name[] = { __stringify(DEL_L2TP_VLAN_MAPPING), __stringify(IPA_PER_CLIENT_STATS_CONNECT_EVENT), __stringify(IPA_PER_CLIENT_STATS_DISCONNECT_EVENT), + __stringify(ADD_BRIDGE_VLAN_MAPPING), + __stringify(DEL_BRIDGE_VLAN_MAPPING), }; const char *ipa3_hdr_l2_type_name[] = { diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index ab7e36fac3d8..9ced0f9d73e0 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -96,6 +96,8 @@ #define IPA_IOCTL_DEL_NAT_TABLE 54 #define IPA_IOCTL_DEL_IPV6CT_TABLE 55 #define IPA_IOCTL_GET_VLAN_MODE 56 +#define IPA_IOCTL_ADD_BRIDGE_VLAN_MAPPING 57 +#define IPA_IOCTL_DEL_BRIDGE_VLAN_MAPPING 58 /** * max size of the header to be inserted @@ -510,7 +512,13 @@ enum ipa_per_client_stats_event { IPA_PER_CLIENT_STATS_EVENT_MAX }; -#define IPA_EVENT_MAX_NUM (IPA_PER_CLIENT_STATS_EVENT_MAX) +enum ipa_vlan_bridge_event { + ADD_BRIDGE_VLAN_MAPPING = IPA_PER_CLIENT_STATS_EVENT_MAX, + DEL_BRIDGE_VLAN_MAPPING, + BRIDGE_VLAN_MAPPING_MAX +}; + +#define IPA_EVENT_MAX_NUM (BRIDGE_VLAN_MAPPING_MAX) #define IPA_EVENT_MAX ((int)IPA_EVENT_MAX_NUM) /** @@ -1878,6 +1886,20 @@ struct ipa_ioc_get_vlan_mode { uint32_t is_vlan_mode; }; +/** + * struct ipa_ioc_bridge_vlan_mapping_info - vlan to bridge mapping info + * @bridge_name: bridge interface name + * @vlan_id: vlan ID bridge is mapped to + * @bridge_ipv4: bridge interface ipv4 address + * @subnet_mask: bridge interface subnet mask + */ +struct ipa_ioc_bridge_vlan_mapping_info { + char bridge_name[IPA_RESOURCE_NAME_MAX]; + uint16_t vlan_id; + uint32_t bridge_ipv4; + uint32_t subnet_mask; +}; + /** * actual IOCTLs supported by IPA driver */ @@ -2059,6 +2081,15 @@ struct ipa_ioc_get_vlan_mode { #define IPA_IOC_GET_VLAN_MODE _IOWR(IPA_IOC_MAGIC, \ IPA_IOCTL_GET_VLAN_MODE, \ struct ipa_ioc_get_vlan_mode *) + +#define IPA_IOC_ADD_BRIDGE_VLAN_MAPPING _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ADD_BRIDGE_VLAN_MAPPING, \ + struct ipa_ioc_bridge_vlan_mapping_info) + +#define IPA_IOC_DEL_BRIDGE_VLAN_MAPPING _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_DEL_BRIDGE_VLAN_MAPPING, \ + struct ipa_ioc_bridge_vlan_mapping_info) + /* * unique magic number of the Tethering bridge ioctls */ -- GitLab From 16d2b29a91da565aa7bfb23c9ff220ee86cf622f Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Sun, 10 Jun 2018 13:05:52 +0300 Subject: [PATCH 0065/1299] msm: ipa: Remove obsolete entries from kconfig starting 4.14 kernel, IPA and RMNET_IPA drivers are not supported anymore (IPA3 and RMNET_IPA3 still supported). Change-Id: I4177627c8fb082cfa8954d92a61a41f08e420bdb Signed-off-by: Ghanim Fodi --- drivers/platform/msm/Kconfig | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig index 453503322384..269005a50a64 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -63,28 +63,6 @@ config USB_BAM USB BAM driver was added to supports SPS Peripheral-to-Peripheral transfers between the USB and other peripheral. -config IPA - tristate "IPA support" - depends on SPS && NET - help - This driver supports the Internet Packet Accelerator (IPA) core. - IPA is a programmable protocol processor HW block. - It is designed to support generic HW processing of UL/DL IP packets - for various use cases independent of radio technology. - The driver support client connection and configuration - for the IPA core. - Kernel and user-space processes can call the IPA driver - to configure IPA core. - -config RMNET_IPA - tristate "IPA RMNET WWAN Network Device" - depends on IPA && MSM_QMI_INTERFACE - help - This WWAN Network Driver implements network stack class device. - It supports Embedded data transfer from A7 to Q6. Configures IPA HW - for RmNet Data Driver and also exchange of QMI messages between - A7 and Q6 IPA-driver. - config GSI bool "GSI support" help @@ -131,7 +109,7 @@ config RMNET_IPA3 config ECM_IPA tristate "STD ECM LAN Driver support" - depends on IPA || IPA3 + depends on IPA3 help Enables LAN between applications processor and a tethered host using the STD ECM protocol. @@ -140,7 +118,7 @@ config ECM_IPA config RNDIS_IPA tristate "RNDIS_IPA Network Interface Driver support" - depends on IPA || IPA3 + depends on IPA3 help Enables LAN between applications processor and a tethered host using the RNDIS protocol. -- GitLab From 0040f8d8ef341ac4fc5d6c3c2766507039cb8532 Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Fri, 8 Jun 2018 00:58:40 -0700 Subject: [PATCH 0066/1299] ARM: dts: msm: rename pinctrl smb1390_stat_default Rename pin control smb1390_stat_default to smb_stat_default, as the GPIO is used for both SMB1390 and SMB1355 STAT pin. Change-Id: Iaf3bf34f58bcd2169e435bc412fb7fecbddbee64 Signed-off-by: Harry Yang --- arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi | 2 +- arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi | 4 ++-- arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi index e330b3a35b22..a33ffd67a6e8 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi @@ -569,7 +569,7 @@ &smb1390 { pinctrl-names = "default"; - pinctrl-0 = <&smb1390_stat_default>; + pinctrl-0 = <&smb_stat_default>; status = "ok"; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi index 6d137062270a..c1a7aaed9805 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi @@ -88,8 +88,8 @@ }; &pm8150b_gpios { - smb1390_stat { - smb1390_stat_default: smb1390_stat_default { + smb_stat { + smb_stat_default: smb_stat_default { pins = "gpio6"; function = "normal"; input-enable; diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi index f347370cc17a..70f7bd1efbcc 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi @@ -498,7 +498,7 @@ &smb1390 { pinctrl-names = "default"; - pinctrl-0 = <&smb1390_stat_default>; + pinctrl-0 = <&smb_stat_default>; status = "ok"; }; -- GitLab From 1af407b3cb832e271934ecfe61961df8a4f5b36b Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Mon, 28 May 2018 01:01:11 -0700 Subject: [PATCH 0067/1299] ARM: dts: msm: Add SMB1355 device and enable it on MTP and QRD Specify the configuration for the charger device that is present on SMB1355, which will be used for SM8150 platforms. Also enable SMB1355 on SM8150 MTP and QRD platforms. This implementation is based on snapshot of the sdm845 device tree msm-4.9 commit 801aa2e7a860 ("ARM: dts: msm: add SMB1355 charger device for SDM845 MTP/QRD"). Change-Id: I2a7ab225888b5c39a235bed9f92762a1380df9ae Signed-off-by: Harry Yang --- arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi | 9 ++++ arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi | 9 ++++ arch/arm64/boot/dts/qcom/smb1355.dtsi | 58 ++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/smb1355.dtsi diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi index a33ffd67a6e8..3b225b463986 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi @@ -19,6 +19,7 @@ #include "sm8150-camera-sensor-mtp.dtsi" #include "sm8150-thermal-overlay.dtsi" #include "smb1390.dtsi" +#include "smb1355.dtsi" &qupv3_se12_2uart { status = "ok"; @@ -580,3 +581,11 @@ &usb1 { extcon = <&extcon_usb1>; }; + +&smb1355 { + status = "ok"; +}; + +&smb1355_charger { + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi index 70f7bd1efbcc..b617cdc3e70c 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi @@ -19,6 +19,7 @@ #include "sm8150-camera-sensor-qrd.dtsi" #include "sm8150-thermal-overlay.dtsi" #include "smb1390.dtsi" +#include "smb1355.dtsi" &vendor { bluetooth: bt_wcn3990 { @@ -511,3 +512,11 @@ <0x49 0x70 0x28 0x74>; }; + +&smb1355 { + status = "ok"; +}; + +&smb1355_charger { + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/qcom/smb1355.dtsi b/arch/arm64/boot/dts/qcom/smb1355.dtsi new file mode 100644 index 000000000000..70b03901269a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/smb1355.dtsi @@ -0,0 +1,58 @@ +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +&qupv3_se4_i2c { + smb1355: qcom,smb1355@c { + compatible = "qcom,i2c-pmic"; + reg = <0xc>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <&spmi_bus>; + interrupts = <0x2 0xC5 0x0 IRQ_TYPE_LEVEL_LOW>; + interrupt_names = "smb1355"; + interrupt-controller; + #interrupt-cells = <3>; + qcom,periph-map = <0x10 0x12 0x13 0x16>; + status = "disabled"; + + smb1355_revid: qcom,revid@100 { + compatible = "qcom,qpnp-revid"; + reg = <0x100 0x100>; + }; + + smb1355_charger: qcom,smb1355-charger@1000 { + compatible = "qcom,smb1355"; + qcom,pmic-revid = <&smb1355_revid>; + reg = <0x1000 0x700>; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&smb1355>; + status = "disabled"; + + qcom,chgr@1000 { + reg = <0x1000 0x100>; + interrupts = <0x10 0x1 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "chg-state-change"; + }; + + qcom,chgr-misc@1600 { + reg = <0x1600 0x100>; + interrupts = <0x16 0x1 IRQ_TYPE_EDGE_RISING>, + <0x16 0x6 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog-bark", + "temperature-change"; + }; + }; + }; +}; -- GitLab From 3b2486c79931ad258844bdd2c00415775dbe9904 Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Fri, 18 May 2018 14:31:28 +0530 Subject: [PATCH 0068/1299] clk: qcom: Support to add hardware clocks to of_clk_hw_provider Currently the hardware clocks are added from each clock controller individually and are not added to the of_clk_provider. But there could be clocks which are required by clients to be used. Add the hardware clocks to the of_clk_hw_provide list. Change-Id: Id88823b03ece283bf9fcb5bcaaf382210e60d0d6 Signed-off-by: Taniya Das Signed-off-by: Odelu Kukatla --- drivers/clk/qcom/common.c | 24 +++++++++++++++++++++--- drivers/clk/qcom/common.h | 4 +++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 71fd4f2997e2..6fa3aa56b5a3 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2017-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -28,7 +28,9 @@ struct qcom_cc { struct qcom_reset_controller reset; struct clk_regmap **rclks; + struct clk_hw **hwclks; size_t num_rclks; + size_t num_hwclks; }; const @@ -205,11 +207,14 @@ static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec, struct qcom_cc *cc = data; unsigned int idx = clkspec->args[0]; - if (idx >= cc->num_rclks) { - pr_err("%s: invalid index %u\n", __func__, idx); + if (idx >= cc->num_rclks + cc->num_hwclks) { + pr_err("invalid index %u\n", idx); return ERR_PTR(-EINVAL); } + if (idx < cc->num_hwclks && cc->hwclks[idx]) + return cc->hwclks[idx]; + return cc->rclks[idx] ? &cc->rclks[idx]->hw : ERR_PTR(-ENOENT); } @@ -222,7 +227,9 @@ int qcom_cc_really_probe(struct platform_device *pdev, struct qcom_cc *cc; struct gdsc_desc *scd; size_t num_clks = desc->num_clks; + size_t num_hwclks = desc->num_hwclks; struct clk_regmap **rclks = desc->clks; + struct clk_hw **hwclks = desc->hwclks; cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL); if (!cc) @@ -230,6 +237,17 @@ int qcom_cc_really_probe(struct platform_device *pdev, cc->rclks = rclks; cc->num_rclks = num_clks; + cc->hwclks = hwclks; + cc->num_hwclks = num_hwclks; + + for (i = 0; i < num_hwclks; i++) { + if (!hwclks[i]) + continue; + + ret = devm_clk_hw_register(dev, hwclks[i]); + if (ret) + return ret; + } for (i = 0; i < num_clks; i++) { if (!rclks[i]) diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h index 210785ccf1a4..92c067c6d64d 100644 --- a/drivers/clk/qcom/common.h +++ b/drivers/clk/qcom/common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2017-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -36,7 +36,9 @@ struct parent_map; struct qcom_cc_desc { const struct regmap_config *config; struct clk_regmap **clks; + struct clk_hw **hwclks; size_t num_clks; + size_t num_hwclks; const struct qcom_reset_map *resets; size_t num_resets; struct gdsc **gdscs; -- GitLab From c2cd870b1f5dc4b34a1af85e0cf1daee2b5e93c7 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Mon, 11 Jun 2018 07:53:01 +0300 Subject: [PATCH 0069/1299] wil6210: enable AMSDU by default Enable AMSDU to allow MSDU aggregation for performance improvements. As AMSDU requires FW support, add new FW capability WMI_FW_CAPABILITY_AMSDU to notify the driver on its support. Change the amsdu_en module parameter to debugfs parameter to allow disabling of AMSDU for debug purposes (default true), usage: echo 0 > amsdu_en Change-Id: Iceaa075276de1ae929d0a8defeacf0a39db577af Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/debugfs.c | 1 + drivers/net/wireless/ath/wil6210/main.c | 2 ++ drivers/net/wireless/ath/wil6210/wil6210.h | 3 +++ drivers/net/wireless/ath/wil6210/wmi.c | 8 ++------ drivers/net/wireless/ath/wil6210/wmi.h | 1 + 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 4719dd5a1ef6..61fc8d06d710 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -2165,6 +2165,7 @@ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(wakeup_trigger, 0644, doff_u8), WIL_FIELD(ring_idle_trsh, 0644, doff_u32), WIL_FIELD(num_rx_status_rings, 0644, doff_u8), + WIL_FIELD(amsdu_en, 0644, doff_u8), {}, }; diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 980b84e63900..3c319bf1fd16 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -653,6 +653,8 @@ int wil_priv_init(struct wil6210_priv *wil) /* num of rx srings can be updated via debugfs before allocation */ wil->num_rx_status_rings = WIL_DEFAULT_NUM_RX_STATUS_RINGS; + wil->amsdu_en = 1; + return 0; out_wmi_wq: diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 2fe3c9aaba04..f5ef47c2e755 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -1004,6 +1004,9 @@ struct wil6210_priv { bool secured_boot; u8 boot_config; + + /* relevant only for eDMA */ + bool amsdu_en; }; #define wil_to_wiphy(i) (i->wiphy) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 6d87369589db..4d2aea70e35d 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -39,10 +39,6 @@ module_param(led_id, byte, 0444); MODULE_PARM_DESC(led_id, " 60G device led enablement. Set the led ID (0-2) to enable"); -static bool amsdu_en; -module_param(amsdu_en, bool, 0444); -MODULE_PARM_DESC(amsdu_en, " enable A-MSDU, default: false"); - #define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200 #define WIL_WMI_CALL_GENERAL_TO_MS 100 @@ -2153,8 +2149,8 @@ int wmi_addba(struct wil6210_priv *wil, u8 mid, u8 ringid, u8 size, u16 timeout) { u8 amsdu = wil->use_enhanced_dma_hw && use_rx_hw_reordering && - amsdu_en ? 1 : 0; - + test_bit(WMI_FW_CAPABILITY_AMSDU, wil->fw_capabilities) && + wil->amsdu_en; struct wmi_ring_ba_en_cmd cmd = { .ring_id = ringid, .agg_max_wsize = size, diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 93f9e08b7710..329c5aea8b3d 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -74,6 +74,7 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_PNO = 15, WMI_FW_CAPABILITY_CONNECT_SNR_THR = 16, WMI_FW_CAPABILITY_REF_CLOCK_CONTROL = 18, + WMI_FW_CAPABILITY_AMSDU = 23, WMI_FW_CAPABILITY_MAX, }; -- GitLab From 0398acce8b765482485e5b723929c8aee49f810d Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Mon, 11 Jun 2018 11:38:29 +0530 Subject: [PATCH 0070/1299] defconfig: enable ADSP RPC driver for qcs405 Configure ADSP RPC driver, which provide a communication mechanism that allows for clients to make remote method invocations across processor boundary to applications DSP processor. Change-Id: I57fef3c8c80b5c03df83093cdac5d7a02c5c96fa Acked-by: Chenna Kesava Raju Signed-off-by: Tharun Kumar Merugu --- arch/arm/configs/qcs405_defconfig | 1 + arch/arm64/configs/qcs405_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/qcs405_defconfig b/arch/arm/configs/qcs405_defconfig index b6ee98ca78ef..663a688b27f2 100644 --- a/arch/arm/configs/qcs405_defconfig +++ b/arch/arm/configs/qcs405_defconfig @@ -261,6 +261,7 @@ CONFIG_INPUT_GPIO=y CONFIG_SERIAL_MSM=y CONFIG_SERIAL_MSM_CONSOLE=y CONFIG_HW_RANDOM=y +CONFIG_MSM_ADSPRPC=y CONFIG_I2C_CHARDEV=y CONFIG_SPI=y CONFIG_SPI_DEBUG=y diff --git a/arch/arm64/configs/qcs405_defconfig b/arch/arm64/configs/qcs405_defconfig index 903254566905..e2785bf2dd03 100644 --- a/arch/arm64/configs/qcs405_defconfig +++ b/arch/arm64/configs/qcs405_defconfig @@ -259,6 +259,7 @@ CONFIG_SERIAL_MSM=y CONFIG_SERIAL_MSM_CONSOLE=y CONFIG_SERIAL_MSM_HS=y CONFIG_HW_RANDOM=y +CONFIG_MSM_ADSPRPC=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_MSM_V2=y CONFIG_SPI=y -- GitLab From c24308dfea8507258e58727d1396e34c9fc52808 Mon Sep 17 00:00:00 2001 From: Ramprasad Katkam Date: Tue, 24 Apr 2018 12:45:08 +0530 Subject: [PATCH 0071/1299] ARM: dts: msm: Add lpass pil node for sm6150 Add Lpass pil node to facilitate LPASS subsystem loading for SM6150. Change-Id: I105370ef6a2cdd29a029ba0e9df31605975a2684 Signed-off-by: Ramprasad Katkam Signed-off-by: Jitendra Sharma --- arch/arm64/boot/dts/qcom/sm6150.dtsi | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index e384dd622a7c..2a88b4ebc203 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1476,6 +1477,46 @@ #thermal-sensor-cells = <1>; }; + qcom,lpass@62400000 { + compatible = "qcom,pil-tz-generic"; + reg = <0x62400000 0x00100>; + + vdd_cx-supply = <&L8A_LEVEL>; + qcom,vdd_cx-uV-uA = ; + qcom,proxy-reg-names = "vdd_cx"; + + clocks = <&clock_rpmh RPMH_CXO_CLK>; + clock-names = "xo"; + qcom,proxy-clock-names = "xo"; + + qcom,pas-id = <1>; + qcom,proxy-timeout-ms = <10000>; + qcom,smem-id = <423>; + qcom,sysmon-id = <1>; + qcom,ssctl-instance-id = <0x14>; + qcom,firmware-name = "adsp"; + memory-region = <&pil_adsp_mem>; + + /* Inputs from lpass */ + interrupts-extended = <&pdc 0 162 1>, + <&adsp_smp2p_in 0 0>, + <&adsp_smp2p_in 2 0>, + <&adsp_smp2p_in 1 0>, + <&adsp_smp2p_in 3 0>; + + interrupt-names = "qcom,wdog", + "qcom,err-fatal", + "qcom,proxy-unvote", + "qcom,err-ready", + "qcom,stop-ack"; + + /* Outputs to lpass */ + qcom,smem-states = <&adsp_smp2p_out 0>; + qcom,smem-state-names = "qcom,force-stop"; + + mboxes = <&qmp_aop 0>; + mbox-names = "adsp-pil"; + }; }; #include "pm6150.dtsi" -- GitLab From 425c99325e3ab6b92ad6aea56263919bf16a79b6 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Mon, 11 Jun 2018 12:28:22 +0530 Subject: [PATCH 0072/1299] ARM: dts: msm: Enable dynamic domain switching for sm6150 Enable dynamic domain to support the GPU driver per process pagetable which will allow switching between multiple domains within a single context bank. Change-Id: I217141ceffeaf5457cc4339a78ca51306a04bee2 Signed-off-by: Hareesh Gundu --- arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi index 2db42735c717..f3b34e457e33 100644 --- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi @@ -19,6 +19,7 @@ <0x50c2000 0x20>; reg-names = "base", "tcu-base"; #iommu-cells = <2>; + qcom,dynamic; qcom,skip-init; qcom,use-3-lvl-tables; #global-interrupts = <1>; -- GitLab From d53c2277fc427e7b61f92dfb21ef541681cff6cc Mon Sep 17 00:00:00 2001 From: Qiwei Liu Date: Fri, 8 Jun 2018 16:04:01 +0800 Subject: [PATCH 0073/1299] msm: vidc: refine instance info stats Add operating-rate and priority info when printing running instances info stats. CRs-Fixed: 2255248 Change-Id: I670caaf36f856568646600dc30db3c818ba7e1f5 Signed-off-by: Qiwei Liu --- .../media/platform/msm/vidc/msm_vidc_common.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 79b7c665d4f7..6b42c26224bd 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -3091,10 +3091,11 @@ static int msm_comm_session_init(int flipped_state, static void msm_vidc_print_running_insts(struct msm_vidc_core *core) { struct msm_vidc_inst *temp; + int op_rate = 0; dprintk(VIDC_ERR, "Running instances:\n"); - dprintk(VIDC_ERR, "%4s|%4s|%4s|%4s|%4s\n", - "type", "w", "h", "fps", "prop"); + dprintk(VIDC_ERR, "%4s|%4s|%4s|%4s|%4s|%4s\n", + "type", "w", "h", "fps", "opr", "prop"); mutex_lock(&core->lock); list_for_each_entry(temp, &core->instances, list) { @@ -3108,13 +3109,21 @@ static void msm_vidc_print_running_insts(struct msm_vidc_core *core) if (is_turbo_session(temp)) strlcat(properties, "T", sizeof(properties)); - dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d|%4s\n", + if (is_realtime_session(temp)) + strlcat(properties, "R", sizeof(properties)); + + if (temp->clk_data.operating_rate) + op_rate = temp->clk_data.operating_rate >> 16; + else + op_rate = temp->prop.fps; + + dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d|%4d|%4s\n", temp->session_type, max(temp->prop.width[CAPTURE_PORT], temp->prop.width[OUTPUT_PORT]), max(temp->prop.height[CAPTURE_PORT], temp->prop.height[OUTPUT_PORT]), - temp->prop.fps, properties); + temp->prop.fps, op_rate, properties); } } mutex_unlock(&core->lock); -- GitLab From e049bee5ad35a0f579c7f7c12f2558437c0a2615 Mon Sep 17 00:00:00 2001 From: Konstantin Dorfman Date: Mon, 11 Jun 2018 11:00:13 +0300 Subject: [PATCH 0074/1299] soc: qcom: spcom: release ion buffer on rpmsg channel remove This change decreases reference count on shared memory buffers locked by hlos application, because rpmsg channel device removed when secure processor communication endpoint disconnected. The reason for such is ssr event. Change-Id: Ifd3167101a7c20160d0e8bae98f79ab424db2390 Signed-off-by: Konstantin Dorfman --- drivers/soc/qcom/spcom.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index cb531e5f31ad..a4353bc0d72d 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -1935,17 +1935,27 @@ static int spcom_rpdev_probe(struct rpmsg_device *rpdev) static void spcom_rpdev_remove(struct rpmsg_device *rpdev) { struct spcom_channel *ch; + int i; if (!rpdev) { pr_err("rpdev is NULL\n"); return; } + dev_info(&rpdev->dev, "rpmsg device %s removed\n", rpdev->id.name); ch = dev_get_drvdata(&rpdev->dev); if (!ch) { pr_err("channel %s not found\n", rpdev->id.name); return; } + /* release all ion buffers locked by the channel */ + for (i = 0 ; i < ARRAY_SIZE(ch->dmabuf_handle_table) ; i++) { + if (ch->dmabuf_handle_table[i]) { + dma_buf_put(ch->dmabuf_handle_table[i]); + ch->dmabuf_handle_table[i] = NULL; + dev_info(&rpdev->dev, "dma_buf_put(%d)\n", i); + } + } mutex_lock(&ch->lock); ch->rpdev = NULL; ch->rpmsg_abort = true; @@ -1956,7 +1966,6 @@ static void spcom_rpdev_remove(struct rpmsg_device *rpdev) if (atomic_dec_and_test(&spcom_dev->rpmsg_dev_count)) complete_all(&spcom_dev->rpmsg_state_change); - dev_info(&rpdev->dev, "rpmsg device %s removed\n", rpdev->id.name); } /* register rpmsg driver to match with channel ch_name */ -- GitLab From 6ac24824728d00907b334d36183389423dee2a93 Mon Sep 17 00:00:00 2001 From: Narender Ankam Date: Mon, 11 Jun 2018 14:51:06 +0530 Subject: [PATCH 0075/1299] defconfig: qcs405: enable MDSS PLL driver Add config options to enable MDSS PLL driver for qcs405. Change-Id: Ibb5f1dd96c51bc20a9f07ac37c0b0cf5a8e12e98 Signed-off-by: Narender Ankam --- arch/arm/configs/qcs405_defconfig | 1 + arch/arm64/configs/qcs405_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/qcs405_defconfig b/arch/arm/configs/qcs405_defconfig index b6ee98ca78ef..8884ce3e8a76 100644 --- a/arch/arm/configs/qcs405_defconfig +++ b/arch/arm/configs/qcs405_defconfig @@ -369,6 +369,7 @@ CONFIG_ION=y CONFIG_QPNP_REVID=y CONFIG_SPS=y CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_QCOM_MDSS_PLL=y CONFIG_COMMON_CLK_QCOM=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_MDM_GCC_QCS405=y diff --git a/arch/arm64/configs/qcs405_defconfig b/arch/arm64/configs/qcs405_defconfig index 903254566905..1a27cd7e7e9e 100644 --- a/arch/arm64/configs/qcs405_defconfig +++ b/arch/arm64/configs/qcs405_defconfig @@ -371,6 +371,7 @@ CONFIG_ION=y CONFIG_QPNP_REVID=y CONFIG_SPS=y CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_QCOM_MDSS_PLL=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_MDM_GCC_QCS405=y CONFIG_MDM_DEBUGCC_QCS405=y -- GitLab From c3eac846d2ef51f4070f683d260f729e22022068 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Fri, 8 Jun 2018 12:28:32 +0530 Subject: [PATCH 0076/1299] ARM: dts: msm: add qcom,disable-atos for smmu on qcs405 Define qcom,disable-atos property for smmu device nodes to disable the ATOS operation that is undefined in qcs405. Also rename phandle from apps_iommu to apps_smmu. Change-Id: I1307cc176989fa8c65789ecf8be4b1c839dc1f67 Signed-off-by: Charan Teja Reddy --- arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi index 0779eddcb0bb..0dbe87184902 100644 --- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi @@ -21,6 +21,7 @@ #iommu-cells = <2>; qcom,tz-device-id = "GPU"; qcom,skip-init; + qcom,disable-atos; qcom,dynamic; qcom,use-3-lvl-tables; #global-interrupts = <0>; @@ -36,7 +37,7 @@ clock-names = "iface_clk", "core_clk"; }; - apps_iommu: qcom,iommu@1e00000 { + apps_smmu: qcom,iommu@1e00000 { status = "okay"; compatible = "qcom,qsmmu-v500"; reg = <0x1e00000 0x40000>, @@ -45,6 +46,7 @@ #iommu-cells = <2>; qcom,tz-device-id = "APPS"; qcom,skip-init; + qcom,disable-atos; qcom,enable-static-cb; qcom,use-3-lvl-tables; #global-interrupts = <0>; -- GitLab From cc3383409c063089c6eb38406695b81f1f77b846 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Fri, 25 May 2018 14:43:43 +0530 Subject: [PATCH 0077/1299] mm: oom_kill: dump info of ulmk killed process after reaping Dump the memory information of tasks that receives a SIGKILL from userspace and oom reaped. Change-Id: I3183f8893442d2597f2fc1cd6d092d9807226b2f Signed-off-by: Charan Teja Reddy --- mm/oom_kill.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index d69ed837fb89..b23ca26b13ae 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "internal.h" @@ -1128,8 +1129,35 @@ void pagefault_out_of_memory(void) mutex_unlock(&oom_lock); } +/* Call this function with task_lock being held as we're accessing ->mm */ +void dump_killed_info(struct task_struct *selected) +{ + int selected_tasksize = get_mm_rss(selected->mm); + + pr_info("Killing '%s' (%d), adj %hd,\n" + " to free %ldkB on behalf of '%s' (%d)\n" + " Free CMA is %ldkB\n" + " Total reserve is %ldkB\n" + " Total free pages is %ldkB\n" + " Total file cache is %ldkB\n", + selected->comm, selected->pid, + selected->signal->oom_score_adj, + selected_tasksize * (long)(PAGE_SIZE / 1024), + current->comm, current->pid, + global_zone_page_state(NR_FREE_CMA_PAGES) * + (long)(PAGE_SIZE / 1024), + totalreserve_pages * (long)(PAGE_SIZE / 1024), + global_zone_page_state(NR_FREE_PAGES) * + (long)(PAGE_SIZE / 1024), + global_node_page_state(NR_FILE_PAGES) * + (long)(PAGE_SIZE / 1024)); +} + void add_to_oom_reaper(struct task_struct *p) { + static DEFINE_RATELIMIT_STATE(reaper_rs, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); + if (!sysctl_reap_mem_on_sigkill) return; @@ -1142,6 +1170,16 @@ void add_to_oom_reaper(struct task_struct *p) __mark_oom_victim(p); wake_oom_reaper(p); } + + dump_killed_info(p); task_unlock(p); + + if (__ratelimit(&reaper_rs) && p->signal->oom_score_adj == 0) { + show_mem(SHOW_MEM_FILTER_NODES, NULL); + show_mem_call_notifiers(); + if (sysctl_oom_dump_tasks) + dump_tasks(NULL, NULL); + } + put_task_struct(p); } -- GitLab From 34ba1341c29f7c2031b63f7cd5457821e23fc659 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Mon, 11 Jun 2018 13:41:17 +0300 Subject: [PATCH 0078/1299] msm: gsi: Support GSI channel not full irq GSI version 2.5 adds new interrupt indicating if channel not full. This change configures the MCS (GSI firmware controller) to handle it. CRs-Fixed: 2257475 Change-Id: Ia51ed43734627af5003d3b01b9d444e2c717bc29 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/gsi/gsi.c | 20 ++++++++++++++--- drivers/platform/msm/gsi/gsi_reg.h | 6 ++++++ drivers/platform/msm/ipa/ipa_v3/ipa.c | 31 ++++++++++++++------------- include/linux/msm_gsi.h | 5 +++-- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 2b4780b90632..daa7f361f72a 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -2849,7 +2849,7 @@ int gsi_set_channel_cfg(unsigned long chan_hdl, struct gsi_chan_props *props, } EXPORT_SYMBOL(gsi_set_channel_cfg); -static void gsi_configure_ieps(void *base) +static void gsi_configure_ieps(void *base, enum gsi_ver ver) { void __iomem *gsi_base = base; @@ -2866,6 +2866,10 @@ static void gsi_configure_ieps(void *base) gsi_writel(11, gsi_base + GSI_GSI_IRAM_PTR_NEW_RE_OFFS); gsi_writel(12, gsi_base + GSI_GSI_IRAM_PTR_READ_ENG_COMP_OFFS); gsi_writel(13, gsi_base + GSI_GSI_IRAM_PTR_TIMER_EXPIRED_OFFS); + + if (ver >= GSI_VER_2_5) + gsi_writel(17, + gsi_base + GSI_V2_5_GSI_IRAM_PTR_TLV_CH_NOT_FULL_OFFS); } static void gsi_configure_bck_prs_matrix(void *base) @@ -2908,10 +2912,20 @@ static void gsi_configure_bck_prs_matrix(void *base) } int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, - phys_addr_t per_base_addr) + phys_addr_t per_base_addr, enum gsi_ver ver) { void __iomem *gsi_base; + if (!gsi_ctx) { + pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); + return -GSI_STATUS_NODEV; + } + + if (ver <= GSI_VER_ERR || ver >= GSI_VER_MAX) { + GSIERR("Incorrect version %d\n", ver); + return -GSI_STATUS_ERROR; + } + gsi_base = ioremap_nocache(gsi_base_addr, gsi_size); if (!gsi_base) { GSIERR("ioremap failed\n"); @@ -2921,7 +2935,7 @@ int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, gsi_writel(per_base_addr, gsi_base + GSI_GSI_PERIPH_BASE_ADDR_LSB_OFFS); gsi_configure_bck_prs_matrix((void *)gsi_base); - gsi_configure_ieps(gsi_base); + gsi_configure_ieps(gsi_base, ver); iounmap(gsi_base); return 0; diff --git a/drivers/platform/msm/gsi/gsi_reg.h b/drivers/platform/msm/gsi/gsi_reg.h index 377e39ad22ab..51ebb0152b4c 100644 --- a/drivers/platform/msm/gsi/gsi_reg.h +++ b/drivers/platform/msm/gsi/gsi_reg.h @@ -604,6 +604,12 @@ #define GSI_GSI_IRAM_PTR_EE_GENERIC_CMD_IRAM_PTR_BMSK 0xfff #define GSI_GSI_IRAM_PTR_EE_GENERIC_CMD_IRAM_PTR_SHFT 0x0 +#define GSI_V2_5_GSI_IRAM_PTR_TLV_CH_NOT_FULL_OFFS \ + (GSI_GSI_REG_BASE_OFFS + 0x00000408) +#define GSI_V2_5_GSI_IRAM_PTR_TLV_CH_NOT_FULL_RMSK 0xfff +#define GSI_V2_5_GSI_IRAM_PTR_TLV_CH_NOT_FULL_IRAM_PTR_BMSK 0xfff +#define GSI_V2_5_GSI_IRAM_PTR_TLV_CH_NOT_FULL_IRAM_PTR_SHFT 0x0 + #define GSI_GSI_IRAM_PTR_CH_DB_OFFS \ (GSI_GSI_REG_BASE_OFFS + 0x00000418) #define GSI_GSI_IRAM_PTR_CH_DB_RMSK 0xfff diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 92120c009a2c..f23b8957a7b8 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -4421,21 +4421,6 @@ static void ipa3_trigger_ipa_ready_cbs(void) mutex_unlock(&ipa3_ctx->lock); } -static int ipa3_gsi_pre_fw_load_init(void) -{ - int result; - - result = gsi_configure_regs(ipa3_res.transport_mem_base, - ipa3_res.transport_mem_size, - ipa3_res.ipa_mem_base); - if (result) { - IPAERR("Failed to configure GSI registers\n"); - return -EINVAL; - } - - return 0; -} - static void ipa3_uc_is_loaded(void) { IPADBG("\n"); @@ -4478,6 +4463,22 @@ static enum gsi_ver ipa3_get_gsi_ver(enum ipa_hw_type ipa_hw_type) return gsi_ver; } +static int ipa3_gsi_pre_fw_load_init(void) +{ + int result; + + result = gsi_configure_regs(ipa3_res.transport_mem_base, + ipa3_res.transport_mem_size, + ipa3_res.ipa_mem_base, + ipa3_get_gsi_ver(ipa3_res.ipa_hw_type)); + if (result) { + IPAERR("Failed to configure GSI registers\n"); + return -EINVAL; + } + + return 0; +} + /** * ipa3_post_init() - Initialize the IPA Driver (Part II). * This part contains all initialization which requires interaction with diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h index c41fe65c5d9b..e2ed01bce254 100644 --- a/include/linux/msm_gsi.h +++ b/include/linux/msm_gsi.h @@ -1069,11 +1069,12 @@ int gsi_start_xfer(unsigned long chan_hdl); * @gsi_base_addr: Base address of GSI register space * @gsi_size: Mapping size of the GSI register space * @per_base_addr: Base address of the peripheral using GSI + * @ver: GSI core version * * @Return gsi_status */ int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, - phys_addr_t per_base_addr); + phys_addr_t per_base_addr, enum gsi_ver ver); /** * gsi_enable_fw - Peripheral should call this function @@ -1308,7 +1309,7 @@ static inline int gsi_set_evt_ring_cfg(unsigned long evt_ring_hdl, } static inline int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, - phys_addr_t per_base_addr) + phys_addr_t per_base_addr, enum gsi_ver ver) { return -GSI_STATUS_UNSUPPORTED_OP; } -- GitLab From fe3e7ab133e9bd6e401ad0c2f59a5745de073c9f Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Mon, 11 Jun 2018 13:56:29 +0300 Subject: [PATCH 0079/1299] msm: gsi: update IRAM size to 32KB for GSI 2.5 Update the GSI driver code to return the IRAM size and offset of new GSI version 2.5. CRs-Fixed: 2258048 Change-Id: Iac52cfa89199040d7b9254d9e73361badd13db71 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/gsi/gsi.c | 43 ++++++++++++++++++--- drivers/platform/msm/gsi/gsi_reg.h | 5 +++ drivers/platform/msm/ipa/ipa_v3/ipa.c | 3 +- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 3 +- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 12 +++++- include/linux/msm_gsi.h | 5 ++- 6 files changed, 60 insertions(+), 11 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index daa7f361f72a..b0415234659c 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -2997,13 +2997,46 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size, enum gsi_ver ver) EXPORT_SYMBOL(gsi_enable_fw); void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, - unsigned long *size) + unsigned long *size, enum gsi_ver ver) { - if (base_offset) - *base_offset = GSI_GSI_INST_RAM_n_OFFS(0); + unsigned long maxn; + + if (!gsi_ctx) { + pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); + return; + } + + switch (ver) { + case GSI_VER_1_0: + case GSI_VER_1_2: + case GSI_VER_1_3: + maxn = GSI_GSI_INST_RAM_n_MAXn; + break; + case GSI_VER_2_0: + maxn = GSI_V2_0_GSI_INST_RAM_n_MAXn; + break; + case GSI_VER_2_2: + maxn = GSI_V2_2_GSI_INST_RAM_n_MAXn; + break; + case GSI_VER_2_5: + maxn = GSI_V2_5_GSI_INST_RAM_n_MAXn; + break; + case GSI_VER_ERR: + case GSI_VER_MAX: + default: + GSIERR("GSI version is not supported %d\n", ver); + WARN_ON(1); + return; + } if (size) - *size = GSI_GSI_INST_RAM_n_WORD_SZ * - (GSI_GSI_INST_RAM_n_MAXn + 1); + *size = GSI_GSI_INST_RAM_n_WORD_SZ * (maxn + 1); + + if (base_offset) { + if (ver < GSI_VER_2_5) + *base_offset = GSI_GSI_INST_RAM_n_OFFS(0); + else + *base_offset = GSI_V2_5_GSI_INST_RAM_n_OFFS(0); + } } EXPORT_SYMBOL(gsi_get_inst_ram_offset_and_size); diff --git a/drivers/platform/msm/gsi/gsi_reg.h b/drivers/platform/msm/gsi/gsi_reg.h index 51ebb0152b4c..e332bf274ec2 100644 --- a/drivers/platform/msm/gsi/gsi_reg.h +++ b/drivers/platform/msm/gsi/gsi_reg.h @@ -697,8 +697,13 @@ #define GSI_GSI_INST_RAM_n_WORD_SZ 0x4 #define GSI_GSI_INST_RAM_n_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x00004000 + GSI_GSI_INST_RAM_n_WORD_SZ * (n)) +#define GSI_V2_5_GSI_INST_RAM_n_OFFS(n) \ + (GSI_GSI_REG_BASE_OFFS + 0x0001b000 + GSI_GSI_INST_RAM_n_WORD_SZ * (n)) #define GSI_GSI_INST_RAM_n_RMSK 0xffffffff #define GSI_GSI_INST_RAM_n_MAXn 4095 +#define GSI_V2_0_GSI_INST_RAM_n_MAXn 6143 +#define GSI_V2_2_GSI_INST_RAM_n_MAXn 4095 +#define GSI_V2_5_GSI_INST_RAM_n_MAXn 8191 #define GSI_GSI_INST_RAM_n_INST_BYTE_3_BMSK 0xff000000 #define GSI_GSI_INST_RAM_n_INST_BYTE_3_SHFT 0x18 #define GSI_GSI_INST_RAM_n_INST_BYTE_2_BMSK 0xff0000 diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index f23b8957a7b8..9c6c913f121a 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -4783,7 +4783,8 @@ static int ipa3_manual_load_ipa_fws(void) IPADBG("FWs are available for loading\n"); - result = ipa3_load_fws(fw, ipa3_res.transport_mem_base); + result = ipa3_load_fws(fw, ipa3_res.transport_mem_base, + ipa3_get_gsi_ver(ipa3_res.ipa_hw_type)); if (result) { IPAERR("Manual IPA FWs loading has failed\n"); release_firmware(fw); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 02da317c05a3..c71d9448186d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -2364,7 +2364,8 @@ int ipa3_uc_panic_notifier(struct notifier_block *this, unsigned long event, void *ptr); void ipa3_inc_acquire_wakelock(void); void ipa3_dec_release_wakelock(void); -int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base); +int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base, + enum gsi_ver); int ipa3_register_ipa_ready_cb(void (*ipa_ready_cb)(void *), void *user_data); const char *ipa_hw_error_str(enum ipa3_hw_errors err_type); int ipa_gsi_ch20_wa(void); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 6fac15b6d203..9e0017c90489 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -5933,11 +5933,13 @@ static int ipa3_load_single_fw(const struct firmware *firmware, * * @firmware: Structure which contains the FW data from the user space. * @gsi_mem_base: GSI base address + * @gsi_ver: GSI Version * * Return value: 0 on success, negative otherwise * */ -int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base) +int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base, + enum gsi_ver gsi_ver) { const struct elf32_hdr *ehdr; const struct elf32_phdr *phdr; @@ -5947,6 +5949,11 @@ int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base) u32 ipa_reg_ofst; int rc; + if (gsi_ver == GSI_VER_ERR) { + IPAERR("Invalid GSI Version\n"); + return -EINVAL; + } + if (!gsi_mem_base) { IPAERR("Invalid GSI base address\n"); return -EINVAL; @@ -5977,7 +5984,8 @@ int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base) */ /* Load GSI FW image */ - gsi_get_inst_ram_offset_and_size(&gsi_iram_ofst, &gsi_iram_size); + gsi_get_inst_ram_offset_and_size(&gsi_iram_ofst, &gsi_iram_size, + gsi_ver); if (phdr->p_vaddr != (gsi_mem_base + gsi_iram_ofst)) { IPAERR( "Invalid GSI FW img load addr vaddr=0x%x gsi_mem_base=%pa gsi_iram_ofst=0x%lx\n" diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h index e2ed01bce254..fe8a7138e5fe 100644 --- a/include/linux/msm_gsi.h +++ b/include/linux/msm_gsi.h @@ -1095,11 +1095,12 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size, enum gsi_ver ver); * * @base_offset:[OUT] - IRAM base offset address * @size: [OUT] - IRAM size + * @ver: GSI core version * @Return none */ void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, - unsigned long *size); + unsigned long *size, enum gsi_ver ver); /** * gsi_halt_channel_ee - Peripheral should call this function @@ -1320,7 +1321,7 @@ static inline int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size) } static inline void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, - unsigned long *size) + unsigned long *size, enum gsi_ver ver) { } -- GitLab From 22b33bca2be40dc5baa8d0dff646d4de090e10ec Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Mon, 21 May 2018 17:44:44 +0530 Subject: [PATCH 0080/1299] ARM: dts: msm: describe reserved-memory regions for sdmmagpie Add carveout memory regions, based on memory map v3. Add CMA regions. Change-Id: I81693d842ddb2fa9c1d6f62c0068bb92524620ae Signed-off-by: Prakash Gupta --- arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 155 ++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index cb536c68516c..9c34302e729e 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -336,6 +336,161 @@ }; }; }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hyp_region: hyp_region@85700000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x85700000 0 0x600000>; + }; + + xbl_aop_mem: xbl_aop_mem@85e00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x85e00000 0x0 0x1ff000>; + }; + + sec_apps_mem: sec_apps_region@85fff000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x85fff000 0x0 0x1000>; + }; + + smem_region: smem@86000000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x86000000 0x0 0x200000>; + }; + + removed_region: removed_region@86200000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x86200000 0 0x2d00000>; + }; + + pil_camera_mem: camera_region@8ab00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x8ab00000 0 0x500000>; + }; + + pil_modem_mem: modem_region@8b000000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x8b000000 0 0x7e00000>; + }; + + pil_video_mem: pil_video_region@92e00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x92e00000 0 0x500000>; + }; + + wlan_msa_mem: wlan_msa_region@93300000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x93300000 0 0x100000>; + }; + + pil_cdsp_mem: cdsp_regions@93400000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x93400000 0 0x800000>; + }; + + pil_adsp_mem: pil_adsp_region@93c00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x93c00000 0 0x1e00000>; + }; + + pil_ipa_fw_mem: ips_fw_region@95a00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x95a00000 0 0x10000>; + }; + + pil_ipa_gsi_mem: ipa_gsi_region@95a10000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x95a10000 0 0x5000>; + }; + + pil_gpu_mem: gpu_region@95a15000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x95a15000 0 0x2000>; + }; + + npu_mem: npu_region@95a80000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0 0x95a80000 0 0x80000>; + }; + + qseecom_mem: qseecom_region@9e400000 { + compatible = "shared-dma-pool"; + no-map; + reg = <0 0x9e400000 0 0x1400000>; + }; + + adsp_mem: adsp_region { + compatible = "shared-dma-pool"; + alloc-ranges = <0 0x00000000 0 0xffffffff>; + reusable; + alignment = <0 0x400000>; + size = <0 0xc00000>; + }; + + qseecom_ta_mem: qseecom_ta_region { + compatible = "shared-dma-pool"; + alloc-ranges = <0 0x00000000 0 0xffffffff>; + reusable; + alignment = <0 0x400000>; + size = <0 0x1000000>; + }; + + sp_mem: sp_region { /* SPSS-HLOS ION shared mem */ + compatible = "shared-dma-pool"; + alloc-ranges = <0 0x00000000 0 0xffffffff>; /* 32-bit */ + reusable; + alignment = <0 0x400000>; + size = <0 0x800000>; + }; + + secure_display_memory: secure_display_region { + compatible = "shared-dma-pool"; + alloc-ranges = <0 0x00000000 0 0xffffffff>; + reusable; + alignment = <0 0x400000>; + size = <0 0x5c00000>; + }; + + cont_splash_memory: cont_splash_region@9d400000 { + reg = <0x0 0x9d400000 0x0 0x02400000>; + label = "cont_splash_region"; + }; + + dump_mem: mem_dump_region { + compatible = "shared-dma-pool"; + reusable; + size = <0 0x2400000>; + }; + + /* global autoconfigured region for contiguous allocations */ + linux,cma { + compatible = "shared-dma-pool"; + alloc-ranges = <0 0x00000000 0 0xffffffff>; + reusable; + alignment = <0 0x400000>; + size = <0 0x2000000>; + linux,cma-default; + }; + }; }; &soc { -- GitLab From 8fa5c6b33b774f5ebd7d4aafc0a6d2a30cabadfb Mon Sep 17 00:00:00 2001 From: Lingutla Chandrasekhar Date: Wed, 6 Jun 2018 17:42:24 +0530 Subject: [PATCH 0081/1299] ARM: dts: msm: Add energy costs for qcs405 Add energy costs for qcs405 target. These costs are used in energy aware scheduler's task placement decisions. Change-Id: I7aa1b8734e3405c7c34724a36edb900da62285d2 Signed-off-by: Lingutla Chandrasekhar --- arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi b/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi index 3f83fd04b6de..ed48793d348c 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi @@ -42,6 +42,7 @@ compatible = "arm,cortex-a53"; reg = <0x100>; enable-method = "psci"; + sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; L2_1: l2-cache { @@ -65,6 +66,7 @@ compatible = "arm,cortex-a53"; reg = <0x101>; enable-method = "psci"; + sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; L1_I_101: l1-icache { @@ -82,6 +84,7 @@ compatible = "arm,cortex-a53"; reg = <0x102>; enable-method = "psci"; + sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; L1_I_102: l1-icache { @@ -99,6 +102,7 @@ compatible = "arm,cortex-a53"; reg = <0x103>; enable-method = "psci"; + sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; L1_I_103: l1-icache { @@ -111,6 +115,37 @@ }; }; }; + + energy_costs: energy-costs { + compatible = "sched-energy"; + + CPU_COST_0: core-cost0 { + busy-cost-data = < + 960000 159 + 1305600 207 + 1497600 256 + 1708800 327 + 1804800 343 + 1958400 445 + >; + idle-cost-data = < + 100 80 60 40 + >; + }; + CLUSTER_COST_0: cluster-cost0 { + busy-cost-data = < + 960000 53 + 1305600 61 + 1497600 71 + 1708800 85 + 1804800 88 + 1958400 110 + >; + idle-cost-data = < + 4 3 2 1 + >; + }; + }; }; &soc { -- GitLab From b630a007866404c775e68afe9bdb7b7daa46f23b Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Wed, 6 Jun 2018 10:04:02 +0530 Subject: [PATCH 0082/1299] ARM: dts: msm: Add ion heaps for sdmmagpie Add device tree configuration corresponding to all supported ion heaps to allow clients to allocate memory from ion for sdmmagpie. Change-Id: I0783bc04d193d855a383b40c6612e00cf7404fc0 Signed-off-by: Vijayanand Jitta --- arch/arm64/boot/dts/qcom/sdmmagpie-ion.dtsi | 59 +++++++++++++++++++++ arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 2 + 2 files changed, 61 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sdmmagpie-ion.dtsi diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-ion.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-ion.dtsi new file mode 100644 index 000000000000..a8bfab8603ec --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-ion.dtsi @@ -0,0 +1,59 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + qcom,ion { + compatible = "qcom,msm-ion"; + #address-cells = <1>; + #size-cells = <0>; + + system_heap: qcom,ion-heap@25 { + reg = <25>; + qcom,ion-heap-type = "SYSTEM"; + }; + + qcom,ion-heap@22 { /* ADSP HEAP */ + reg = <22>; + memory-region = <&adsp_mem>; + qcom,ion-heap-type = "DMA"; + }; + + qcom,ion-heap@27 { /* QSEECOM HEAP */ + reg = <27>; + memory-region = <&qseecom_mem>; + qcom,ion-heap-type = "DMA"; + }; + + qcom,ion-heap@19 { /* QSEECOM TA HEAP */ + reg = <19>; + memory-region = <&qseecom_ta_mem>; + qcom,ion-heap-type = "DMA"; + }; + + qcom,ion-heap@13 { /* SPSS HEAP */ + reg = <13>; + memory-region = <&sp_mem>; + qcom,ion-heap-type = "DMA"; + }; + + qcom,ion-heap@10 { /* SECURE DISPLAY HEAP */ + reg = <10>; + memory-region = <&secure_display_memory>; + qcom,ion-heap-type = "HYP_CMA"; + }; + + qcom,ion-heap@9 { + reg = <9>; + qcom,ion-heap-type = "SYSTEM_SECURE"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index 9c34302e729e..ae45757380c1 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -971,3 +971,5 @@ &npu_core_gdsc { status = "ok"; }; + +#include "sdmmagpie-ion.dtsi" -- GitLab From 35cb1eb43a55b932b321c6623587f18547453892 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Mon, 21 May 2018 19:28:45 +0530 Subject: [PATCH 0083/1299] ARM: dts: msm: Add smmu device for sdmmagpie Describe the register address and settings for the graphics and apps smmu device for sdmmagpie. Change-Id: Iae38b2acd053b207d84aa99cfd51264ba2dc22a5 Signed-off-by: Prakash Gupta --- .../boot/dts/qcom/msm-arm-smmu-sdmmagpie.dtsi | 245 ++++++++++++++++++ arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 1 + 2 files changed, 246 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/msm-arm-smmu-sdmmagpie.dtsi diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdmmagpie.dtsi new file mode 100644 index 000000000000..b5b2e87c9be2 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdmmagpie.dtsi @@ -0,0 +1,245 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +&soc { + kgsl_smmu: arm,smmu-kgsl@5040000 { + status = "ok"; + compatible = "qcom,smmu-v2"; + reg = <0x5040000 0x10000>; + #iommu-cells = <1>; + qcom,dynamic; + qcom,use-3-lvl-tables; + qcom,disable-atos; + #global-interrupts = <2>; + qcom,regulator-names = "vdd"; + vdd-supply = <&gpu_cx_gdsc>; + interrupts = , + , + , + , + , + , + , + , + , + ; + clock-names = "gcc_gpu_memnoc_gfx_clk"; + clocks = <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>; + attach-impl-defs = + <0x6000 0x2378>, + <0x6060 0x1055>, + <0x678c 0x8>, + <0x6794 0x28>, + <0x6800 0x6>, + <0x6900 0x3ff>, + <0x6924 0x204>, + <0x6928 0x11000>, + <0x6930 0x800>, + <0x6960 0xffffffff>, + <0x6b64 0x1a5551>, + <0x6b68 0x9a82a382>; + }; + + apps_smmu: apps-smmu@0x15000000 { + compatible = "qcom,qsmmu-v500"; + reg = <0x15000000 0x100000>, + <0x15182000 0x20>; + reg-names = "base", "tcu-base"; + #iommu-cells = <2>; + qcom,skip-init; + qcom,use-3-lvl-tables; + #global-interrupts = <1>; + #size-cells = <1>; + #address-cells = <1>; + ranges; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + + anoc_1_tbu: anoc_1_tbu@0x15185000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15185000 0x1000>, + <0x15182200 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x0 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_aggre_noc_mmu_tbu1_gdsc>; + }; + + anoc_2_tbu: anoc_2_tbu@0x15189000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15189000 0x1000>, + <0x15182208 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x400 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_aggre_noc_mmu_tbu2_gdsc>; + }; + + mnoc_hf_0_tbu: mnoc_hf_0_tbu@0x1518d000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x1518d000 0x1000>, + <0x15182210 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x800 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc>; + }; + + mnoc_hf_1_tbu: mnoc_hf_1_tbu@0x15191000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15191000 0x1000>, + <0x15182218 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0xc00 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc>; + }; + + mnoc_sf_0_tbu: mnoc_sf_0_tbu@0x15195000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15195000 0x1000>, + <0x15182220 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x1000 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_mmnoc_mmu_tbu_sf_gdsc>; + }; + + compute_dsp_0_tbu: compute_dsp_0_tbu@0x15199000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15199000 0x1000>, + <0x15182228 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x1400 0x400>; + /* No GDSC */ + }; + + adsp_tbu: adsp_tbu@0x1519d000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x1519d000 0x1000>, + <0x15182230 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x1800 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_aggre_noc_mmu_audio_tbu_gdsc>; + }; + + anoc_1_pcie_tbu: anoc_1_pcie_tbu@0x151a1000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x151a1000 0x1000>, + <0x15182238 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x1c00 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc>; + clock-names = "gcc_aggre_noc_pcie_tbu_clk"; + clocks = <&clock_gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>; + }; + }; + + kgsl_iommu_test_device { + compatible = "iommu-debug-test"; + iommus = <&kgsl_smmu 0x7>; + }; + + apps_iommu_test_device { + compatible = "iommu-debug-test"; + iommus = <&apps_smmu 0x21 0>; + }; + + apps_iommu_coherent_test_device { + compatible = "iommu-debug-test"; + iommus = <&apps_smmu 0x23 0>; + dma-coherent; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index ae45757380c1..3e9b89a4607a 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -973,3 +973,4 @@ }; #include "sdmmagpie-ion.dtsi" +#include "msm-arm-smmu-sdmmagpie.dtsi" -- GitLab From cd7638068fe32e77769cdfe0a23e93ba48fbca9a Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Mon, 11 Jun 2018 16:47:52 +0530 Subject: [PATCH 0084/1299] mm: Kconfig: add HAVE_LOW_MEMORY_KILLER When a low memory killer is available either as a user/kernel space module, we do not prefer the OOM killer to trigger early. Add a config to avoid premature OOMs in the presence of such low memory killers. Change-Id: I27f51e347aa7ba559e54753e9962e5ebc67c9ce7 Signed-off-by: Vinayak Menon --- mm/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mm/Kconfig b/mm/Kconfig index 5b77318feff1..d099a3e2a3e8 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -799,3 +799,11 @@ config SPECULATIVE_PAGE_FAULT detected or because underlying PMD or PTE tables are not yet allocating, it is failing its processing and a classic page fault is then tried. + +config HAVE_LOW_MEMORY_KILLER + bool "Have user/kernel space low memory killer" + default n + help + Say 'y' if you have a user/kernel low memory killer and thus you + want page allocator to provide sufficient time before it triggers + Out of Memory killer. -- GitLab From caf42c2bf2e38028865e920c911658abf2e483fc Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Fri, 9 Feb 2018 18:24:58 +0530 Subject: [PATCH 0085/1299] mm: consider killable task's anon as reclaimable zone_reclaimable_pages which is used by should_reclaim_retry to make a decision on retrying reclaim does not consider anon pages if swap is full. This logic works on systems which rely on OOM to kill tasks and free up memory. But when reclaimers like android lowmemorykiller is used, reclaim should retry enough so that lowmemorykiller is invoked via shrinkers, thus avoiding OOM. This fixes the premature order 0 OOM killer invocations observed when swap is full. Change-Id: I99e6585b5a5dd2d871678c13349e7a62d5aefee0 Signed-off-by: Vinayak Menon --- mm/vmscan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index c7c8e56da46a..cfc335d220e3 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -213,7 +213,8 @@ unsigned long zone_reclaimable_pages(struct zone *zone) nr = zone_page_state_snapshot(zone, NR_ZONE_INACTIVE_FILE) + zone_page_state_snapshot(zone, NR_ZONE_ACTIVE_FILE); - if (get_nr_swap_pages() > 0) + if (get_nr_swap_pages() > 0 + || IS_ENABLED(CONFIG_HAVE_LOW_MEMORY_KILLER)) nr += zone_page_state_snapshot(zone, NR_ZONE_INACTIVE_ANON) + zone_page_state_snapshot(zone, NR_ZONE_ACTIVE_ANON); -- GitLab From 53ac5139d0168a0725d79812497308afeafcb82f Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Fri, 9 Feb 2018 19:29:08 +0530 Subject: [PATCH 0086/1299] mm: do not fail non-costly allocs if there are reclaimable pages should_reclaim_retry can fail for order > 0 allocs even if there are reclaimable pages. The decision to retry is then left to compaction progress in should_compact_retry. Shrinkers like lowmemorykiller which does the reclaim based on page cache levels can take time to free up memory. By this time, compaction can complete scanning (COMPACT_COMPLETE) without success. This results in an early failure (compaction_failed) in should_compact_retry, when there are enough tasks available for lowmemorykiller to kill. This results in premature OOMs. It can be argued, how this condition is different from a case where any reclaimable slab is consuming major part of system's memory. The difference is that for other reclaimable slabs, a pressure equivalent to that put on LRU is put on them, resulting in faster reclaim. But that is the not the case with lowmemorykiller which doesn't even trigger until certain page cache levels are reached, and there can be cases of tasks not available in lower oom_score_adj ranges resulting in no kills. Thus when lowmemorykiller is enabled, retry non-costly allocs till there are enough reclaimable pages and if we are making progress in reclaim. For costly orders leave the decision to existing compaction progress logic. Change-Id: I177cdd11e3f45d7f8fcf02435f7ef5834408fb6f Signed-off-by: Vinayak Menon --- mm/page_alloc.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 5f67c3902a32..58d5361706f1 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3424,6 +3424,46 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, return NULL; } +#ifdef CONFIG_HAVE_LOW_MEMORY_KILLER +static inline bool +should_compact_lmk_retry(struct alloc_context *ac, int order, int alloc_flags) +{ + struct zone *zone; + struct zoneref *z; + + /* Let costly order requests check for compaction progress */ + if (order > PAGE_ALLOC_COSTLY_ORDER) + return false; + + /* + * For (0 < order < PAGE_ALLOC_COSTLY_ORDER) allow the shrinkers + * to run and free up memory. Do not let these allocations fail + * if shrinkers can free up memory. This is similar to + * should_compact_retry implementation for !CONFIG_COMPACTION. + */ + for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, + ac->high_zoneidx, ac->nodemask) { + unsigned long available; + + available = zone_reclaimable_pages(zone); + available += + zone_page_state_snapshot(zone, NR_FREE_PAGES); + + if (__zone_watermark_ok(zone, 0, min_wmark_pages(zone), + ac_classzone_idx(ac), alloc_flags, available)) + return true; + } + + return false; +} +#else +static inline bool +should_compact_lmk_retry(struct alloc_context *ac, int order, int alloc_flags) +{ + return false; +} +#endif + static inline bool should_compact_retry(struct alloc_context *ac, int order, int alloc_flags, enum compact_result compact_result, @@ -3439,6 +3479,9 @@ should_compact_retry(struct alloc_context *ac, int order, int alloc_flags, if (!order) return false; + if (should_compact_lmk_retry(ac, order, alloc_flags)) + return true; + if (compaction_made_progress(compact_result)) (*compaction_retries)++; -- GitLab From 23ba63a1c1039880c9e6ef069f4261f9ccc575b2 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Mon, 12 Feb 2018 10:54:26 +0530 Subject: [PATCH 0087/1299] mm: retry more before OOM in the presence of slow shrinkers Shrinkers like lowmemorykiller makes the decision of killing tasks based on cached levels and also whether previous killed tasks have been reaped. This can delay the reclaim and by this time no progress loops of should_reclaim_retry can reach max retries, thus resulting in premature kills. How fast the no progress loops can complete depends on cpu speed, thus retry until reclaimable pages are too less (when __zone_watermark_ok of shouuld_reclaim_retry fails) in the case of slow shrinkers. This fixes premature order 0 OOMs. Now, for (0 < order < costly order) cases, should_reclaim_retry can bail out fast. The decision to try should_compact_retry is based on progress made in the previous reclaim. A single no progress reclaim can result in OOMs for higher orders. Fix that too. Change-Id: I189311e25fc663a2e27d4dc4a38b24024c4cd2a3 Signed-off-by: Vinayak Menon --- mm/page_alloc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 58d5361706f1..1d8e455e0266 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3793,7 +3793,8 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order, * their order will become available due to high fragmentation so * always increment the no progress counter for them */ - if (did_some_progress && order <= PAGE_ALLOC_COSTLY_ORDER) + if ((did_some_progress && order <= PAGE_ALLOC_COSTLY_ORDER) || + IS_ENABLED(CONFIG_HAVE_LOW_MEMORY_KILLER)) *no_progress_loops = 0; else (*no_progress_loops)++; @@ -4095,7 +4096,8 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, * implementation of the compaction depends on the sufficient amount * of free memory (see __compaction_suitable) */ - if (did_some_progress > 0 && + if ((did_some_progress > 0 || + IS_ENABLED(CONFIG_HAVE_LOW_MEMORY_KILLER)) && should_compact_retry(ac, order, alloc_flags, compact_result, &compact_priority, &compaction_retries)) -- GitLab From b684b6c51ff572b4e8a1c4da0b44387630ef37ca Mon Sep 17 00:00:00 2001 From: Ashay Jaiswal Date: Sun, 20 May 2018 15:42:59 +0530 Subject: [PATCH 0088/1299] ARM: dts: msm: add regulator devices for sdmmagpie Add RPMH/Stub based regulator device nodes for sdmmagpie which are used by clients to vote on their supply regulators. Stub regulators are can be used on platforms where PMIC or RPMH support is not present. Change-Id: Iea8e640430bf27ca7756e062f3c958e691db5e58 Signed-off-by: Ashay Jaiswal --- .../boot/dts/qcom/sdmmagpie-regulator.dtsi | 744 ++++++++++++++++++ .../dts/qcom/sdmmagpie-stub-regulator.dtsi | 352 +++++++++ 2 files changed, 1096 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi create mode 100644 arch/arm64/boot/dts/qcom/sdmmagpie-stub-regulator.dtsi diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi new file mode 100644 index 000000000000..621a6edad16a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi @@ -0,0 +1,744 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +/* TODO: Update volatge range once PGA is locked */ +&soc { + /* RPMh regulators */ + /* PM6150 S2 = VDD_GFX supply */ + rpmh-regulator-gfxlvl { + compatible = "qcom,rpmh-arc-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "gfx.lvl"; + VDD_GFX_LEVEL: + S2A_LEVEL: pm6150_s2_level: regulator-pm6150-s2-level { + regulator-name = "pm6150_s2_level"; + qcom,set = ; + regulator-min-microvolt + = ; + regulator-max-microvolt + = ; + qcom,init-voltage-level + = ; + }; + }; + + /* pm6150 S3 = VDD_MX supply */ + rpmh-regulator-mxlvl { + compatible = "qcom,rpmh-arc-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "mx.lvl"; + + VDD_MX_LEVEL: + S3A_LEVEL: pm6150_s3_level: regulator-pm6150-s3 { + regulator-name = "pm6150_s3_level"; + qcom,set = ; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,init-voltage-level = + ; + }; + + VDD_MX_LEVEL_AO: + S3A_LEVEL_AO: pm6150_s3_level_ao: regulator-pm6150-s3-level-ao { + regulator-name = "pm6150_s3_level_ao"; + qcom,set = ; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,init-voltage-level = + ; + }; + }; + + rpmh-regulator-smpc1 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "smpc1"; + S1C: pm6150l_s1: regulator-pm6150l-s1 { + regulator-name = "pm6150l_s1"; + qcom,set = ; + regulator-min-microvolt = <1128000>; + regulator-max-microvolt = <1128000>; + qcom,init-voltage = <1128000>; + }; + }; + + /* pm6150l S2 + S3 = 2 phase VDD_CX supply */ + rpmh-regulator-cxlvl { + compatible = "qcom,rpmh-arc-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "cx.lvl"; + + VDD_CX_LEVEL: + S2C_LEVEL: pm6150l_s2_level: regulator-pm6150l-s2 { + regulator-name = "pm6150l_s2_level"; + qcom,set = ; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,init-voltage-level = + ; + qcom,min-dropout-voltage-level = <(-1)>; + }; + + VDD_CX_LEVEL_AO: S2C_LEVEL_AO: + pm6150l_s2_level_ao: regulator-pm6150l-s2-level-ao { + qcom,set = ; + regulator-name = "pm6150l_s2_level_ao"; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,init-voltage-level = + ; + qcom,min-dropout-voltage-level = <(-1)>; + }; + }; + + /* pm6150l S7 = VDD_MSS supply */ + rpmh-regulator-modemlvl { + compatible = "qcom,rpmh-arc-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "mss.lvl"; + + VDD_MSS_LEVEL: + S7C_LEVEL: pm6150l_s7_level: regulator-pm6150l-s7 { + regulator-name = "pm6150l_s7_level"; + qcom,set = ; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,init-voltage-level = + ; + }; + }; + + rpmh-regulator-smpc8 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "smpc8"; + S8C: pm6150l_s8: regulator-pm6150l-s8 { + regulator-name = "pm6150l_s8"; + qcom,set = ; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1400000>; + qcom,init-voltage = <1200000>; + }; + }; + + rpmh-regulator-ldoa1 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa1"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L1A: pm6150_l1: regulator-pm6150-l1 { + regulator-name = "pm6150_l1"; + qcom,set = ; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1252000>; + qcom,init-voltage = <1200000>; + }; + }; + + rpmh-regulator-ldoa2 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa2"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L2A: pm6150_l2: regulator-pm6150-l2 { + regulator-name = "pm6150_l2"; + qcom,set = ; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1050000>; + qcom,init-voltage = <1000000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa3 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa3"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L3A: pm6150_l3: regulator-pm6150-l3 { + regulator-name = "pm6150_l3"; + qcom,set = ; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1060000>; + qcom,init-voltage = <1000000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa4 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa4"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L4A: pm6150_l4: regulator-pm6150-l4 { + regulator-name = "pm6150_l4"; + qcom,set = ; + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <975000>; + qcom,init-voltage = <875000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa5 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa5"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L5A: pm6150_l5: regulator-pm6150-l5 { + regulator-name = "pm6150_l5"; + qcom,set = ; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2970000>; + qcom,init-voltage = <2500000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa6 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa6"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L6A: pm6150_l6: regulator-pm6150-l6 { + regulator-name = "pm6150_l6"; + qcom,set = ; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + qcom,init-voltage = <1200000>; + qcom,init-mode = ; + }; + }; + + /* pm6150 L7 = LPI_MX supply */ + rpmh-regulator-lmxlvl { + compatible = "qcom,rpmh-arc-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "lmx.lvl"; + LPI_MX_LEVEL: + L7A_LEVEL: pm6150_l7_level: regulator-pm6150-l7 { + regulator-name = "pm6150_l7_level"; + qcom,set = ; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,init-voltage-level = + ; + }; + }; + + /* pm6150 L8 = LPI_CX supply */ + rpmh-regulator-lcxlvl { + compatible = "qcom,rpmh-arc-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "lcx.lvl"; + LPI_CX_LEVEL: + L8A_LEVEL: pm6150_l8_level: regulator-pm6150-l8 { + regulator-name = "pm6150_l8_level"; + qcom,set = ; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,init-voltage-level = + ; + }; + }; + + /* pm6150 L9 = WCSS_CX supply */ + rpmh-regulator-ldoa9 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa9"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + WCSS_CX: + L9A: pm6150_l9: regulator-pm6150-l9 { + regulator-name = "pm6150_l9"; + qcom,set = ; + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <728000>; + qcom,init-voltage = <400000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa10 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa10"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L10A: pm6150_l10: regulator-pm6150-l10 { + regulator-name = "pm6150_l10"; + qcom,set = ; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1829000>; + qcom,init-voltage = <1800000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa11 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa11"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L11A: pm6150_l11: regulator-pm6150-l11 { + regulator-name = "pm6150_l11"; + qcom,set = ; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1890000>; + qcom,init-voltage = <1800000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa12 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa12"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L12A: pm6150_l12: regulator-pm6150-l12 { + regulator-name = "pm6150_l12"; + qcom,set = ; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1950000>; + qcom,init-voltage = <1800000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa13 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa13"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L13A: pm6150_l13: regulator-pm6150-l13 { + regulator-name = "pm6150_l13"; + qcom,set = ; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + qcom,init-voltage = <1800000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa14 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa14"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L14A: pm6150_l14: regulator-pm6150-l14 { + regulator-name = "pm6150_l14"; + qcom,set = ; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1850000>; + qcom,init-voltage = <1800000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa15 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa15"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L15A: pm6150_l15: regulator-pm6150-l15 { + regulator-name = "pm6150_l15"; + qcom,set = ; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + qcom,init-voltage = <1800000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa16 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa16"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L16A: pm6150_l16: regulator-pm6150-l16 { + regulator-name = "pm6150_l16"; + qcom,set = ; + regulator-min-microvolt = <2430000>; + regulator-max-microvolt = <2970000>; + qcom,init-voltage = <2430000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa17 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa17"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L17A: pm6150_l17: regulator-pm6150-l17 { + regulator-name = "pm6150_l17"; + qcom,set = ; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3230000>; + qcom,init-voltage = <3000000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa18 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa18"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L18A: pm6150_l18: regulator-pm6150-l18 { + regulator-name = "pm6150_l18"; + qcom,set = ; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; + qcom,init-voltage = <3000000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoa19 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoa19"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L19A: pm6150_l19: regulator-pm6150-l19 { + regulator-name = "pm6150_l19"; + qcom,set = ; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3008000>; + qcom,init-voltage = <2700000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc1 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc1"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L1C: pm6150l_l1: regulator-pm6150l-l1 { + regulator-name = "pm6150l_l1"; + qcom,set = ; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + qcom,init-voltage = <1800000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc2 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc2"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L2C: pm6150l_l2: regulator-pm6150l-l2 { + regulator-name = "pm6150l_l2"; + qcom,set = ; + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1304000>; + qcom,init-voltage = <1300000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc3 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc3"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L3C: pm6150l_l3: regulator-pm6150l-l3 { + regulator-name = "pm6150l_l3"; + qcom,set = ; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + qcom,init-voltage = <1200000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc4 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc4"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L4C: pm6150l_l4: regulator-pm6150l-l4 { + regulator-name = "pm6150l_l4"; + qcom,set = ; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + qcom,init-voltage = <1650000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc5 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc5"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L5C: pm6150l_l5: regulator-pm6150l-l5 { + regulator-name = "pm6150l_l5"; + qcom,set = ; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + qcom,init-voltage = <1650000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc6 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc6"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L6C: pm6150l_l6: regulator-pm6150l-l6 { + regulator-name = "pm6150l_l6"; + qcom,set = ; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <3100000>; + qcom,init-voltage = <1650000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc7 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc7"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L7C: pm6150l_l7: regulator-pm6150l-l7 { + regulator-name = "pm6150l_l7"; + qcom,set = ; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3312000>; + qcom,init-voltage = <3000000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc8 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc8"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L8C: pm6150l_l8: regulator-pm6150l-l8 { + regulator-name = "pm6150l_l8"; + qcom,set = ; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + qcom,init-voltage = <1800000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc9 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc9"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L9C: pm6150l_l9: regulator-pm6150l-l9 { + regulator-name = "pm6150l_l9"; + qcom,set = ; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <3312000>; + qcom,init-voltage = <2950000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc10 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc10"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L10C: pm6150l_l10: regulator-pm6150l-l10 { + regulator-name = "pm6150l_l10"; + qcom,set = ; + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3312000>; + qcom,init-voltage = <3200000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-ldoc11 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "ldoc11"; + qcom,regulator-type = "pmic5-ldo"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1>; + L11C: pm6150l_l11: regulator-pm6150l-l11 { + regulator-name = "pm6150l_l11"; + qcom,set = ; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <3312000>; + qcom,init-voltage = <2950000>; + qcom,init-mode = ; + }; + }; + + rpmh-regulator-bobc1 { + compatible = "qcom,rpmh-vrm-regulator"; + mboxes = <&apps_rsc 0>; + qcom,resource-name = "bobc1"; + qcom,regulator-type = "pmic5-bob"; + qcom,supported-modes = + ; + qcom,mode-threshold-currents = <0 1000000 2000000>; + qcom,send-defaults; + + BOB: pm6150l_bob: regulator-pm6150l-bob { + regulator-name = "pm6150l_bob"; + qcom,set = ; + regulator-min-microvolt = <3296000>; + regulator-max-microvolt = <3960000>; + qcom,init-voltage = <3296000>; + qcom,init-mode = ; + }; + + BOB_AO: pm6150l_bob_ao: regulator-pm6150l-bob-ao { + regulator-name = "pm6150l_bob_ao"; + qcom,set = ; + regulator-min-microvolt = <3296000>; + regulator-max-microvolt = <3960000>; + qcom,init-voltage = <3296000>; + qcom,init-mode = ; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-stub-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-stub-regulator.dtsi new file mode 100644 index 000000000000..0407b95513ba --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-stub-regulator.dtsi @@ -0,0 +1,352 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +/* TODO: Update volatge range once PGA is locked */ +/* Stub regulators */ + +/ { + /* PM6150 S2 = VDD_GFX supply */ + VDD_GFX_LEVEL: + pm6150_s2_level: regulator-pm6150-s2-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_s2_level"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = ; + regulator-max-microvolt = ; + }; + + /* pm6150 S3 = VDD_MX supply */ + VDD_MX_LEVEL: + S3A_LEVEL: pm6150_s3_level: regulator-pm6150-s3 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_s3_level"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = ; + regulator-max-microvolt = ; + }; + + VDD_MX_LEVEL_AO: + S3A_LEVEL_AO: pm6150_s3_level_ao: regulator-pm6150-s3-level-ao { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_s3_level_ao"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = ; + regulator-max-microvolt = ; + }; + + S1C: pm6150l_s1: regulator-pm6150l-s1 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_s1"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <1128000>; + regulator-max-microvolt = <1128000>; + }; + + /* pm6150l S2 + S3 = 2 phase VDD_CX supply */ + VDD_CX_LEVEL: + pm6150l_s2_level: regulator-pm6150l-s2-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_s2_level"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = ; + regulator-max-microvolt = ; + }; + + VDD_CX_LEVEL_AO: + pm6150l_s2_level_ao: regulator-pm6150l-s2-level-ao { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_s2_level_ao"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = ; + regulator-max-microvolt = ; + }; + + /* pm6150l S7 = VDD_MSS supply */ + VDD_MSS_LEVEL: + S7C_LEVEL: pm6150l_s7_level: regulator-pm6150l-s7 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_s7_level"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = ; + regulator-max-microvolt = ; + }; + + S8C: pm6150l_s8: regulator-pm6150l-s8 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_s8"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1400000>; + }; + + L1A: pm6150_l1: regulator-pm6150-l1 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l1"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1252000>; + }; + + L2A: pm6150_l2: regulator-pm6150-l2 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l2"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1050000>; + }; + + L3A: pm6150_l3: regulator-pm6150-l3 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l3"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1060000>; + }; + + L4A: pm6150_l4: regulator-pm6150-l4 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l4"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <975000>; + }; + + L5A: pm6150_l5: regulator-pm6150-l5 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l5"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2970000>; + }; + + L6A: pm6150_l6: regulator-pm6150-l6 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l6"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + /* pm6150 L7 = LPI_MX supply */ + LPI_MX_LEVEL: + L7A_LEVEL: pm6150_l7_level: regulator-pm6150-l7-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l7_level"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = ; + regulator-max-microvolt = ; + }; + + /* pm6150 L8 = LPI_CX supply */ + LPI_CX_LEVEL: + L8A_LEVEL: pm6150_l8_level: regulator-pm6150-l8-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l8_level"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = ; + regulator-max-microvolt = ; + }; + + /* pm6150 L9 = WCSS_CX supply */ + WCSS_CX: + L9A: pm6150_l9: regulator-pm6150-l9 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l9"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <728000>; + }; + + L10A: pm6150_l10: regulator-pm6150-l10 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l10"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1829000>; + }; + + L11A: pm6150_l11: regulator-pm6150-l11 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l11"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1890000>; + }; + + L12A: pm6150_l12: regulator-pm6150-l12 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l12"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1950000>; + }; + + L13A: pm6150_l13: regulator-pm6150-l13 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l13"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + }; + + L14A: pm6150_l14: regulator-pm6150-l14 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l14"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1850000>; + }; + + L15A: pm6150_l15: regulator-pm6150-l15 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l15"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + }; + + L16A: pm6150_l16: regulator-pm6150-l16 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l16"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <2430000>; + regulator-max-microvolt = <2970000>; + }; + + L17A: pm6150_l17: regulator-pm6150-l17 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l17"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3230000>; + }; + + L18A: pm6150_l18: regulator-pm6150-l18 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l18"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; + }; + + L19A: pm6150_l19: regulator-pm6150-l19 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150_l19"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3008000>; + }; + + L1C: pm6150l_l1: regulator-pm6150l-l1 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l1"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + }; + + L2C: pm6150l_l2: regulator-pm6150l-l2 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l2"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1304000>; + }; + + L3C: pm6150l_l3: regulator-pm6150l-l3 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l3"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + }; + + L4C: pm6150l_l4: regulator-pm6150l-l4 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l4"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + }; + + L5C: pm6150l_l5: regulator-pm6150l-l5 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l5"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + }; + + L6C: pm6150l_l6: regulator-pm6150l-l6 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l6"; + qcom,hpm-min-load = <5000>; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <3100000>; + }; + + L7C: pm6150l_l7: regulator-pm6150l-l7 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l7"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3312000>; + }; + + L8C: pm6150l_l8: regulator-pm6150l-l8 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l8"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + }; + + L9C: pm6150l_l9: regulator-pm6150l-l9 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l9"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <3312000>; + }; + + L10C: pm6150l_l10: regulator-pm6150l-l10 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l10"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3312000>; + }; + + L11C: pm6150l_l11: regulator-pm6150l-l11 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_l11"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <3312000>; + }; + + BOB: pm6150l_bob: regulator-pm6150l-bob { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_bob"; + regulator-min-microvolt = <3296000>; + regulator-max-microvolt = <3960000>; + }; + + BOB_AO: pm6150l_bob_ao: regulator-pm6150l-bob-ao { + compatible = "qcom,stub-regulator"; + regulator-name = "pm6150l_bob_ao"; + regulator-min-microvolt = <3296000>; + regulator-max-microvolt = <3960000>; + }; +}; -- GitLab From 00508fa9c5c8f38450fc2d1f73fb104b156aae95 Mon Sep 17 00:00:00 2001 From: Ashay Jaiswal Date: Sun, 20 May 2018 16:33:56 +0530 Subject: [PATCH 0089/1299] ARM: dts: msm: add regulator support for sdmmagpie RUMI Add regulator support for sdmmagpie RUMI, this allows clients to vote on their supply regulators. Change-Id: Ib14e7b84ab6e87f5495b4a08da06a5417fd0cf0f Signed-off-by: Ashay Jaiswal --- arch/arm64/boot/dts/qcom/sdmmagpie-rumi.dtsi | 42 ++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-rumi.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-rumi.dtsi index a683d878cc32..f9e417fcca94 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-rumi.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-rumi.dtsi @@ -23,3 +23,45 @@ status = "disabled"; }; }; + +&soc { + /delete-node/ rpmh-regulator-gfxlvl; + /delete-node/ rpmh-regulator-mxlvl; + /delete-node/ rpmh-regulator-cxlvl; + /delete-node/ rpmh-regulator-smpc1; + /delete-node/ rpmh-regulator-modemlvl; + /delete-node/ rpmh-regulator-smpc8; + /delete-node/ rpmh-regulator-ldoa1; + /delete-node/ rpmh-regulator-ldoa2; + /delete-node/ rpmh-regulator-ldoa3; + /delete-node/ rpmh-regulator-ldoa4; + /delete-node/ rpmh-regulator-ldoa5; + /delete-node/ rpmh-regulator-ldoa6; + /delete-node/ rpmh-regulator-lmxlvl; + /delete-node/ rpmh-regulator-lcxlvl; + /delete-node/ rpmh-regulator-ldoa9; + /delete-node/ rpmh-regulator-ldoa10; + /delete-node/ rpmh-regulator-ldoa11; + /delete-node/ rpmh-regulator-ldoa12; + /delete-node/ rpmh-regulator-ldoa13; + /delete-node/ rpmh-regulator-ldoa14; + /delete-node/ rpmh-regulator-ldoa15; + /delete-node/ rpmh-regulator-ldoa16; + /delete-node/ rpmh-regulator-ldoa17; + /delete-node/ rpmh-regulator-ldoa18; + /delete-node/ rpmh-regulator-ldoa19; + /delete-node/ rpmh-regulator-ldoc1; + /delete-node/ rpmh-regulator-ldoc2; + /delete-node/ rpmh-regulator-ldoc3; + /delete-node/ rpmh-regulator-ldoc4; + /delete-node/ rpmh-regulator-ldoc5; + /delete-node/ rpmh-regulator-ldoc6; + /delete-node/ rpmh-regulator-ldoc7; + /delete-node/ rpmh-regulator-ldoc8; + /delete-node/ rpmh-regulator-ldoc9; + /delete-node/ rpmh-regulator-ldoc10; + /delete-node/ rpmh-regulator-ldoc11; + /delete-node/ rpmh-regulator-bobc1; +}; + +#include "sdmmagpie-stub-regulator.dtsi" -- GitLab From 60331ba37e09569647afa308faea8e73d7da40db Mon Sep 17 00:00:00 2001 From: Konstantin Dorfman Date: Thu, 7 Jun 2018 09:26:19 +0300 Subject: [PATCH 0090/1299] soc: qcom: spcom: remove excessive log This change removes excessive log message. Change-Id: Ia270ee5bb968f0a1f4521b2409ba8053e6484eb9 Signed-off-by: Konstantin Dorfman --- drivers/soc/qcom/spcom.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index cb531e5f31ad..763c4da5162e 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -532,7 +532,7 @@ static int spcom_handle_restart_sp_command(void) { void *subsystem_get_retval = NULL; - pr_err("restart - PIL FW loading process initiated\n"); + pr_debug("restart - PIL FW loading process initiated\n"); subsystem_get_retval = subsystem_get("spss"); if (!subsystem_get_retval) { @@ -540,7 +540,7 @@ static int spcom_handle_restart_sp_command(void) return -EINVAL; } - pr_err("restart - PIL FW loading process is complete\n"); + pr_debug("restart - PIL FW loading process is complete\n"); return 0; } @@ -882,7 +882,7 @@ static int spcom_handle_lock_ion_buf_command(struct spcom_channel *ch, /* Check if this shared buffer is already locked */ for (i = 0 ; i < ARRAY_SIZE(ch->dmabuf_handle_table) ; i++) { if (ch->dmabuf_handle_table[i] == dma_buf) { - pr_err("fd [%d] shared buf is already locked.\n", fd); + pr_debug("fd [%d] shared buf is already locked.\n", fd); /* decrement back the ref count */ mutex_unlock(&ch->lock); dma_buf_put(dma_buf); @@ -1293,8 +1293,6 @@ static int spcom_device_release(struct inode *inode, struct file *filp) const char *name = file_to_filename(filp); int ret = 0; - pr_err("close file [%s].\n", name); - if (strcmp(name, "unknown") == 0) { pr_err("name is unknown\n"); return -EINVAL; @@ -1893,7 +1891,7 @@ static int spcom_rpdev_cb(struct rpmsg_device *rpdev, spin_lock_irqsave(&spcom_dev->rx_lock, flags); list_add(&rx_item->list, &spcom_dev->rx_list_head); spin_unlock_irqrestore(&spcom_dev->rx_lock, flags); - pr_err("signaling rx item for %s, received %d bytes\n", + pr_debug("signaling rx item for %s, received %d bytes\n", rpdev->id.name, len); schedule_work(&rpmsg_rx_consumer); -- GitLab From c88d00c6ed7a2edf7ef43aa35af6e4cf78b0db65 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 5 Jun 2018 13:02:04 -0700 Subject: [PATCH 0091/1299] power: fg-memif: Add workaround for DMA during SRAM access in PM8150B v1 Sometimes in PM8150B v1, FG SRAM can be accessed by HW over DMA even after the access is granted to the SW by arbiter. When this happens, FG SRAM data can get corrupted as HW might be modifying it along with SW. As per the hardware recommendation, configure PEEK_MUX4 to poll the status of ALG active. If it is asserted low, wait for 1 ms before DMA is requested during FG SRAM access. Change-Id: I0d1be7d86f40a515513e6a931264740344eb3263 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-memif.c | 51 ++++++++++++++++++++++++++++ drivers/power/supply/qcom/fg-reg.h | 6 ++++ 2 files changed, 57 insertions(+) diff --git a/drivers/power/supply/qcom/fg-memif.c b/drivers/power/supply/qcom/fg-memif.c index 4e4589a24960..d14a55db72fb 100644 --- a/drivers/power/supply/qcom/fg-memif.c +++ b/drivers/power/supply/qcom/fg-memif.c @@ -793,6 +793,37 @@ int fg_interleaved_mem_write(struct fg_dev *fg, u16 address, u8 offset, return rc; } +static int fg_poll_alg_active(struct fg_dev *fg) +{ + u32 retries = 35, poll_time_us = 10000; + int rc; + u8 val; + + /* + * ALG active should be asserted low within ~164 ms mostly however + * during ESR pulsing, a worst case delay of ~320 ms is needed. + */ + while (retries--) { + rc = fg_read(fg, BATT_INFO_PEEK_RD(fg), &val, 1); + if (rc < 0) { + pr_err("failed to read PEEK_MUX rc=%d\n", rc); + return rc; + } + + if (!(val & ALG_ACTIVE_BIT)) + break; + + usleep_range(poll_time_us, poll_time_us + 1); + } + + if (val & ALG_ACTIVE_BIT) + return -ETIMEDOUT; + + /* Wait for 1 ms after ALG active is asserted low */ + usleep_range(1000, 1001); + return rc; +} + static int fg_direct_mem_release(struct fg_dev *fg) { int rc; @@ -823,6 +854,14 @@ static int fg_direct_mem_request(struct fg_dev *fg) int rc, ret, i = 0; u8 val, mask, poll_bit; + if (fg->wa_flags & PM8150B_V1_DMA_WA) { + rc = fg_poll_alg_active(fg); + if (rc < 0) { + pr_err("Failed to assert ALG active rc=%d\n", rc); + return rc; + } + } + val = mask = MEM_ARB_REQ_BIT; rc = fg_masked_write(fg, MEM_IF_MEM_ARB_CFG(fg), mask, val); if (rc < 0) { @@ -1169,6 +1208,7 @@ static struct fg_dma_address fg_gen4_addr_map[6] = { static int fg_dma_init(struct fg_dev *fg) { int rc; + u8 val; if (fg->version == GEN3_FG) { fg->sram.addr_map = fg_gen3_addr_map; @@ -1217,6 +1257,17 @@ static int fg_dma_init(struct fg_dev *fg) return rc; } + /* Configure PEEK_MUX only for PM8150B v1.0 */ + if (fg->wa_flags & PM8150B_V1_DMA_WA) { + val = ALG_ACTIVE_PEEK_CFG; + rc = fg_write(fg, BATT_INFO_PEEK_MUX4(fg), &val, 1); + if (rc < 0) { + pr_err("failed to configure batt_info_peek_mux4 rc:%d\n", + rc); + return rc; + } + } + return 0; } diff --git a/drivers/power/supply/qcom/fg-reg.h b/drivers/power/supply/qcom/fg-reg.h index 5c20fb13bb4a..26e281090e51 100644 --- a/drivers/power/supply/qcom/fg-reg.h +++ b/drivers/power/supply/qcom/fg-reg.h @@ -275,6 +275,12 @@ #define ESR_REQ_CTL_BIT BIT(1) #define ESR_REQ_CTL_EN_BIT BIT(0) +#define BATT_INFO_PEEK_MUX4(chip) (chip->batt_info_base + 0xEE) +#define ALG_ACTIVE_PEEK_CFG 0xAC + +#define BATT_INFO_PEEK_RD(chip) (chip->batt_info_base + 0xEF) +#define ALG_ACTIVE_BIT BIT(3) + /* FG_MEM_IF register and bit definitions */ #define MEM_IF_INT_RT_STS(chip) ((chip->mem_if_base) + 0x10) #define MEM_XCP_BIT BIT(1) -- GitLab From 92bd16b58d6b6f7e4d35c76fa809e5cadd150c26 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 5 Jun 2018 18:06:31 -0700 Subject: [PATCH 0092/1299] power: fg-util: Update getting battery voltage and current from FG Currently, battery voltage and current are obtained from FG by reading VBATT and IBATT registers in FG_BATT_INFO peripheral. To get a more reliable reading, read the shadow registers VBATT_CP and IBATT_CP as well. If they match, then use them to show it to the clients. Change-Id: Idb5d57e3dd9b9c2a33e77c1b874823fb087c54d9 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-util.c | 70 +++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c index 7a0e4686ef51..9b34ab20de73 100644 --- a/drivers/power/supply/qcom/fg-util.c +++ b/drivers/power/supply/qcom/fg-util.c @@ -26,6 +26,7 @@ CHARS_PER_ITEM) + 1) \ #define VOLTAGE_15BIT_MASK GENMASK(14, 0) +#define MAX_READ_TRIES 5 int fg_decode_voltage_15b(struct fg_sram_param *sp, enum fg_sram_param_id id, int value) @@ -826,13 +827,12 @@ int fg_restart(struct fg_dev *fg, int wait_time_ms) /* All fg_get_* , fg_set_* functions here */ -#define MAX_TRIES_SOC 5 int fg_get_msoc_raw(struct fg_dev *fg, int *val) { u8 cap[2]; int rc, tries = 0; - while (tries < MAX_TRIES_SOC) { + while (tries < MAX_READ_TRIES) { rc = fg_read(fg, BATT_SOC_FG_MONOTONIC_SOC(fg), cap, 2); if (rc < 0) { pr_err("failed to read addr=0x%04x, rc=%d\n", @@ -846,8 +846,8 @@ int fg_get_msoc_raw(struct fg_dev *fg, int *val) tries++; } - if (tries == MAX_TRIES_SOC) { - pr_err("shadow registers do not match\n"); + if (tries == MAX_READ_TRIES) { + pr_err("MSOC: shadow registers do not match\n"); return -EINVAL; } @@ -934,15 +934,32 @@ int fg_get_battery_resistance(struct fg_dev *fg, int *val) #define BATT_CURRENT_DENR 1000 int fg_get_battery_current(struct fg_dev *fg, int *val) { - int rc = 0; + int rc = 0, tries = 0; int64_t temp = 0; - u8 buf[2]; + u8 buf[2], buf_cp[2]; - rc = fg_read(fg, BATT_INFO_IBATT_LSB(fg), buf, 2); - if (rc < 0) { - pr_err("failed to read addr=0x%04x, rc=%d\n", - BATT_INFO_IBATT_LSB(fg), rc); - return rc; + while (tries++ < MAX_READ_TRIES) { + rc = fg_read(fg, BATT_INFO_IBATT_LSB(fg), buf, 2); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + BATT_INFO_IBATT_LSB(fg), rc); + return rc; + } + + rc = fg_read(fg, BATT_INFO_IBATT_LSB_CP(fg), buf_cp, 2); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + BATT_INFO_IBATT_LSB_CP(fg), rc); + return rc; + } + + if (buf[0] == buf_cp[0] && buf[1] == buf_cp[1]) + break; + } + + if (tries == MAX_READ_TRIES) { + pr_err("IBATT: shadow registers do not match\n"); + return -EINVAL; } if (fg->wa_flags & PMI8998_V1_REV_WA) @@ -961,15 +978,32 @@ int fg_get_battery_current(struct fg_dev *fg, int *val) #define BATT_VOLTAGE_DENR 1000 int fg_get_battery_voltage(struct fg_dev *fg, int *val) { - int rc = 0; + int rc = 0, tries = 0; u16 temp = 0; - u8 buf[2]; + u8 buf[2], buf_cp[2]; - rc = fg_read(fg, BATT_INFO_VBATT_LSB(fg), buf, 2); - if (rc < 0) { - pr_err("failed to read addr=0x%04x, rc=%d\n", - BATT_INFO_VBATT_LSB(fg), rc); - return rc; + while (tries++ < MAX_READ_TRIES) { + rc = fg_read(fg, BATT_INFO_VBATT_LSB(fg), buf, 2); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + BATT_INFO_VBATT_LSB(fg), rc); + return rc; + } + + rc = fg_read(fg, BATT_INFO_VBATT_LSB_CP(fg), buf_cp, 2); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + BATT_INFO_VBATT_LSB_CP(fg), rc); + return rc; + } + + if (buf[0] == buf_cp[0] && buf[1] == buf_cp[1]) + break; + } + + if (tries == MAX_READ_TRIES) { + pr_err("VBATT: shadow registers do not match\n"); + return -EINVAL; } if (fg->wa_flags & PMI8998_V1_REV_WA) -- GitLab From 988fc47fade77245eca0c2994a80342d2df7175d Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Wed, 6 Jun 2018 20:49:30 -0700 Subject: [PATCH 0093/1299] power: qpnp-fg-gen4: Add support for configuring more Ki coefficients Currently, GEN4 FG driver supports configuring Ki coefficients for medium and high discharging conditions based on the SOC thresholds. In addition, add support to configure Ki coefficients for low discharging conditions based on SOC thresholds. Also, add support to configure Ki coefficients for low, medium and high charging conditions one time during HW initialization based on the device tree property. Change-Id: I8e72bb19f594ac072b4df37d1433b8676c85e5b4 Signed-off-by: Subbaraman Narayanamurthy --- .../power/supply/qcom/qpnp-fg-gen4.txt | 32 ++++ drivers/power/supply/qcom/fg-core.h | 4 + drivers/power/supply/qcom/qpnp-fg-gen4.c | 141 ++++++++++++++++-- 3 files changed, 163 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt index ceb97b552e3e..9ee8eca053eb 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt +++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt @@ -229,6 +229,17 @@ First Level Node - FG Gen4 device This should be defined in the ascending order and in the range of 0-100. Array limit is set to 3. +- qcom,ki-coeff-low-dischg + Usage: optional + Value type: + Definition: Array of ki coefficient values for low discharge current + during discharge. These values will be applied when the + monotonic SOC goes below the SOC threshold specified under + qcom,ki-coeff-soc-dischg. Array limit is set to 3. This + property should be specified if qcom,ki-coeff-soc-dischg + is specified to make it fully functional. Value has no + unit. Allowed range is 62 to 15564 in micro units. + - qcom,ki-coeff-med-dischg Usage: optional Value type: @@ -251,6 +262,27 @@ First Level Node - FG Gen4 device is specified to make it fully functional. Value has no unit. Allowed range is 62 to 15564 in micro units. +- qcom,ki-coeff-low-chg + Usage: optional + Value type: + Definition: ki coefficient value for low charge current during + charging. Value has no unit. Allowed range is 62 to 15564 + in micro units. + +- qcom,ki-coeff-med-chg + Usage: optional + Value type: + Definition: ki coefficient value for medium charge current during + charging. Value has no unit. Allowed range is 62 to 15564 + in micro units. + +- qcom,ki-coeff-hi-chg + Usage: optional + Value type: + Definition: ki coefficient value for high charge current during + charging. Value has no unit. Allowed range is 62 to 15564 + in micro units. + - qcom,fg-rconn-uohms Usage: optional Value type: diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 06df23611eb2..af928abcae3d 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -190,8 +190,12 @@ enum fg_sram_param_id { FG_SRAM_DELTA_BSOC_THR, FG_SRAM_RECHARGE_SOC_THR, FG_SRAM_RECHARGE_VBATT_THR, + FG_SRAM_KI_COEFF_LOW_DISCHG, FG_SRAM_KI_COEFF_MED_DISCHG, FG_SRAM_KI_COEFF_HI_DISCHG, + FG_SRAM_KI_COEFF_LOW_CHG, + FG_SRAM_KI_COEFF_MED_CHG, + FG_SRAM_KI_COEFF_HI_CHG, FG_SRAM_KI_COEFF_FULL_SOC, FG_SRAM_ESR_TIGHT_FILTER, FG_SRAM_ESR_BROAD_FILTER, diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index b15f5960d68e..19edf4d45a54 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -67,10 +67,18 @@ #define SYS_TERM_CURR_OFFSET 0 #define VBATT_FULL_WORD 23 #define VBATT_FULL_OFFSET 0 +#define KI_COEFF_LOW_DISCHG_WORD 25 +#define KI_COEFF_LOW_DISCHG_OFFSET 1 #define KI_COEFF_MED_DISCHG_WORD 26 #define KI_COEFF_MED_DISCHG_OFFSET 0 #define KI_COEFF_HI_DISCHG_WORD 26 #define KI_COEFF_HI_DISCHG_OFFSET 1 +#define KI_COEFF_LOW_CHG_WORD 28 +#define KI_COEFF_LOW_CHG_OFFSET 0 +#define KI_COEFF_MED_CHG_WORD 28 +#define KI_COEFF_MED_CHG_OFFSET 1 +#define KI_COEFF_HI_CHG_WORD 29 +#define KI_COEFF_HI_CHG_OFFSET 0 #define DELTA_BSOC_THR_WORD 30 #define DELTA_BSOC_THR_OFFSET 1 #define SLOPE_LIMIT_WORD 32 @@ -134,7 +142,11 @@ struct fg_dt_props { int esr_pulse_thresh_ma; int esr_meas_curr_ma; int slope_limit_temp; + int ki_coeff_low_chg; + int ki_coeff_med_chg; + int ki_coeff_hi_chg; int ki_coeff_soc[KI_COEFF_SOC_LEVELS]; + int ki_coeff_low_dischg[KI_COEFF_SOC_LEVELS]; int ki_coeff_med_dischg[KI_COEFF_SOC_LEVELS]; int ki_coeff_hi_dischg[KI_COEFF_SOC_LEVELS]; int slope_limit_coeffs[SLOPE_LIMIT_NUM_COEFFS]; @@ -223,12 +235,21 @@ static struct fg_sram_param pm8150_sram_params[] = { ESR_TIMER_CHG_INIT_OFFSET, 1, 1, 1, 0, fg_encode_default, NULL), PARAM(ESR_PULSE_THRESH, ESR_PULSE_THRESH_WORD, ESR_PULSE_THRESH_OFFSET, 1, 1000, 15625, 0, fg_encode_default, NULL), + PARAM(KI_COEFF_LOW_DISCHG, KI_COEFF_LOW_DISCHG_WORD, + KI_COEFF_LOW_DISCHG_OFFSET, 1, 1000, 61035, 0, + fg_encode_default, NULL), PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_WORD, KI_COEFF_MED_DISCHG_OFFSET, 1, 1000, 61035, 0, fg_encode_default, NULL), PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_WORD, KI_COEFF_HI_DISCHG_OFFSET, 1, 1000, 61035, 0, fg_encode_default, NULL), + PARAM(KI_COEFF_LOW_CHG, KI_COEFF_LOW_CHG_WORD, KI_COEFF_LOW_CHG_OFFSET, + 1, 1000, 61035, 0, fg_encode_default, NULL), + PARAM(KI_COEFF_MED_CHG, KI_COEFF_MED_CHG_WORD, KI_COEFF_MED_CHG_OFFSET, + 1, 1000, 61035, 0, fg_encode_default, NULL), + PARAM(KI_COEFF_HI_CHG, KI_COEFF_HI_CHG_WORD, KI_COEFF_HI_CHG_OFFSET, 1, + 1000, 61035, 0, fg_encode_default, NULL), PARAM(SLOPE_LIMIT, SLOPE_LIMIT_WORD, SLOPE_LIMIT_OFFSET, 1, 8192, 1000000, 0, fg_encode_default, NULL), PARAM(BATT_TEMP_COLD, BATT_TEMP_CONFIG_WORD, BATT_TEMP_COLD_OFFSET, 1, @@ -670,12 +691,14 @@ static int fg_gen4_store_count(void *data, u16 *buf, int id, int length) /* All worker and helper functions below */ +#define KI_COEFF_LOW_DISCHG_DEFAULT 428 #define KI_COEFF_MED_DISCHG_DEFAULT 245 #define KI_COEFF_HI_DISCHG_DEFAULT 123 static int fg_gen4_adjust_ki_coeff_dischg(struct fg_dev *fg) { struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int rc, i, msoc; + int ki_coeff_low = KI_COEFF_LOW_DISCHG_DEFAULT; int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT; int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT; u8 val; @@ -692,36 +715,58 @@ static int fg_gen4_adjust_ki_coeff_dischg(struct fg_dev *fg) if (fg->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) { for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) { if (msoc < chip->dt.ki_coeff_soc[i]) { + ki_coeff_low = chip->dt.ki_coeff_low_dischg[i]; ki_coeff_med = chip->dt.ki_coeff_med_dischg[i]; ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i]; } } } - fg_encode(fg->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val); - rc = fg_sram_write(fg, + if (ki_coeff_low > 0) { + fg_encode(fg->sp, FG_SRAM_KI_COEFF_LOW_DISCHG, ki_coeff_low, + &val); + rc = fg_sram_write(fg, + fg->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].addr_word, + fg->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].addr_byte, &val, + fg->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].len, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ki_coeff_low, rc=%d\n", rc); + return rc; + } + fg_dbg(fg, FG_STATUS, "Wrote ki_coeff_low %d\n", ki_coeff_low); + } + + if (ki_coeff_med > 0) { + fg_encode(fg->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, + &val); + rc = fg_sram_write(fg, fg->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word, fg->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_byte, &val, fg->sp[FG_SRAM_KI_COEFF_MED_DISCHG].len, FG_IMA_DEFAULT); - if (rc < 0) { - pr_err("Error in writing ki_coeff_med, rc=%d\n", rc); - return rc; + if (rc < 0) { + pr_err("Error in writing ki_coeff_med, rc=%d\n", rc); + return rc; + } + fg_dbg(fg, FG_STATUS, "Wrote ki_coeff_med %d\n", ki_coeff_med); } - fg_encode(fg->sp, FG_SRAM_KI_COEFF_HI_DISCHG, ki_coeff_hi, &val); - rc = fg_sram_write(fg, + if (ki_coeff_hi > 0) { + fg_encode(fg->sp, FG_SRAM_KI_COEFF_HI_DISCHG, ki_coeff_hi, + &val); + rc = fg_sram_write(fg, fg->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_word, fg->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_byte, &val, fg->sp[FG_SRAM_KI_COEFF_HI_DISCHG].len, FG_IMA_DEFAULT); - if (rc < 0) { - pr_err("Error in writing ki_coeff_hi, rc=%d\n", rc); - return rc; + if (rc < 0) { + pr_err("Error in writing ki_coeff_hi, rc=%d\n", rc); + return rc; + } + fg_dbg(fg, FG_STATUS, "Wrote ki_coeff_hi %d\n", ki_coeff_hi); } - fg_dbg(fg, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n", - ki_coeff_med, ki_coeff_hi); return 0; } @@ -2817,6 +2862,50 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip) } } + if (chip->dt.ki_coeff_low_chg != -EINVAL) { + fg_encode(fg->sp, FG_SRAM_KI_COEFF_LOW_CHG, + chip->dt.ki_coeff_low_chg, &val); + rc = fg_sram_write(fg, + fg->sp[FG_SRAM_KI_COEFF_LOW_CHG].addr_word, + fg->sp[FG_SRAM_KI_COEFF_LOW_CHG].addr_byte, &val, + fg->sp[FG_SRAM_KI_COEFF_LOW_CHG].len, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ki_coeff_low_chg, rc=%d\n", + rc); + return rc; + } + } + + if (chip->dt.ki_coeff_med_chg != -EINVAL) { + fg_encode(fg->sp, FG_SRAM_KI_COEFF_MED_CHG, + chip->dt.ki_coeff_med_chg, &val); + rc = fg_sram_write(fg, + fg->sp[FG_SRAM_KI_COEFF_MED_CHG].addr_word, + fg->sp[FG_SRAM_KI_COEFF_MED_CHG].addr_byte, &val, + fg->sp[FG_SRAM_KI_COEFF_MED_CHG].len, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ki_coeff_med_chg, rc=%d\n", + rc); + return rc; + } + } + + if (chip->dt.ki_coeff_hi_chg != -EINVAL) { + fg_encode(fg->sp, FG_SRAM_KI_COEFF_HI_CHG, + chip->dt.ki_coeff_hi_chg, &val); + rc = fg_sram_write(fg, + fg->sp[FG_SRAM_KI_COEFF_HI_CHG].addr_word, + fg->sp[FG_SRAM_KI_COEFF_HI_CHG].addr_byte, &val, + fg->sp[FG_SRAM_KI_COEFF_HI_CHG].len, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ki_coeff_hi_chg, rc=%d\n", rc); + return rc; + } + } + rc = restore_cycle_count(chip->counter); if (rc < 0) { pr_err("Error in restoring cycle_count, rc=%d\n", rc); @@ -2889,9 +2978,22 @@ static int fg_parse_ki_coefficients(struct fg_dev *fg) struct device_node *node = fg->dev->of_node; int rc, i; + chip->dt.ki_coeff_low_chg = -EINVAL; + of_property_read_u32(node, "qcom,ki-coeff-low-chg", + &chip->dt.ki_coeff_low_chg); + + chip->dt.ki_coeff_med_chg = -EINVAL; + of_property_read_u32(node, "qcom,ki-coeff-med-chg", + &chip->dt.ki_coeff_med_chg); + + chip->dt.ki_coeff_hi_chg = -EINVAL; + of_property_read_u32(node, "qcom,ki-coeff-hi-chg", + &chip->dt.ki_coeff_hi_chg); + if (!of_find_property(node, "qcom,ki-coeff-soc-dischg", NULL) || - !of_find_property(node, "qcom,ki-coeff-med-dischg", NULL) || - !of_find_property(node, "qcom,ki-coeff-hi-dischg", NULL)) + (!of_find_property(node, "qcom,ki-coeff-low-dischg", NULL) && + !of_find_property(node, "qcom,ki-coeff-med-dischg", NULL) && + !of_find_property(node, "qcom,ki-coeff-hi-dischg", NULL))) return 0; rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-soc-dischg", @@ -2899,6 +3001,11 @@ static int fg_parse_ki_coefficients(struct fg_dev *fg) if (rc < 0) return rc; + rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-low-dischg", + chip->dt.ki_coeff_low_dischg, KI_COEFF_SOC_LEVELS); + if (rc < 0) + return rc; + rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-med-dischg", chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS); if (rc < 0) @@ -2916,6 +3023,12 @@ static int fg_parse_ki_coefficients(struct fg_dev *fg) return -EINVAL; } + if (chip->dt.ki_coeff_low_dischg[i] < 0 || + chip->dt.ki_coeff_low_dischg[i] > KI_COEFF_MAX) { + pr_err("Error in ki_coeff_low_dischg values\n"); + return -EINVAL; + } + if (chip->dt.ki_coeff_med_dischg[i] < 0 || chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) { pr_err("Error in ki_coeff_med_dischg values\n"); -- GitLab From 7f5b94548fe8a955768a9aec238761564e67b98f Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Fri, 8 Jun 2018 18:59:39 -0700 Subject: [PATCH 0094/1299] power: qpnp-fg-gen4: qpnp-fg-gen3: Update TTF variable names TTF algorithm is getting moved to fg-alg.c so that GEN4 FG driver can share it with QG driver. In preparation for it, change TTF variable names so that the namespace won't conflict. Change-Id: I80d899277692c259182d537533551f9503a7cd3e Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-core.h | 8 ++++---- drivers/power/supply/qcom/qpnp-fg-gen3.c | 20 ++++++++++---------- drivers/power/supply/qcom/qpnp-fg-gen4.c | 14 +++++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 06df23611eb2..5a010a99ffb4 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -269,9 +269,9 @@ enum esr_timer_config { NUM_ESR_TIMERS, }; -enum ttf_mode { - TTF_MODE_NORMAL = 0, - TTF_MODE_QNOVO, +enum fg_ttf_mode { + FG_TTF_MODE_NORMAL = 0, + FG_TTF_MODE_QNOVO, }; /* parameters from battery profile */ @@ -327,7 +327,7 @@ struct fg_pt { s32 y; }; -struct ttf { +struct fg_ttf { struct fg_circ_buf ibatt; struct fg_circ_buf vbatt; struct fg_cc_step_data cc_step; diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index a0f5226c6f97..3e4447c3de94 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -214,7 +214,7 @@ struct fg_gen3_chip { struct mutex qnovo_esr_ctrl_lock; struct fg_cyc_ctr_data cyc_ctr; struct fg_cap_learning cl; - struct ttf ttf; + struct fg_ttf ttf; struct delayed_work ttf_work; struct delayed_work pl_enable_work; enum slope_limit_status slope_limit_sts; @@ -1693,13 +1693,13 @@ static int fg_adjust_recharge_soc(struct fg_dev *fg) if (!chip->dt.auto_recharge_soc) return 0; - rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH, + rc = power_supply_get_property(fg->batt_psy, POWER_SUPPLY_PROP_HEALTH, &prop); if (rc < 0) { pr_err("Error in getting battery health, rc=%d\n", rc); return rc; } - chip->health = prop.intval; + fg->health = prop.intval; recharge_soc = chip->dt.recharge_soc_thr; recharge_soc_status = fg->recharge_soc_adjusted; @@ -1731,7 +1731,7 @@ static int fg_adjust_recharge_soc(struct fg_dev *fg) if (!fg->recharge_soc_adjusted) return 0; - if (chip->health != POWER_SUPPLY_HEALTH_GOOD) + if (fg->health != POWER_SUPPLY_HEALTH_GOOD) return 0; /* Restore the default value */ @@ -2727,9 +2727,9 @@ static int fg_get_time_to_full_locked(struct fg_dev *fg, int *val) } if (is_qnovo_en(fg)) - ttf_mode = TTF_MODE_QNOVO; + ttf_mode = FG_TTF_MODE_QNOVO; else - ttf_mode = TTF_MODE_NORMAL; + ttf_mode = FG_TTF_MODE_NORMAL; /* when switching TTF algorithms the TTF needs to be reset */ if (chip->ttf.mode != ttf_mode) { @@ -2795,11 +2795,11 @@ static int fg_get_time_to_full_locked(struct fg_dev *fg, int *val) /* estimated battery current at the CC to CV transition */ switch (chip->ttf.mode) { - case TTF_MODE_NORMAL: + case FG_TTF_MODE_NORMAL: i_cc2cv = ibatt_avg * vbatt_avg / max(MILLI_UNIT, fg->bp.float_volt_uv / MILLI_UNIT); break; - case TTF_MODE_QNOVO: + case FG_TTF_MODE_QNOVO: i_cc2cv = min( chip->ttf.cc_step.arr[MAX_CC_STEPS - 1] / MILLI_UNIT, ibatt_avg * vbatt_avg / @@ -2821,7 +2821,7 @@ static int fg_get_time_to_full_locked(struct fg_dev *fg, int *val) fg_dbg(fg, FG_TTF, "soc_cc2cv=%d\n", soc_cc2cv); switch (chip->ttf.mode) { - case TTF_MODE_NORMAL: + case FG_TTF_MODE_NORMAL: if (soc_cc2cv - msoc <= 0) goto cv_estimate; @@ -2829,7 +2829,7 @@ static int fg_get_time_to_full_locked(struct fg_dev *fg, int *val) t_predicted = div_s64((s64)act_cap_mah * (soc_cc2cv - msoc) * HOURS_TO_SECONDS, divisor); break; - case TTF_MODE_QNOVO: + case FG_TTF_MODE_QNOVO: soc_per_step = 100 / MAX_CC_STEPS; for (i = msoc / soc_per_step; i < MAX_CC_STEPS - 1; ++i) { msoc_next_step = (i + 1) * soc_per_step; diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index b15f5960d68e..4c8f427ad2c7 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -145,7 +145,7 @@ struct fg_gen4_chip { struct fg_dt_props dt; struct cycle_counter *counter; struct cap_learning *cl; - struct ttf ttf; + struct fg_ttf ttf; struct delayed_work ttf_work; char batt_profile[PROFILE_LEN]; int recharge_soc_thr; @@ -1886,9 +1886,9 @@ static int fg_get_time_to_full_locked(struct fg_dev *fg, int *val) } if (is_qnovo_en(fg)) - ttf_mode = TTF_MODE_QNOVO; + ttf_mode = FG_TTF_MODE_QNOVO; else - ttf_mode = TTF_MODE_NORMAL; + ttf_mode = FG_TTF_MODE_NORMAL; /* when switching TTF algorithms the TTF needs to be reset */ if (chip->ttf.mode != ttf_mode) { @@ -1954,11 +1954,11 @@ static int fg_get_time_to_full_locked(struct fg_dev *fg, int *val) /* estimated battery current at the CC to CV transition */ switch (chip->ttf.mode) { - case TTF_MODE_NORMAL: + case FG_TTF_MODE_NORMAL: i_cc2cv = ibatt_avg * vbatt_avg / max(MILLI_UNIT, fg->bp.float_volt_uv / MILLI_UNIT); break; - case TTF_MODE_QNOVO: + case FG_TTF_MODE_QNOVO: i_cc2cv = min( chip->ttf.cc_step.arr[MAX_CC_STEPS - 1] / MILLI_UNIT, ibatt_avg * vbatt_avg / @@ -1980,7 +1980,7 @@ static int fg_get_time_to_full_locked(struct fg_dev *fg, int *val) fg_dbg(fg, FG_TTF, "soc_cc2cv=%d\n", soc_cc2cv); switch (chip->ttf.mode) { - case TTF_MODE_NORMAL: + case FG_TTF_MODE_NORMAL: if (soc_cc2cv - msoc <= 0) goto cv_estimate; @@ -1988,7 +1988,7 @@ static int fg_get_time_to_full_locked(struct fg_dev *fg, int *val) t_predicted = div_s64((s64)act_cap_mah * (soc_cc2cv - msoc) * HOURS_TO_SECONDS, divisor); break; - case TTF_MODE_QNOVO: + case FG_TTF_MODE_QNOVO: soc_per_step = 100 / MAX_CC_STEPS; for (i = msoc / soc_per_step; i < MAX_CC_STEPS - 1; ++i) { msoc_next_step = (i + 1) * soc_per_step; -- GitLab From 40f7f2854303ef578e7f837818801957dd0fbe74 Mon Sep 17 00:00:00 2001 From: Vamshi Krishna B V Date: Mon, 28 May 2018 22:47:06 +0530 Subject: [PATCH 0095/1299] power: fg-alg: Add support for TTF and TTE calculation Add support for Time to full (TTF) and Time to empty (TTE) calculations in fg-alg.c that can be used by FG and QG drivers. CRs-Fixed: 2254530 Change-Id: I28e21da30911a8d879f176ae3ff8736aed807020 Signed-off-by: Vamshi Krishna B V --- drivers/power/supply/qcom/fg-alg.c | 531 +++++++++++++++++++++++++++++ drivers/power/supply/qcom/fg-alg.h | 57 ++++ 2 files changed, 588 insertions(+) diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c index 726623a3de6c..b230f7295441 100644 --- a/drivers/power/supply/qcom/fg-alg.c +++ b/drivers/power/supply/qcom/fg-alg.c @@ -16,11 +16,37 @@ #include #include #include +#include +#include #include "fg-alg.h" #define FULL_SOC_RAW 255 #define CAPACITY_DELTA_DECIPCT 500 +#define CENTI_ICORRECT_C0 105 +#define CENTI_ICORRECT_C1 20 + +#define HOURS_TO_SECONDS 3600 +#define OCV_SLOPE_UV 10869 +#define MILLI_UNIT 1000 +#define MICRO_UNIT 1000000 +#define NANO_UNIT 1000000000 + +#define DEFAULT_TTF_RUN_PERIOD_MS 10000 +#define DEFAULT_TTF_ITERM_DELTA_MA 200 + +static const struct ttf_pt ttf_ln_table[] = { + { 1000, 0 }, + { 2000, 693 }, + { 4000, 1386 }, + { 6000, 1792 }, + { 8000, 2079 }, + { 16000, 2773 }, + { 32000, 3466 }, + { 64000, 4159 }, + { 128000, 4852 }, +}; + /* Cycle counter APIs */ /** @@ -670,3 +696,508 @@ int cap_learning_init(struct cap_learning *cl) mutex_init(&cl->lock); return 0; } + +/* Time to full/empty algorithm helper functions */ + +static void ttf_circ_buf_add(struct ttf_circ_buf *buf, int val) +{ + buf->arr[buf->head] = val; + buf->head = (buf->head + 1) % ARRAY_SIZE(buf->arr); + buf->size = min(++buf->size, (int)ARRAY_SIZE(buf->arr)); +} + +static void ttf_circ_buf_clr(struct ttf_circ_buf *buf) +{ + buf->size = 0; + buf->head = 0; + memset(buf->arr, 0, sizeof(buf->arr)); +} + +static int cmp_int(const void *a, const void *b) +{ + return *(int *)a - *(int *)b; +} + +static int ttf_circ_buf_median(struct ttf_circ_buf *buf, int *median) +{ + int *temp; + + if (buf->size == 0) + return -ENODATA; + + if (buf->size == 1) { + *median = buf->arr[0]; + return 0; + } + + temp = kmalloc_array(buf->size, sizeof(*temp), GFP_KERNEL); + if (!temp) + return -ENOMEM; + + memcpy(temp, buf->arr, buf->size * sizeof(*temp)); + sort(temp, buf->size, sizeof(*temp), cmp_int, NULL); + + if (buf->size % 2) + *median = temp[buf->size / 2]; + else + *median = (temp[buf->size / 2 - 1] + temp[buf->size / 2]) / 2; + + kfree(temp); + return 0; +} + +static int ttf_lerp(const struct ttf_pt *pts, size_t tablesize, + s32 input, s32 *output) +{ + int i; + s64 temp; + + if (pts == NULL) { + pr_err("Table is NULL\n"); + return -EINVAL; + } + + if (tablesize < 1) { + pr_err("Table has no entries\n"); + return -ENOENT; + } + + if (tablesize == 1) { + *output = pts[0].y; + return 0; + } + + if (pts[0].x > pts[1].x) { + pr_err("Table is not in acending order\n"); + return -EINVAL; + } + + if (input <= pts[0].x) { + *output = pts[0].y; + return 0; + } + + if (input >= pts[tablesize - 1].x) { + *output = pts[tablesize - 1].y; + return 0; + } + + for (i = 1; i < tablesize; i++) { + if (input >= pts[i].x) + continue; + + temp = ((s64)pts[i].y - pts[i - 1].y) * + ((s64)input - pts[i - 1].x); + temp = div_s64(temp, pts[i].x - pts[i - 1].x); + *output = temp + pts[i - 1].y; + return 0; + } + + return -EINVAL; +} + +static int get_time_to_full_locked(struct ttf *ttf, int *val) +{ + int rc, ibatt_avg, vbatt_avg, rbatt = 0, msoc = 0, act_cap_mah = 0, + i_cc2cv = 0, soc_cc2cv, tau, divisor, iterm = 0, ttf_mode = 0, + i, soc_per_step, msoc_this_step, msoc_next_step, + ibatt_this_step, t_predicted_this_step, ttf_slope, + t_predicted_cv, t_predicted = 0, charge_type = 0, + float_volt_uv = 0; + s64 delta_ms; + + rc = ttf->get_ttf_param(ttf->data, TTF_MSOC, &msoc); + if (rc < 0) { + pr_err("failed to get msoc rc=%d\n", rc); + return rc; + } + pr_debug("TTF: msoc=%d\n", msoc); + + /* the battery is considered full if the SOC is 100% */ + if (msoc >= 100) { + *val = 0; + return 0; + } + + rc = ttf->get_ttf_param(ttf->data, TTF_MODE, &ttf_mode); + + /* when switching TTF algorithms the TTF needs to be reset */ + if (ttf->mode != ttf_mode) { + ttf_circ_buf_clr(&ttf->ibatt); + ttf_circ_buf_clr(&ttf->vbatt); + ttf->last_ttf = 0; + ttf->last_ms = 0; + ttf->mode = ttf_mode; + } + + /* at least 10 samples are required to produce a stable IBATT */ + if (ttf->ibatt.size < MAX_TTF_SAMPLES) { + *val = -1; + return 0; + } + + rc = ttf_circ_buf_median(&ttf->ibatt, &ibatt_avg); + if (rc < 0) { + pr_err("failed to get IBATT AVG rc=%d\n", rc); + return rc; + } + + rc = ttf_circ_buf_median(&ttf->vbatt, &vbatt_avg); + if (rc < 0) { + pr_err("failed to get VBATT AVG rc=%d\n", rc); + return rc; + } + + ibatt_avg = -ibatt_avg / MILLI_UNIT; + vbatt_avg /= MILLI_UNIT; + + rc = ttf->get_ttf_param(ttf->data, TTF_ITERM, &iterm); + if (rc < 0) { + pr_err("failed to get iterm rc=%d\n", rc); + return rc; + } + /* clamp ibatt_avg to iterm */ + if (ibatt_avg < abs(iterm)) + ibatt_avg = abs(iterm); + + rc = ttf->get_ttf_param(ttf->data, TTF_RBATT, &rbatt); + if (rc < 0) { + pr_err("failed to get battery resistance rc=%d\n", rc); + return rc; + } + rbatt /= MILLI_UNIT; + + rc = ttf->get_ttf_param(ttf->data, TTF_FCC, &act_cap_mah); + if (rc < 0) { + pr_err("failed to get ACT_BATT_CAP rc=%d\n", rc); + return rc; + } + + pr_debug(" TTF: ibatt_avg=%d vbatt_avg=%d rbatt=%d act_cap_mah=%d\n", + ibatt_avg, vbatt_avg, rbatt, act_cap_mah); + + rc = ttf->get_ttf_param(ttf->data, TTF_VFLOAT, &float_volt_uv); + if (rc < 0) { + pr_err("failed to get float_volt_uv rc=%d\n", rc); + return rc; + } + + rc = ttf->get_ttf_param(ttf->data, TTF_CHG_TYPE, &charge_type); + if (rc < 0) { + pr_err("failed to get charge_type rc=%d\n", rc); + return rc; + } + /* estimated battery current at the CC to CV transition */ + switch (ttf->mode) { + case TTF_MODE_NORMAL: + i_cc2cv = ibatt_avg * vbatt_avg / + max(MILLI_UNIT, float_volt_uv / MILLI_UNIT); + break; + case TTF_MODE_QNOVO: + i_cc2cv = min( + ttf->cc_step.arr[MAX_CC_STEPS - 1] / MILLI_UNIT, + ibatt_avg * vbatt_avg / + max(MILLI_UNIT, float_volt_uv / MILLI_UNIT)); + break; + default: + pr_err("TTF mode %d is not supported\n", ttf->mode); + break; + } + pr_debug("TTF: i_cc2cv=%d\n", i_cc2cv); + + /* if we are already in CV state then we can skip estimating CC */ + if (charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER) + goto cv_estimate; + + /* estimated SOC at the CC to CV transition */ + soc_cc2cv = DIV_ROUND_CLOSEST(rbatt * i_cc2cv, OCV_SLOPE_UV); + soc_cc2cv = 100 - soc_cc2cv; + pr_debug("TTF: soc_cc2cv=%d\n", soc_cc2cv); + + switch (ttf->mode) { + case TTF_MODE_NORMAL: + if (soc_cc2cv - msoc <= 0) + goto cv_estimate; + + divisor = max(100, (ibatt_avg + i_cc2cv) / 2 * 100); + t_predicted = div_s64((s64)act_cap_mah * (soc_cc2cv - msoc) * + HOURS_TO_SECONDS, divisor); + break; + case TTF_MODE_QNOVO: + soc_per_step = 100 / MAX_CC_STEPS; + for (i = msoc / soc_per_step; i < MAX_CC_STEPS - 1; ++i) { + msoc_next_step = (i + 1) * soc_per_step; + if (i == msoc / soc_per_step) + msoc_this_step = msoc; + else + msoc_this_step = i * soc_per_step; + + /* scale ibatt by 85% to account for discharge pulses */ + ibatt_this_step = min( + ttf->cc_step.arr[i] / MILLI_UNIT, + ibatt_avg) * 85 / 100; + divisor = max(100, ibatt_this_step * 100); + t_predicted_this_step = div_s64((s64)act_cap_mah * + (msoc_next_step - msoc_this_step) * + HOURS_TO_SECONDS, divisor); + t_predicted += t_predicted_this_step; + pr_debug("TTF: [%d, %d] ma=%d t=%d\n", + msoc_this_step, msoc_next_step, + ibatt_this_step, t_predicted_this_step); + } + break; + default: + pr_err("TTF mode %d is not supported\n", ttf->mode); + break; + } + +cv_estimate: + pr_debug("TTF: t_predicted_cc=%d\n", t_predicted); + + iterm = max(100, abs(iterm) + ttf->iterm_delta); + pr_debug("TTF: iterm=%d\n", iterm); + + if (charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER) + tau = max(MILLI_UNIT, ibatt_avg * MILLI_UNIT / iterm); + else + tau = max(MILLI_UNIT, i_cc2cv * MILLI_UNIT / iterm); + + rc = ttf_lerp(ttf_ln_table, ARRAY_SIZE(ttf_ln_table), tau, &tau); + if (rc < 0) { + pr_err("failed to interpolate tau rc=%d\n", rc); + return rc; + } + + /* tau is scaled linearly from 95% to 100% SOC */ + if (msoc >= 95) + tau = tau * 2 * (100 - msoc) / 10; + + pr_debug("TTF: tau=%d\n", tau); + t_predicted_cv = div_s64((s64)act_cap_mah * rbatt * tau * + HOURS_TO_SECONDS, NANO_UNIT); + pr_debug("TTF: t_predicted_cv=%d\n", t_predicted_cv); + t_predicted += t_predicted_cv; + + pr_debug("TTF: t_predicted_prefilter=%d\n", t_predicted); + if (ttf->last_ms != 0) { + delta_ms = ktime_ms_delta(ktime_get_boottime(), + ms_to_ktime(ttf->last_ms)); + if (delta_ms > 10000) { + ttf_slope = div64_s64( + ((s64)t_predicted - ttf->last_ttf) * + MICRO_UNIT, delta_ms); + if (ttf_slope > -100) + ttf_slope = -100; + else if (ttf_slope < -2000) + ttf_slope = -2000; + + t_predicted = div_s64( + (s64)ttf_slope * delta_ms, MICRO_UNIT) + + ttf->last_ttf; + pr_debug("TTF: ttf_slope=%d\n", ttf_slope); + } else { + t_predicted = ttf->last_ttf; + } + } + + /* clamp the ttf to 0 */ + if (t_predicted < 0) + t_predicted = 0; + + pr_debug("TTF: t_predicted_postfilter=%d\n", t_predicted); + *val = t_predicted; + return 0; +} + +/** + * ttf_get_time_to_full - + * @ttf: ttf object + * @val: Average time to full returned to the caller + * + * Get Average time to full the battery based on current soc, rbatt + * battery voltage and charge current etc. + */ +int ttf_get_time_to_full(struct ttf *ttf, int *val) +{ + int rc; + + mutex_lock(&ttf->lock); + rc = get_time_to_full_locked(ttf, val); + mutex_unlock(&ttf->lock); + + return rc; +} + +static void ttf_work(struct work_struct *work) +{ + struct ttf *ttf = container_of(work, + struct ttf, ttf_work.work); + int rc, ibatt_now, vbatt_now, ttf_now, charge_status; + ktime_t ktime_now; + + mutex_lock(&ttf->lock); + rc = ttf->get_ttf_param(ttf->data, TTF_CHG_STATUS, &charge_status); + if (rc < 0) { + pr_err("failed to get charge_status rc=%d\n", rc); + goto end_work; + } + if (charge_status != POWER_SUPPLY_STATUS_CHARGING && + charge_status != POWER_SUPPLY_STATUS_DISCHARGING) + goto end_work; + + rc = ttf->get_ttf_param(ttf->data, TTF_IBAT, &ibatt_now); + if (rc < 0) { + pr_err("failed to get battery current, rc=%d\n", rc); + goto end_work; + } + + rc = ttf->get_ttf_param(ttf->data, TTF_VBAT, &vbatt_now); + if (rc < 0) { + pr_err("failed to get battery voltage, rc=%d\n", rc); + goto end_work; + } + + ttf_circ_buf_add(&ttf->ibatt, ibatt_now); + ttf_circ_buf_add(&ttf->vbatt, vbatt_now); + + if (charge_status == POWER_SUPPLY_STATUS_CHARGING) { + rc = get_time_to_full_locked(ttf, &ttf_now); + if (rc < 0) { + pr_err("failed to get ttf, rc=%d\n", rc); + goto end_work; + } + + /* keep the wake lock and prime the IBATT and VBATT buffers */ + if (ttf_now < 0) { + /* delay for one FG cycle */ + schedule_delayed_work(&ttf->ttf_work, + msecs_to_jiffies(1000)); + mutex_unlock(&ttf->lock); + return; + } + + /* update the TTF reference point every minute */ + ktime_now = ktime_get_boottime(); + if (ktime_ms_delta(ktime_now, + ms_to_ktime(ttf->last_ms)) > 60000 || + ttf->last_ms == 0) { + ttf->last_ttf = ttf_now; + ttf->last_ms = ktime_to_ms(ktime_now); + } + } + + /* recurse every 10 seconds */ + schedule_delayed_work(&ttf->ttf_work, msecs_to_jiffies(ttf->period_ms)); +end_work: + ttf->awake_voter(ttf->data, false); + mutex_unlock(&ttf->lock); +} + +/** + * ttf_get_time_to_empty - + * @ttf: ttf object + * @val: Average time to empty returned to the caller + * + * Get Average time to empty the battery based on current soc + * and average battery current. + */ +int ttf_get_time_to_empty(struct ttf *ttf, int *val) +{ + int rc, ibatt_avg, msoc, act_cap_mah, divisor; + + rc = ttf_circ_buf_median(&ttf->ibatt, &ibatt_avg); + if (rc < 0) { + /* try to get instantaneous current */ + rc = ttf->get_ttf_param(ttf->data, TTF_IBAT, &ibatt_avg); + if (rc < 0) { + pr_err("failed to get battery current, rc=%d\n", rc); + return rc; + } + } + + ibatt_avg /= MILLI_UNIT; + /* clamp ibatt_avg to 100mA */ + if (ibatt_avg < 100) + ibatt_avg = 100; + + rc = ttf->get_ttf_param(ttf->data, TTF_MSOC, &msoc); + if (rc < 0) { + pr_err("Error in getting capacity, rc=%d\n", rc); + return rc; + } + + rc = ttf->get_ttf_param(ttf->data, TTF_FCC, &act_cap_mah); + if (rc < 0) { + pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc); + return rc; + } + + divisor = CENTI_ICORRECT_C0 * 100 + CENTI_ICORRECT_C1 * msoc; + divisor = ibatt_avg * divisor / 100; + divisor = max(100, divisor); + *val = act_cap_mah * msoc * HOURS_TO_SECONDS / divisor; + return 0; +} + +/** + * ttf_update - + * @ttf: ttf object + * @input_present: Indicator for input presence + * + * Called by FG/QG driver when there is a state change (Charging status, SOC) + * + */ +void ttf_update(struct ttf *ttf, bool input_present) +{ + int delay_ms; + + if (ttf->input_present == input_present) + return; + + ttf->input_present = input_present; + if (input_present) + /* wait 35 seconds for the input to settle */ + delay_ms = 35000; + else + /* wait 5 seconds for current to settle during discharge */ + delay_ms = 5000; + + ttf->awake_voter(ttf->data, true); + cancel_delayed_work_sync(&ttf->ttf_work); + mutex_lock(&ttf->lock); + ttf_circ_buf_clr(&ttf->ibatt); + ttf_circ_buf_clr(&ttf->vbatt); + ttf->last_ttf = 0; + ttf->last_ms = 0; + mutex_unlock(&ttf->lock); + schedule_delayed_work(&ttf->ttf_work, msecs_to_jiffies(delay_ms)); +} + +/** + * ttf_tte_init - + * @ttf: Time to full object + * + * FG/QG have to call this during driver probe to validate the required + * parameters after allocating ttf object. + * + */ +int ttf_tte_init(struct ttf *ttf) +{ + if (!ttf) + return -ENODEV; + + if (!ttf->awake_voter || !ttf->get_ttf_param) { + pr_err("Insufficient functions for supporting ttf\n"); + return -EINVAL; + } + + if (!ttf->iterm_delta) + ttf->iterm_delta = DEFAULT_TTF_ITERM_DELTA_MA; + if (!ttf->period_ms) + ttf->period_ms = DEFAULT_TTF_RUN_PERIOD_MS; + + mutex_init(&ttf->lock); + INIT_DELAYED_WORK(&ttf->ttf_work, ttf_work); + + return 0; +} diff --git a/drivers/power/supply/qcom/fg-alg.h b/drivers/power/supply/qcom/fg-alg.h index 0eba2bdc5a7c..7c75bac8843b 100644 --- a/drivers/power/supply/qcom/fg-alg.h +++ b/drivers/power/supply/qcom/fg-alg.h @@ -15,6 +15,8 @@ #define BUCKET_COUNT 8 #define BUCKET_SOC_PCT (256 / BUCKET_COUNT) +#define MAX_CC_STEPS 20 +#define MAX_TTF_SAMPLES 10 struct cycle_counter { void *data; @@ -58,6 +60,57 @@ struct cap_learning { int (*prime_cc_soc)(void *data, u32 cc_soc_sw); }; +enum ttf_mode { + TTF_MODE_NORMAL = 0, + TTF_MODE_QNOVO, +}; + +enum ttf_param { + TTF_MSOC = 0, + TTF_VBAT, + TTF_IBAT, + TTF_FCC, + TTF_MODE, + TTF_ITERM, + TTF_RBATT, + TTF_VFLOAT, + TTF_CHG_TYPE, + TTF_CHG_STATUS, +}; + +struct ttf_circ_buf { + int arr[MAX_TTF_SAMPLES]; + int size; + int head; +}; + +struct ttf_cc_step_data { + int arr[MAX_CC_STEPS]; + int sel; +}; + +struct ttf_pt { + s32 x; + s32 y; +}; + +struct ttf { + void *data; + struct ttf_circ_buf ibatt; + struct ttf_circ_buf vbatt; + struct ttf_cc_step_data cc_step; + struct mutex lock; + int mode; + int last_ttf; + int input_present; + int iterm_delta; + int period_ms; + s64 last_ms; + struct delayed_work ttf_work; + int (*get_ttf_param)(void *data, enum ttf_param, int *val); + int (*awake_voter)(void *data, bool vote); +}; + int restore_cycle_count(struct cycle_counter *counter); void clear_cycle_count(struct cycle_counter *counter); void cycle_count_update(struct cycle_counter *counter, int batt_soc, @@ -72,5 +125,9 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, int cap_learning_init(struct cap_learning *cl); int cap_learning_post_profile_init(struct cap_learning *cl, int64_t nom_cap_uah); +void ttf_update(struct ttf *ttf, bool input_present); +int ttf_get_time_to_empty(struct ttf *ttf, int *val); +int ttf_get_time_to_full(struct ttf *ttf, int *val); +int ttf_tte_init(struct ttf *ttf); #endif -- GitLab From b5a4c8cd0aa99d1fb9c6686683615f2862421e09 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Mon, 7 May 2018 17:20:32 -0700 Subject: [PATCH 0096/1299] ARM: dts: msm: enable MHI hardware offload channels for sm8150 MHI hardware offload channels can be used to send IP packets between sm8150 internal modem and sdx50 external modem over PCIe bus. CRs-Fixed: 2257422 Change-Id: I5c6a8cabce82addefb969ba67db23f358d975b7c Signed-off-by: Sujeev Dias --- arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi | 45 ++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi index b5055c8ab3ec..43ed4c86d1b1 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi @@ -347,6 +347,27 @@ mhi,ee = <2>; }; + mhi_chan@104 { + reg = <104>; + label = "IP_HW_OFFLOAD_0"; + mhi,event-ring = <6>; + mhi,chan-dir = <1>; + mhi,data-type = <3>; + mhi,ee = <2>; + mhi,offload-chan; + }; + + mhi_chan@105 { + reg = <105>; + label = "IP_HW_OFFLOAD_0"; + mhi,event-ring = <7>; + mhi,chan-dir = <2>; + mhi,data-type = <3>; + mhi,ee = <2>; + mhi,offload-chan; + mhi,lpm-notify; + }; + mhi_event@0 { mhi,num-elements = <32>; mhi,intmod = <1>; @@ -401,6 +422,30 @@ mhi,client-manage; }; + mhi_event@6 { + mhi,num-elements = <0>; + mhi,intmod = <0>; + mhi,msi = <7>; + mhi,chan = <104>; + mhi,priority = <1>; + mhi,brstmode = <3>; + mhi,hw-ev; + mhi,client-manage; + mhi,offload; + }; + + mhi_event@7 { + mhi,num-elements = <0>; + mhi,intmod = <0>; + mhi,msi = <8>; + mhi,chan = <105>; + mhi,priority = <1>; + mhi,brstmode = <3>; + mhi,hw-ev; + mhi,client-manage; + mhi,offload; + }; + mhi_netdev_0: mhi_rmnet@0 { reg = <0x0>; mhi,chan = "IP_HW0"; -- GitLab From e06e9bf5353eca7fd9e7554afbbb703a541b811d Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Sat, 9 Jun 2018 08:23:58 -0700 Subject: [PATCH 0097/1299] ARM: dts: msm: disable legacy IP_HW channels for sm8150 SM8150 uses hardware offload channels 104, and 105 to send ip packets between external modem and sm8150. Disable legacy channels 100, and 101. CRs-Fixed: 2257422 Change-Id: Id5a10e4ca767c8868cf7079ce4953ac97208ca04 Signed-off-by: Sujeev Dias --- arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi | 54 +++--------------------- 1 file changed, 5 insertions(+), 49 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi index 43ed4c86d1b1..0f1c82fac015 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi @@ -324,33 +324,10 @@ mhi,ee = <2>; }; - mhi_chan@100 { - reg = <100>; - label = "IP_HW0"; - mhi,num-elements = <512>; - mhi,event-ring = <4>; - mhi,chan-dir = <1>; - mhi,data-type = <1>; - mhi,doorbell-mode = <3>; - mhi,ee = <2>; - mhi,db-mode-switch; - }; - - mhi_chan@101 { - reg = <101>; - label = "IP_HW0"; - mhi,num-elements = <512>; - mhi,event-ring = <5>; - mhi,chan-dir = <2>; - mhi,data-type = <1>; - mhi,doorbell-mode = <3>; - mhi,ee = <2>; - }; - mhi_chan@104 { reg = <104>; label = "IP_HW_OFFLOAD_0"; - mhi,event-ring = <6>; + mhi,event-ring = <4>; mhi,chan-dir = <1>; mhi,data-type = <3>; mhi,ee = <2>; @@ -360,7 +337,7 @@ mhi_chan@105 { reg = <105>; label = "IP_HW_OFFLOAD_0"; - mhi,event-ring = <7>; + mhi,event-ring = <5>; mhi,chan-dir = <2>; mhi,data-type = <3>; mhi,ee = <2>; @@ -402,30 +379,9 @@ }; mhi_event@4 { - mhi,num-elements = <1024>; - mhi,intmod = <5>; - mhi,msi = <5>; - mhi,chan = <100>; - mhi,priority = <1>; - mhi,brstmode = <3>; - mhi,hw-ev; - }; - - mhi_event@5 { - mhi,num-elements = <1024>; - mhi,intmod = <5>; - mhi,msi = <6>; - mhi,chan = <101>; - mhi,priority = <1>; - mhi,brstmode = <3>; - mhi,hw-ev; - mhi,client-manage; - }; - - mhi_event@6 { mhi,num-elements = <0>; mhi,intmod = <0>; - mhi,msi = <7>; + mhi,msi = <5>; mhi,chan = <104>; mhi,priority = <1>; mhi,brstmode = <3>; @@ -434,10 +390,10 @@ mhi,offload; }; - mhi_event@7 { + mhi_event@5 { mhi,num-elements = <0>; mhi,intmod = <0>; - mhi,msi = <8>; + mhi,msi = <6>; mhi,chan = <105>; mhi,priority = <1>; mhi,brstmode = <3>; -- GitLab From dc139576cf4b53b0a719e6c03f1fc8836a6e4d27 Mon Sep 17 00:00:00 2001 From: Gustavo Solaira Date: Thu, 17 May 2018 16:23:20 -0700 Subject: [PATCH 0098/1299] mhi: core: add MHI ready state transition support MHI state transition ready was not handled before, adding support for MHI ready state. CRs-Fixed: 2257733 Change-Id: Ib31f353f5a0ca6d160c94b0604d4d836281f58ad Signed-off-by: Gustavo Solaira Signed-off-by: Sujeev Dias --- drivers/bus/mhi/core/mhi_pm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bus/mhi/core/mhi_pm.c b/drivers/bus/mhi/core/mhi_pm.c index 5ed4e2a0856e..8572f12da49f 100644 --- a/drivers/bus/mhi/core/mhi_pm.c +++ b/drivers/bus/mhi/core/mhi_pm.c @@ -777,6 +777,9 @@ void mhi_pm_st_worker(struct work_struct *work) case MHI_ST_TRANSITION_AMSS: mhi_pm_amss_transition(mhi_cntrl); break; + case MHI_ST_TRANSITION_READY: + mhi_ready_state_transition(mhi_cntrl); + break; default: break; } -- GitLab From fb48ba73ec97d9890e13f64930af1d89a6ad081e Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Mon, 11 Jun 2018 11:56:23 -0700 Subject: [PATCH 0099/1299] msm: vidc: Correct resolution check Compare the number of macroblock per frame instead of the number of pixels per frame to avoid batching enabled for video playback resolutions greater than 1080p. Change-Id: I07bbfae5513e9dc4b57058edea587d315d3f0c21 Signed-off-by: Maheshwar Ajja --- drivers/media/platform/msm/vidc/msm_vidc_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 455d4ce648f1..48f8311bfb44 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -2761,7 +2761,7 @@ bool is_batching_allowed(struct msm_vidc_inst *inst) */ if (is_decode_session(inst) && inst->core->resources.decode_batching && (msm_vidc_get_mbs_per_frame(inst) <= - MAX_DEC_BATCH_WIDTH * MAX_DEC_BATCH_HEIGHT) && + NUM_MBS_PER_FRAME(MAX_DEC_BATCH_HEIGHT, MAX_DEC_BATCH_WIDTH)) && !inst->clk_data.low_latency_mode && !is_thumbnail_session(inst) && (inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_NV12_UBWC || -- GitLab From 5fa6ccabb5029f7eda90864519fb8a78784fcf89 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Sun, 10 Jun 2018 23:42:35 -0700 Subject: [PATCH 0100/1299] mhi: dev: uci: exit immediately if MHI channel is in disabled state If write thread woke up because device is in a disabled state, exit immediately and return error to user. CRs-Fixed: 2258304 Change-Id: I7de224e29d0ef9b414a014ef0d874156367d0cb6 Signed-off-by: Sujeev Dias --- drivers/bus/mhi/devices/mhi_uci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bus/mhi/devices/mhi_uci.c b/drivers/bus/mhi/devices/mhi_uci.c index dd7581e36d03..bc02e1097924 100644 --- a/drivers/bus/mhi/devices/mhi_uci.c +++ b/drivers/bus/mhi/devices/mhi_uci.c @@ -278,8 +278,8 @@ static ssize_t mhi_uci_write(struct file *file, (nr_avail = mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE)) > 0); - if (ret == -ERESTARTSYS) { - MSG_LOG("Exit signal caught for node\n"); + if (ret == -ERESTARTSYS || !uci_dev->enabled) { + MSG_LOG("Exit signal caught for node or not enabled\n"); return -ERESTARTSYS; } -- GitLab From c92a68f9d95ecf0a09cd952c7650147ae9068d40 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Fri, 8 Jun 2018 19:10:30 -0700 Subject: [PATCH 0101/1299] power: qpnp-fg-gen4: Switch to using TTF/TTE algorithms from fg-alg.c Currently, Time to full (TTF) and Time to empty (TTE) algorithms are supported in GEN4 FG driver locally. Since the algorithms are moved to fg-alg.c to share it with QG driver, make changes to GEN4 FG driver to switch using that. Change-Id: I0059630c0ca0103b958ced10ae4bad8e1ccea8f7 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/qpnp-fg-gen4.c | 582 ++++++----------------- 1 file changed, 156 insertions(+), 426 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 4c8f427ad2c7..afd0c9ed7d8f 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -23,6 +23,7 @@ #include "fg-alg.h" #define FG_GEN4_DEV_NAME "qcom,fg-gen4" +#define TTF_AWAKE_VOTER "fg_ttf_awake" #define PERPH_SUBTYPE_REG 0x05 #define FG_BATT_SOC_PM8150B 0x10 @@ -145,8 +146,7 @@ struct fg_gen4_chip { struct fg_dt_props dt; struct cycle_counter *counter; struct cap_learning *cl; - struct fg_ttf ttf; - struct delayed_work ttf_work; + struct ttf *ttf; char batt_profile[PROFILE_LEN]; int recharge_soc_thr; bool ki_coeff_dischg_en; @@ -548,6 +548,76 @@ static inline void get_esr_meas_current(int curr_ma, u8 *val) /* ALG callback functions below */ +static int fg_gen4_get_ttf_param(void *data, enum ttf_param param, int *val) +{ + struct fg_gen4_chip *chip = data; + struct fg_dev *fg; + int rc = 0, act_cap_mah, full_soc; + + if (!chip) + return -ENODEV; + + fg = &chip->fg; + if (fg->battery_missing) + return -EPERM; + + switch (param) { + case TTF_MSOC: + rc = fg_gen4_get_prop_capacity(fg, val); + break; + case TTF_VBAT: + rc = fg_get_battery_voltage(fg, val); + break; + case TTF_IBAT: + rc = fg_get_battery_current(fg, val); + break; + case TTF_FCC: + rc = fg_get_sram_prop(fg, FG_SRAM_ACT_BATT_CAP, &act_cap_mah); + if (rc < 0) { + pr_err("Failed to get ACT_BATT_CAP rc=%d\n", rc); + break; + } + + rc = fg_get_sram_prop(fg, FG_SRAM_FULL_SOC, &full_soc); + if (rc < 0) { + pr_err("Failed to get FULL_SOC rc=%d\n", rc); + break; + } + + full_soc = DIV_ROUND_CLOSEST(((u16)full_soc >> 8) * + FULL_CAPACITY, FULL_SOC_RAW); + *val = full_soc * act_cap_mah / FULL_CAPACITY; + break; + case TTF_MODE: + if (is_qnovo_en(fg)) + *val = TTF_MODE_QNOVO; + else + *val = TTF_MODE_NORMAL; + break; + case TTF_ITERM: + *val = chip->dt.sys_term_curr_ma; + break; + case TTF_RBATT: + rc = fg_get_battery_resistance(fg, val); + break; + case TTF_VFLOAT: + *val = fg->bp.float_volt_uv; + break; + case TTF_CHG_TYPE: + *val = fg->charge_type; + break; + case TTF_CHG_STATUS: + *val = fg->charge_status; + break; + default: + pr_err_ratelimited("Unsupported parameter %d\n", param); + rc = -EINVAL; + break; + } + + return rc; +} + static int fg_gen4_store_learned_capacity(void *data, int64_t learned_cap_uah) { struct fg_gen4_chip *chip = data; @@ -1032,6 +1102,7 @@ static void profile_load_work(struct work_struct *work) batt_psy_initialized(fg); fg_notify_charger(fg); + schedule_delayed_work(&chip->ttf->ttf_work, 10000); fg_dbg(fg, FG_STATUS, "profile loaded successfully"); out: fg->soc_reporting_ready = true; @@ -1718,70 +1789,6 @@ static bool is_batt_empty(struct fg_dev *fg) return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false); } -static void fg_ttf_update(struct fg_dev *fg) -{ - struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); - int rc; - int delay_ms; - union power_supply_propval prop = {0, }; - int online = 0; - - if (usb_psy_initialized(fg)) { - rc = power_supply_get_property(fg->usb_psy, - POWER_SUPPLY_PROP_ONLINE, &prop); - if (rc < 0) { - pr_err("Couldn't read usb ONLINE prop rc=%d\n", rc); - return; - } - - online = online || prop.intval; - } - - if (pc_port_psy_initialized(fg)) { - rc = power_supply_get_property(fg->pc_port_psy, - POWER_SUPPLY_PROP_ONLINE, &prop); - if (rc < 0) { - pr_err("Couldn't read pc_port ONLINE prop rc=%d\n", rc); - return; - } - - online = online || prop.intval; - } - - if (dc_psy_initialized(fg)) { - rc = power_supply_get_property(fg->dc_psy, - POWER_SUPPLY_PROP_ONLINE, &prop); - if (rc < 0) { - pr_err("Couldn't read dc ONLINE prop rc=%d\n", rc); - return; - } - - online = online || prop.intval; - } - - - if (fg->online_status == online) - return; - - fg->online_status = online; - if (online) - /* wait 35 seconds for the input to settle */ - delay_ms = 35000; - else - /* wait 5 seconds for current to settle during discharge */ - delay_ms = 5000; - - vote(fg->awake_votable, TTF_PRIMING, true, 0); - cancel_delayed_work_sync(&chip->ttf_work); - mutex_lock(&chip->ttf.lock); - fg_circ_buf_clr(&chip->ttf.ibatt); - fg_circ_buf_clr(&chip->ttf.vbatt); - chip->ttf.last_ttf = 0; - chip->ttf.last_ms = 0; - mutex_unlock(&chip->ttf.lock); - schedule_delayed_work(&chip->ttf_work, msecs_to_jiffies(delay_ms)); -} - static void status_change_work(struct work_struct *work) { struct fg_dev *fg = container_of(work, @@ -1836,7 +1843,7 @@ static void status_change_work(struct work_struct *work) if (rc < 0) pr_err("Error in adjusting recharge SOC, rc=%d\n", rc); - fg_ttf_update(fg); + ttf_update(chip->ttf, input_present); fg->prev_charge_status = fg->charge_status; out: fg_dbg(fg, FG_STATUS, "charge_status:%d charge_type:%d charge_done:%d\n", @@ -1844,359 +1851,6 @@ static void status_change_work(struct work_struct *work) pm_relax(fg->dev); } -#define HOURS_TO_SECONDS 3600 -#define OCV_SLOPE_UV 10869 -#define MILLI_UNIT 1000 -#define MICRO_UNIT 1000000 -#define NANO_UNIT 1000000000 -static int fg_get_time_to_full_locked(struct fg_dev *fg, int *val) -{ - struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); - int rc, ibatt_avg, vbatt_avg, rbatt, msoc, full_soc, act_cap_mah, - i_cc2cv = 0, soc_cc2cv, tau, divisor, iterm, ttf_mode, - i, soc_per_step, msoc_this_step, msoc_next_step, - ibatt_this_step, t_predicted_this_step, ttf_slope, - t_predicted_cv, t_predicted = 0; - s64 delta_ms; - - if (!fg->soc_reporting_ready) - return -ENODATA; - - if (fg->bp.float_volt_uv <= 0) { - pr_err("battery profile is not loaded\n"); - return -ENODATA; - } - - if (!batt_psy_initialized(fg)) { - fg_dbg(fg, FG_TTF, "charger is not available\n"); - return -ENODATA; - } - - rc = fg_gen4_get_prop_capacity(fg, &msoc); - if (rc < 0) { - pr_err("failed to get msoc rc=%d\n", rc); - return rc; - } - fg_dbg(fg, FG_TTF, "msoc=%d\n", msoc); - - /* the battery is considered full if the SOC is 100% */ - if (msoc >= 100) { - *val = 0; - return 0; - } - - if (is_qnovo_en(fg)) - ttf_mode = FG_TTF_MODE_QNOVO; - else - ttf_mode = FG_TTF_MODE_NORMAL; - - /* when switching TTF algorithms the TTF needs to be reset */ - if (chip->ttf.mode != ttf_mode) { - fg_circ_buf_clr(&chip->ttf.ibatt); - fg_circ_buf_clr(&chip->ttf.vbatt); - chip->ttf.last_ttf = 0; - chip->ttf.last_ms = 0; - chip->ttf.mode = ttf_mode; - } - - /* at least 10 samples are required to produce a stable IBATT */ - if (chip->ttf.ibatt.size < 10) { - *val = -1; - return 0; - } - - rc = fg_circ_buf_median(&chip->ttf.ibatt, &ibatt_avg); - if (rc < 0) { - pr_err("failed to get IBATT AVG rc=%d\n", rc); - return rc; - } - - rc = fg_circ_buf_median(&chip->ttf.vbatt, &vbatt_avg); - if (rc < 0) { - pr_err("failed to get VBATT AVG rc=%d\n", rc); - return rc; - } - - ibatt_avg = -ibatt_avg / MILLI_UNIT; - vbatt_avg /= MILLI_UNIT; - - /* clamp ibatt_avg to iterm */ - if (ibatt_avg < abs(chip->dt.sys_term_curr_ma)) - ibatt_avg = abs(chip->dt.sys_term_curr_ma); - - fg_dbg(fg, FG_TTF, "ibatt_avg=%d\n", ibatt_avg); - fg_dbg(fg, FG_TTF, "vbatt_avg=%d\n", vbatt_avg); - - rc = fg_get_battery_resistance(fg, &rbatt); - if (rc < 0) { - pr_err("failed to get battery resistance rc=%d\n", rc); - return rc; - } - - rbatt /= MILLI_UNIT; - fg_dbg(fg, FG_TTF, "rbatt=%d\n", rbatt); - - rc = fg_get_sram_prop(fg, FG_SRAM_ACT_BATT_CAP, &act_cap_mah); - if (rc < 0) { - pr_err("failed to get ACT_BATT_CAP rc=%d\n", rc); - return rc; - } - - rc = fg_get_sram_prop(fg, FG_SRAM_FULL_SOC, &full_soc); - if (rc < 0) { - pr_err("failed to get full soc rc=%d\n", rc); - return rc; - } - full_soc = DIV_ROUND_CLOSEST(((u16)full_soc >> 8) * FULL_CAPACITY, - FULL_SOC_RAW); - act_cap_mah = full_soc * act_cap_mah / 100; - fg_dbg(fg, FG_TTF, "act_cap_mah=%d\n", act_cap_mah); - - /* estimated battery current at the CC to CV transition */ - switch (chip->ttf.mode) { - case FG_TTF_MODE_NORMAL: - i_cc2cv = ibatt_avg * vbatt_avg / - max(MILLI_UNIT, fg->bp.float_volt_uv / MILLI_UNIT); - break; - case FG_TTF_MODE_QNOVO: - i_cc2cv = min( - chip->ttf.cc_step.arr[MAX_CC_STEPS - 1] / MILLI_UNIT, - ibatt_avg * vbatt_avg / - max(MILLI_UNIT, fg->bp.float_volt_uv / MILLI_UNIT)); - break; - default: - pr_err("TTF mode %d is not supported\n", chip->ttf.mode); - break; - } - fg_dbg(fg, FG_TTF, "i_cc2cv=%d\n", i_cc2cv); - - /* if we are already in CV state then we can skip estimating CC */ - if (fg->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER) - goto cv_estimate; - - /* estimated SOC at the CC to CV transition */ - soc_cc2cv = DIV_ROUND_CLOSEST(rbatt * i_cc2cv, OCV_SLOPE_UV); - soc_cc2cv = 100 - soc_cc2cv; - fg_dbg(fg, FG_TTF, "soc_cc2cv=%d\n", soc_cc2cv); - - switch (chip->ttf.mode) { - case FG_TTF_MODE_NORMAL: - if (soc_cc2cv - msoc <= 0) - goto cv_estimate; - - divisor = max(100, (ibatt_avg + i_cc2cv) / 2 * 100); - t_predicted = div_s64((s64)act_cap_mah * (soc_cc2cv - msoc) * - HOURS_TO_SECONDS, divisor); - break; - case FG_TTF_MODE_QNOVO: - soc_per_step = 100 / MAX_CC_STEPS; - for (i = msoc / soc_per_step; i < MAX_CC_STEPS - 1; ++i) { - msoc_next_step = (i + 1) * soc_per_step; - if (i == msoc / soc_per_step) - msoc_this_step = msoc; - else - msoc_this_step = i * soc_per_step; - - /* scale ibatt by 85% to account for discharge pulses */ - ibatt_this_step = min( - chip->ttf.cc_step.arr[i] / MILLI_UNIT, - ibatt_avg) * 85 / 100; - divisor = max(100, ibatt_this_step * 100); - t_predicted_this_step = div_s64((s64)act_cap_mah * - (msoc_next_step - msoc_this_step) * - HOURS_TO_SECONDS, divisor); - t_predicted += t_predicted_this_step; - fg_dbg(fg, FG_TTF, "[%d, %d] ma=%d t=%d\n", - msoc_this_step, msoc_next_step, - ibatt_this_step, t_predicted_this_step); - } - break; - default: - pr_err("TTF mode %d is not supported\n", chip->ttf.mode); - break; - } - -cv_estimate: - fg_dbg(fg, FG_TTF, "t_predicted_cc=%d\n", t_predicted); - - iterm = max(100, abs(chip->dt.sys_term_curr_ma) + 200); - fg_dbg(fg, FG_TTF, "iterm=%d\n", iterm); - - if (fg->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER) - tau = max(MILLI_UNIT, ibatt_avg * MILLI_UNIT / iterm); - else - tau = max(MILLI_UNIT, i_cc2cv * MILLI_UNIT / iterm); - - rc = fg_lerp(fg_ln_table, ARRAY_SIZE(fg_ln_table), tau, &tau); - if (rc < 0) { - pr_err("failed to interpolate tau rc=%d\n", rc); - return rc; - } - - /* tau is scaled linearly from 95% to 100% SOC */ - if (msoc >= 95) - tau = tau * 2 * (100 - msoc) / 10; - - fg_dbg(fg, FG_TTF, "tau=%d\n", tau); - t_predicted_cv = div_s64((s64)act_cap_mah * rbatt * tau * - HOURS_TO_SECONDS, NANO_UNIT); - fg_dbg(fg, FG_TTF, "t_predicted_cv=%d\n", t_predicted_cv); - t_predicted += t_predicted_cv; - - fg_dbg(fg, FG_TTF, "t_predicted_prefilter=%d\n", t_predicted); - if (chip->ttf.last_ms != 0) { - delta_ms = ktime_ms_delta(ktime_get_boottime(), - ms_to_ktime(chip->ttf.last_ms)); - if (delta_ms > 10000) { - ttf_slope = div64_s64( - ((s64)t_predicted - chip->ttf.last_ttf) * - MICRO_UNIT, delta_ms); - if (ttf_slope > -100) - ttf_slope = -100; - else if (ttf_slope < -2000) - ttf_slope = -2000; - - t_predicted = div_s64( - (s64)ttf_slope * delta_ms, MICRO_UNIT) + - chip->ttf.last_ttf; - fg_dbg(fg, FG_TTF, "ttf_slope=%d\n", ttf_slope); - } else { - t_predicted = chip->ttf.last_ttf; - } - } - - /* clamp the ttf to 0 */ - if (t_predicted < 0) - t_predicted = 0; - - fg_dbg(fg, FG_TTF, "t_predicted_postfilter=%d\n", t_predicted); - *val = t_predicted; - return 0; -} - -static int fg_get_time_to_full(struct fg_dev *fg, int *val) -{ - struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); - int rc; - - mutex_lock(&chip->ttf.lock); - rc = fg_get_time_to_full_locked(fg, val); - mutex_unlock(&chip->ttf.lock); - return rc; -} - -static void ttf_work(struct work_struct *work) -{ - struct fg_gen4_chip *chip = container_of(work, - struct fg_gen4_chip, ttf_work.work); - struct fg_dev *fg = &chip->fg; - int rc, ibatt_now, vbatt_now, ttf; - ktime_t ktime_now; - - mutex_lock(&chip->ttf.lock); - if (fg->charge_status != POWER_SUPPLY_STATUS_CHARGING && - fg->charge_status != POWER_SUPPLY_STATUS_DISCHARGING) - goto end_work; - - rc = fg_get_battery_current(fg, &ibatt_now); - if (rc < 0) { - pr_err("failed to get battery current, rc=%d\n", rc); - goto end_work; - } - - rc = fg_get_battery_voltage(fg, &vbatt_now); - if (rc < 0) { - pr_err("failed to get battery voltage, rc=%d\n", rc); - goto end_work; - } - - fg_circ_buf_add(&chip->ttf.ibatt, ibatt_now); - fg_circ_buf_add(&chip->ttf.vbatt, vbatt_now); - - if (fg->charge_status == POWER_SUPPLY_STATUS_CHARGING) { - rc = fg_get_time_to_full_locked(fg, &ttf); - if (rc < 0) { - pr_err("failed to get ttf, rc=%d\n", rc); - goto end_work; - } - - /* keep the wake lock and prime the IBATT and VBATT buffers */ - if (ttf < 0) { - /* delay for one FG cycle */ - schedule_delayed_work(&chip->ttf_work, - msecs_to_jiffies(1000)); - mutex_unlock(&chip->ttf.lock); - return; - } - - /* update the TTF reference point every minute */ - ktime_now = ktime_get_boottime(); - if (ktime_ms_delta(ktime_now, - ms_to_ktime(chip->ttf.last_ms)) > 60000 || - chip->ttf.last_ms == 0) { - chip->ttf.last_ttf = ttf; - chip->ttf.last_ms = ktime_to_ms(ktime_now); - } - } - - /* recurse every 10 seconds */ - schedule_delayed_work(&chip->ttf_work, msecs_to_jiffies(10000)); -end_work: - vote(fg->awake_votable, TTF_PRIMING, false, 0); - mutex_unlock(&chip->ttf.lock); -} - -#define CENTI_ICORRECT_C0 105 -#define CENTI_ICORRECT_C1 20 -static int fg_get_time_to_empty(struct fg_dev *fg, int *val) -{ - struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); - int rc, ibatt_avg, msoc, full_soc, act_cap_mah, divisor; - - rc = fg_circ_buf_median(&chip->ttf.ibatt, &ibatt_avg); - if (rc < 0) { - /* try to get instantaneous current */ - rc = fg_get_battery_current(fg, &ibatt_avg); - if (rc < 0) { - pr_err("failed to get battery current, rc=%d\n", rc); - return rc; - } - } - - ibatt_avg /= MILLI_UNIT; - /* clamp ibatt_avg to 100mA */ - if (ibatt_avg < 100) - ibatt_avg = 100; - - rc = fg_gen4_get_prop_capacity(fg, &msoc); - if (rc < 0) { - pr_err("Error in getting capacity, rc=%d\n", rc); - return rc; - } - - rc = fg_get_sram_prop(fg, FG_SRAM_ACT_BATT_CAP, &act_cap_mah); - if (rc < 0) { - pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc); - return rc; - } - - rc = fg_get_sram_prop(fg, FG_SRAM_FULL_SOC, &full_soc); - if (rc < 0) { - pr_err("failed to get full soc rc=%d\n", rc); - return rc; - } - full_soc = DIV_ROUND_CLOSEST(((u16)full_soc >> 8) * FULL_CAPACITY, - FULL_SOC_RAW); - act_cap_mah = full_soc * act_cap_mah / 100; - - divisor = CENTI_ICORRECT_C0 * 100 + CENTI_ICORRECT_C1 * msoc; - divisor = ibatt_avg * divisor / 100; - divisor = max(100, divisor); - *val = act_cap_mah * msoc * HOURS_TO_SECONDS / divisor; - return 0; -} - - static void sram_dump_work(struct work_struct *work) { struct fg_dev *fg = container_of(work, struct fg_dev, @@ -2392,10 +2046,24 @@ static int fg_psy_get_property(struct power_supply *psy, rc = fg_get_sram_prop(fg, FG_SRAM_VBATT_FULL, &pval->intval); break; case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: - rc = fg_get_time_to_full(fg, &pval->intval); + rc = ttf_get_time_to_full(chip->ttf, &pval->intval); break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: - rc = fg_get_time_to_empty(fg, &pval->intval); + rc = ttf_get_time_to_empty(chip->ttf, &pval->intval); + break; + case POWER_SUPPLY_PROP_CC_STEP: + if ((chip->ttf->cc_step.sel >= 0) && + (chip->ttf->cc_step.sel < MAX_CC_STEPS)) { + pval->intval = + chip->ttf->cc_step.arr[chip->ttf->cc_step.sel]; + } else { + pr_err("cc_step_sel is out of bounds [0, %d]\n", + chip->ttf->cc_step.sel); + return -EINVAL; + } + break; + case POWER_SUPPLY_PROP_CC_STEP_SEL: + pval->intval = chip->ttf->cc_step.sel; break; default: pr_err("unsupported property %d\n", psp); @@ -2432,6 +2100,26 @@ static int fg_psy_set_property(struct power_supply *psy, chip->cl->learned_cap_uah = pval->intval; mutex_unlock(&chip->cl->lock); break; + case POWER_SUPPLY_PROP_CC_STEP: + if ((chip->ttf->cc_step.sel >= 0) && + (chip->ttf->cc_step.sel < MAX_CC_STEPS)) { + chip->ttf->cc_step.arr[chip->ttf->cc_step.sel] = + pval->intval; + } else { + pr_err("cc_step_sel is out of bounds [0, %d]\n", + chip->ttf->cc_step.sel); + return -EINVAL; + } + break; + case POWER_SUPPLY_PROP_CC_STEP_SEL: + if ((pval->intval >= 0) && (pval->intval < MAX_CC_STEPS)) { + chip->ttf->cc_step.sel = pval->intval; + } else { + pr_err("cc_step_sel is out of bounds [0, %d]\n", + pval->intval); + return -EINVAL; + } + break; default: break; } @@ -2444,6 +2132,8 @@ static int fg_property_is_writeable(struct power_supply *psy, { switch (psp) { case POWER_SUPPLY_PROP_CHARGE_FULL: + case POWER_SUPPLY_PROP_CC_STEP: + case POWER_SUPPLY_PROP_CC_STEP_SEL: return 1; default: break; @@ -2474,6 +2164,8 @@ static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, + POWER_SUPPLY_PROP_CC_STEP, + POWER_SUPPLY_PROP_CC_STEP_SEL, }; static const struct power_supply_desc fg_psy_desc = { @@ -2528,6 +2220,22 @@ static int fg_awake_cb(struct votable *votable, void *data, int awake, return 0; } +static int fg_gen4_ttf_awake_voter(void *data, bool val) +{ + struct fg_gen4_chip *chip = data; + struct fg_dev *fg = &chip->fg; + + if (!chip) + return -ENODEV; + + if (fg->battery_missing || + fg->profile_load_status == PROFILE_NOT_LOADED) + return -EPERM; + + vote(fg->awake_votable, TTF_AWAKE_VOTER, val, 0); + return 0; +} + static int fg_delta_bsoc_irq_en_cb(struct votable *votable, void *data, int enable, const char *client) { @@ -2554,6 +2262,7 @@ static int fg_alg_init(struct fg_gen4_chip *chip) struct fg_dev *fg = &chip->fg; struct cycle_counter *counter; struct cap_learning *cl; + struct ttf *ttf; int rc; counter = devm_kzalloc(fg->dev, sizeof(*counter), GFP_KERNEL); @@ -2599,6 +2308,29 @@ static int fg_alg_init(struct fg_gen4_chip *chip) chip->cl = cl; + ttf = devm_kzalloc(fg->dev, sizeof(*ttf), GFP_KERNEL); + if (!ttf) + return -ENOMEM; + + ttf->get_ttf_param = fg_gen4_get_ttf_param; + ttf->awake_voter = fg_gen4_ttf_awake_voter; + ttf->iterm_delta = 0; + ttf->data = chip; + + rc = ttf_tte_init(ttf); + if (rc < 0) { + dev_err(fg->dev, "Error in initializing ttf, rc:%d\n", rc); + ttf->data = NULL; + counter->data = NULL; + cl->data = NULL; + devm_kfree(fg->dev, ttf); + devm_kfree(fg->dev, counter); + devm_kfree(fg->dev, cl); + return rc; + } + + chip->ttf = ttf; + return 0; } @@ -3282,13 +3014,11 @@ static int fg_gen4_probe(struct platform_device *pdev) mutex_init(&fg->bus_lock); mutex_init(&fg->sram_rw_lock); mutex_init(&fg->charge_full_lock); - mutex_init(&chip->ttf.lock); init_completion(&fg->soc_update); init_completion(&fg->soc_ready); INIT_WORK(&fg->status_change_work, status_change_work); INIT_DELAYED_WORK(&fg->profile_load_work, profile_load_work); INIT_DELAYED_WORK(&fg->sram_dump_work, sram_dump_work); - INIT_DELAYED_WORK(&chip->ttf_work, ttf_work); rc = fg_memif_init(fg); if (rc < 0) { @@ -3414,7 +3144,7 @@ static int fg_gen4_suspend(struct device *dev) struct fg_gen4_chip *chip = dev_get_drvdata(dev); struct fg_dev *fg = &chip->fg; - cancel_delayed_work_sync(&chip->ttf_work); + cancel_delayed_work_sync(&chip->ttf->ttf_work); if (fg_sram_dump) cancel_delayed_work_sync(&fg->sram_dump_work); return 0; @@ -3425,7 +3155,7 @@ static int fg_gen4_resume(struct device *dev) struct fg_gen4_chip *chip = dev_get_drvdata(dev); struct fg_dev *fg = &chip->fg; - schedule_delayed_work(&chip->ttf_work, 0); + schedule_delayed_work(&chip->ttf->ttf_work, 0); if (fg_sram_dump) schedule_delayed_work(&fg->sram_dump_work, msecs_to_jiffies(fg_sram_dump_period_ms)); -- GitLab From 1110636ed2d91dd63599af646305e280d89000a8 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 2 Mar 2018 07:19:28 +0900 Subject: [PATCH 0102/1299] scsi: sd_zbc: Fix potential memory leak commit 4b433924b2755a94f99258c178684a0e05c344de upstream. Rework sd_zbc_check_zone_size() to avoid a memory leak due to an early return if sd_zbc_report_zones() fails. Reported-by: David.butterfield Signed-off-by: Damien Le Moal Cc: stable@vger.kernel.org Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sd_zbc.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 2eb61d54bbb4..bc3cb81a9c7d 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -425,7 +425,7 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp, static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) { - u64 zone_blocks; + u64 zone_blocks = 0; sector_t block = 0; unsigned char *buf; unsigned char *rec; @@ -443,10 +443,8 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) /* Do a report zone to get the same field */ ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, 0); - if (ret) { - zone_blocks = 0; - goto out; - } + if (ret) + goto out_free; same = buf[4] & 0x0f; if (same > 0) { @@ -489,7 +487,7 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, block); if (ret) - return ret; + goto out_free; } } while (block < sdkp->capacity); @@ -497,34 +495,32 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) zone_blocks = sdkp->zone_blocks; out: - kfree(buf); - if (!zone_blocks) { if (sdkp->first_scan) sd_printk(KERN_NOTICE, sdkp, "Devices with non constant zone " "size are not supported\n"); - return -ENODEV; - } - - if (!is_power_of_2(zone_blocks)) { + ret = -ENODEV; + } else if (!is_power_of_2(zone_blocks)) { if (sdkp->first_scan) sd_printk(KERN_NOTICE, sdkp, "Devices with non power of 2 zone " "size are not supported\n"); - return -ENODEV; - } - - if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) { + ret = -ENODEV; + } else if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) { if (sdkp->first_scan) sd_printk(KERN_NOTICE, sdkp, "Zone size too large\n"); - return -ENODEV; + ret = -ENODEV; + } else { + sdkp->zone_blocks = zone_blocks; + sdkp->zone_shift = ilog2(zone_blocks); } - sdkp->zone_blocks = zone_blocks; +out_free: + kfree(buf); - return 0; + return ret; } static int sd_zbc_setup(struct scsi_disk *sdkp) -- GitLab From 7cb10a4ce724ba1d72b0d10673176124c379714c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 16 Apr 2018 18:04:41 -0700 Subject: [PATCH 0103/1299] scsi: sd_zbc: Avoid that resetting a zone fails sporadically commit ccce20fc7968d546fb1e8e147bf5cdc8afc4278a upstream. Since SCSI scanning occurs asynchronously, since sd_revalidate_disk() is called from sd_probe_async() and since sd_revalidate_disk() calls sd_zbc_read_zones() it can happen that sd_zbc_read_zones() is called concurrently with blkdev_report_zones() and/or blkdev_reset_zones(). That can cause these functions to fail with -EIO because sd_zbc_read_zones() e.g. sets q->nr_zones to zero before restoring it to the actual value, even if no drive characteristics have changed. Avoid that this can happen by making the following changes: - Protect the code that updates zone information with blk_queue_enter() and blk_queue_exit(). - Modify sd_zbc_setup_seq_zones_bitmap() and sd_zbc_setup() such that these functions do not modify struct scsi_disk before all zone information has been obtained. Note: since commit 055f6e18e08f ("block: Make q_usage_counter also track legacy requests"; kernel v4.15) the request queue freezing mechanism also affects legacy request queues. Fixes: 89d947561077 ("sd: Implement support for ZBC devices") Signed-off-by: Bart Van Assche Cc: Jens Axboe Cc: Damien Le Moal Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: stable@vger.kernel.org # v4.16 Reviewed-by: Damien Le Moal Signed-off-by: Martin K. Petersen Signed-off-by: Damien Le Moal Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sd_zbc.c | 98 +++++++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index bc3cb81a9c7d..ea9e1e0ed5b8 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -423,7 +423,16 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp, #define SD_ZBC_BUF_SIZE 131072 -static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) +/** + * sd_zbc_check_zone_size - Check the device zone sizes + * @sdkp: Target disk + * + * Check that all zones of the device are equal. The last zone can however + * be smaller. The zone size must also be a power of two number of LBAs. + * + * Returns the zone size in bytes upon success or an error code upon failure. + */ +static s64 sd_zbc_check_zone_size(struct scsi_disk *sdkp) { u64 zone_blocks = 0; sector_t block = 0; @@ -434,8 +443,6 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) int ret; u8 same; - sdkp->zone_blocks = 0; - /* Get a buffer */ buf = kmalloc(SD_ZBC_BUF_SIZE, GFP_KERNEL); if (!buf) @@ -470,16 +477,17 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) /* Parse zone descriptors */ while (rec < buf + buf_len) { - zone_blocks = get_unaligned_be64(&rec[8]); - if (sdkp->zone_blocks == 0) { - sdkp->zone_blocks = zone_blocks; - } else if (zone_blocks != sdkp->zone_blocks && - (block + zone_blocks < sdkp->capacity - || zone_blocks > sdkp->zone_blocks)) { + u64 this_zone_blocks = get_unaligned_be64(&rec[8]); + + if (zone_blocks == 0) { + zone_blocks = this_zone_blocks; + } else if (this_zone_blocks != zone_blocks && + (block + this_zone_blocks < sdkp->capacity + || this_zone_blocks > zone_blocks)) { zone_blocks = 0; goto out; } - block += zone_blocks; + block += this_zone_blocks; rec += 64; } @@ -492,8 +500,6 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) } while (block < sdkp->capacity); - zone_blocks = sdkp->zone_blocks; - out: if (!zone_blocks) { if (sdkp->first_scan) @@ -513,8 +519,7 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) "Zone size too large\n"); ret = -ENODEV; } else { - sdkp->zone_blocks = zone_blocks; - sdkp->zone_shift = ilog2(zone_blocks); + ret = zone_blocks; } out_free: @@ -523,23 +528,44 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp) return ret; } -static int sd_zbc_setup(struct scsi_disk *sdkp) +static int sd_zbc_setup(struct scsi_disk *sdkp, u32 zone_blocks) { + struct request_queue *q = sdkp->disk->queue; + u32 zone_shift = ilog2(zone_blocks); + u32 nr_zones; /* chunk_sectors indicates the zone size */ - blk_queue_chunk_sectors(sdkp->disk->queue, - logical_to_sectors(sdkp->device, sdkp->zone_blocks)); - sdkp->zone_shift = ilog2(sdkp->zone_blocks); - sdkp->nr_zones = sdkp->capacity >> sdkp->zone_shift; - if (sdkp->capacity & (sdkp->zone_blocks - 1)) - sdkp->nr_zones++; - - if (!sdkp->zones_wlock) { - sdkp->zones_wlock = kcalloc(BITS_TO_LONGS(sdkp->nr_zones), - sizeof(unsigned long), - GFP_KERNEL); - if (!sdkp->zones_wlock) - return -ENOMEM; + blk_queue_chunk_sectors(q, + logical_to_sectors(sdkp->device, zone_blocks)); + nr_zones = round_up(sdkp->capacity, zone_blocks) >> zone_shift; + + /* + * Initialize the disk zone write lock bitmap if the number + * of zones changed. + */ + if (nr_zones != sdkp->nr_zones) { + unsigned long *zones_wlock = NULL; + + if (nr_zones) { + zones_wlock = kcalloc(BITS_TO_LONGS(nr_zones), + sizeof(unsigned long), + GFP_KERNEL); + if (!zones_wlock) + return -ENOMEM; + } + + blk_mq_freeze_queue(q); + sdkp->zone_blocks = zone_blocks; + sdkp->zone_shift = zone_shift; + sdkp->nr_zones = nr_zones; + swap(sdkp->zones_wlock, zones_wlock); + blk_mq_unfreeze_queue(q); + + kfree(zones_wlock); + + /* READ16/WRITE16 is mandatory for ZBC disks */ + sdkp->device->use_16_for_rw = 1; + sdkp->device->use_10_for_rw = 0; } return 0; @@ -548,6 +574,7 @@ static int sd_zbc_setup(struct scsi_disk *sdkp) int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf) { + int64_t zone_blocks; int ret; if (!sd_is_zoned(sdkp)) @@ -585,19 +612,19 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, * Check zone size: only devices with a constant zone size (except * an eventual last runt zone) that is a power of 2 are supported. */ - ret = sd_zbc_check_zone_size(sdkp); - if (ret) + zone_blocks = sd_zbc_check_zone_size(sdkp); + ret = -EFBIG; + if (zone_blocks != (u32)zone_blocks) + goto err; + ret = zone_blocks; + if (ret < 0) goto err; /* The drive satisfies the kernel restrictions: set it up */ - ret = sd_zbc_setup(sdkp); + ret = sd_zbc_setup(sdkp, zone_blocks); if (ret) goto err; - /* READ16/WRITE16 is mandatory for ZBC disks */ - sdkp->device->use_16_for_rw = 1; - sdkp->device->use_10_for_rw = 0; - return 0; err: @@ -610,6 +637,7 @@ void sd_zbc_remove(struct scsi_disk *sdkp) { kfree(sdkp->zones_wlock); sdkp->zones_wlock = NULL; + sdkp->nr_zones = 0; } void sd_zbc_print_zones(struct scsi_disk *sdkp) -- GitLab From 16d7ceb04b554207aa68dd27c1bc11f8933813fd Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 11 May 2018 09:52:01 -0700 Subject: [PATCH 0104/1299] mmap: introduce sane default mmap limits commit be83bbf806822b1b89e0a0f23cd87cddc409e429 upstream. The internal VM "mmap()" interfaces are based on the mmap target doing everything using page indexes rather than byte offsets, because traditionally (ie 32-bit) we had the situation that the byte offset didn't fit in a register. So while the mmap virtual address was limited by the word size of the architecture, the backing store was not. So we're basically passing "pgoff" around as a page index, in order to be able to describe backing store locations that are much bigger than the word size (think files larger than 4GB etc). But while this all makes a ton of sense conceptually, we've been dogged by various drivers that don't really understand this, and internally work with byte offsets, and then try to work with the page index by turning it into a byte offset with "pgoff << PAGE_SHIFT". Which obviously can overflow. Adding the size of the mapping to it to get the byte offset of the end of the backing store just exacerbates the problem, and if you then use this overflow-prone value to check various limits of your device driver mmap capability, you're just setting yourself up for problems. The correct thing for drivers to do is to do their limit math in page indices, the way the interface is designed. Because the generic mmap code _does_ test that the index doesn't overflow, since that's what the mmap code really cares about. HOWEVER. Finding and fixing various random drivers is a sisyphean task, so let's just see if we can just make the core mmap() code do the limiting for us. Realistically, the only "big" backing stores we need to care about are regular files and block devices, both of which are known to do this properly, and which have nice well-defined limits for how much data they can access. So let's special-case just those two known cases, and then limit other random mmap users to a backing store that still fits in "unsigned long". Realistically, that's not much of a limit at all on 64-bit, and on 32-bit architectures the only worry might be the GPU drivers, which can have big physical address spaces. To make it possible for drivers like that to say that they are 64-bit clean, this patch does repurpose the "FMODE_UNSIGNED_OFFSET" bit in the file flags to allow drivers to mark their file descriptors as safe in the full 64-bit mmap address space. [ The timing for doing this is less than optimal, and this should really go in a merge window. But realistically, this needs wide testing more than it needs anything else, and being main-line is the only way to do that. So the earlier the better, even if it's outside the proper development cycle - Linus ] Cc: Kees Cook Cc: Dan Carpenter Cc: Al Viro Cc: Willy Tarreau Cc: Dave Airlie Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mmap.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/mm/mmap.c b/mm/mmap.c index 11f96fad5271..f9c7747cd9e6 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1315,6 +1315,35 @@ static inline int mlock_future_check(struct mm_struct *mm, return 0; } +static inline u64 file_mmap_size_max(struct file *file, struct inode *inode) +{ + if (S_ISREG(inode->i_mode)) + return inode->i_sb->s_maxbytes; + + if (S_ISBLK(inode->i_mode)) + return MAX_LFS_FILESIZE; + + /* Special "we do even unsigned file positions" case */ + if (file->f_mode & FMODE_UNSIGNED_OFFSET) + return 0; + + /* Yes, random drivers might want more. But I'm tired of buggy drivers */ + return ULONG_MAX; +} + +static inline bool file_mmap_ok(struct file *file, struct inode *inode, + unsigned long pgoff, unsigned long len) +{ + u64 maxsize = file_mmap_size_max(file, inode); + + if (maxsize && len > maxsize) + return false; + maxsize -= len; + if (pgoff > maxsize >> PAGE_SHIFT) + return false; + return true; +} + /* * The caller must hold down_write(¤t->mm->mmap_sem). */ @@ -1388,6 +1417,9 @@ unsigned long do_mmap(struct file *file, unsigned long addr, if (file) { struct inode *inode = file_inode(file); + if (!file_mmap_ok(file, inode, pgoff, len)) + return -EOVERFLOW; + switch (flags & MAP_TYPE) { case MAP_SHARED: if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE)) -- GitLab From af760b568ef165ca90aec68aec112375481ab4cb Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 19 May 2018 09:29:11 -0700 Subject: [PATCH 0105/1299] mmap: relax file size limit for regular files commit 423913ad4ae5b3e8fb8983f70969fb522261ba26 upstream. Commit be83bbf80682 ("mmap: introduce sane default mmap limits") was introduced to catch problems in various ad-hoc character device drivers doing mmap and getting the size limits wrong. In the process, it used "known good" limits for the normal cases of mapping regular files and block device drivers. It turns out that the "s_maxbytes" limit was less "known good" than I thought. In particular, /proc doesn't set it, but exposes one regular file to mmap: /proc/vmcore. As a result, that file got limited to the default MAX_INT s_maxbytes value. This went unnoticed for a while, because apparently the only thing that needs it is the s390 kernel zfcpdump, but there might be other tools that use this too. Vasily suggested just changing s_maxbytes for all of /proc, which isn't wrong, but makes me nervous at this stage. So instead, just make the new mmap limit always be MAX_LFS_FILESIZE for regular files, which won't affect anything else. It wasn't the regular file case I was worried about. I'd really prefer for maxsize to have been per-inode, but that is not how things are today. Fixes: be83bbf80682 ("mmap: introduce sane default mmap limits") Reported-by: Vasily Gorbik Cc: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mmap.c b/mm/mmap.c index f9c7747cd9e6..f858b1f336af 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1318,7 +1318,7 @@ static inline int mlock_future_check(struct mm_struct *mm, static inline u64 file_mmap_size_max(struct file *file, struct inode *inode) { if (S_ISREG(inode->i_mode)) - return inode->i_sb->s_maxbytes; + return MAX_LFS_FILESIZE; if (S_ISBLK(inode->i_mode)) return MAX_LFS_FILESIZE; -- GitLab From 058dd233b5593a1a5fae4b8df6cb44cbcdccb537 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Tue, 9 Jan 2018 09:05:41 +0800 Subject: [PATCH 0106/1299] btrfs: define SUPER_FLAG_METADUMP_V2 commit e2731e55884f2138a252b0a3d7b24d57e49c3c59 upstream. btrfs-progs uses super flag bit BTRFS_SUPER_FLAG_METADUMP_V2 (1ULL << 34). So just define that in kernel so that we know its been used. Signed-off-by: Anand Jain Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/disk-io.c | 3 ++- include/uapi/linux/btrfs_tree.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 27d59cf36341..b475d1ebbbbf 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -59,7 +59,8 @@ BTRFS_HEADER_FLAG_RELOC |\ BTRFS_SUPER_FLAG_ERROR |\ BTRFS_SUPER_FLAG_SEEDING |\ - BTRFS_SUPER_FLAG_METADUMP) + BTRFS_SUPER_FLAG_METADUMP |\ + BTRFS_SUPER_FLAG_METADUMP_V2) static const struct extent_io_ops btree_extent_io_ops; static void end_workqueue_fn(struct btrfs_work *work); diff --git a/include/uapi/linux/btrfs_tree.h b/include/uapi/linux/btrfs_tree.h index 8f659bb7badc..7115838fbf2a 100644 --- a/include/uapi/linux/btrfs_tree.h +++ b/include/uapi/linux/btrfs_tree.h @@ -456,6 +456,7 @@ struct btrfs_free_space_header { #define BTRFS_SUPER_FLAG_SEEDING (1ULL << 32) #define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33) +#define BTRFS_SUPER_FLAG_METADUMP_V2 (1ULL << 34) /* -- GitLab From d58cf41924e89dd75a9aa77c9c8191cc4e274caa Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Sat, 2 Jun 2018 09:02:09 -0700 Subject: [PATCH 0107/1299] kconfig: Avoid format overflow warning from GCC 8.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 2ae89c7a82ea9d81a19b4fc2df23bef4b112f24e upstream. In file included from scripts/kconfig/zconf.tab.c:2485: scripts/kconfig/confdata.c: In function ‘conf_write’: scripts/kconfig/confdata.c:773:22: warning: ‘%s’ directive writing likely 7 or more bytes into a region of size between 1 and 4097 [-Wformat-overflow=] sprintf(newname, "%s%s", dirname, basename); ^~ scripts/kconfig/confdata.c:773:19: note: assuming directive output of 7 bytes sprintf(newname, "%s%s", dirname, basename); ^~~~~~ scripts/kconfig/confdata.c:773:2: note: ‘sprintf’ output 1 or more bytes (assuming 4104) into a destination of size 4097 sprintf(newname, "%s%s", dirname, basename); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ scripts/kconfig/confdata.c:776:23: warning: ‘.tmpconfig.’ directive writing 11 bytes into a region of size between 1 and 4097 [-Wformat-overflow=] sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); ^~~~~~~~~~~ scripts/kconfig/confdata.c:776:3: note: ‘sprintf’ output between 13 and 4119 bytes into a destination of size 4097 sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Increase the size of tmpname and newname to make GCC happy. Signed-off-by: Nathan Chancellor Signed-off-by: Masahiro Yamada Signed-off-by: Greg Kroah-Hartman --- scripts/kconfig/confdata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 297b079ae4d9..27aac273205b 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -745,7 +745,7 @@ int conf_write(const char *name) struct menu *menu; const char *basename; const char *str; - char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; + char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8]; char *env; dirname[0] = 0; -- GitLab From 128f0d700569d70e9ac03bd65b8313357e22736c Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Mon, 28 May 2018 01:26:06 -0400 Subject: [PATCH 0108/1299] be2net: Fix error detection logic for BE3 [ Upstream commit d2c2725c2cdbcc108a191f50953d31c7b6556761 ] Check for 0xE00 (RECOVERABLE_ERR) along with ARMFW UE (0x0) in be_detect_error() to know whether the error is valid error or not Fixes: 673c96e5a ("be2net: Fix UE detection logic for BE3") Signed-off-by: Suresh Reddy Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/emulex/benet/be_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 1b03c32afc1f..7e2b70c2bba3 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3294,7 +3294,9 @@ void be_detect_error(struct be_adapter *adapter) if ((val & POST_STAGE_FAT_LOG_START) != POST_STAGE_FAT_LOG_START && (val & POST_STAGE_ARMFW_UE) - != POST_STAGE_ARMFW_UE) + != POST_STAGE_ARMFW_UE && + (val & POST_STAGE_RECOVERABLE_ERR) + != POST_STAGE_RECOVERABLE_ERR) return; } -- GitLab From d591263c7947e5dd5f7e2b824c1a629b84044530 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 6 Jun 2018 15:03:22 +0200 Subject: [PATCH 0109/1299] bnx2x: use the right constant [ Upstream commit dd612f18a49b63af8b3a5f572d999bdb197385bc ] Nearby code that also tests port suggests that the P0 constant should be used when port is zero. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e,e1; @@ * e ? e1 : e1 // Fixes: 6c3218c6f7e5 ("bnx2x: Adjust ETS to 578xx") Signed-off-by: Julia Lawall Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 7dd83d0ef0a0..22243c480a05 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -588,7 +588,7 @@ static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params, * slots for the highest priority. */ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS : - NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100); + NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100); /* Mapping between the CREDIT_WEIGHT registers and actual client * numbers */ -- GitLab From 0d2eb422fe35342cfb031f543add4a8934c82a32 Mon Sep 17 00:00:00 2001 From: Alexey Kodanev Date: Mon, 21 May 2018 19:28:44 +0300 Subject: [PATCH 0110/1299] dccp: don't free ccid2_hc_tx_sock struct in dccp_disconnect() [ Upstream commit 2677d20677314101293e6da0094ede7b5526d2b1 ] Syzbot reported the use-after-free in timer_is_static_object() [1]. This can happen because the structure for the rto timer (ccid2_hc_tx_sock) is removed in dccp_disconnect(), and ccid2_hc_tx_rto_expire() can be called after that. The report [1] is similar to the one in commit 120e9dabaf55 ("dccp: defer ccid_hc_tx_delete() at dismantle time"). And the fix is the same, delay freeing ccid2_hc_tx_sock structure, so that it is freed in dccp_sk_destruct(). [1] ================================================================== BUG: KASAN: use-after-free in timer_is_static_object+0x80/0x90 kernel/time/timer.c:607 Read of size 8 at addr ffff8801bebb5118 by task syz-executor2/25299 CPU: 1 PID: 25299 Comm: syz-executor2 Not tainted 4.17.0-rc5+ #54 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1b9/0x294 lib/dump_stack.c:113 print_address_description+0x6c/0x20b mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report.cold.7+0x242/0x2fe mm/kasan/report.c:412 __asan_report_load8_noabort+0x14/0x20 mm/kasan/report.c:433 timer_is_static_object+0x80/0x90 kernel/time/timer.c:607 debug_object_activate+0x2d9/0x670 lib/debugobjects.c:508 debug_timer_activate kernel/time/timer.c:709 [inline] debug_activate kernel/time/timer.c:764 [inline] __mod_timer kernel/time/timer.c:1041 [inline] mod_timer+0x4d3/0x13b0 kernel/time/timer.c:1102 sk_reset_timer+0x22/0x60 net/core/sock.c:2742 ccid2_hc_tx_rto_expire+0x587/0x680 net/dccp/ccids/ccid2.c:147 call_timer_fn+0x230/0x940 kernel/time/timer.c:1326 expire_timers kernel/time/timer.c:1363 [inline] __run_timers+0x79e/0xc50 kernel/time/timer.c:1666 run_timer_softirq+0x4c/0x70 kernel/time/timer.c:1692 __do_softirq+0x2e0/0xaf5 kernel/softirq.c:285 invoke_softirq kernel/softirq.c:365 [inline] irq_exit+0x1d1/0x200 kernel/softirq.c:405 exiting_irq arch/x86/include/asm/apic.h:525 [inline] smp_apic_timer_interrupt+0x17e/0x710 arch/x86/kernel/apic/apic.c:1052 apic_timer_interrupt+0xf/0x20 arch/x86/entry/entry_64.S:863 ... Allocated by task 25374: save_stack+0x43/0xd0 mm/kasan/kasan.c:448 set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc+0xc4/0xe0 mm/kasan/kasan.c:553 kasan_slab_alloc+0x12/0x20 mm/kasan/kasan.c:490 kmem_cache_alloc+0x12e/0x760 mm/slab.c:3554 ccid_new+0x25b/0x3e0 net/dccp/ccid.c:151 dccp_hdlr_ccid+0x27/0x150 net/dccp/feat.c:44 __dccp_feat_activate+0x184/0x270 net/dccp/feat.c:344 dccp_feat_activate_values+0x3a7/0x819 net/dccp/feat.c:1538 dccp_create_openreq_child+0x472/0x610 net/dccp/minisocks.c:128 dccp_v4_request_recv_sock+0x12c/0xca0 net/dccp/ipv4.c:408 dccp_v6_request_recv_sock+0x125d/0x1f10 net/dccp/ipv6.c:415 dccp_check_req+0x455/0x6a0 net/dccp/minisocks.c:197 dccp_v4_rcv+0x7b8/0x1f3f net/dccp/ipv4.c:841 ip_local_deliver_finish+0x2e3/0xd80 net/ipv4/ip_input.c:215 NF_HOOK include/linux/netfilter.h:288 [inline] ip_local_deliver+0x1e1/0x720 net/ipv4/ip_input.c:256 dst_input include/net/dst.h:450 [inline] ip_rcv_finish+0x81b/0x2200 net/ipv4/ip_input.c:396 NF_HOOK include/linux/netfilter.h:288 [inline] ip_rcv+0xb70/0x143d net/ipv4/ip_input.c:492 __netif_receive_skb_core+0x26f5/0x3630 net/core/dev.c:4592 __netif_receive_skb+0x2c/0x1e0 net/core/dev.c:4657 process_backlog+0x219/0x760 net/core/dev.c:5337 napi_poll net/core/dev.c:5735 [inline] net_rx_action+0x7b7/0x1930 net/core/dev.c:5801 __do_softirq+0x2e0/0xaf5 kernel/softirq.c:285 Freed by task 25374: save_stack+0x43/0xd0 mm/kasan/kasan.c:448 set_track mm/kasan/kasan.c:460 [inline] __kasan_slab_free+0x11a/0x170 mm/kasan/kasan.c:521 kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528 __cache_free mm/slab.c:3498 [inline] kmem_cache_free+0x86/0x2d0 mm/slab.c:3756 ccid_hc_tx_delete+0xc3/0x100 net/dccp/ccid.c:190 dccp_disconnect+0x130/0xc66 net/dccp/proto.c:286 dccp_close+0x3bc/0xe60 net/dccp/proto.c:1045 inet_release+0x104/0x1f0 net/ipv4/af_inet.c:427 inet6_release+0x50/0x70 net/ipv6/af_inet6.c:460 sock_release+0x96/0x1b0 net/socket.c:594 sock_close+0x16/0x20 net/socket.c:1149 __fput+0x34d/0x890 fs/file_table.c:209 ____fput+0x15/0x20 fs/file_table.c:243 task_work_run+0x1e4/0x290 kernel/task_work.c:113 tracehook_notify_resume include/linux/tracehook.h:191 [inline] exit_to_usermode_loop+0x2bd/0x310 arch/x86/entry/common.c:166 prepare_exit_to_usermode arch/x86/entry/common.c:196 [inline] syscall_return_slowpath arch/x86/entry/common.c:265 [inline] do_syscall_64+0x6ac/0x800 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe The buggy address belongs to the object at ffff8801bebb4cc0 which belongs to the cache ccid2_hc_tx_sock of size 1240 The buggy address is located 1112 bytes inside of 1240-byte region [ffff8801bebb4cc0, ffff8801bebb5198) The buggy address belongs to the page: page:ffffea0006faed00 count:1 mapcount:0 mapping:ffff8801bebb41c0 index:0xffff8801bebb5240 compound_mapcount: 0 flags: 0x2fffc0000008100(slab|head) raw: 02fffc0000008100 ffff8801bebb41c0 ffff8801bebb5240 0000000100000003 raw: ffff8801cdba3138 ffffea0007634120 ffff8801cdbaab40 0000000000000000 page dumped because: kasan: bad access detected ... ================================================================== Reported-by: syzbot+5d47e9ec91a6f15dbd6f@syzkaller.appspotmail.com Signed-off-by: Alexey Kodanev Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/dccp/proto.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/dccp/proto.c b/net/dccp/proto.c index ff3b058cf58c..936dab12f99f 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -280,9 +280,7 @@ int dccp_disconnect(struct sock *sk, int flags) dccp_clear_xmit_timers(sk); ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); - ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_rx_ccid = NULL; - dp->dccps_hc_tx_ccid = NULL; __skb_queue_purge(&sk->sk_receive_queue); __skb_queue_purge(&sk->sk_write_queue); -- GitLab From cbf561634db3a364d0ec8868fc23c21d955b30dd Mon Sep 17 00:00:00 2001 From: Govindarajulu Varadarajan Date: Wed, 23 May 2018 11:17:39 -0700 Subject: [PATCH 0111/1299] enic: set DMA mask to 47 bit [ Upstream commit 322eaa06d55ebc1402a4a8d140945cff536638b4 ] In commit 624dbf55a359b ("driver/net: enic: Try DMA 64 first, then failover to DMA") DMA mask was changed from 40 bits to 64 bits. Hardware actually supports only 47 bits. Fixes: 624dbf55a359b ("driver/net: enic: Try DMA 64 first, then failover to DMA") Signed-off-by: Govindarajulu Varadarajan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/cisco/enic/enic_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index aef40f02c77f..a03a32a4ffca 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -2703,11 +2703,11 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); /* Query PCI controller on system for DMA addressing - * limitation for the device. Try 64-bit first, and + * limitation for the device. Try 47-bit first, and * fail to 32-bit. */ - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(47)); if (err) { err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { @@ -2721,10 +2721,10 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_release_regions; } } else { - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(47)); if (err) { dev_err(dev, "Unable to obtain %u-bit DMA " - "for consistent allocations, aborting\n", 64); + "for consistent allocations, aborting\n", 47); goto err_out_release_regions; } using_dac = 1; -- GitLab From 989986db8f663561a1b89e2fd1170e56265e4e19 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Tue, 5 Jun 2018 15:01:59 +0200 Subject: [PATCH 0112/1299] ip6mr: only set ip6mr_table from setsockopt when ip6mr_new_table succeeds [ Upstream commit 848235edb5c93ed086700584c8ff64f6d7fc778d ] Currently, raw6_sk(sk)->ip6mr_table is set unconditionally during ip6_mroute_setsockopt(MRT6_TABLE). A subsequent attempt at the same setsockopt will fail with -ENOENT, since we haven't actually created that table. A similar fix for ipv4 was included in commit 5e1859fbcc3c ("ipv4: ipmr: various fixes and cleanups"). Fixes: d1db275dd3f6 ("ipv6: ip6mr: support multiple tables") Signed-off-by: Sabrina Dubroca Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6mr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index e1060f28410d..8015e74fd7d9 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1795,7 +1795,8 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns ret = 0; if (!ip6mr_new_table(net, v)) ret = -ENOMEM; - raw6_sk(sk)->ip6mr_table = v; + else + raw6_sk(sk)->ip6mr_table = v; rtnl_unlock(); return ret; } -- GitLab From f200de49dff8fdee95d52d0e127dff72b3409863 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 31 May 2018 10:59:33 +0200 Subject: [PATCH 0113/1299] ip6_tunnel: remove magic mtu value 0xFFF8 [ Upstream commit f7ff1fde9441b4fcc8ffb6e66e6e5a00d008937e ] I don't know where this value comes from (probably a copy and paste and paste and paste ...). Let's use standard values which are a bit greater. Link: https://git.kernel.org/pub/scm/linux/kernel/git/davem/netdev-vger-cvs.git/commit/?id=e5afd356a411a Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_tunnel.c | 11 ++++++++--- net/ipv6/sit.c | 5 +++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 565a0388587a..84ee2eb88121 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1693,8 +1693,13 @@ int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) if (new_mtu < ETH_MIN_MTU) return -EINVAL; } - if (new_mtu > 0xFFF8 - dev->hard_header_len) - return -EINVAL; + if (tnl->parms.proto == IPPROTO_IPV6 || tnl->parms.proto == 0) { + if (new_mtu > IP6_MAX_MTU - dev->hard_header_len) + return -EINVAL; + } else { + if (new_mtu > IP_MAX_MTU - dev->hard_header_len) + return -EINVAL; + } dev->mtu = new_mtu; return 0; } @@ -1842,7 +1847,7 @@ ip6_tnl_dev_init_gen(struct net_device *dev) if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) dev->mtu -= 8; dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = 0xFFF8 - dev->hard_header_len; + dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len; return 0; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index ad1e7e6ce009..5d00a38cd1cb 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1360,7 +1360,7 @@ static void ipip6_tunnel_setup(struct net_device *dev) dev->hard_header_len = LL_MAX_HEADER + t_hlen; dev->mtu = ETH_DATA_LEN - t_hlen; dev->min_mtu = IPV6_MIN_MTU; - dev->max_mtu = 0xFFF8 - t_hlen; + dev->max_mtu = IP6_MAX_MTU - t_hlen; dev->flags = IFF_NOARP; netif_keep_dst(dev); dev->addr_len = 4; @@ -1572,7 +1572,8 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev, if (tb[IFLA_MTU]) { u32 mtu = nla_get_u32(tb[IFLA_MTU]); - if (mtu >= IPV6_MIN_MTU && mtu <= 0xFFF8 - dev->hard_header_len) + if (mtu >= IPV6_MIN_MTU && + mtu <= IP6_MAX_MTU - dev->hard_header_len) dev->mtu = mtu; } -- GitLab From f1409a73b6f4516da803405a3bc89dd8a2d10d99 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 21 May 2018 10:51:53 -0700 Subject: [PATCH 0114/1299] ipmr: properly check rhltable_init() return value [ Upstream commit 66fb33254f45df4b049f487aff1cbde1ef919390 ] commit 8fb472c09b9d ("ipmr: improve hash scalability") added a call to rhltable_init() without checking its return value. This problem was then later copied to IPv6 and factorized in commit 0bbbf0e7d0e7 ("ipmr, ip6mr: Unite creation of new mr_table") kasan: CONFIG_KASAN_INLINE enabled kasan: GPF could be caused by NULL-ptr deref or user memory access general protection fault: 0000 [#1] SMP KASAN Dumping ftrace buffer: (ftrace buffer empty) Modules linked in: CPU: 1 PID: 31552 Comm: syz-executor7 Not tainted 4.17.0-rc5+ #60 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:rht_key_hashfn include/linux/rhashtable.h:277 [inline] RIP: 0010:__rhashtable_lookup include/linux/rhashtable.h:630 [inline] RIP: 0010:rhltable_lookup include/linux/rhashtable.h:716 [inline] RIP: 0010:mr_mfc_find_parent+0x2ad/0xbb0 net/ipv4/ipmr_base.c:63 RSP: 0018:ffff8801826aef70 EFLAGS: 00010203 RAX: 0000000000000001 RBX: 0000000000000001 RCX: ffffc90001ea0000 RDX: 0000000000000079 RSI: ffffffff8661e859 RDI: 000000000000000c RBP: ffff8801826af1c0 R08: ffff8801b2212000 R09: ffffed003b5e46c2 R10: ffffed003b5e46c2 R11: ffff8801daf23613 R12: dffffc0000000000 R13: ffff8801826af198 R14: ffff8801cf8225c0 R15: ffff8801826af658 FS: 00007ff7fa732700(0000) GS:ffff8801daf00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000003ffffff9c CR3: 00000001b0210000 CR4: 00000000001406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: ip6mr_cache_find_parent net/ipv6/ip6mr.c:981 [inline] ip6mr_mfc_delete+0x1fe/0x6b0 net/ipv6/ip6mr.c:1221 ip6_mroute_setsockopt+0x15c6/0x1d70 net/ipv6/ip6mr.c:1698 do_ipv6_setsockopt.isra.9+0x422/0x4660 net/ipv6/ipv6_sockglue.c:163 ipv6_setsockopt+0xbd/0x170 net/ipv6/ipv6_sockglue.c:922 rawv6_setsockopt+0x59/0x140 net/ipv6/raw.c:1060 sock_common_setsockopt+0x9a/0xe0 net/core/sock.c:3039 __sys_setsockopt+0x1bd/0x390 net/socket.c:1903 __do_sys_setsockopt net/socket.c:1914 [inline] __se_sys_setsockopt net/socket.c:1911 [inline] __x64_sys_setsockopt+0xbe/0x150 net/socket.c:1911 do_syscall_64+0x1b1/0x800 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x49/0xbe Fixes: 8fb472c09b9d ("ipmr: improve hash scalability") Fixes: 0bbbf0e7d0e7 ("ipmr, ip6mr: Unite creation of new mr_table") Signed-off-by: Eric Dumazet Cc: Nikolay Aleksandrov Cc: Yuval Mintz Reported-by: syzbot Acked-by: Nikolay Aleksandrov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ipmr.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index c9b3e6e069ae..cbd9c0d8a788 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -323,6 +323,7 @@ static const struct rhashtable_params ipmr_rht_params = { static struct mr_table *ipmr_new_table(struct net *net, u32 id) { struct mr_table *mrt; + int err; /* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */ if (id != RT_TABLE_DEFAULT && id >= 1000000000) @@ -338,7 +339,11 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) write_pnet(&mrt->net, net); mrt->id = id; - rhltable_init(&mrt->mfc_hash, &ipmr_rht_params); + err = rhltable_init(&mrt->mfc_hash, &ipmr_rht_params); + if (err) { + kfree(mrt); + return ERR_PTR(err); + } INIT_LIST_HEAD(&mrt->mfc_cache_list); INIT_LIST_HEAD(&mrt->mfc_unres_queue); -- GitLab From ff33a32949c887670715272d5ce7fc861b277708 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Wed, 23 May 2018 14:29:52 -0400 Subject: [PATCH 0115/1299] ipv4: remove warning in ip_recv_error [ Upstream commit 730c54d59403658a62af6517338fa8d4922c1b28 ] A precondition check in ip_recv_error triggered on an otherwise benign race. Remove the warning. The warning triggers when passing an ipv6 socket to this ipv4 error handling function. RaceFuzzer was able to trigger it due to a race in setsockopt IPV6_ADDRFORM. --- CPU0 do_ipv6_setsockopt sk->sk_socket->ops = &inet_dgram_ops; --- CPU1 sk->sk_prot->recvmsg udp_recvmsg ip_recv_error WARN_ON_ONCE(sk->sk_family == AF_INET6); --- CPU0 do_ipv6_setsockopt sk->sk_family = PF_INET; This socket option converts a v6 socket that is connected to a v4 peer to an v4 socket. It updates the socket on the fly, changing fields in sk as well as other structs. This is inherently non-atomic. It races with the lockless udp_recvmsg path. No other code makes an assumption that these fields are updated atomically. It is benign here, too, as ip_recv_error cares only about the protocol of the skbs enqueued on the error queue, for which sk_family is not a precise predictor (thanks to another isue with IPV6_ADDRFORM). Link: http://lkml.kernel.org/r/20180518120826.GA19515@dragonet.kaist.ac.kr Fixes: 7ce875e5ecb8 ("ipv4: warn once on passing AF_INET6 socket to ip_recv_error") Reported-by: DaeRyong Jeong Suggested-by: Eric Dumazet Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_sockglue.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 1e70ed5244ea..d07ba4d5917b 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -511,8 +511,6 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) int err; int copied; - WARN_ON_ONCE(sk->sk_family == AF_INET6); - err = -EAGAIN; skb = sock_dequeue_err_skb(sk); if (!skb) -- GitLab From 3f8f52c5f200d574451182881d7b3b9e76f43a3d Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Mon, 4 Jun 2018 11:36:05 +0200 Subject: [PATCH 0116/1299] ipv6: omit traffic class when calculating flow hash [ Upstream commit fa1be7e01ea863e911349e30456706749518eeab ] Some of the code paths calculating flow hash for IPv6 use flowlabel member of struct flowi6 which, despite its name, encodes both flow label and traffic class. If traffic class changes within a TCP connection (as e.g. ssh does), ECMP route can switch between path. It's also inconsistent with other code paths where ip6_flowlabel() (returning only flow label) is used to feed the key. Use only flow label everywhere, including one place where hash key is set using ip6_flowinfo(). Fixes: 51ebd3181572 ("ipv6: add support of equal cost multipath (ECMP)") Fixes: f70ea018da06 ("net: Add functions to get skb->hash based on flow structures") Signed-off-by: Michal Kubecek Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/ipv6.h | 5 +++++ net/core/flow_dissector.c | 2 +- net/ipv6/route.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 9596aa93d6ef..a54b8c58ccb7 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -861,6 +861,11 @@ static inline __be32 ip6_make_flowinfo(unsigned int tclass, __be32 flowlabel) return htonl(tclass << IPV6_TCLASS_SHIFT) | flowlabel; } +static inline __be32 flowi6_get_flowlabel(const struct flowi6 *fl6) +{ + return fl6->flowlabel & IPV6_FLOWLABEL_MASK; +} + /* * Prototypes exported by ipv6 */ diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index f950b80c0dd1..d8796a7874b6 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1179,7 +1179,7 @@ __u32 __get_hash_from_flowi6(const struct flowi6 *fl6, struct flow_keys *keys) keys->ports.src = fl6->fl6_sport; keys->ports.dst = fl6->fl6_dport; keys->keyid.keyid = fl6->fl6_gre_key; - keys->tags.flow_label = (__force u32)fl6->flowlabel; + keys->tags.flow_label = (__force u32)flowi6_get_flowlabel(fl6); keys->basic.ip_proto = fl6->flowi6_proto; return flow_hash_from_keys(keys); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7d50d889ab6e..375b20d5bbd7 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1250,7 +1250,7 @@ static void ip6_multipath_l3_keys(const struct sk_buff *skb, keys->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; keys->addrs.v6addrs.src = key_iph->saddr; keys->addrs.v6addrs.dst = key_iph->daddr; - keys->tags.flow_label = ip6_flowinfo(key_iph); + keys->tags.flow_label = ip6_flowlabel(key_iph); keys->basic.ip_proto = key_iph->nexthdr; } -- GitLab From ebe79f9cf44f8d9d3a2ad5b0334b2c6642775b54 Mon Sep 17 00:00:00 2001 From: Wenwen Wang Date: Mon, 21 May 2018 01:58:07 -0500 Subject: [PATCH 0117/1299] isdn: eicon: fix a missing-check bug [ Upstream commit 6009d1fe6ba3bb2dab55921da60465329cc1cd89 ] In divasmain.c, the function divas_write() firstly invokes the function diva_xdi_open_adapter() to open the adapter that matches with the adapter number provided by the user, and then invokes the function diva_xdi_write() to perform the write operation using the matched adapter. The two functions diva_xdi_open_adapter() and diva_xdi_write() are located in diva.c. In diva_xdi_open_adapter(), the user command is copied to the object 'msg' from the userspace pointer 'src' through the function pointer 'cp_fn', which eventually calls copy_from_user() to do the copy. Then, the adapter number 'msg.adapter' is used to find out a matched adapter from the 'adapter_queue'. A matched adapter will be returned if it is found. Otherwise, NULL is returned to indicate the failure of the verification on the adapter number. As mentioned above, if a matched adapter is returned, the function diva_xdi_write() is invoked to perform the write operation. In this function, the user command is copied once again from the userspace pointer 'src', which is the same as the 'src' pointer in diva_xdi_open_adapter() as both of them are from the 'buf' pointer in divas_write(). Similarly, the copy is achieved through the function pointer 'cp_fn', which finally calls copy_from_user(). After the successful copy, the corresponding command processing handler of the matched adapter is invoked to perform the write operation. It is obvious that there are two copies here from userspace, one is in diva_xdi_open_adapter(), and one is in diva_xdi_write(). Plus, both of these two copies share the same source userspace pointer, i.e., the 'buf' pointer in divas_write(). Given that a malicious userspace process can race to change the content pointed by the 'buf' pointer, this can pose potential security issues. For example, in the first copy, the user provides a valid adapter number to pass the verification process and a valid adapter can be found. Then the user can modify the adapter number to an invalid number. This way, the user can bypass the verification process of the adapter number and inject inconsistent data. This patch reuses the data copied in diva_xdi_open_adapter() and passes it to diva_xdi_write(). This way, the above issues can be avoided. Signed-off-by: Wenwen Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/hardware/eicon/diva.c | 22 +++++++++++++++------- drivers/isdn/hardware/eicon/diva.h | 5 +++-- drivers/isdn/hardware/eicon/divasmain.c | 18 +++++++++++------- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c index 944a7f338099..1b25d8bc153a 100644 --- a/drivers/isdn/hardware/eicon/diva.c +++ b/drivers/isdn/hardware/eicon/diva.c @@ -388,10 +388,10 @@ void divasa_xdi_driver_unload(void) ** Receive and process command from user mode utility */ void *diva_xdi_open_adapter(void *os_handle, const void __user *src, - int length, + int length, void *mptr, divas_xdi_copy_from_user_fn_t cp_fn) { - diva_xdi_um_cfg_cmd_t msg; + diva_xdi_um_cfg_cmd_t *msg = (diva_xdi_um_cfg_cmd_t *)mptr; diva_os_xdi_adapter_t *a = NULL; diva_os_spin_lock_magic_t old_irql; struct list_head *tmp; @@ -401,21 +401,21 @@ void *diva_xdi_open_adapter(void *os_handle, const void __user *src, length, sizeof(diva_xdi_um_cfg_cmd_t))) return NULL; } - if ((*cp_fn) (os_handle, &msg, src, sizeof(msg)) <= 0) { + if ((*cp_fn) (os_handle, msg, src, sizeof(*msg)) <= 0) { DBG_ERR(("A: A(?) open, write error")) return NULL; } diva_os_enter_spin_lock(&adapter_lock, &old_irql, "open_adapter"); list_for_each(tmp, &adapter_queue) { a = list_entry(tmp, diva_os_xdi_adapter_t, link); - if (a->controller == (int)msg.adapter) + if (a->controller == (int)msg->adapter) break; a = NULL; } diva_os_leave_spin_lock(&adapter_lock, &old_irql, "open_adapter"); if (!a) { - DBG_ERR(("A: A(%d) open, adapter not found", msg.adapter)) + DBG_ERR(("A: A(%d) open, adapter not found", msg->adapter)) } return (a); @@ -437,8 +437,10 @@ void diva_xdi_close_adapter(void *adapter, void *os_handle) int diva_xdi_write(void *adapter, void *os_handle, const void __user *src, - int length, divas_xdi_copy_from_user_fn_t cp_fn) + int length, void *mptr, + divas_xdi_copy_from_user_fn_t cp_fn) { + diva_xdi_um_cfg_cmd_t *msg = (diva_xdi_um_cfg_cmd_t *)mptr; diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter; void *data; @@ -459,7 +461,13 @@ diva_xdi_write(void *adapter, void *os_handle, const void __user *src, return (-2); } - length = (*cp_fn) (os_handle, data, src, length); + if (msg) { + *(diva_xdi_um_cfg_cmd_t *)data = *msg; + length = (*cp_fn) (os_handle, (char *)data + sizeof(*msg), + src + sizeof(*msg), length - sizeof(*msg)); + } else { + length = (*cp_fn) (os_handle, data, src, length); + } if (length > 0) { if ((*(a->interface.cmd_proc)) (a, (diva_xdi_um_cfg_cmd_t *) data, length)) { diff --git a/drivers/isdn/hardware/eicon/diva.h b/drivers/isdn/hardware/eicon/diva.h index b067032093a8..1ad76650fbf9 100644 --- a/drivers/isdn/hardware/eicon/diva.h +++ b/drivers/isdn/hardware/eicon/diva.h @@ -20,10 +20,11 @@ int diva_xdi_read(void *adapter, void *os_handle, void __user *dst, int max_length, divas_xdi_copy_to_user_fn_t cp_fn); int diva_xdi_write(void *adapter, void *os_handle, const void __user *src, - int length, divas_xdi_copy_from_user_fn_t cp_fn); + int length, void *msg, + divas_xdi_copy_from_user_fn_t cp_fn); void *diva_xdi_open_adapter(void *os_handle, const void __user *src, - int length, + int length, void *msg, divas_xdi_copy_from_user_fn_t cp_fn); void diva_xdi_close_adapter(void *adapter, void *os_handle); diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c index b2023e08dcd2..932e98d0d901 100644 --- a/drivers/isdn/hardware/eicon/divasmain.c +++ b/drivers/isdn/hardware/eicon/divasmain.c @@ -591,19 +591,22 @@ static int divas_release(struct inode *inode, struct file *file) static ssize_t divas_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { + diva_xdi_um_cfg_cmd_t msg; int ret = -EINVAL; if (!file->private_data) { file->private_data = diva_xdi_open_adapter(file, buf, - count, + count, &msg, xdi_copy_from_user); - } - if (!file->private_data) { - return (-ENODEV); + if (!file->private_data) + return (-ENODEV); + ret = diva_xdi_write(file->private_data, file, + buf, count, &msg, xdi_copy_from_user); + } else { + ret = diva_xdi_write(file->private_data, file, + buf, count, NULL, xdi_copy_from_user); } - ret = diva_xdi_write(file->private_data, file, - buf, count, xdi_copy_from_user); switch (ret) { case -1: /* Message should be removed from rx mailbox first */ ret = -EBUSY; @@ -622,11 +625,12 @@ static ssize_t divas_write(struct file *file, const char __user *buf, static ssize_t divas_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { + diva_xdi_um_cfg_cmd_t msg; int ret = -EINVAL; if (!file->private_data) { file->private_data = diva_xdi_open_adapter(file, buf, - count, + count, &msg, xdi_copy_from_user); } if (!file->private_data) { -- GitLab From c6fae49a447ca86d65922f92281d232c3adbb1db Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Fri, 1 Jun 2018 14:30:38 +0300 Subject: [PATCH 0118/1299] kcm: Fix use-after-free caused by clonned sockets [ Upstream commit eb7f54b90bd8f469834c5e86dcf72ebf9a629811 ] (resend for properly queueing in patchwork) kcm_clone() creates kernel socket, which does not take net counter. Thus, the net may die before the socket is completely destructed, i.e. kcm_exit_net() is executed before kcm_done(). Reported-by: syzbot+5f1a04e374a635efc426@syzkaller.appspotmail.com Signed-off-by: Kirill Tkhai Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/kcm/kcmsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c index 01a4ff3df60b..9bf997404918 100644 --- a/net/kcm/kcmsock.c +++ b/net/kcm/kcmsock.c @@ -1672,7 +1672,7 @@ static struct file *kcm_clone(struct socket *osock) __module_get(newsock->ops->owner); newsk = sk_alloc(sock_net(osock->sk), PF_KCM, GFP_KERNEL, - &kcm_proto, true); + &kcm_proto, false); if (!newsk) { sock_release(newsock); return ERR_PTR(-ENOMEM); -- GitLab From be1f1827a89a1d57dd2c9dafc9b6ddc96e8b2ebe Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 5 Jun 2018 09:48:13 -0700 Subject: [PATCH 0119/1299] netdev-FAQ: clarify DaveM's position for stable backports [ Upstream commit 75d4e704fa8d2cf33ff295e5b441317603d7f9fd ] Per discussion with David at netconf 2018, let's clarify DaveM's position of handling stable backports in netdev-FAQ. This is important for people relying on upstream -stable releases. Cc: Greg Kroah-Hartman Signed-off-by: Cong Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- Documentation/networking/netdev-FAQ.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/networking/netdev-FAQ.txt b/Documentation/networking/netdev-FAQ.txt index cfc66ea72329..a365656e4873 100644 --- a/Documentation/networking/netdev-FAQ.txt +++ b/Documentation/networking/netdev-FAQ.txt @@ -176,6 +176,15 @@ A: No. See above answer. In short, if you think it really belongs in dash marker line as described in Documentation/process/submitting-patches.rst to temporarily embed that information into the patch that you send. +Q: Are all networking bug fixes backported to all stable releases? + +A: Due to capacity, Dave could only take care of the backports for the last + 2 stable releases. For earlier stable releases, each stable branch maintainer + is supposed to take care of them. If you find any patch is missing from an + earlier stable branch, please notify stable@vger.kernel.org with either a + commit ID or a formal patch backported, and CC Dave and other relevant + networking developers. + Q: Someone said that the comment style and coding convention is different for the networking content. Is this true? -- GitLab From 341c03313a9a78f223badc4de307886c684f3cd9 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 22 May 2018 13:44:51 -0700 Subject: [PATCH 0120/1299] net: ipv4: add missing RTA_TABLE to rtm_ipv4_policy [ Upstream commit 2eabd764cb5512f1338d06ffc054c8bc9fbe9104 ] Signed-off-by: Roopa Prabhu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/fib_frontend.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index d72874150905..df8fd3ce713d 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -625,6 +625,7 @@ const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = { [RTA_ENCAP] = { .type = NLA_NESTED }, [RTA_UID] = { .type = NLA_U32 }, [RTA_MARK] = { .type = NLA_U32 }, + [RTA_TABLE] = { .type = NLA_U32 }, }; static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, -- GitLab From 95159ad9635a944645b5a30c04a39934994c8933 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 5 Jun 2018 06:06:19 -0700 Subject: [PATCH 0121/1299] net: metrics: add proper netlink validation [ Upstream commit 5b5e7a0de2bbf2a1afcd9f49e940010e9fb80d53 ] Before using nla_get_u32(), better make sure the attribute is of the proper size. Code recently was changed, but bug has been there from beginning of git. BUG: KMSAN: uninit-value in rtnetlink_put_metrics+0x553/0x960 net/core/rtnetlink.c:746 CPU: 1 PID: 14139 Comm: syz-executor6 Not tainted 4.17.0-rc5+ #103 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x185/0x1d0 lib/dump_stack.c:113 kmsan_report+0x149/0x260 mm/kmsan/kmsan.c:1084 __msan_warning_32+0x6e/0xc0 mm/kmsan/kmsan_instr.c:686 rtnetlink_put_metrics+0x553/0x960 net/core/rtnetlink.c:746 fib_dump_info+0xc42/0x2190 net/ipv4/fib_semantics.c:1361 rtmsg_fib+0x65f/0x8c0 net/ipv4/fib_semantics.c:419 fib_table_insert+0x2314/0x2b50 net/ipv4/fib_trie.c:1287 inet_rtm_newroute+0x210/0x340 net/ipv4/fib_frontend.c:779 rtnetlink_rcv_msg+0xa32/0x1560 net/core/rtnetlink.c:4646 netlink_rcv_skb+0x378/0x600 net/netlink/af_netlink.c:2448 rtnetlink_rcv+0x50/0x60 net/core/rtnetlink.c:4664 netlink_unicast_kernel net/netlink/af_netlink.c:1310 [inline] netlink_unicast+0x1678/0x1750 net/netlink/af_netlink.c:1336 netlink_sendmsg+0x104f/0x1350 net/netlink/af_netlink.c:1901 sock_sendmsg_nosec net/socket.c:629 [inline] sock_sendmsg net/socket.c:639 [inline] ___sys_sendmsg+0xec0/0x1310 net/socket.c:2117 __sys_sendmsg net/socket.c:2155 [inline] __do_sys_sendmsg net/socket.c:2164 [inline] __se_sys_sendmsg net/socket.c:2162 [inline] __x64_sys_sendmsg+0x331/0x460 net/socket.c:2162 do_syscall_64+0x152/0x230 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x455a09 RSP: 002b:00007faae5fd8c68 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00007faae5fd96d4 RCX: 0000000000455a09 RDX: 0000000000000000 RSI: 0000000020000000 RDI: 0000000000000013 RBP: 000000000072bea0 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff R13: 00000000000005d0 R14: 00000000006fdc20 R15: 0000000000000000 Uninit was stored to memory at: kmsan_save_stack_with_flags mm/kmsan/kmsan.c:279 [inline] kmsan_save_stack mm/kmsan/kmsan.c:294 [inline] kmsan_internal_chain_origin+0x12b/0x210 mm/kmsan/kmsan.c:685 __msan_chain_origin+0x69/0xc0 mm/kmsan/kmsan_instr.c:529 fib_convert_metrics net/ipv4/fib_semantics.c:1056 [inline] fib_create_info+0x2d46/0x9dc0 net/ipv4/fib_semantics.c:1150 fib_table_insert+0x3e4/0x2b50 net/ipv4/fib_trie.c:1146 inet_rtm_newroute+0x210/0x340 net/ipv4/fib_frontend.c:779 rtnetlink_rcv_msg+0xa32/0x1560 net/core/rtnetlink.c:4646 netlink_rcv_skb+0x378/0x600 net/netlink/af_netlink.c:2448 rtnetlink_rcv+0x50/0x60 net/core/rtnetlink.c:4664 netlink_unicast_kernel net/netlink/af_netlink.c:1310 [inline] netlink_unicast+0x1678/0x1750 net/netlink/af_netlink.c:1336 netlink_sendmsg+0x104f/0x1350 net/netlink/af_netlink.c:1901 sock_sendmsg_nosec net/socket.c:629 [inline] sock_sendmsg net/socket.c:639 [inline] ___sys_sendmsg+0xec0/0x1310 net/socket.c:2117 __sys_sendmsg net/socket.c:2155 [inline] __do_sys_sendmsg net/socket.c:2164 [inline] __se_sys_sendmsg net/socket.c:2162 [inline] __x64_sys_sendmsg+0x331/0x460 net/socket.c:2162 do_syscall_64+0x152/0x230 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Uninit was created at: kmsan_save_stack_with_flags mm/kmsan/kmsan.c:279 [inline] kmsan_internal_poison_shadow+0xb8/0x1b0 mm/kmsan/kmsan.c:189 kmsan_kmalloc+0x94/0x100 mm/kmsan/kmsan.c:315 kmsan_slab_alloc+0x10/0x20 mm/kmsan/kmsan.c:322 slab_post_alloc_hook mm/slab.h:446 [inline] slab_alloc_node mm/slub.c:2753 [inline] __kmalloc_node_track_caller+0xb32/0x11b0 mm/slub.c:4395 __kmalloc_reserve net/core/skbuff.c:138 [inline] __alloc_skb+0x2cb/0x9e0 net/core/skbuff.c:206 alloc_skb include/linux/skbuff.h:988 [inline] netlink_alloc_large_skb net/netlink/af_netlink.c:1182 [inline] netlink_sendmsg+0x76e/0x1350 net/netlink/af_netlink.c:1876 sock_sendmsg_nosec net/socket.c:629 [inline] sock_sendmsg net/socket.c:639 [inline] ___sys_sendmsg+0xec0/0x1310 net/socket.c:2117 __sys_sendmsg net/socket.c:2155 [inline] __do_sys_sendmsg net/socket.c:2164 [inline] __se_sys_sendmsg net/socket.c:2162 [inline] __x64_sys_sendmsg+0x331/0x460 net/socket.c:2162 do_syscall_64+0x152/0x230 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: a919525ad832 ("net: Move fib_convert_metrics to metrics file") Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Eric Dumazet Reported-by: syzbot Cc: David Ahern Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/fib_semantics.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index f39955913d3f..b557af72cde9 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -725,6 +725,8 @@ bool fib_metrics_match(struct fib_config *cfg, struct fib_info *fi) nla_strlcpy(tmp, nla, sizeof(tmp)); val = tcp_ca_get_key_by_name(tmp, &ecn_ca); } else { + if (nla_len(nla) != sizeof(u32)) + return false; val = nla_get_u32(nla); } @@ -1051,6 +1053,8 @@ fib_convert_metrics(struct fib_info *fi, const struct fib_config *cfg) if (val == TCP_CA_UNSPEC) return -EINVAL; } else { + if (nla_len(nla) != sizeof(u32)) + return -EINVAL; val = nla_get_u32(nla); } if (type == RTAX_ADVMSS && val > 65535 - 40) -- GitLab From c85df6eb6e86d38f3e0374e0557a4912427585f9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 1 Jun 2018 09:23:02 -0700 Subject: [PATCH 0122/1299] net/packet: refine check for priv area size [ Upstream commit eb73190f4fbeedf762394e92d6a4ec9ace684c88 ] syzbot was able to trick af_packet again [1] Various commits tried to address the problem in the past, but failed to take into account V3 header size. [1] tpacket_rcv: packet too big, clamped from 72 to 4294967224. macoff=96 BUG: KASAN: use-after-free in prb_run_all_ft_ops net/packet/af_packet.c:1016 [inline] BUG: KASAN: use-after-free in prb_fill_curr_block.isra.59+0x4e5/0x5c0 net/packet/af_packet.c:1039 Write of size 2 at addr ffff8801cb62000e by task kworker/1:2/2106 CPU: 1 PID: 2106 Comm: kworker/1:2 Not tainted 4.17.0-rc7+ #77 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: ipv6_addrconf addrconf_dad_work Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1b9/0x294 lib/dump_stack.c:113 print_address_description+0x6c/0x20b mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report.cold.7+0x242/0x2fe mm/kasan/report.c:412 __asan_report_store2_noabort+0x17/0x20 mm/kasan/report.c:436 prb_run_all_ft_ops net/packet/af_packet.c:1016 [inline] prb_fill_curr_block.isra.59+0x4e5/0x5c0 net/packet/af_packet.c:1039 __packet_lookup_frame_in_block net/packet/af_packet.c:1094 [inline] packet_current_rx_frame net/packet/af_packet.c:1117 [inline] tpacket_rcv+0x1866/0x3340 net/packet/af_packet.c:2282 dev_queue_xmit_nit+0x891/0xb90 net/core/dev.c:2018 xmit_one net/core/dev.c:3049 [inline] dev_hard_start_xmit+0x16b/0xc10 net/core/dev.c:3069 __dev_queue_xmit+0x2724/0x34c0 net/core/dev.c:3584 dev_queue_xmit+0x17/0x20 net/core/dev.c:3617 neigh_resolve_output+0x679/0xad0 net/core/neighbour.c:1358 neigh_output include/net/neighbour.h:482 [inline] ip6_finish_output2+0xc9c/0x2810 net/ipv6/ip6_output.c:120 ip6_finish_output+0x5fe/0xbc0 net/ipv6/ip6_output.c:154 NF_HOOK_COND include/linux/netfilter.h:277 [inline] ip6_output+0x227/0x9b0 net/ipv6/ip6_output.c:171 dst_output include/net/dst.h:444 [inline] NF_HOOK include/linux/netfilter.h:288 [inline] ndisc_send_skb+0x100d/0x1570 net/ipv6/ndisc.c:491 ndisc_send_ns+0x3c1/0x8d0 net/ipv6/ndisc.c:633 addrconf_dad_work+0xbef/0x1340 net/ipv6/addrconf.c:4033 process_one_work+0xc1e/0x1b50 kernel/workqueue.c:2145 worker_thread+0x1cc/0x1440 kernel/workqueue.c:2279 kthread+0x345/0x410 kernel/kthread.c:240 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:412 The buggy address belongs to the page: page:ffffea00072d8800 count:0 mapcount:-127 mapping:0000000000000000 index:0xffff8801cb620e80 flags: 0x2fffc0000000000() raw: 02fffc0000000000 0000000000000000 ffff8801cb620e80 00000000ffffff80 raw: ffffea00072e3820 ffffea0007132d20 0000000000000002 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8801cb61ff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff8801cb61ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >ffff8801cb620000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ^ ffff8801cb620080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ffff8801cb620100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff Fixes: 2b6867c2ce76 ("net/packet: fix overflow in check for priv area size") Fixes: dc808110bb62 ("packet: handle too big packets for PACKET_V3") Fixes: f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation.") Signed-off-by: Eric Dumazet Reported-by: syzbot Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/packet/af_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8351faabba62..455f10328818 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -4293,7 +4293,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, goto out; if (po->tp_version >= TPACKET_V3 && req->tp_block_size <= - BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv)) + BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv) + sizeof(struct tpacket3_hdr)) goto out; if (unlikely(req->tp_frame_size < po->tp_hdrlen + po->tp_reserve)) -- GitLab From 8acb0708ab6d7d29db9276befc08bbc20271ab44 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 22 May 2018 17:04:49 -0700 Subject: [PATCH 0123/1299] net: phy: broadcom: Fix bcm_write_exp() [ Upstream commit 79fb218d97980d4fee9a64f4c8ff05289364ba25 ] On newer PHYs, we need to select the expansion register to write with setting bits [11:8] to 0xf. This was done correctly by bcm7xxx.c prior to being migrated to generic code under bcm-phy-lib.c which unfortunately used the older implementation from the BCM54xx days. Fix this by creating an inline stub: bcm_write_exp_sel() which adds the correct value (MII_BCM54XX_EXP_SEL_ER) and update both the Cygnus PHY and BCM7xxx PHY drivers which require setting these bits. broadcom.c is unchanged because some PHYs even use a different selector method, so let them specify it directly (e.g: SerDes secondary selector). Fixes: a1cba5613edf ("net: phy: Add Broadcom phy library for common interfaces") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/phy/bcm-cygnus.c | 6 +++--- drivers/net/phy/bcm-phy-lib.h | 7 +++++++ drivers/net/phy/bcm7xxx.c | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/bcm-cygnus.c b/drivers/net/phy/bcm-cygnus.c index 3fe8cc5c177e..9b27ca264c66 100644 --- a/drivers/net/phy/bcm-cygnus.c +++ b/drivers/net/phy/bcm-cygnus.c @@ -61,17 +61,17 @@ static int bcm_cygnus_afe_config(struct phy_device *phydev) return rc; /* make rcal=100, since rdb default is 000 */ - rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB1, 0x10); + rc = bcm_phy_write_exp_sel(phydev, MII_BRCM_CORE_EXPB1, 0x10); if (rc < 0) return rc; /* CORE_EXPB0, Reset R_CAL/RC_CAL Engine */ - rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x10); + rc = bcm_phy_write_exp_sel(phydev, MII_BRCM_CORE_EXPB0, 0x10); if (rc < 0) return rc; /* CORE_EXPB0, Disable Reset R_CAL/RC_CAL Engine */ - rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x00); + rc = bcm_phy_write_exp_sel(phydev, MII_BRCM_CORE_EXPB0, 0x00); return 0; } diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h index 7c73808cbbde..81cceaa412fe 100644 --- a/drivers/net/phy/bcm-phy-lib.h +++ b/drivers/net/phy/bcm-phy-lib.h @@ -14,11 +14,18 @@ #ifndef _LINUX_BCM_PHY_LIB_H #define _LINUX_BCM_PHY_LIB_H +#include #include int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val); int bcm_phy_read_exp(struct phy_device *phydev, u16 reg); +static inline int bcm_phy_write_exp_sel(struct phy_device *phydev, + u16 reg, u16 val) +{ + return bcm_phy_write_exp(phydev, reg | MII_BCM54XX_EXP_SEL_ER, val); +} + int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val); int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum); diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index 8b33f688ac8a..3c5b2a2e2fcc 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -65,10 +65,10 @@ struct bcm7xxx_phy_priv { static void r_rc_cal_reset(struct phy_device *phydev) { /* Reset R_CAL/RC_CAL Engine */ - bcm_phy_write_exp(phydev, 0x00b0, 0x0010); + bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0010); /* Disable Reset R_AL/RC_CAL Engine */ - bcm_phy_write_exp(phydev, 0x00b0, 0x0000); + bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0000); } static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) -- GitLab From 1c2c7767e876c547d5c74cacfbe5b6665cf56c5e Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Thu, 31 May 2018 11:18:29 +0200 Subject: [PATCH 0124/1299] net: usb: cdc_mbim: add flag FLAG_SEND_ZLP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 9f7c728332e8966084242fcd951aa46583bc308c ] Testing Telit LM940 with ICMP packets > 14552 bytes revealed that the modem needs FLAG_SEND_ZLP to properly work, otherwise the cdc mbim data interface won't be anymore responsive. Signed-off-by: Daniele Palmas Acked-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/cdc_mbim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 7220cd620717..0362acd5cdca 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -609,7 +609,7 @@ static const struct driver_info cdc_mbim_info_ndp_to_end = { */ static const struct driver_info cdc_mbim_info_avoid_altsetting_toggle = { .description = "CDC MBIM", - .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN, + .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP, .bind = cdc_mbim_bind, .unbind = cdc_mbim_unbind, .manage_power = cdc_mbim_manage_power, -- GitLab From 0d751192afdef9f40746f36a47e802c35bc1075a Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 24 May 2018 18:10:30 -0400 Subject: [PATCH 0125/1299] packet: fix reserve calculation [ Upstream commit 9aad13b087ab0a588cd68259de618f100053360e ] Commit b84bbaf7a6c8 ("packet: in packet_snd start writing at link layer allocation") ensures that packet_snd always starts writing the link layer header in reserved headroom allocated for this purpose. This is needed because packets may be shorter than hard_header_len, in which case the space up to hard_header_len may be zeroed. But that necessary padding is not accounted for in skb->len. The fix, however, is buggy. It calls skb_push, which grows skb->len when moving skb->data back. But in this case packet length should not change. Instead, call skb_reserve, which moves both skb->data and skb->tail back, without changing length. Fixes: b84bbaf7a6c8 ("packet: in packet_snd start writing at link layer allocation") Reported-by: Tariq Toukan Signed-off-by: Willem de Bruijn Acked-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/packet/af_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 455f10328818..7806e166669a 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2920,7 +2920,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) if (unlikely(offset < 0)) goto out_free; } else if (reserve) { - skb_push(skb, reserve); + skb_reserve(skb, -reserve); } /* Returns -EFAULT on error */ -- GitLab From 0a3608662ff6f22b6f5a56569ca639820ff63333 Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Mon, 21 May 2018 12:31:47 -0700 Subject: [PATCH 0126/1299] qed: Fix mask for physical address in ILT entry [ Upstream commit fdd13dd350dda1826579eb5c333d76b14513b812 ] ILT entry requires 12 bit right shifted physical address. Existing mask for ILT entry of physical address i.e. ILT_ENTRY_PHY_ADDR_MASK is not sufficient to handle 64bit address because upper 8 bits of 64 bit address were getting masked which resulted in completer abort error on PCIe bus due to invalid address. Fix that mask to handle 64bit physical address. Fixes: fe56b9e6a8d9 ("qed: Add module with basic common support") Signed-off-by: Shahed Shaikh Signed-off-by: Ariel Elior Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/qlogic/qed/qed_cxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c index 629bfa0cd3f0..27ba476f761d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -77,7 +77,7 @@ #define ILT_CFG_REG(cli, reg) PSWRQ2_REG_ ## cli ## _ ## reg ## _RT_OFFSET /* ILT entry structure */ -#define ILT_ENTRY_PHY_ADDR_MASK 0x000FFFFFFFFFFFULL +#define ILT_ENTRY_PHY_ADDR_MASK (~0ULL >> 12) #define ILT_ENTRY_PHY_ADDR_SHIFT 0 #define ILT_ENTRY_VALID_MASK 0x1ULL #define ILT_ENTRY_VALID_SHIFT 52 -- GitLab From 60473d7034eec45f7dfe94b59fafba2dc683dfe7 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Tue, 5 Jun 2018 12:16:58 +0800 Subject: [PATCH 0127/1299] sctp: not allow transport timeout value less than HZ/5 for hb_timer [ Upstream commit 1d88ba1ebb2763aa86172cd7ca05dedbeccc0d35 ] syzbot reported a rcu_sched self-detected stall on CPU which is caused by too small value set on rto_min with SCTP_RTOINFO sockopt. With this value, hb_timer will get stuck there, as in its timer handler it starts this timer again with this value, then goes to the timer handler again. This problem is there since very beginning, and thanks to Eric for the reproducer shared from a syzbot mail. This patch fixes it by not allowing sctp_transport_timeout to return a smaller value than HZ/5 for hb_timer, which is based on TCP's min rto. Note that it doesn't fix this issue by limiting rto_min, as some users are still using small rto and no proper value was found for it yet. Reported-by: syzbot+3dcd59a1f907245f891f@syzkaller.appspotmail.com Suggested-by: Marcelo Ricardo Leitner Signed-off-by: Xin Long Acked-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 7ef77fd7b52a..e0c2a4e23039 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -637,7 +637,7 @@ unsigned long sctp_transport_timeout(struct sctp_transport *trans) trans->state != SCTP_PF) timeout += trans->hbinterval; - return timeout; + return max_t(unsigned long, timeout, HZ / 5); } /* Reset transport variables to their initial values */ -- GitLab From f2bb94069f3e88ca9d62eec614ace16d03695b4a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 4 Jun 2018 17:46:01 +0300 Subject: [PATCH 0128/1299] team: use netdev_features_t instead of u32 [ Upstream commit 25ea66544bfd1d9df1b7e1502f8717e85fa1e6e6 ] This code was introduced in 2011 around the same time that we made netdev_features_t a u64 type. These days a u32 is not big enough to hold all the potential features. Signed-off-by: Dan Carpenter Acked-by: Jiri Pirko Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/team/team.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 8a222ae5950e..83c591713837 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1004,7 +1004,8 @@ static void team_port_disable(struct team *team, static void __team_compute_features(struct team *team) { struct team_port *port; - u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL; + netdev_features_t vlan_features = TEAM_VLAN_FEATURES & + NETIF_F_ALL_FOR_ALL; netdev_features_t enc_features = TEAM_ENC_FEATURES; unsigned short max_hard_header_len = ETH_HLEN; unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE | -- GitLab From 6d431f6e6880b7c626650326ba4c72c50b1426f8 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 22 May 2018 19:58:57 +0800 Subject: [PATCH 0129/1299] vhost: synchronize IOTLB message with dev cleanup [ Upstream commit 1b15ad683ab42a203f98b67045b40720e99d0e9a ] DaeRyong Jeong reports a race between vhost_dev_cleanup() and vhost_process_iotlb_msg(): Thread interleaving: CPU0 (vhost_process_iotlb_msg) CPU1 (vhost_dev_cleanup) (In the case of both VHOST_IOTLB_UPDATE and VHOST_IOTLB_INVALIDATE) ===== ===== vhost_umem_clean(dev->iotlb); if (!dev->iotlb) { ret = -EFAULT; break; } dev->iotlb = NULL; The reason is we don't synchronize between them, fixing by protecting vhost_process_iotlb_msg() with dev mutex. Reported-by: DaeRyong Jeong Fixes: 6b1e6cc7855b0 ("vhost: new device IOTLB API") Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/vhost/vhost.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 8e3ca4400766..50e48afd88ff 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -993,6 +993,7 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev, { int ret = 0; + mutex_lock(&dev->mutex); vhost_dev_lock_vqs(dev); switch (msg->type) { case VHOST_IOTLB_UPDATE: @@ -1024,6 +1025,8 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev, } vhost_dev_unlock_vqs(dev); + mutex_unlock(&dev->mutex); + return ret; } ssize_t vhost_chr_write_iter(struct vhost_dev *dev, -- GitLab From c5e1541ef6fe00b7f909e31851a5d6322997b331 Mon Sep 17 00:00:00 2001 From: Stephen Suryaputra Date: Fri, 1 Jun 2018 00:05:21 -0400 Subject: [PATCH 0130/1299] vrf: check the original netdevice for generating redirect [ Upstream commit 2f17becfbea5e9a0529b51da7345783e96e69516 ] Use the right device to determine if redirect should be sent especially when using vrf. Same as well as when sending the redirect. Signed-off-by: Stephen Suryaputra Acked-by: David Ahern Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_output.c | 3 ++- net/ipv6/ndisc.c | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 0f2d74885bcb..32fcce711855 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -506,7 +506,8 @@ int ip6_forward(struct sk_buff *skb) send redirects to source routed frames. We don't send redirects to frames decapsulated from IPsec. */ - if (skb->dev == dst->dev && opt->srcrt == 0 && !skb_sec_path(skb)) { + if (IP6CB(skb)->iif == dst->dev->ifindex && + opt->srcrt == 0 && !skb_sec_path(skb)) { struct in6_addr *target = NULL; struct inet_peer *peer; struct rt6_info *rt; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index dd28005efb97..d081db125905 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1568,6 +1568,12 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) ops_data_buf[NDISC_OPS_REDIRECT_DATA_SPACE], *ops_data = NULL; bool ret; + if (netif_is_l3_master(skb->dev)) { + dev = __dev_get_by_index(dev_net(skb->dev), IPCB(skb)->iif); + if (!dev) + return; + } + if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { ND_PRINTK(2, warn, "Redirect: no link-local address on %s\n", dev->name); -- GitLab From 8d80a839c1793f2237b91df59a5c46d4b02e7eda Mon Sep 17 00:00:00 2001 From: Mathieu Xhonneux Date: Fri, 25 May 2018 13:29:41 +0100 Subject: [PATCH 0131/1299] ipv6: sr: fix memory OOB access in seg6_do_srh_encap/inline [ Upstream commit bbb40a0b75209734ff9286f3326171638c9f6569 ] seg6_do_srh_encap and seg6_do_srh_inline can possibly do an out-of-bounds access when adding the SRH to the packet. This no longer happen when expanding the skb not only by the size of the SRH (+ outer IPv6 header), but also by skb->mac_len. [ 53.793056] BUG: KASAN: use-after-free in seg6_do_srh_encap+0x284/0x620 [ 53.794564] Write of size 14 at addr ffff88011975ecfa by task ping/674 [ 53.796665] CPU: 0 PID: 674 Comm: ping Not tainted 4.17.0-rc3-ARCH+ #90 [ 53.796670] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-20171110_100015-anatol 04/01/2014 [ 53.796673] Call Trace: [ 53.796679] [ 53.796689] dump_stack+0x71/0xab [ 53.796700] print_address_description+0x6a/0x270 [ 53.796707] kasan_report+0x258/0x380 [ 53.796715] ? seg6_do_srh_encap+0x284/0x620 [ 53.796722] memmove+0x34/0x50 [ 53.796730] seg6_do_srh_encap+0x284/0x620 [ 53.796741] ? seg6_do_srh+0x29b/0x360 [ 53.796747] seg6_do_srh+0x29b/0x360 [ 53.796756] seg6_input+0x2e/0x2e0 [ 53.796765] lwtunnel_input+0x93/0xd0 [ 53.796774] ipv6_rcv+0x690/0x920 [ 53.796783] ? ip6_input+0x170/0x170 [ 53.796791] ? eth_gro_receive+0x2d0/0x2d0 [ 53.796800] ? ip6_input+0x170/0x170 [ 53.796809] __netif_receive_skb_core+0xcc0/0x13f0 [ 53.796820] ? netdev_info+0x110/0x110 [ 53.796827] ? napi_complete_done+0xb6/0x170 [ 53.796834] ? e1000_clean+0x6da/0xf70 [ 53.796845] ? process_backlog+0x129/0x2a0 [ 53.796853] process_backlog+0x129/0x2a0 [ 53.796862] net_rx_action+0x211/0x5c0 [ 53.796870] ? napi_complete_done+0x170/0x170 [ 53.796887] ? run_rebalance_domains+0x11f/0x150 [ 53.796891] __do_softirq+0x10e/0x39e [ 53.796894] do_softirq_own_stack+0x2a/0x40 [ 53.796895] [ 53.796898] do_softirq.part.16+0x54/0x60 [ 53.796900] __local_bh_enable_ip+0x5b/0x60 [ 53.796903] ip6_finish_output2+0x416/0x9f0 [ 53.796906] ? ip6_dst_lookup_flow+0x110/0x110 [ 53.796909] ? ip6_sk_dst_lookup_flow+0x390/0x390 [ 53.796911] ? __rcu_read_unlock+0x66/0x80 [ 53.796913] ? ip6_mtu+0x44/0xf0 [ 53.796916] ? ip6_output+0xfc/0x220 [ 53.796918] ip6_output+0xfc/0x220 [ 53.796921] ? ip6_finish_output+0x2b0/0x2b0 [ 53.796923] ? memcpy+0x34/0x50 [ 53.796926] ip6_send_skb+0x43/0xc0 [ 53.796929] rawv6_sendmsg+0x1216/0x1530 [ 53.796932] ? __orc_find+0x6b/0xc0 [ 53.796934] ? rawv6_rcv_skb+0x160/0x160 [ 53.796937] ? __rcu_read_unlock+0x66/0x80 [ 53.796939] ? __rcu_read_unlock+0x66/0x80 [ 53.796942] ? is_bpf_text_address+0x1e/0x30 [ 53.796944] ? kernel_text_address+0xec/0x100 [ 53.796946] ? __kernel_text_address+0xe/0x30 [ 53.796948] ? unwind_get_return_address+0x2f/0x50 [ 53.796950] ? __save_stack_trace+0x92/0x100 [ 53.796954] ? save_stack+0x89/0xb0 [ 53.796956] ? kasan_kmalloc+0xa0/0xd0 [ 53.796958] ? kmem_cache_alloc+0xd2/0x1f0 [ 53.796961] ? prepare_creds+0x23/0x160 [ 53.796963] ? __x64_sys_capset+0x252/0x3e0 [ 53.796966] ? do_syscall_64+0x69/0x160 [ 53.796968] ? entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 53.796971] ? __alloc_pages_nodemask+0x170/0x380 [ 53.796973] ? __alloc_pages_slowpath+0x12c0/0x12c0 [ 53.796977] ? tty_vhangup+0x20/0x20 [ 53.796979] ? policy_nodemask+0x1a/0x90 [ 53.796982] ? __mod_node_page_state+0x8d/0xa0 [ 53.796986] ? __check_object_size+0xe7/0x240 [ 53.796989] ? __sys_sendto+0x229/0x290 [ 53.796991] ? rawv6_rcv_skb+0x160/0x160 [ 53.796993] __sys_sendto+0x229/0x290 [ 53.796996] ? __ia32_sys_getpeername+0x50/0x50 [ 53.796999] ? commit_creds+0x2de/0x520 [ 53.797002] ? security_capset+0x57/0x70 [ 53.797004] ? __x64_sys_capset+0x29f/0x3e0 [ 53.797007] ? __x64_sys_rt_sigsuspend+0xe0/0xe0 [ 53.797011] ? __do_page_fault+0x664/0x770 [ 53.797014] __x64_sys_sendto+0x74/0x90 [ 53.797017] do_syscall_64+0x69/0x160 [ 53.797019] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 53.797022] RIP: 0033:0x7f43b7a6714a [ 53.797023] RSP: 002b:00007ffd891bd368 EFLAGS: 00000246 ORIG_RAX: 000000000000002c [ 53.797026] RAX: ffffffffffffffda RBX: 00000000006129c0 RCX: 00007f43b7a6714a [ 53.797028] RDX: 0000000000000040 RSI: 00000000006129c0 RDI: 0000000000000004 [ 53.797029] RBP: 00007ffd891be640 R08: 0000000000610940 R09: 000000000000001c [ 53.797030] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000040 [ 53.797032] R13: 000000000060e6a0 R14: 0000000000008004 R15: 000000000040b661 [ 53.797171] Allocated by task 642: [ 53.797460] kasan_kmalloc+0xa0/0xd0 [ 53.797463] kmem_cache_alloc+0xd2/0x1f0 [ 53.797465] getname_flags+0x40/0x210 [ 53.797467] user_path_at_empty+0x1d/0x40 [ 53.797469] do_faccessat+0x12a/0x320 [ 53.797471] do_syscall_64+0x69/0x160 [ 53.797473] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 53.797607] Freed by task 642: [ 53.797869] __kasan_slab_free+0x130/0x180 [ 53.797871] kmem_cache_free+0xa8/0x230 [ 53.797872] filename_lookup+0x15b/0x230 [ 53.797874] do_faccessat+0x12a/0x320 [ 53.797876] do_syscall_64+0x69/0x160 [ 53.797878] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 53.798014] The buggy address belongs to the object at ffff88011975e600 which belongs to the cache names_cache of size 4096 [ 53.799043] The buggy address is located 1786 bytes inside of 4096-byte region [ffff88011975e600, ffff88011975f600) [ 53.800013] The buggy address belongs to the page: [ 53.800414] page:ffffea000465d600 count:1 mapcount:0 mapping:0000000000000000 index:0x0 compound_mapcount: 0 [ 53.801259] flags: 0x17fff0000008100(slab|head) [ 53.801640] raw: 017fff0000008100 0000000000000000 0000000000000000 0000000100070007 [ 53.803147] raw: dead000000000100 dead000000000200 ffff88011b185a40 0000000000000000 [ 53.803787] page dumped because: kasan: bad access detected [ 53.804384] Memory state around the buggy address: [ 53.804788] ffff88011975eb80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 53.805384] ffff88011975ec00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 53.805979] >ffff88011975ec80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 53.806577] ^ [ 53.807165] ffff88011975ed00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 53.807762] ffff88011975ed80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 53.808356] ================================================================== [ 53.808949] Disabling lock debugging due to kernel taint Fixes: 6c8702c60b88 ("ipv6: sr: add support for SRH encapsulation and injection with lwtunnels") Signed-off-by: David Lebrun Signed-off-by: Mathieu Xhonneux Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/seg6_iptunnel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c index 5fe139484919..bf4763fd68c2 100644 --- a/net/ipv6/seg6_iptunnel.c +++ b/net/ipv6/seg6_iptunnel.c @@ -103,7 +103,7 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) hdrlen = (osrh->hdrlen + 1) << 3; tot_len = hdrlen + sizeof(*hdr); - err = skb_cow_head(skb, tot_len); + err = skb_cow_head(skb, tot_len + skb->mac_len); if (unlikely(err)) return err; @@ -161,7 +161,7 @@ int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh) hdrlen = (osrh->hdrlen + 1) << 3; - err = skb_cow_head(skb, hdrlen); + err = skb_cow_head(skb, hdrlen + skb->mac_len); if (unlikely(err)) return err; -- GitLab From 900679988fdf24d687c746e909b10e47e442ad05 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 22 May 2018 16:22:26 -0700 Subject: [PATCH 0132/1299] net: phy: broadcom: Fix auxiliary control register reads [ Upstream commit 733a969a7ed14fc5786bcc59c1bdda83c7ddb46e ] We are currently doing auxiliary control register reads with the shadow register value 0b111 (0x7) which incidentally is also the selector value that should be present in bits [2:0]. Fix this by using the appropriate selector mask which is defined (MII_BCM54XX_AUXCTL_SHDWSEL_MASK). This does not have a functional impact yet because we always access the MII_BCM54XX_AUXCTL_SHDWSEL_MISC (0x7) register in the current code. This might change at some point though. Fixes: 5b4e29005123 ("net: phy: broadcom: add bcm54xx_auxctl_read") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/phy/bcm-phy-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c index 171010eb4d9c..8d96c6f048d0 100644 --- a/drivers/net/phy/bcm-phy-lib.c +++ b/drivers/net/phy/bcm-phy-lib.c @@ -56,7 +56,7 @@ int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum) /* The register must be written to both the Shadow Register Select and * the Shadow Read Register Selector */ - phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | + phy_write(phydev, MII_BCM54XX_AUX_CTL, MII_BCM54XX_AUXCTL_SHDWSEL_MASK | regnum << MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT); return phy_read(phydev, MII_BCM54XX_AUX_CTL); } -- GitLab From 0dbd822f64401cbdef40e9e476e89f67c690be64 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 31 May 2018 15:59:46 -0400 Subject: [PATCH 0133/1299] net-sysfs: Fix memory leak in XPS configuration [ Upstream commit 664088f8d68178809b848ca450f2797efb34e8e7 ] This patch reorders the error cases in showing the XPS configuration so that we hold off on memory allocation until after we have verified that we can support XPS on a given ring. Fixes: 184c449f91fe ("net: Add support for XPS with QoS via traffic classes") Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/net-sysfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 927a6dcbad96..8f17724a173c 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1207,9 +1207,6 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue, cpumask_var_t mask; unsigned long index; - if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) - return -ENOMEM; - index = get_netdev_queue_index(queue); if (dev->num_tc) { @@ -1219,6 +1216,9 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue, return -EINVAL; } + if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) + return -ENOMEM; + rcu_read_lock(); dev_maps = rcu_dereference(dev->xps_maps); if (dev_maps) { -- GitLab From 31c1e078e3caa5812240e6f9b93ffc43eff3c717 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 22 May 2018 11:44:29 +0800 Subject: [PATCH 0134/1299] virtio-net: correctly transmit XDP buff after linearizing [ Upstream commit 5d458a13dd59d04b4d6658a6d5b94d42732b15ae ] We should not go for the error path after successfully transmitting a XDP buffer after linearizing. Since the error path may try to pop and drop next packet and increase the drop counters. Fixing this by simply drop the refcnt of original page and go for xmit path. Fixes: 72979a6c3590 ("virtio_net: xdp, add slowpath case for non contiguous buffers") Cc: John Fastabend Acked-by: Michael S. Tsirkin Signed-off-by: Jason Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/virtio_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 948611317c97..925d15ea35cb 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -688,7 +688,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, trace_xdp_exception(vi->dev, xdp_prog, act); ewma_pkt_len_add(&rq->mrg_avg_pkt_len, len); if (unlikely(xdp_page != page)) - goto err_xdp; + put_page(page); rcu_read_unlock(); goto xdp_xmit; default: -- GitLab From 43153f09016530e35836878183fea73e4d9b2f4e Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Wed, 23 May 2018 10:41:59 +0300 Subject: [PATCH 0135/1299] net/mlx4: Fix irq-unsafe spinlock usage [ Upstream commit d546b67cda015fb92bfee93d5dc0ceadb91deaee ] spin_lock/unlock was used instead of spin_un/lock_irq in a procedure used in process space, on a spinlock which can be grabbed in an interrupt. This caused the stack trace below to be displayed (on kernel 4.17.0-rc1 compiled with Lock Debugging enabled): [ 154.661474] WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected [ 154.668909] 4.17.0-rc1-rdma_rc_mlx+ #3 Tainted: G I [ 154.675856] ----------------------------------------------------- [ 154.682706] modprobe/10159 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: [ 154.690254] 00000000f3b0e495 (&(&qp_table->lock)->rlock){+.+.}, at: mlx4_qp_remove+0x20/0x50 [mlx4_core] [ 154.700927] and this task is already holding: [ 154.707461] 0000000094373b5d (&(&cq->lock)->rlock/1){....}, at: destroy_qp_common+0x111/0x560 [mlx4_ib] [ 154.718028] which would create a new lock dependency: [ 154.723705] (&(&cq->lock)->rlock/1){....} -> (&(&qp_table->lock)->rlock){+.+.} [ 154.731922] but this new dependency connects a SOFTIRQ-irq-safe lock: [ 154.740798] (&(&cq->lock)->rlock){..-.} [ 154.740800] ... which became SOFTIRQ-irq-safe at: [ 154.752163] _raw_spin_lock_irqsave+0x3e/0x50 [ 154.757163] mlx4_ib_poll_cq+0x36/0x900 [mlx4_ib] [ 154.762554] ipoib_tx_poll+0x4a/0xf0 [ib_ipoib] ... to a SOFTIRQ-irq-unsafe lock: [ 154.815603] (&(&qp_table->lock)->rlock){+.+.} [ 154.815604] ... which became SOFTIRQ-irq-unsafe at: [ 154.827718] ... [ 154.827720] _raw_spin_lock+0x35/0x50 [ 154.833912] mlx4_qp_lookup+0x1e/0x50 [mlx4_core] [ 154.839302] mlx4_flow_attach+0x3f/0x3d0 [mlx4_core] Since mlx4_qp_lookup() is called only in process space, we can simply replace the spin_un/lock calls with spin_un/lock_irq calls. Fixes: 6dc06c08bef1 ("net/mlx4: Fix the check in attaching steering rules") Signed-off-by: Jack Morgenstein Signed-off-by: Tariq Toukan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/mellanox/mlx4/qp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 22a3bfe1ed8f..73419224367a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -393,11 +393,11 @@ struct mlx4_qp *mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn) struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; struct mlx4_qp *qp; - spin_lock(&qp_table->lock); + spin_lock_irq(&qp_table->lock); qp = __mlx4_qp_lookup(dev, qpn); - spin_unlock(&qp_table->lock); + spin_unlock_irq(&qp_table->lock); return qp; } -- GitLab From e2d47fa107f98e131b2025aed208c4c9ed9549b9 Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Mon, 28 May 2018 19:37:49 +0900 Subject: [PATCH 0136/1299] tun: Fix NULL pointer dereference in XDP redirect [ Upstream commit 6547e387d7f52f2ba681a229de3c13e5b9e01ee1 ] Calling XDP redirection requires bh disabled. Softirq can call another XDP function and redirection functions, then the percpu static variable ri->map can be overwritten to NULL. This is a generic XDP case called from tun. [ 3535.736058] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 [ 3535.743974] PGD 0 P4D 0 [ 3535.746530] Oops: 0000 [#1] SMP PTI [ 3535.750049] Modules linked in: vhost_net vhost tap tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter sunrpc vfat fat ext4 mbcache jbd2 intel_rapl skx_edac nfit libnvdimm x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm ipmi_ssif irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcbc ses aesni_intel crypto_simd cryptd enclosure hpwdt hpilo glue_helper ipmi_si pcspkr wmi mei_me ioatdma mei ipmi_devintf shpchp dca ipmi_msghandler lpc_ich acpi_power_meter sch_fq_codel ip_tables xfs libcrc32c sd_mod mgag200 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm smartpqi i40e crc32c_intel scsi_transport_sas tg3 i2c_core ptp pps_core [ 3535.813456] CPU: 5 PID: 1630 Comm: vhost-1614 Not tainted 4.17.0-rc4 #2 [ 3535.820127] Hardware name: HPE ProLiant DL360 Gen10/ProLiant DL360 Gen10, BIOS U32 11/14/2017 [ 3535.828732] RIP: 0010:__xdp_map_lookup_elem+0x5/0x30 [ 3535.833740] RSP: 0018:ffffb4bc47bf7c58 EFLAGS: 00010246 [ 3535.839009] RAX: ffff9fdfcfea1c40 RBX: 0000000000000000 RCX: ffff9fdf27fe3100 [ 3535.846205] RDX: ffff9fdfca769200 RSI: 0000000000000000 RDI: 0000000000000000 [ 3535.853402] RBP: ffffb4bc491d9000 R08: 00000000000045ad R09: 0000000000000ec0 [ 3535.860597] R10: 0000000000000001 R11: ffff9fdf26c3ce4e R12: ffff9fdf9e72c000 [ 3535.867794] R13: 0000000000000000 R14: fffffffffffffff2 R15: ffff9fdfc82cdd00 [ 3535.874990] FS: 0000000000000000(0000) GS:ffff9fdfcfe80000(0000) knlGS:0000000000000000 [ 3535.883152] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 3535.888948] CR2: 0000000000000018 CR3: 0000000bde724004 CR4: 00000000007626e0 [ 3535.896145] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 3535.903342] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 3535.910538] PKRU: 55555554 [ 3535.913267] Call Trace: [ 3535.915736] xdp_do_generic_redirect+0x7a/0x310 [ 3535.920310] do_xdp_generic.part.117+0x285/0x370 [ 3535.924970] tun_get_user+0x5b9/0x1260 [tun] [ 3535.929279] tun_sendmsg+0x52/0x70 [tun] [ 3535.933237] handle_tx+0x2ad/0x5f0 [vhost_net] [ 3535.937721] vhost_worker+0xa5/0x100 [vhost] [ 3535.942030] kthread+0xf5/0x130 [ 3535.945198] ? vhost_dev_ioctl+0x3b0/0x3b0 [vhost] [ 3535.950031] ? kthread_bind+0x10/0x10 [ 3535.953727] ret_from_fork+0x35/0x40 [ 3535.957334] Code: 0e 74 15 83 f8 10 75 05 e9 49 aa b3 ff f3 c3 0f 1f 80 00 00 00 00 f3 c3 e9 29 9d b3 ff 66 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 <8b> 47 18 83 f8 0e 74 0d 83 f8 10 75 05 e9 49 a9 b3 ff 31 c0 c3 [ 3535.976387] RIP: __xdp_map_lookup_elem+0x5/0x30 RSP: ffffb4bc47bf7c58 [ 3535.982883] CR2: 0000000000000018 [ 3535.987096] ---[ end trace 383b299dd1430240 ]--- [ 3536.131325] Kernel panic - not syncing: Fatal exception [ 3536.137484] Kernel Offset: 0x26a00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) [ 3536.281406] ---[ end Kernel panic - not syncing: Fatal exception ]--- And a kernel with generic case fixed still panics in tun driver XDP redirect, because it disabled only preemption, but not bh. [ 2055.128746] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 [ 2055.136662] PGD 0 P4D 0 [ 2055.139219] Oops: 0000 [#1] SMP PTI [ 2055.142736] Modules linked in: vhost_net vhost tap tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter sunrpc vfat fat ext4 mbcache jbd2 intel_rapl skx_edac nfit libnvdimm x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcbc ses aesni_intel ipmi_ssif crypto_simd enclosure cryptd hpwdt glue_helper ioatdma hpilo wmi dca pcspkr ipmi_si acpi_power_meter ipmi_devintf shpchp mei_me ipmi_msghandler mei lpc_ich sch_fq_codel ip_tables xfs libcrc32c sd_mod mgag200 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm i40e smartpqi tg3 scsi_transport_sas crc32c_intel i2c_core ptp pps_core [ 2055.206142] CPU: 6 PID: 1693 Comm: vhost-1683 Tainted: G W 4.17.0-rc5-fix-tun+ #1 [ 2055.215011] Hardware name: HPE ProLiant DL360 Gen10/ProLiant DL360 Gen10, BIOS U32 11/14/2017 [ 2055.223617] RIP: 0010:__xdp_map_lookup_elem+0x5/0x30 [ 2055.228624] RSP: 0018:ffff998b07607cc0 EFLAGS: 00010246 [ 2055.233892] RAX: ffff8dbd8e235700 RBX: ffff8dbd8ff21c40 RCX: 0000000000000004 [ 2055.241089] RDX: ffff998b097a9000 RSI: 0000000000000000 RDI: 0000000000000000 [ 2055.248286] RBP: 0000000000000000 R08: 00000000000065a8 R09: 0000000000005d80 [ 2055.255483] R10: 0000000000000040 R11: ffff8dbcf0100000 R12: ffff998b097a9000 [ 2055.262681] R13: ffff8dbd8c98c000 R14: 0000000000000000 R15: ffff998b07607d78 [ 2055.269879] FS: 0000000000000000(0000) GS:ffff8dbd8ff00000(0000) knlGS:0000000000000000 [ 2055.278039] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2055.283834] CR2: 0000000000000018 CR3: 0000000c0c8cc005 CR4: 00000000007626e0 [ 2055.291030] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 2055.298227] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 2055.305424] PKRU: 55555554 [ 2055.308153] Call Trace: [ 2055.310624] xdp_do_redirect+0x7b/0x380 [ 2055.314499] tun_get_user+0x10fe/0x12a0 [tun] [ 2055.318895] tun_sendmsg+0x52/0x70 [tun] [ 2055.322852] handle_tx+0x2ad/0x5f0 [vhost_net] [ 2055.327337] vhost_worker+0xa5/0x100 [vhost] [ 2055.331646] kthread+0xf5/0x130 [ 2055.334813] ? vhost_dev_ioctl+0x3b0/0x3b0 [vhost] [ 2055.339646] ? kthread_bind+0x10/0x10 [ 2055.343343] ret_from_fork+0x35/0x40 [ 2055.346950] Code: 0e 74 15 83 f8 10 75 05 e9 e9 aa b3 ff f3 c3 0f 1f 80 00 00 00 00 f3 c3 e9 c9 9d b3 ff 66 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 <8b> 47 18 83 f8 0e 74 0d 83 f8 10 75 05 e9 e9 a9 b3 ff 31 c0 c3 [ 2055.366004] RIP: __xdp_map_lookup_elem+0x5/0x30 RSP: ffff998b07607cc0 [ 2055.372500] CR2: 0000000000000018 [ 2055.375856] ---[ end trace 2a2dcc5e9e174268 ]--- [ 2055.523626] Kernel panic - not syncing: Fatal exception [ 2055.529796] Kernel Offset: 0x2e000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) [ 2055.677539] ---[ end Kernel panic - not syncing: Fatal exception ]--- v2: - Removed preempt_disable/enable since local_bh_disable will prevent preemption as well, feedback from Jason Wang. Fixes: 761876c857cb ("tap: XDP support") Signed-off-by: Toshiaki Makita Acked-by: Jason Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/tun.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index bc38d54e37b9..3d9ad11e4f28 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1315,7 +1315,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, else *skb_xdp = 0; - preempt_disable(); + local_bh_disable(); rcu_read_lock(); xdp_prog = rcu_dereference(tun->xdp_prog); if (xdp_prog && !*skb_xdp) { @@ -1338,7 +1338,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, if (err) goto err_redirect; rcu_read_unlock(); - preempt_enable(); + local_bh_enable(); return NULL; case XDP_TX: xdp_xmit = true; @@ -1360,7 +1360,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, skb = build_skb(buf, buflen); if (!skb) { rcu_read_unlock(); - preempt_enable(); + local_bh_enable(); return ERR_PTR(-ENOMEM); } @@ -1373,12 +1373,12 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, skb->dev = tun->dev; generic_xdp_tx(skb, xdp_prog); rcu_read_unlock(); - preempt_enable(); + local_bh_enable(); return NULL; } rcu_read_unlock(); - preempt_enable(); + local_bh_enable(); return skb; @@ -1386,7 +1386,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, put_page(alloc_frag->page); err_xdp: rcu_read_unlock(); - preempt_enable(); + local_bh_enable(); this_cpu_inc(tun->pcpu_stats->rx_dropped); return NULL; } @@ -1556,16 +1556,19 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, struct bpf_prog *xdp_prog; int ret; + local_bh_disable(); rcu_read_lock(); xdp_prog = rcu_dereference(tun->xdp_prog); if (xdp_prog) { ret = do_xdp_generic(xdp_prog, skb); if (ret != XDP_PASS) { rcu_read_unlock(); + local_bh_enable(); return total_len; } } rcu_read_unlock(); + local_bh_enable(); } rxhash = __skb_get_hash_symmetric(skb); -- GitLab From 155cd575588bca1ef1dd77e37386a737f4c0153e Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 22 May 2018 11:44:30 +0800 Subject: [PATCH 0137/1299] virtio-net: correctly check num_buf during err path [ Upstream commit 850e088d5bbb333342fd4def08d0a4035f2b7126 ] If we successfully linearize the packet, num_buf will be set to zero which may confuse error handling path which assumes num_buf is at least 1 and this can lead the code tries to pop the descriptor of next buffer. Fixing this by checking num_buf against 1 before decreasing. Fixes: 4941d472bf95 ("virtio-net: do not reset during XDP set") Signed-off-by: Jason Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/virtio_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 925d15ea35cb..c5a1d221c49b 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -777,7 +777,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, rcu_read_unlock(); err_skb: put_page(page); - while (--num_buf) { + while (num_buf-- > 1) { buf = virtqueue_get_buf(rq->vq, &len); if (unlikely(!buf)) { pr_debug("%s: rx error: %d buffers missing\n", -- GitLab From 2b8b2b26c378398d003a8833fe9177af9247cfef Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Tue, 1 May 2018 16:25:07 +0300 Subject: [PATCH 0138/1299] net/mlx5e: When RXFCS is set, add FCS data into checksum calculation [ Upstream commit 902a545904c71d719ed144234d67df75f31db63b ] When RXFCS feature is enabled, the HW do not strip the FCS data, however it is not present in the checksum calculated by the HW. Fix that by manually calculating the FCS checksum and adding it to the SKB checksum field. Add helper function to find the FCS data for all SKB forms (linear, one fragment or more). Fixes: 102722fc6832 ("net/mlx5e: Add support for RXFCS feature flag") Signed-off-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed Signed-off-by: Greg Kroah-Hartman --- .../net/ethernet/mellanox/mlx5/core/en_rx.c | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 3476f594c195..8285e6d24f30 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -635,6 +635,45 @@ static inline bool is_first_ethertype_ip(struct sk_buff *skb) return (ethertype == htons(ETH_P_IP) || ethertype == htons(ETH_P_IPV6)); } +static __be32 mlx5e_get_fcs(struct sk_buff *skb) +{ + int last_frag_sz, bytes_in_prev, nr_frags; + u8 *fcs_p1, *fcs_p2; + skb_frag_t *last_frag; + __be32 fcs_bytes; + + if (!skb_is_nonlinear(skb)) + return *(__be32 *)(skb->data + skb->len - ETH_FCS_LEN); + + nr_frags = skb_shinfo(skb)->nr_frags; + last_frag = &skb_shinfo(skb)->frags[nr_frags - 1]; + last_frag_sz = skb_frag_size(last_frag); + + /* If all FCS data is in last frag */ + if (last_frag_sz >= ETH_FCS_LEN) + return *(__be32 *)(skb_frag_address(last_frag) + + last_frag_sz - ETH_FCS_LEN); + + fcs_p2 = (u8 *)skb_frag_address(last_frag); + bytes_in_prev = ETH_FCS_LEN - last_frag_sz; + + /* Find where the other part of the FCS is - Linear or another frag */ + if (nr_frags == 1) { + fcs_p1 = skb_tail_pointer(skb); + } else { + skb_frag_t *prev_frag = &skb_shinfo(skb)->frags[nr_frags - 2]; + + fcs_p1 = skb_frag_address(prev_frag) + + skb_frag_size(prev_frag); + } + fcs_p1 -= bytes_in_prev; + + memcpy(&fcs_bytes, fcs_p1, bytes_in_prev); + memcpy(((u8 *)&fcs_bytes) + bytes_in_prev, fcs_p2, last_frag_sz); + + return fcs_bytes; +} + static inline void mlx5e_handle_csum(struct net_device *netdev, struct mlx5_cqe64 *cqe, struct mlx5e_rq *rq, @@ -653,6 +692,9 @@ static inline void mlx5e_handle_csum(struct net_device *netdev, if (is_first_ethertype_ip(skb)) { skb->ip_summed = CHECKSUM_COMPLETE; skb->csum = csum_unfold((__force __sum16)cqe->check_sum); + if (unlikely(netdev->features & NETIF_F_RXFCS)) + skb->csum = csum_add(skb->csum, + (__force __wsum)mlx5e_get_fcs(skb)); rq->stats.csum_complete++; return; } -- GitLab From fa11d992533bd4e33e13d8857e6e4d35f0546d12 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 22 May 2018 11:44:31 +0800 Subject: [PATCH 0139/1299] virtio-net: fix leaking page for gso packet during mergeable XDP [ Upstream commit 3d62b2a0db505bbf9ed0755f254e45d775f9807f ] We need to drop refcnt to xdp_page if we see a gso packet. Otherwise it will be leaked. Fixing this by moving the check of gso packet above the linearizing logic. While at it, remove useless comment as well. Cc: John Fastabend Fixes: 72979a6c3590 ("virtio_net: xdp, add slowpath case for non contiguous buffers") Signed-off-by: Jason Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/virtio_net.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c5a1d221c49b..9e93e7a5df7e 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -632,6 +632,13 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, void *data; u32 act; + /* Transient failure which in theory could occur if + * in-flight packets from before XDP was enabled reach + * the receive path after XDP is loaded. + */ + if (unlikely(hdr->hdr.gso_type)) + goto err_xdp; + /* This happens when rx buffer size is underestimated */ if (unlikely(num_buf > 1 || headroom < virtnet_get_headroom(vi))) { @@ -647,14 +654,6 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, xdp_page = page; } - /* Transient failure which in theory could occur if - * in-flight packets from before XDP was enabled reach - * the receive path after XDP is loaded. In practice I - * was not able to create this condition. - */ - if (unlikely(hdr->hdr.gso_type)) - goto err_xdp; - /* Allow consuming headroom but reserve enough space to push * the descriptor on if we get an XDP_TX return code. */ -- GitLab From c931c9aee2f36f6b7e52b5ba5e35b033d7e0233b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 5 Jun 2018 09:25:19 -0700 Subject: [PATCH 0140/1299] rtnetlink: validate attributes in do_setlink() [ Upstream commit 644c7eebbfd59e72982d11ec6cc7d39af12450ae ] It seems that rtnl_group_changelink() can call do_setlink while a prior call to validate_linkmsg(dev = NULL, ...) could not validate IFLA_ADDRESS / IFLA_BROADCAST Make sure do_setlink() calls validate_linkmsg() instead of letting its callers having this responsibility. With help from Dmitry Vyukov, thanks a lot ! BUG: KMSAN: uninit-value in is_valid_ether_addr include/linux/etherdevice.h:199 [inline] BUG: KMSAN: uninit-value in eth_prepare_mac_addr_change net/ethernet/eth.c:275 [inline] BUG: KMSAN: uninit-value in eth_mac_addr+0x203/0x2b0 net/ethernet/eth.c:308 CPU: 1 PID: 8695 Comm: syz-executor3 Not tainted 4.17.0-rc5+ #103 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x185/0x1d0 lib/dump_stack.c:113 kmsan_report+0x149/0x260 mm/kmsan/kmsan.c:1084 __msan_warning_32+0x6e/0xc0 mm/kmsan/kmsan_instr.c:686 is_valid_ether_addr include/linux/etherdevice.h:199 [inline] eth_prepare_mac_addr_change net/ethernet/eth.c:275 [inline] eth_mac_addr+0x203/0x2b0 net/ethernet/eth.c:308 dev_set_mac_address+0x261/0x530 net/core/dev.c:7157 do_setlink+0xbc3/0x5fc0 net/core/rtnetlink.c:2317 rtnl_group_changelink net/core/rtnetlink.c:2824 [inline] rtnl_newlink+0x1fe9/0x37a0 net/core/rtnetlink.c:2976 rtnetlink_rcv_msg+0xa32/0x1560 net/core/rtnetlink.c:4646 netlink_rcv_skb+0x378/0x600 net/netlink/af_netlink.c:2448 rtnetlink_rcv+0x50/0x60 net/core/rtnetlink.c:4664 netlink_unicast_kernel net/netlink/af_netlink.c:1310 [inline] netlink_unicast+0x1678/0x1750 net/netlink/af_netlink.c:1336 netlink_sendmsg+0x104f/0x1350 net/netlink/af_netlink.c:1901 sock_sendmsg_nosec net/socket.c:629 [inline] sock_sendmsg net/socket.c:639 [inline] ___sys_sendmsg+0xec0/0x1310 net/socket.c:2117 __sys_sendmsg net/socket.c:2155 [inline] __do_sys_sendmsg net/socket.c:2164 [inline] __se_sys_sendmsg net/socket.c:2162 [inline] __x64_sys_sendmsg+0x331/0x460 net/socket.c:2162 do_syscall_64+0x152/0x230 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x455a09 RSP: 002b:00007fc07480ec68 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00007fc07480f6d4 RCX: 0000000000455a09 RDX: 0000000000000000 RSI: 00000000200003c0 RDI: 0000000000000014 RBP: 000000000072bea0 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff R13: 00000000000005d0 R14: 00000000006fdc20 R15: 0000000000000000 Uninit was stored to memory at: kmsan_save_stack_with_flags mm/kmsan/kmsan.c:279 [inline] kmsan_save_stack mm/kmsan/kmsan.c:294 [inline] kmsan_internal_chain_origin+0x12b/0x210 mm/kmsan/kmsan.c:685 kmsan_memcpy_origins+0x11d/0x170 mm/kmsan/kmsan.c:527 __msan_memcpy+0x109/0x160 mm/kmsan/kmsan_instr.c:478 do_setlink+0xb84/0x5fc0 net/core/rtnetlink.c:2315 rtnl_group_changelink net/core/rtnetlink.c:2824 [inline] rtnl_newlink+0x1fe9/0x37a0 net/core/rtnetlink.c:2976 rtnetlink_rcv_msg+0xa32/0x1560 net/core/rtnetlink.c:4646 netlink_rcv_skb+0x378/0x600 net/netlink/af_netlink.c:2448 rtnetlink_rcv+0x50/0x60 net/core/rtnetlink.c:4664 netlink_unicast_kernel net/netlink/af_netlink.c:1310 [inline] netlink_unicast+0x1678/0x1750 net/netlink/af_netlink.c:1336 netlink_sendmsg+0x104f/0x1350 net/netlink/af_netlink.c:1901 sock_sendmsg_nosec net/socket.c:629 [inline] sock_sendmsg net/socket.c:639 [inline] ___sys_sendmsg+0xec0/0x1310 net/socket.c:2117 __sys_sendmsg net/socket.c:2155 [inline] __do_sys_sendmsg net/socket.c:2164 [inline] __se_sys_sendmsg net/socket.c:2162 [inline] __x64_sys_sendmsg+0x331/0x460 net/socket.c:2162 do_syscall_64+0x152/0x230 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Uninit was created at: kmsan_save_stack_with_flags mm/kmsan/kmsan.c:279 [inline] kmsan_internal_poison_shadow+0xb8/0x1b0 mm/kmsan/kmsan.c:189 kmsan_kmalloc+0x94/0x100 mm/kmsan/kmsan.c:315 kmsan_slab_alloc+0x10/0x20 mm/kmsan/kmsan.c:322 slab_post_alloc_hook mm/slab.h:446 [inline] slab_alloc_node mm/slub.c:2753 [inline] __kmalloc_node_track_caller+0xb32/0x11b0 mm/slub.c:4395 __kmalloc_reserve net/core/skbuff.c:138 [inline] __alloc_skb+0x2cb/0x9e0 net/core/skbuff.c:206 alloc_skb include/linux/skbuff.h:988 [inline] netlink_alloc_large_skb net/netlink/af_netlink.c:1182 [inline] netlink_sendmsg+0x76e/0x1350 net/netlink/af_netlink.c:1876 sock_sendmsg_nosec net/socket.c:629 [inline] sock_sendmsg net/socket.c:639 [inline] ___sys_sendmsg+0xec0/0x1310 net/socket.c:2117 __sys_sendmsg net/socket.c:2155 [inline] __do_sys_sendmsg net/socket.c:2164 [inline] __se_sys_sendmsg net/socket.c:2162 [inline] __x64_sys_sendmsg+0x331/0x460 net/socket.c:2162 do_syscall_64+0x152/0x230 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: e7ed828f10bd ("netlink: support setting devgroup parameters") Signed-off-by: Eric Dumazet Reported-by: syzbot Cc: Dmitry Vyukov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/rtnetlink.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 5ace48926b19..4cfdad08aca0 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1958,6 +1958,10 @@ static int do_setlink(const struct sk_buff *skb, const struct net_device_ops *ops = dev->netdev_ops; int err; + err = validate_linkmsg(dev, tb); + if (err < 0) + return err; + if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) { struct net *net = rtnl_link_get_net(dev_net(dev), tb); if (IS_ERR(net)) { @@ -2296,10 +2300,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, goto errout; } - err = validate_linkmsg(dev, tb); - if (err < 0) - goto errout; - err = do_setlink(skb, dev, ifm, extack, tb, ifname, 0); errout: return err; -- GitLab From dd4be396b8c5d926775f664a6b2aad0509fa6cc3 Mon Sep 17 00:00:00 2001 From: Paul Blakey Date: Wed, 30 May 2018 11:29:15 +0300 Subject: [PATCH 0141/1299] cls_flower: Fix incorrect idr release when failing to modify rule [ Upstream commit 8258d2da9f9f521dce7019e018360c28d116354e ] When we fail to modify a rule, we incorrectly release the idr handle of the unmodified old rule. Fix that by checking if we need to release it. Fixes: fe2502e49b58 ("net_sched: remove cls_flower idr on failure") Reported-by: Vlad Buslov Reviewed-by: Roi Dayan Acked-by: Jiri Pirko Signed-off-by: Paul Blakey Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/cls_flower.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 7a838d1c1c00..1879665e5a2b 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -1007,7 +1007,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, return 0; errout_idr: - if (fnew->handle) + if (!fold) idr_remove_ext(&head->handle_idr, fnew->handle); errout: tcf_exts_destroy(&fnew->exts); -- GitLab From 3fe4b0cf93833af2ef497784bdfb2a4eecaabb6e Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Wed, 23 May 2018 21:12:01 +0000 Subject: [PATCH 0142/1299] PCI: hv: Do not wait forever on a device that has disappeared commit c3635da2a336441253c33298b87b3042db100725 upstream. Before the guest finishes the device initialization, the device can be removed anytime by the host, and after that the host won't respond to the guest's request, so the guest should be prepared to handle this case. Add a polling mechanism to detect device presence. Signed-off-by: Dexuan Cui [lorenzo.pieralisi@arm.com: edited commit log] Signed-off-by: Lorenzo Pieralisi Reviewed-by: Haiyang Zhang Cc: Stephen Hemminger Cc: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/pci/host/pci-hyperv.c | 46 ++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index c91662927de0..0b750228ad70 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c @@ -566,6 +566,26 @@ static void put_pcichild(struct hv_pci_dev *hv_pcidev, static void get_hvpcibus(struct hv_pcibus_device *hv_pcibus); static void put_hvpcibus(struct hv_pcibus_device *hv_pcibus); +/* + * There is no good way to get notified from vmbus_onoffer_rescind(), + * so let's use polling here, since this is not a hot path. + */ +static int wait_for_response(struct hv_device *hdev, + struct completion *comp) +{ + while (true) { + if (hdev->channel->rescind) { + dev_warn_once(&hdev->device, "The device is gone.\n"); + return -ENODEV; + } + + if (wait_for_completion_timeout(comp, HZ / 10)) + break; + } + + return 0; +} + /** * devfn_to_wslot() - Convert from Linux PCI slot to Windows * @devfn: The Linux representation of PCI slot @@ -1582,7 +1602,8 @@ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus, if (ret) goto error; - wait_for_completion(&comp_pkt.host_event); + if (wait_for_response(hbus->hdev, &comp_pkt.host_event)) + goto error; hpdev->desc = *desc; refcount_set(&hpdev->refs, 1); @@ -2075,15 +2096,16 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev) sizeof(struct pci_version_request), (unsigned long)pkt, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (!ret) + ret = wait_for_response(hdev, &comp_pkt.host_event); + if (ret) { dev_err(&hdev->device, - "PCI Pass-through VSP failed sending version reqquest: %#x", + "PCI Pass-through VSP failed to request version: %d", ret); goto exit; } - wait_for_completion(&comp_pkt.host_event); - if (comp_pkt.completion_status >= 0) { pci_protocol_version = pci_protocol_versions[i]; dev_info(&hdev->device, @@ -2292,11 +2314,12 @@ static int hv_pci_enter_d0(struct hv_device *hdev) ret = vmbus_sendpacket(hdev->channel, d0_entry, sizeof(*d0_entry), (unsigned long)pkt, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (!ret) + ret = wait_for_response(hdev, &comp_pkt.host_event); + if (ret) goto exit; - wait_for_completion(&comp_pkt.host_event); - if (comp_pkt.completion_status < 0) { dev_err(&hdev->device, "PCI Pass-through VSP failed D0 Entry with status %x\n", @@ -2336,11 +2359,10 @@ static int hv_pci_query_relations(struct hv_device *hdev) ret = vmbus_sendpacket(hdev->channel, &message, sizeof(message), 0, VM_PKT_DATA_INBAND, 0); - if (ret) - return ret; + if (!ret) + ret = wait_for_response(hdev, &comp); - wait_for_completion(&comp); - return 0; + return ret; } /** @@ -2410,11 +2432,11 @@ static int hv_send_resources_allocated(struct hv_device *hdev) size_res, (unsigned long)pkt, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (!ret) + ret = wait_for_response(hdev, &comp_pkt.host_event); if (ret) break; - wait_for_completion(&comp_pkt.host_event); - if (comp_pkt.completion_status < 0) { ret = -EPROTO; dev_err(&hdev->device, -- GitLab From 2abd4c3ed20df4609c28cefa4df36b3dad9dfed7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 15 May 2018 13:38:15 +1000 Subject: [PATCH 0143/1299] drm: set FMODE_UNSIGNED_OFFSET for drm files commit 76ef6b28ea4f81c3d511866a9b31392caa833126 upstream. Since we have the ttm and gem vma managers using a subset of the file address space for objects, and these start at 0x100000000 they will overflow the new mmap checks. I've checked all the mmap routines I could see for any bad behaviour but overall most people use GEM/TTM VMA managers even the legacy drivers have a hashtable. Reported-and-Tested-by: Arthur Marsh (amarsh04 on #radeon) Fixes: be83bbf8068 (mmap: introduce sane default mmap limits) Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index b3c6e997ccdb..03244b3c985d 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -212,6 +212,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) return -ENOMEM; filp->private_data = priv; + filp->f_mode |= FMODE_UNSIGNED_OFFSET; priv->filp = filp; priv->pid = get_pid(task_pid(current)); priv->minor = minor; -- GitLab From 70d7bbd9b504c1dde0dc44a469a513695d9cbdd6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Jun 2018 22:49:22 +0200 Subject: [PATCH 0144/1299] Linux 4.14.49 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7a246f1ce44e..480ae7ef755c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 48 +SUBLEVEL = 49 EXTRAVERSION = NAME = Petit Gorille -- GitLab From bcf9234202eb64ee27d40bc06db8975478650f60 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Wed, 2 May 2018 15:01:59 +0800 Subject: [PATCH 0145/1299] ARM: dts: msm: change msm-audio-ion as child node of apr on sm8150 During bootup, ION probe may get called before adsp up notification arrives. And it would fail to register ION SMMU which would cause playback or record has no sound. Move msm-audio-ion as child node of apr to make sure ION probe is called after adsp up notification arrives. Change-Id: If94ea8e2cab48f448a3f4bc43270f0f5ccd6acee Signed-off-by: Meng Wang --- arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi index ce2c509521e5..8bf9c1872289 100644 --- a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi @@ -299,6 +299,13 @@ audio_apr: qcom,msm-audio-apr { compatible = "qcom,msm-audio-apr"; qcom,subsys-name = "apr_adsp"; + + msm_audio_ion: qcom,msm-audio-ion { + compatible = "qcom,msm-audio-ion"; + qcom,smmu-version = <2>; + qcom,smmu-enabled; + iommus = <&apps_smmu 0x1b21 0x0>; + }; }; dai_pri_auxpcm: qcom,msm-pri-auxpcm { @@ -376,13 +383,6 @@ qcom,dba-bridge-chip = "adv7533"; }; - msm_audio_ion: qcom,msm-audio-ion { - compatible = "qcom,msm-audio-ion"; - qcom,smmu-version = <2>; - qcom,smmu-enabled; - iommus = <&apps_smmu 0x1b21 0x0>; - }; - qcom,msm-adsp-loader { status = "ok"; compatible = "qcom,adsp-loader"; -- GitLab From 3b8866b41b308b40272db3b0a935dd51574cd6d4 Mon Sep 17 00:00:00 2001 From: Jayant Shekhar Date: Mon, 11 Jun 2018 16:00:11 +0530 Subject: [PATCH 0146/1299] fbdev: msm: Fix compilation issues in FB driver Fix compilation issues in framebuffer and postproc files in display framebuffer driver. Change-Id: Ife150bd95f17c6321714fcdab1ba1da661e3680f Signed-off-by: Jayant Shekhar --- drivers/video/fbdev/msm/mdss_fb.c | 2 +- drivers/video/fbdev/msm/mdss_mdp_pp.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index a122e8ccae38..52159abf64b3 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -2136,7 +2136,7 @@ void mdss_fb_free_fb_ion_memory(struct msm_fb_data_type *mfd) int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd, size_t fb_size) { - int rc = 0, fd = 0; + int rc = 0; void *vaddr; int domain; diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c index aef51e3e5020..b510e916b8d1 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c @@ -3132,12 +3132,10 @@ static int pp_ad_calc_bl(struct msm_fb_data_type *mfd, int bl_in, int *bl_out, return -EPERM; } - if (!ad->bl_mfd || !ad->bl_mfd->panel_info || - !ad->bl_att_lut) { - pr_err("Invalid ad info: bl_mfd = 0x%pK, ad->bl_mfd->panel_info = 0x%pK, bl_att_lut = 0x%pK\n", + if (!ad->bl_mfd || !ad->bl_mfd->panel_info) { + pr_err("Invalid ad info: bl_mfd = 0x%pK, ad->bl_mfd->panel_info = 0x%pK\n", ad->bl_mfd, - (!ad->bl_mfd) ? NULL : ad->bl_mfd->panel_info, - ad->bl_att_lut); + (!ad->bl_mfd) ? NULL : ad->bl_mfd->panel_info); mutex_unlock(&ad->lock); return -EINVAL; } @@ -6672,7 +6670,7 @@ static int is_valid_calib_dspp_addr(char __iomem *ptr) ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE; break; /* Dither enable/disable */ - } else if ((ptr == base + MDSS_MDP_REG_DSPP_DITHER_DEPTH)) { + } else if (ptr == (base + MDSS_MDP_REG_DSPP_DITHER_DEPTH)) { ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE; break; /* Six zone and mem color */ -- GitLab From 7f371beca000c28efb08069323c55ad87c16e6ab Mon Sep 17 00:00:00 2001 From: Jeevan Shriram Date: Tue, 1 May 2018 10:22:33 -0700 Subject: [PATCH 0147/1299] ARM: dts: msm: Add devicetree files for sdxprairie target Add Pinctrl, RUMI, CDP and MTP devicetree files to support SDXPRAIRIE target. Change-Id: I616e681e6755f13e1c7fed0732a40cd9741cf328 Signed-off-by: Jeevan Shriram --- arch/arm64/boot/dts/qcom/Makefile | 3 + arch/arm64/boot/dts/qcom/sdxprairie-cdp.dts | 22 +++ arch/arm64/boot/dts/qcom/sdxprairie-cdp.dtsi | 13 ++ arch/arm64/boot/dts/qcom/sdxprairie-mtp.dts | 22 +++ arch/arm64/boot/dts/qcom/sdxprairie-mtp.dtsi | 13 ++ .../boot/dts/qcom/sdxprairie-pinctrl.dtsi | 49 ++++++ arch/arm64/boot/dts/qcom/sdxprairie-rumi.dts | 23 +++ arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi | 23 +++ arch/arm64/boot/dts/qcom/sdxprairie.dtsi | 140 ++++++++++++++++++ arch/arm64/boot/dts/qcom/skeleton.dtsi | 18 +++ 10 files changed, 326 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sdxprairie-cdp.dts create mode 100644 arch/arm64/boot/dts/qcom/sdxprairie-cdp.dtsi create mode 100644 arch/arm64/boot/dts/qcom/sdxprairie-mtp.dts create mode 100644 arch/arm64/boot/dts/qcom/sdxprairie-mtp.dtsi create mode 100644 arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi create mode 100644 arch/arm64/boot/dts/qcom/sdxprairie-rumi.dts create mode 100644 arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi create mode 100644 arch/arm64/boot/dts/qcom/sdxprairie.dtsi create mode 100644 arch/arm64/boot/dts/qcom/skeleton.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index b27f1d9ab513..aa1d9445a0ff 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -103,6 +103,9 @@ dtb-$(CONFIG_ARCH_SDMMAGPIE) += sdmmagpie-rumi.dtb \ sdmmagpie-qrd.dtb endif +dtb-$(CONFIG_ARCH_SDXPRAIRIE) += sdxprairie-rumi.dtb \ + sdxprairie-cdp.dtb \ + sdxprairie-mtp.dtb ifeq ($(CONFIG_ARM64),y) always := $(dtb-y) diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dts b/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dts new file mode 100644 index 000000000000..56d0e61a65d9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "sdxprairie-cdp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDXPRAIRIE CDP"; + compatible = "qcom,sdxprairie-cdp", + "qcom,sdxprairie", "qcom,cdp"; + qcom,board-id = <1 0x102>; +}; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dtsi new file mode 100644 index 000000000000..3f6f520f6007 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dtsi @@ -0,0 +1,13 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sdxprairie.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dts b/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dts new file mode 100644 index 000000000000..b2d5be0382cc --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "sdxprairie-mtp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDXPRAIRIE MTP"; + compatible = "qcom,sdxprairie-mtp", + "qcom,sdxprairie", "qcom,mtp"; + qcom,board-id = <8 0x102>; +}; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dtsi new file mode 100644 index 000000000000..3f6f520f6007 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dtsi @@ -0,0 +1,13 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sdxprairie.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi new file mode 100644 index 000000000000..ab6e1c7a99cb --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi @@ -0,0 +1,49 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + tlmm: pinctrl@f100000 { + compatible = "qcom,sdxprairie-pinctrl"; + reg = <0xf100000 0x300000>, + <0xb204900 0x280>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + interrupt-parent = <&intc>; + #interrupt-cells = <2>; + + uart3_console_active: uart3_console_active { + mux { + pins = "gpio8", "gpio9"; + function = "blsp_uart3"; + }; + config { + pins = "gpio8", "gpio9"; + drive-strength = <2>; + bias-disable; + }; + }; + + uart3_console_sleep: uart3_console_sleep { + mux { + pins = "gpio8", "gpio9"; + function = "blsp_uart3"; + }; + config { + pins = "gpio8", "gpio9"; + drive-strength = <2>; + bias-disable; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dts b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dts new file mode 100644 index 000000000000..9f94297a7c44 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dts @@ -0,0 +1,23 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + + +#include "sdxprairie-rumi.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDXPRAIRIE RUMI"; + compatible = "qcom,sdxprairie-rumi", + "qcom,sdxprairie", "qcom,rumi"; + qcom,board-id = <15 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi new file mode 100644 index 000000000000..4340663de4f3 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi @@ -0,0 +1,23 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sdxprairie.dtsi" + +&soc { + timer { + clock-frequency = <96000>; + }; + + timer@17820000 { + clock-frequency = <96000>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi new file mode 100644 index 000000000000..b5659a5fe02b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi @@ -0,0 +1,140 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include "skeleton.dtsi" +#include + +/ { + model = "Qualcomm Technologies, Inc. SDXPRAIRIE"; + compatible = "qcom,sdxprairie"; + qcom,msm-id = <357 0x0>; + interrupt-parent = <&intc>; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + peripheral2_mem: peripheral2_region@8fd00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x8fd00000 0x300000>; + label = "peripheral2_mem"; + }; + }; + + cpus { + #size-cells = <0>; + #address-cells = <1>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x0>; + }; + }; + + soc: soc { }; +}; + + +&soc { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + intc: interrupt-controller@17800000 { + compatible = "qcom,msm-qgic2"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x17800000 0x1000>, + <0x17802000 0x1000>; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = <1 13 0xf08>, + <1 12 0xf08>, + <1 10 0xf08>, + <1 11 0xf08>; + clock-frequency = <19200000>; + }; + + timer@17820000 { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0x17820000 0x1000>; + clock-frequency = <19200000>; + + frame@17821000 { + frame-number = <0>; + interrupts = <0 7 0x4>, + <0 6 0x4>; + reg = <0x17821000 0x1000>, + <0x17822000 0x1000>; + }; + + frame@17823000 { + frame-number = <1>; + interrupts = <0 8 0x4>; + reg = <0x17823000 0x1000>; + status = "disabled"; + }; + + frame@17824000 { + frame-number = <2>; + interrupts = <0 9 0x4>; + reg = <0x17824000 0x1000>; + status = "disabled"; + }; + + frame@17825000 { + frame-number = <3>; + interrupts = <0 10 0x4>; + reg = <0x17825000 0x1000>; + status = "disabled"; + }; + + frame@17826000 { + frame-number = <4>; + interrupts = <0 11 0x4>; + reg = <0x17826000 0x1000>; + status = "disabled"; + }; + + frame@17827000 { + frame-number = <5>; + interrupts = <0 12 0x4>; + reg = <0x17827000 0x1000>; + status = "disabled"; + }; + + frame@17828000 { + frame-number = <6>; + interrupts = <0 13 0x4>; + reg = <0x17828000 0x1000>; + status = "disabled"; + }; + + frame@17829000 { + frame-number = <7>; + interrupts = <0 14 0x4>; + reg = <0x17829000 0x1000>; + status = "disabled"; + }; + }; +}; + +#include "sdxprairie-pinctrl.dtsi" diff --git a/arch/arm64/boot/dts/qcom/skeleton.dtsi b/arch/arm64/boot/dts/qcom/skeleton.dtsi new file mode 100644 index 000000000000..34eda68d9ea2 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/skeleton.dtsi @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file is deprecated, and will be removed once existing users have been + * updated. New dts{,i} files should *not* include skeleton.dtsi, and should + * instead explicitly provide the below nodes only as required. + * + * Skeleton device tree; the bare minimum needed to boot; just include and + * add a compatible value. The bootloader will typically populate the memory + * node. + */ + +/ { + #address-cells = <1>; + #size-cells = <1>; + chosen { }; + aliases { }; + memory { device_type = "memory"; reg = <0 0>; }; +}; -- GitLab From ff52e7488606c0af3726204fe1f613a4b965f76c Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Fri, 8 Jun 2018 23:31:00 +0530 Subject: [PATCH 0148/1299] defconfig: arm64: Enable KGSL driver for QCS405 Enable compiling KGSL driver for QCS405. Change-Id: Ibcaeb8f32567b43be17e798d275fa27e76d35ddd Signed-off-by: Deepak Kumar --- arch/arm64/configs/qcs405_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcs405_defconfig b/arch/arm64/configs/qcs405_defconfig index 0f438beb743e..8145f05f7368 100644 --- a/arch/arm64/configs/qcs405_defconfig +++ b/arch/arm64/configs/qcs405_defconfig @@ -406,6 +406,7 @@ CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y CONFIG_PWM=y CONFIG_PWM_QTI_LPG=y +CONFIG_QCOM_KGSL=y CONFIG_QTI_MPM=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y -- GitLab From 7b2b7f5a23d1d93f93d993cff05ed8d7956eb06e Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Mon, 23 Apr 2018 23:09:09 +0530 Subject: [PATCH 0149/1299] clk: qcom: clk-rpmh: add support for clk-rpmh driver for SM6150 Add the support for clock RPMh driver to vote for ARC and VRM managed clock resources. Change-Id: Ibabdcd7b39403acf3eaafddb8fce728314824f9f Signed-off-by: Odelu Kukatla --- .../devicetree/bindings/clock/qcom,rpmh.txt | 2 +- drivers/clk/qcom/clk-rpmh.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmh.txt b/Documentation/devicetree/bindings/clock/qcom,rpmh.txt index 967eeb062b69..3776ae9d1f5c 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmh.txt +++ b/Documentation/devicetree/bindings/clock/qcom,rpmh.txt @@ -2,7 +2,7 @@ Qualcomm Technologies, Inc. RPMh Clocks Required properties: - compatible: Must contain "qcom,rpmh-clk-sm8150" or - "qcom,rpmh-clk-sdmshrike". + "qcom,rpmh-clk-sdmshrike" or "qcom,rpmh-clk-sm6150". - #clock-cells: Must contain 1. - mboxes: List of RPMh mailbox phandle and channel identifier tuples. - mbox-names: List of names to identify the RPMh mailboxes used. diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index d3547a43c316..93a27fb656a8 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -327,6 +327,24 @@ static const struct clk_rpmh_desc clk_rpmh_sm8150 = { .num_clks = ARRAY_SIZE(sm8150_rpmh_clocks), }; +static struct clk_hw *sm6150_rpmh_clocks[] = { + [RPMH_CXO_CLK] = &sm8150_bi_tcxo.hw, + [RPMH_CXO_CLK_A] = &sm8150_bi_tcxo_ao.hw, + [RPMH_LN_BB_CLK2] = &sm8150_ln_bb_clk2.hw, + [RPMH_LN_BB_CLK2_A] = &sm8150_ln_bb_clk2_ao.hw, + [RPMH_LN_BB_CLK3] = &sm8150_ln_bb_clk3.hw, + [RPMH_LN_BB_CLK3_A] = &sm8150_ln_bb_clk3_ao.hw, + [RPMH_RF_CLK1] = &sm8150_rf_clk1.hw, + [RPMH_RF_CLK1_A] = &sm8150_rf_clk1_ao.hw, + [RPMH_RF_CLK2] = &sm8150_rf_clk2.hw, + [RPMH_RF_CLK2_A] = &sm8150_rf_clk2_ao.hw, +}; + +static const struct clk_rpmh_desc clk_rpmh_sm6150 = { + .clks = sm6150_rpmh_clocks, + .num_clks = ARRAY_SIZE(sm6150_rpmh_clocks), +}; + static struct clk_hw *sdmshrike_rpmh_clocks[] = { [RPMH_CXO_CLK] = &sm8150_bi_tcxo.hw, [RPMH_CXO_CLK_A] = &sm8150_bi_tcxo_ao.hw, @@ -352,6 +370,7 @@ static const struct clk_rpmh_desc clk_rpmh_sdmshrike = { static const struct of_device_id clk_rpmh_match_table[] = { { .compatible = "qcom,rpmh-clk-sm8150", .data = &clk_rpmh_sm8150}, { .compatible = "qcom,rpmh-clk-sdmshrike", .data = &clk_rpmh_sdmshrike}, + { .compatible = "qcom,rpmh-clk-sm6150", .data = &clk_rpmh_sm6150}, { } }; MODULE_DEVICE_TABLE(of, clk_rpmh_match_table); -- GitLab From b44a5a7e89bd0cd66ab719437a36d1ba74bb9265 Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Mon, 23 Apr 2018 23:23:53 +0530 Subject: [PATCH 0150/1299] ARM: dts: msm: Update rpmh clock node for SM6150 Modify rpmh dummy clock node to use the real clock controller for all clock controller clients. Change-Id: I4bd2881959aaab29b563b01e0fc5fbde07f461c9 Signed-off-by: Odelu Kukatla --- arch/arm64/boot/dts/qcom/sm6150.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index 2a88b4ebc203..b7e120d1a307 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -597,8 +597,9 @@ }; clock_rpmh: qcom,rpmhclk { - compatible = "qcom,dummycc"; - clock-output-names = "rpm_clocks"; + compatible = "qcom,rpmh-clk-sm6150"; + mboxes = <&apps_rsc 0>; + mbox-names = "apps"; #clock-cells = <1>; }; -- GitLab From ef8a7ffc319fbd46191a0835777af8f9ebc8ba38 Mon Sep 17 00:00:00 2001 From: Vidyakumar Athota Date: Fri, 8 Jun 2018 10:34:31 -0700 Subject: [PATCH 0151/1299] ARM: dts: msm: update number of WSAs for SM8150 Set maximum number of WSAs in WCD9360 codec to 1 to avoid device variant issues for SM8150 platform. Change-Id: I8b99551a2918d28491aa2a12ccc948b8105f2e8b Signed-off-by: Vidyakumar Athota --- arch/arm64/boot/dts/qcom/sm8150-audio-overlay.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sm8150-audio-overlay.dtsi index 145b7e47c43e..dbb6a385e9ad 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-audio-overlay.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-audio-overlay.dtsi @@ -46,7 +46,7 @@ asoc-codec-names = "msm-stub-codec.1", "msm-ext-disp-audio-codec-rx"; - qcom,wsa-max-devs = <2>; + qcom,wsa-max-devs = <1>; qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0212>, <&wsa881x_0213>, <&wsa881x_0214>; qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight", -- GitLab From 51fcbe7c7be9cfa9f6bb88029c638899c9154f44 Mon Sep 17 00:00:00 2001 From: Jitendra Sharma Date: Tue, 8 May 2018 16:54:14 +0530 Subject: [PATCH 0152/1299] ARM: dts: msm: Add modem pil node for SM6150 Add modem PIL node to facilitate modem subsystem loading for SM6150. Change-Id: I56d6715132d74510425965efa6ef00ca90518452 Signed-off-by: Jitendra Sharma --- arch/arm64/boot/dts/qcom/sm6150.dtsi | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index 2a88b4ebc203..43869547c054 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -1517,6 +1517,53 @@ mboxes = <&qmp_aop 0>; mbox-names = "adsp-pil"; }; + + pil_modem: qcom,mss@4080000 { + compatible = "qcom,pil-tz-generic"; + reg = <0x4080000 0x100>; + + clocks = <&clock_rpmh RPMH_CXO_CLK>; + clock-names = "xo"; + qcom,proxy-clock-names = "xo"; + + vdd_cx-supply = <&VDD_CX_LEVEL>; + qcom,vdd_cx-uV-uA = ; + vdd_mss-supply = <&VDD_MSS_LEVEL>; + qcom,vdd_mss-uV-uA = ; + qcom,proxy-reg-names = "vdd_cx", "vdd_mss"; + + qcom,firmware-name = "modem"; + memory-region = <&pil_modem_mem>; + qcom,proxy-timeout-ms = <10000>; + qcom,sysmon-id = <0>; + qcom,ssctl-instance-id = <0x12>; + qcom,pas-id = <4>; + qcom,smem-id = <421>; + qcom,complete-ramdump; + + /* Inputs from mss */ + interrupts-extended = <&pdc 0 266 1>, + <&modem_smp2p_in 0 0>, + <&modem_smp2p_in 2 0>, + <&modem_smp2p_in 1 0>, + <&modem_smp2p_in 3 0>, + <&modem_smp2p_in 7 0>; + + interrupt-names = "qcom,wdog", + "qcom,err-fatal", + "qcom,proxy-unvote", + "qcom,err-ready", + "qcom,stop-ack", + "qcom,shutdown-ack"; + + /* Outputs to mss */ + qcom,smem-states = <&modem_smp2p_out 0>; + qcom,smem-state-names = "qcom,force-stop"; + + mboxes = <&qmp_aop 0>; + mbox-names = "mss-pil"; + }; + }; #include "pm6150.dtsi" -- GitLab From e02a4e21f640189b01f1cfda932e7a00b89c0936 Mon Sep 17 00:00:00 2001 From: Dinesh K Garg Date: Wed, 23 May 2018 16:35:01 -0700 Subject: [PATCH 0153/1299] ext4: Add HW File Based Encryption on ext4 file system HW File Based Encryption (FBE) uses Crypto Engine to encrypt the user data with unique key for each file. File name and data both are encrypted with this feature. 1. security/pfk: New module to support per file encryption using CE. 2. fs/ext4: changes made to support using crypto engine to encyrpt the data. Other changes made to provide support framework for per file encryption. Change-Id: Idea3f6f8bf954c60c3c6caa3d9b048d87fcacbe4 Signed-off-by: Dinesh K Garg --- block/bio.c | 2 +- block/blk-merge.c | 12 +- drivers/crypto/Kconfig | 3 + drivers/crypto/msm/ice.c | 31 +- fs/crypto/Makefile | 2 + fs/crypto/bio.c | 19 +- fs/crypto/ext4_ice.c | 108 ++++ fs/crypto/fscrypt_private.h | 13 + fs/crypto/keyinfo.c | 153 +++-- fs/direct-io.c | 13 + fs/ext4/Kconfig | 10 +- fs/ext4/Makefile | 1 + fs/ext4/ext4.h | 3 + fs/ext4/ext4_ice.h | 104 ++++ fs/ext4/inode.c | 16 +- fs/ext4/ioctl.c | 10 +- fs/ext4/page-io.c | 6 +- fs/namei.c | 12 + include/linux/blk_types.h | 6 + include/linux/fs.h | 2 + include/linux/fscrypt.h | 4 + include/linux/lsm_hooks.h | 3 + include/linux/pfk.h | 57 ++ include/linux/security.h | 10 + security/Kconfig | 5 + security/Makefile | 2 + security/pfe/Kconfig | 28 + security/pfe/Makefile | 10 + security/pfe/pfk.c | 470 +++++++++++++++ security/pfe/pfk_ext4.c | 184 ++++++ security/pfe/pfk_ext4.h | 37 ++ security/pfe/pfk_ice.c | 181 ++++++ security/pfe/pfk_ice.h | 32 + security/pfe/pfk_internal.h | 34 ++ security/pfe/pfk_kc.c | 905 ++++++++++++++++++++++++++++ security/pfe/pfk_kc.h | 33 + security/security.c | 8 + security/selinux/include/objsec.h | 7 +- security/selinux/include/security.h | 1 - 39 files changed, 2433 insertions(+), 104 deletions(-) create mode 100644 fs/crypto/ext4_ice.c create mode 100644 fs/ext4/ext4_ice.h create mode 100644 include/linux/pfk.h create mode 100644 security/pfe/Kconfig create mode 100644 security/pfe/Makefile create mode 100644 security/pfe/pfk.c create mode 100644 security/pfe/pfk_ext4.c create mode 100644 security/pfe/pfk_ext4.h create mode 100644 security/pfe/pfk_ice.c create mode 100644 security/pfe/pfk_ice.h create mode 100644 security/pfe/pfk_internal.h create mode 100644 security/pfe/pfk_kc.c create mode 100644 security/pfe/pfk_kc.h diff --git a/block/bio.c b/block/bio.c index 90f19d7df66c..61975a2bd9e0 100644 --- a/block/bio.c +++ b/block/bio.c @@ -605,7 +605,7 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src) bio->bi_write_hint = bio_src->bi_write_hint; bio->bi_iter = bio_src->bi_iter; bio->bi_io_vec = bio_src->bi_io_vec; - + bio->bi_dio_inode = bio_src->bi_dio_inode; bio_clone_blkcg_association(bio, bio_src); } EXPORT_SYMBOL(__bio_clone_fast); diff --git a/block/blk-merge.c b/block/blk-merge.c index 8d60a5bbcef9..4f7e70419ba2 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -7,7 +7,7 @@ #include #include #include - +#include #include #include "blk.h" @@ -660,6 +660,11 @@ static void blk_account_io_merge(struct request *req) } } +static bool crypto_not_mergeable(const struct bio *bio, const struct bio *nxt) +{ + return (!pfk_allow_merge_bio(bio, nxt)); +} + /* * For non-mq, this has to be called with the request spinlock acquired. * For mq with scheduling, the appropriate queue wide lock should be held. @@ -698,6 +703,8 @@ static struct request *attempt_merge(struct request_queue *q, if (req->write_hint != next->write_hint) return NULL; + if (crypto_not_mergeable(req->bio, next->bio)) + return 0; /* * If we are allowed to merge, then append bio list * from next to rq and release next. merge_requests_fn @@ -829,6 +836,9 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) if (rq->write_hint != bio->bi_write_hint) return false; + if (crypto_not_mergeable(rq->bio, bio)) + return false; + return true; } diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 8effad0e7d26..0359f0c484fc 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -770,4 +770,7 @@ config CRYPTO_DEV_ARTPEC6 To compile this driver as a module, choose M here. +if ARCH_QCOM +source drivers/crypto/msm/Kconfig +endif endif # CRYPTO_HW diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c index 0b648217e8cb..e342d2af1109 100644 --- a/drivers/crypto/msm/ice.c +++ b/drivers/crypto/msm/ice.c @@ -1397,8 +1397,8 @@ static void qcom_ice_debug(struct platform_device *pdev) qcom_ice_dump_test_bus(ice_dev); pr_err("%s: ICE reset start time: %llu ICE reset done time: %llu\n", ice_dev->ice_instance_type, - (unsigned long long)ice_dev->ice_reset_start_time.tv64, - (unsigned long long)ice_dev->ice_reset_complete_time.tv64); + (unsigned long long)ice_dev->ice_reset_start_time, + (unsigned long long)ice_dev->ice_reset_complete_time); if (ktime_to_us(ktime_sub(ice_dev->ice_reset_complete_time, ice_dev->ice_reset_start_time)) > 0) @@ -1430,9 +1430,7 @@ static int qcom_ice_config_start(struct platform_device *pdev, struct request *req, struct ice_data_setting *setting, bool async) { - struct ice_crypto_setting *crypto_data; struct ice_crypto_setting pfk_crypto_data = {0}; - union map_info *info; int ret = 0; bool is_pfe = false; @@ -1455,7 +1453,6 @@ static int qcom_ice_config_start(struct platform_device *pdev, /* It is not an error to have a request with no bio */ return 0; } - //pr_err("%s bio is %pK\n", __func__, req->bio); ret = pfk_load_key_start(req->bio, &pfk_crypto_data, &is_pfe, async); if (is_pfe) { @@ -1470,30 +1467,6 @@ static int qcom_ice_config_start(struct platform_device *pdev, &pfk_crypto_data, setting); } - /* - * info field in req->end_io_data could be used by mulitple dm or - * non-dm entities. To ensure that we are running operation on dm - * based request, check BIO_DONT_FREE flag - */ - if (bio_flagged(req->bio, BIO_INLINECRYPT)) { - info = dm_get_rq_mapinfo(req); - if (!info) { - pr_debug("%s info not available in request\n", - __func__); - return 0; - } - - crypto_data = (struct ice_crypto_setting *)info->ptr; - if (!crypto_data) { - pr_err("%s crypto_data not available in request\n", - __func__); - return -EINVAL; - } - - return qti_ice_setting_config(req, pdev, - crypto_data, setting); - } - /* * It is not an error. If target is not req-crypt based, all request * from storage driver would come here to check if there is any ICE diff --git a/fs/crypto/Makefile b/fs/crypto/Makefile index cb496989a6b6..e7bee887b605 100644 --- a/fs/crypto/Makefile +++ b/fs/crypto/Makefile @@ -2,3 +2,5 @@ obj-$(CONFIG_FS_ENCRYPTION) += fscrypto.o fscrypto-y := crypto.o fname.o hooks.o keyinfo.o policy.o fscrypto-$(CONFIG_BLOCK) += bio.o +ccflags-y += -Ifs/ext4 +fscrypto-$(CONFIG_EXT4_FS_ICE_ENCRYPTION) += ext4_ice.o diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c index 0959044c5cee..d32a5c69ca38 100644 --- a/fs/crypto/bio.c +++ b/fs/crypto/bio.c @@ -25,6 +25,7 @@ #include #include #include "fscrypt_private.h" +#include "ext4_ice.h" static void __fscrypt_decrypt_bio(struct bio *bio, bool done) { @@ -33,14 +34,18 @@ static void __fscrypt_decrypt_bio(struct bio *bio, bool done) bio_for_each_segment_all(bv, bio, i) { struct page *page = bv->bv_page; - int ret = fscrypt_decrypt_page(page->mapping->host, page, - PAGE_SIZE, 0, page->index); - - if (ret) { - WARN_ON_ONCE(1); - SetPageError(page); - } else if (done) { + if (ext4_should_be_processed_by_ice(page->mapping->host)) { SetPageUptodate(page); + } else { + int ret = fscrypt_decrypt_page(page->mapping->host, + page, PAGE_SIZE, 0, page->index); + + if (ret) { + WARN_ON_ONCE(1); + SetPageError(page); + } else if (done) { + SetPageUptodate(page); + } } if (done) unlock_page(page); diff --git a/fs/crypto/ext4_ice.c b/fs/crypto/ext4_ice.c new file mode 100644 index 000000000000..a8098e338f29 --- /dev/null +++ b/fs/crypto/ext4_ice.c @@ -0,0 +1,108 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "ext4_ice.h" +#include "fscrypt_private.h" + +/* + * Retrieves encryption key from the inode + */ +char *ext4_get_ice_encryption_key(const struct inode *inode) +{ + struct fscrypt_info *ci = NULL; + + if (!inode) + return NULL; + + ci = inode->i_crypt_info; + if (!ci) + return NULL; + + return &(ci->ci_raw_key[0]); +} + +/* + * Retrieves encryption salt from the inode + */ +char *ext4_get_ice_encryption_salt(const struct inode *inode) +{ + struct fscrypt_info *ci = NULL; + + if (!inode) + return NULL; + + ci = inode->i_crypt_info; + if (!ci) + return NULL; + + return &(ci->ci_raw_key[ext4_get_ice_encryption_key_size(inode)]); +} + +/* + * returns true if the cipher mode in inode is AES XTS + */ +int ext4_is_aes_xts_cipher(const struct inode *inode) +{ + struct fscrypt_info *ci = NULL; + + ci = inode->i_crypt_info; + if (!ci) + return 0; + + return (ci->ci_data_mode == FS_ENCRYPTION_MODE_PRIVATE); +} + +/* + * returns true if encryption info in both inodes is equal + */ +int ext4_is_ice_encryption_info_equal(const struct inode *inode1, + const struct inode *inode2) +{ + char *key1 = NULL; + char *key2 = NULL; + char *salt1 = NULL; + char *salt2 = NULL; + + if (!inode1 || !inode2) + return 0; + + if (inode1 == inode2) + return 1; + + /* both do not belong to ice, so we don't care, they are equal for us */ + if (!ext4_should_be_processed_by_ice(inode1) && + !ext4_should_be_processed_by_ice(inode2)) + return 1; + + /* one belongs to ice, the other does not -> not equal */ + if (ext4_should_be_processed_by_ice(inode1) ^ + ext4_should_be_processed_by_ice(inode2)) + return 0; + + key1 = ext4_get_ice_encryption_key(inode1); + key2 = ext4_get_ice_encryption_key(inode2); + salt1 = ext4_get_ice_encryption_salt(inode1); + salt2 = ext4_get_ice_encryption_salt(inode2); + + /* key and salt should not be null by this point */ + if (!key1 || !key2 || !salt1 || !salt2 || + (ext4_get_ice_encryption_key_size(inode1) != + ext4_get_ice_encryption_key_size(inode2)) || + (ext4_get_ice_encryption_salt_size(inode1) != + ext4_get_ice_encryption_salt_size(inode2))) + return 0; + + return ((memcmp(key1, key2, + ext4_get_ice_encryption_key_size(inode1)) == 0) && + (memcmp(salt1, salt2, + ext4_get_ice_encryption_salt_size(inode1)) == 0)); +} diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 073165db5641..c9ca9e79411d 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -12,7 +12,9 @@ #ifndef _FSCRYPT_PRIVATE_H #define _FSCRYPT_PRIVATE_H +#ifndef __FS_HAS_ENCRYPTION #define __FS_HAS_ENCRYPTION 1 +#endif #include #include @@ -70,6 +72,7 @@ struct fscrypt_info { struct crypto_skcipher *ci_ctfm; struct crypto_cipher *ci_essiv_tfm; u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; + u8 ci_raw_key[FS_MAX_KEY_SIZE]; }; typedef enum { @@ -95,9 +98,19 @@ static inline bool fscrypt_valid_enc_modes(u32 contents_mode, filenames_mode == FS_ENCRYPTION_MODE_SPECK128_256_CTS) return true; + if (contents_mode == FS_ENCRYPTION_MODE_PRIVATE && + filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) + return true; + return false; } +static inline bool is_private_mode(struct fscrypt_info *ci) +{ + return ci->ci_data_mode == FS_ENCRYPTION_MODE_PRIVATE; +} + + /* crypto.c */ extern struct kmem_cache *fscrypt_info_cachep; extern int fscrypt_initialize(unsigned int cop_flags); diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 6e1b0281daba..27edc5b9eb66 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -16,6 +16,7 @@ #include #include #include "fscrypt_private.h" +#include "ext4_ice.h" static struct crypto_shash *essiv_hash_tfm; @@ -116,7 +117,25 @@ static int validate_user_key(struct fscrypt_info *crypt_info, res = -ENOKEY; goto out; } - res = derive_key_aes(ctx->nonce, master_key, raw_key); + /* + * If we don't need to derive, we still want to do everything + * up until now to validate the key. It's cleaner to fail now + * than to fail in block I/O. + */ + if (!is_private_mode(crypt_info)) { + res = derive_key_aes(ctx->nonce, master_key, + crypt_info->ci_raw_key); + } else { + /* + * Inline encryption: no key derivation required because IVs are + * assigned based on iv_sector. + */ + if (sizeof(crypt_info->ci_raw_key) != sizeof(master_key->raw)) + goto out; + memcpy(crypt_info->ci_raw_key, + master_key->raw, sizeof(crypt_info->ci_raw_key)); + res = 0; + } out: up_read(&keyring_key->sem); key_put(keyring_key); @@ -137,33 +156,42 @@ static const struct { FS_AES_128_CTS_KEY_SIZE }, [FS_ENCRYPTION_MODE_SPECK128_256_XTS] = { "xts(speck128)", 64 }, [FS_ENCRYPTION_MODE_SPECK128_256_CTS] = { "cts(cbc(speck128))", 32 }, + [FS_ENCRYPTION_MODE_PRIVATE] = { "bugon", FS_AES_256_XTS_KEY_SIZE }, }; static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode, - const char **cipher_str_ret, int *keysize_ret) + const char **cipher_str_ret, int *keysize_ret, int *fname) { - u32 mode; - - if (!fscrypt_valid_enc_modes(ci->ci_data_mode, ci->ci_filename_mode)) { - pr_warn_ratelimited("fscrypt: inode %lu uses unsupported encryption modes (contents mode %d, filenames mode %d)\n", - inode->i_ino, - ci->ci_data_mode, ci->ci_filename_mode); - return -EINVAL; + if (S_ISREG(inode->i_mode)) { + if (ci->ci_data_mode == FS_ENCRYPTION_MODE_AES_256_XTS) { + *cipher_str_ret = "xts(aes)"; + *keysize_ret = FS_AES_256_XTS_KEY_SIZE; + return 0; + } else if (ci->ci_data_mode == FS_ENCRYPTION_MODE_PRIVATE) { + *cipher_str_ret = "bugon"; + *keysize_ret = FS_AES_256_XTS_KEY_SIZE; + return 0; + } + pr_warn_once("fscrypto: unsupported contents encryption mode %d for inode %lu\n", + ci->ci_data_mode, inode->i_ino); + return -ENOKEY; } - if (S_ISREG(inode->i_mode)) { - mode = ci->ci_data_mode; - } else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { - mode = ci->ci_filename_mode; - } else { - WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n", - inode->i_ino, (inode->i_mode & S_IFMT)); - return -EINVAL; + if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { + if (ci->ci_filename_mode == FS_ENCRYPTION_MODE_AES_256_CTS) { + *cipher_str_ret = "cts(cbc(aes))"; + *keysize_ret = FS_AES_256_CTS_KEY_SIZE; + *fname = 1; + return 0; + } + pr_warn_once("fscrypto: unsupported filenames encryption mode %d for inode %lu\n", + ci->ci_filename_mode, inode->i_ino); + return -ENOKEY; } - *cipher_str_ret = available_modes[mode].cipher_str; - *keysize_ret = available_modes[mode].keysize; - return 0; + pr_warn_once("fscrypto: unsupported file type %d for inode %lu\n", + (inode->i_mode & S_IFMT), inode->i_ino); + return -ENOKEY; } static void put_crypt_info(struct fscrypt_info *ci) @@ -173,6 +201,7 @@ static void put_crypt_info(struct fscrypt_info *ci) crypto_free_skcipher(ci->ci_ctfm); crypto_free_cipher(ci->ci_essiv_tfm); + memset(ci, 0, sizeof(*ci)); /* sanitizes ->ci_raw_key */ kmem_cache_free(fscrypt_info_cachep, ci); } @@ -242,6 +271,21 @@ void __exit fscrypt_essiv_cleanup(void) crypto_free_shash(essiv_hash_tfm); } +static int fs_data_encryption_mode(void) +{ + return ext4_is_ice_enabled() ? FS_ENCRYPTION_MODE_PRIVATE : + FS_ENCRYPTION_MODE_AES_256_XTS; +} + +int fs_using_hardware_encryption(struct inode *inode) +{ + struct fscrypt_info *ci = inode->i_crypt_info; + + return S_ISREG(inode->i_mode) && ci && + ci->ci_data_mode == FS_ENCRYPTION_MODE_PRIVATE; +} +EXPORT_SYMBOL(fs_using_hardware_encryption); + int fscrypt_get_encryption_info(struct inode *inode) { struct fscrypt_info *crypt_info; @@ -249,8 +293,8 @@ int fscrypt_get_encryption_info(struct inode *inode) struct crypto_skcipher *ctfm; const char *cipher_str; int keysize; - u8 *raw_key = NULL; int res; + int fname = 0; if (inode->i_crypt_info) return 0; @@ -267,7 +311,7 @@ int fscrypt_get_encryption_info(struct inode *inode) /* Fake up a context for an unencrypted directory */ memset(&ctx, 0, sizeof(ctx)); ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; - ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS; + ctx.contents_encryption_mode = fs_data_encryption_mode(); ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS; memset(ctx.master_key_descriptor, 0x42, FS_KEY_DESCRIPTOR_SIZE); } else if (res != sizeof(ctx)) { @@ -292,7 +336,8 @@ int fscrypt_get_encryption_info(struct inode *inode) memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, sizeof(crypt_info->ci_master_key)); - res = determine_cipher_type(crypt_info, inode, &cipher_str, &keysize); + res = determine_cipher_type(crypt_info, inode, &cipher_str, + &keysize, &fname); if (res) goto out; @@ -301,45 +346,50 @@ int fscrypt_get_encryption_info(struct inode *inode) * crypto API as part of key derivation. */ res = -ENOMEM; - raw_key = kmalloc(FS_MAX_KEY_SIZE, GFP_NOFS); - if (!raw_key) - goto out; - res = validate_user_key(crypt_info, &ctx, raw_key, FS_KEY_DESC_PREFIX, - keysize); + if (fscrypt_dummy_context_enabled(inode)) { + memset(crypt_info->ci_raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE); + goto got_key; + } + res = validate_user_key(crypt_info, &ctx, crypt_info->ci_raw_key, + FS_KEY_DESC_PREFIX, FS_KEY_DESC_PREFIX_SIZE); if (res && inode->i_sb->s_cop->key_prefix) { - int res2 = validate_user_key(crypt_info, &ctx, raw_key, - inode->i_sb->s_cop->key_prefix, - keysize); + int res2 = validate_user_key(crypt_info, &ctx, + crypt_info->ci_raw_key, + inode->i_sb->s_cop->key_prefix, keysize); if (res2) { if (res2 == -ENOKEY) res = -ENOKEY; goto out; } + res = 0; } else if (res) { goto out; } - ctfm = crypto_alloc_skcipher(cipher_str, 0, 0); - if (!ctfm || IS_ERR(ctfm)) { - res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; - pr_debug("%s: error %d (inode %lu) allocating crypto tfm\n", - __func__, res, inode->i_ino); - goto out; - } - crypt_info->ci_ctfm = ctfm; - crypto_skcipher_clear_flags(ctfm, ~0); - crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY); - /* - * if the provided key is longer than keysize, we use the first - * keysize bytes of the derived key only - */ - res = crypto_skcipher_setkey(ctfm, raw_key, keysize); - if (res) - goto out; - - if (S_ISREG(inode->i_mode) && +got_key: + if (crypt_info->ci_data_mode != FS_ENCRYPTION_MODE_PRIVATE || fname) { + ctfm = crypto_alloc_skcipher(cipher_str, 0, 0); + if (!ctfm || IS_ERR(ctfm)) { + res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; + pr_err("%s: error %d inode %u allocating crypto tfm\n", + __func__, res, (unsigned int) inode->i_ino); + goto out; + } + crypt_info->ci_ctfm = ctfm; + crypto_skcipher_clear_flags(ctfm, ~0); + crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY); + /* + * if the provided key is longer than keysize, we use the first + * keysize bytes of the derived key only + */ + res = crypto_skcipher_setkey(ctfm, crypt_info->ci_raw_key, + keysize); + if (res) + goto out; + } else if (S_ISREG(inode->i_mode) && crypt_info->ci_data_mode == FS_ENCRYPTION_MODE_AES_128_CBC) { - res = init_essiv_generator(crypt_info, raw_key, keysize); + res = init_essiv_generator(crypt_info, crypt_info->ci_raw_key, + keysize); if (res) { pr_debug("%s: error %d (inode %lu) allocating essiv tfm\n", __func__, res, inode->i_ino); @@ -352,7 +402,6 @@ int fscrypt_get_encryption_info(struct inode *inode) if (res == -ENOKEY) res = 0; put_crypt_info(crypt_info); - kzfree(raw_key); return res; } EXPORT_SYMBOL(fscrypt_get_encryption_info); diff --git a/fs/direct-io.c b/fs/direct-io.c index 625a84aa6484..96a103249a0b 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -452,6 +452,7 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio) bio_set_pages_dirty(bio); dio->bio_disk = bio->bi_disk; + bio->bi_dio_inode = dio->inode; if (sdio->submit_io) { sdio->submit_io(bio, dio->inode, sdio->logical_offset_in_bio); @@ -464,6 +465,18 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio) sdio->logical_offset_in_bio = 0; } +struct inode *dio_bio_get_inode(struct bio *bio) +{ + struct inode *inode = NULL; + + if (bio == NULL) + return NULL; + + inode = bio->bi_dio_inode; + + return inode; +} +EXPORT_SYMBOL(dio_bio_get_inode); /* * Release any resources in case of a failure */ diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index e38039fd96ff..e9232a09af5d 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -109,10 +109,16 @@ config EXT4_ENCRYPTION decrypted pages in the page cache. config EXT4_FS_ENCRYPTION - bool - default y + bool "Ext4 FS Encryption" + default n depends on EXT4_ENCRYPTION +config EXT4_FS_ICE_ENCRYPTION + bool "Ext4 Encryption with ICE support" + default n + depends on EXT4_FS_ENCRYPTION + depends on PFK + config EXT4_DEBUG bool "EXT4 debugging support" depends on EXT4_FS diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile index 8fdfcd3c3e04..7cf69c14f796 100644 --- a/fs/ext4/Makefile +++ b/fs/ext4/Makefile @@ -2,6 +2,7 @@ # # Makefile for the linux ext4-filesystem routines. # +ccflags-y += -Ifs/crypto obj-$(CONFIG_EXT4_FS) += ext4.o diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 27f38bb5046d..f727e10b3522 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -40,7 +40,9 @@ #include #endif +#ifndef __FS_HAS_ENCRYPTION #define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_EXT4_FS_ENCRYPTION) +#endif #include /* @@ -2355,6 +2357,7 @@ static inline int ext4_fname_setup_filename(struct inode *dir, } static inline void ext4_fname_free_filename(struct ext4_filename *fname) { } +#define fscrypt_set_d_op(i) #endif /* dir.c */ diff --git a/fs/ext4/ext4_ice.h b/fs/ext4/ext4_ice.h new file mode 100644 index 000000000000..b0149dd7bad4 --- /dev/null +++ b/fs/ext4/ext4_ice.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _EXT4_ICE_H +#define _EXT4_ICE_H + +#include "ext4.h" +#include + +#ifdef CONFIG_EXT4_FS_ICE_ENCRYPTION +static inline int ext4_should_be_processed_by_ice(const struct inode *inode) +{ + if (!ext4_encrypted_inode((struct inode *)inode)) + return 0; + + return fs_using_hardware_encryption((struct inode *)inode); +} + +static inline int ext4_is_ice_enabled(void) +{ + return 1; +} + +int ext4_is_aes_xts_cipher(const struct inode *inode); + +char *ext4_get_ice_encryption_key(const struct inode *inode); +char *ext4_get_ice_encryption_salt(const struct inode *inode); + +int ext4_is_ice_encryption_info_equal(const struct inode *inode1, + const struct inode *inode2); + +static inline size_t ext4_get_ice_encryption_key_size( + const struct inode *inode) +{ + return FS_AES_256_XTS_KEY_SIZE / 2; +} + +static inline size_t ext4_get_ice_encryption_salt_size( + const struct inode *inode) +{ + return FS_AES_256_XTS_KEY_SIZE / 2; +} + +#else +static inline int ext4_should_be_processed_by_ice(const struct inode *inode) +{ + return 0; +} +static inline int ext4_is_ice_enabled(void) +{ + return 0; +} + +static inline char *ext4_get_ice_encryption_key(const struct inode *inode) +{ + return NULL; +} + +static inline char *ext4_get_ice_encryption_salt(const struct inode *inode) +{ + return NULL; +} + +static inline size_t ext4_get_ice_encryption_key_size( + const struct inode *inode) +{ + return 0; +} + +static inline size_t ext4_get_ice_encryption_salt_size( + const struct inode *inode) +{ + return 0; +} + +static inline int ext4_is_xts_cipher(const struct inode *inode) +{ + return 0; +} + +static inline int ext4_is_ice_encryption_info_equal( + const struct inode *inode1, + const struct inode *inode2) +{ + return 0; +} + +static inline int ext4_is_aes_xts_cipher(const struct inode *inode) +{ + return 0; +} + +#endif + +#endif /* _EXT4_ICE_H */ diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 3a1bd461ceb1..3f7a5ac4a318 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -44,6 +44,7 @@ #include "xattr.h" #include "acl.h" #include "truncate.h" +#include "ext4_ice.h" #include #include @@ -1218,7 +1219,8 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len, ll_rw_block(REQ_OP_READ, 0, 1, &bh); *wait_bh++ = bh; decrypt = ext4_encrypted_inode(inode) && - S_ISREG(inode->i_mode); + S_ISREG(inode->i_mode) && + !ext4_should_be_processed_by_ice(inode); } } /* @@ -3714,6 +3716,12 @@ static ssize_t ext4_direct_IO_write(struct kiocb *iocb, struct iov_iter *iter) get_block_func = ext4_dio_get_block_unwritten_async; dio_flags = DIO_LOCKING; } + +#if defined(CONFIG_EXT4_FS_ENCRYPTION) && \ +!defined(CONFIG_EXT4_FS_ICE_ENCRYPTION) + if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode)) + return 0; +#endif ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter, get_block_func, ext4_end_io_dio, NULL, dio_flags); @@ -3822,7 +3830,8 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter) ssize_t ret; int rw = iov_iter_rw(iter); -#ifdef CONFIG_EXT4_FS_ENCRYPTION +#if defined(CONFIG_EXT4_FS_ENCRYPTION) && \ +!defined(CONFIG_EXT4_FS_ICE_ENCRYPTION) if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode)) return 0; #endif @@ -4032,7 +4041,8 @@ static int __ext4_block_zero_page_range(handle_t *handle, if (!buffer_uptodate(bh)) goto unlock; if (S_ISREG(inode->i_mode) && - ext4_encrypted_inode(inode)) { + ext4_encrypted_inode(inode) && + !ext4_should_be_processed_by_ice(inode)) { /* We expect the key to be set. */ BUG_ON(!fscrypt_has_encryption_key(inode)); BUG_ON(blocksize != PAGE_SIZE); diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 1eb68e626931..53bd5d893a58 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -939,11 +939,13 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case EXT4_IOC_PRECACHE_EXTENTS: return ext4_ext_precache(inode); - case EXT4_IOC_SET_ENCRYPTION_POLICY: - if (!ext4_has_feature_encrypt(sb)) - return -EOPNOTSUPP; + case EXT4_IOC_SET_ENCRYPTION_POLICY: { +#ifdef CONFIG_EXT4_FS_ENCRYPTION return fscrypt_ioctl_set_policy(filp, (const void __user *)arg); - +#else + return -EOPNOTSUPP; +#endif + } case EXT4_IOC_GET_ENCRYPTION_PWSALT: { #ifdef CONFIG_EXT4_FS_ENCRYPTION int err, err2; diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index db7590178dfc..bc475426f0c3 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -29,6 +29,7 @@ #include "ext4_jbd2.h" #include "xattr.h" #include "acl.h" +#include "ext4_ice.h" static struct kmem_cache *io_end_cachep; @@ -482,8 +483,9 @@ int ext4_bio_write_page(struct ext4_io_submit *io, gfp_t gfp_flags = GFP_NOFS; retry_encrypt: - data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, 0, - page->index, gfp_flags); + if (!ext4_should_be_processed_by_ice(inode)) + data_page = fscrypt_encrypt_page(inode, page, PAGE_SIZE, + 0, page->index, gfp_flags); if (IS_ERR(data_page)) { ret = PTR_ERR(data_page); if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) { diff --git a/fs/namei.c b/fs/namei.c index 54fb30f14c3d..055c6c40901b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2913,6 +2913,11 @@ int vfs_create2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, if (error) return error; error = dir->i_op->create(dir, dentry, mode, want_excl); + if (error) + return error; + error = security_inode_post_create(dir, dentry, mode); + if (error) + return error; if (!error) fsnotify_create(dir, dentry); return error; @@ -3735,6 +3740,13 @@ int vfs_mknod2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, u return error; error = dir->i_op->mknod(dir, dentry, mode, dev); + if (error) + return error; + + error = security_inode_post_create(dir, dentry, mode); + if (error) + return error; + if (!error) fsnotify_create(dir, dentry); return error; diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 40090ee2eeb0..be2bee81c748 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -115,6 +115,12 @@ struct bio { struct bio_set *bi_pool; + /* + * When using dircet-io (O_DIRECT), we can't get the inode from a bio + * by walking bio->bi_io_vec->bv_page->mapping->host + * since the page is anon. + */ + struct inode *bi_dio_inode; /* * We can inline a number of vecs at the end of the bio, to avoid * double allocations for a small number of bio_vecs. This member diff --git a/include/linux/fs.h b/include/linux/fs.h index 63b60955042b..b030db4098ee 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3043,6 +3043,8 @@ static inline void inode_dio_end(struct inode *inode) wake_up_bit(&inode->i_state, __I_DIO_WAKEUP); } +struct inode *dio_bio_get_inode(struct bio *bio); + extern void inode_set_flags(struct inode *inode, unsigned int flags, unsigned int mask); diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 952ab97af325..2a3957bc2221 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -17,6 +17,8 @@ #include #define FS_CRYPTO_BLOCK_SIZE 16 +#define FS_ENCRYPTION_MODE_PRIVATE 127 +#define FS_AES_256_XTS_KEY_SIZE 64 struct fscrypt_ctx; struct fscrypt_info; @@ -42,6 +44,8 @@ struct fscrypt_name { /* Maximum value for the third parameter of fscrypt_operations.set_context(). */ #define FSCRYPT_SET_CONTEXT_MAX_SIZE 28 +extern int fs_using_hardware_encryption(struct inode *inode); + #if __FS_HAS_ENCRYPTION #include #else diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 7161d8e7ee79..d1431c1bfed3 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1475,6 +1475,8 @@ union security_list_options { size_t *len); int (*inode_create)(struct inode *dir, struct dentry *dentry, umode_t mode); + int (*inode_post_create)(struct inode *dir, struct dentry *dentry, + umode_t mode); int (*inode_link)(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry); int (*inode_unlink)(struct inode *dir, struct dentry *dentry); @@ -1780,6 +1782,7 @@ struct security_hook_heads { struct list_head inode_free_security; struct list_head inode_init_security; struct list_head inode_create; + struct list_head inode_post_create; struct list_head inode_link; struct list_head inode_unlink; struct list_head inode_symlink; diff --git a/include/linux/pfk.h b/include/linux/pfk.h new file mode 100644 index 000000000000..3c7a389fd4d4 --- /dev/null +++ b/include/linux/pfk.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef PFK_H_ +#define PFK_H_ + +#include + +struct ice_crypto_setting; + +#ifdef CONFIG_PFK + +int pfk_load_key_start(const struct bio *bio, + struct ice_crypto_setting *ice_setting, bool *is_pfe, bool); +int pfk_load_key_end(const struct bio *bio, bool *is_pfe); +int pfk_remove_key(const unsigned char *key, size_t key_size); +bool pfk_allow_merge_bio(const struct bio *bio1, const struct bio *bio2); +void pfk_clear_on_reset(void); + +#else +static inline int pfk_load_key_start(const struct bio *bio, + struct ice_crypto_setting *ice_setting, bool *is_pfe, bool async) +{ + return -ENODEV; +} + +static inline int pfk_load_key_end(const struct bio *bio, bool *is_pfe) +{ + return -ENODEV; +} + +static inline int pfk_remove_key(const unsigned char *key, size_t key_size) +{ + return -ENODEV; +} + +static inline bool pfk_allow_merge_bio(const struct bio *bio1, + const struct bio *bio2) +{ + return true; +} + +static inline void pfk_clear_on_reset(void) +{} + +#endif /* CONFIG_PFK */ + +#endif /* PFK_H */ diff --git a/include/linux/security.h b/include/linux/security.h index 73f1ef625d40..30fb23a4ca81 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -31,6 +31,7 @@ #include #include #include +#include struct linux_binprm; struct cred; @@ -270,6 +271,8 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, const char **name, void **value, size_t *len); int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode); +int security_inode_post_create(struct inode *dir, struct dentry *dentry, + umode_t mode); int security_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry); int security_inode_unlink(struct inode *dir, struct dentry *dentry); @@ -664,6 +667,13 @@ static inline int security_inode_create(struct inode *dir, return 0; } +static inline int security_inode_post_create(struct inode *dir, + struct dentry *dentry, + umode_t mode) +{ + return 0; +} + static inline int security_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) diff --git a/security/Kconfig b/security/Kconfig index 65d29c37d1fc..87d8bb2df7c8 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -6,6 +6,11 @@ menu "Security options" source security/keys/Kconfig +if ARCH_QCOM +source security/pfe/Kconfig +endif + + config SECURITY_DMESG_RESTRICT bool "Restrict unprivileged access to the kernel syslog" default n diff --git a/security/Makefile b/security/Makefile index 4d2d3782ddef..f15945d3800b 100644 --- a/security/Makefile +++ b/security/Makefile @@ -10,6 +10,7 @@ subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor subdir-$(CONFIG_SECURITY_YAMA) += yama subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin +subdir-$(CONFIG_ARCH_QCOM) += pfe # always enable default capabilities obj-y += commoncap.o @@ -25,6 +26,7 @@ obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/ obj-$(CONFIG_SECURITY_YAMA) += yama/ obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/ +obj-$(CONFIG_ARCH_QCOM) += pfe/ obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o # Object integrity file lists diff --git a/security/pfe/Kconfig b/security/pfe/Kconfig new file mode 100644 index 000000000000..0cd9e81a4952 --- /dev/null +++ b/security/pfe/Kconfig @@ -0,0 +1,28 @@ +menu "Qualcomm Technologies, Inc Per File Encryption security device drivers" + depends on ARCH_QCOM + +config PFT + bool "Per-File-Tagger driver" + depends on SECURITY + default n + help + This driver is used for tagging enterprise files. + It is part of the Per-File-Encryption (PFE) feature. + The driver is tagging files when created by + registered application. + Tagged files are encrypted using the dm-req-crypt driver. + +config PFK + bool "Per-File-Key driver" + depends on SECURITY + depends on SECURITY_SELINUX + default n + help + This driver is used for storing eCryptfs information + in file node. + This is part of eCryptfs hardware enhanced solution + provided by Qualcomm Technologies, Inc. + Information is used when file is encrypted later using + ICE or dm crypto engine + +endmenu diff --git a/security/pfe/Makefile b/security/pfe/Makefile new file mode 100644 index 000000000000..242a2165fccb --- /dev/null +++ b/security/pfe/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the MSM specific security device drivers. +# + +ccflags-y += -Isecurity/selinux -Isecurity/selinux/include +ccflags-y += -Ifs/ext4 +ccflags-y += -Ifs/crypto + +obj-$(CONFIG_PFT) += pft.o +obj-$(CONFIG_PFK) += pfk.o pfk_kc.o pfk_ice.o pfk_ext4.o diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c new file mode 100644 index 000000000000..b38cd5c4b05d --- /dev/null +++ b/security/pfe/pfk.c @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * Per-File-Key (PFK). + * + * This driver is responsible for overall management of various + * Per File Encryption variants that work on top of or as part of different + * file systems. + * + * The driver has the following purpose : + * 1) Define priorities between PFE's if more than one is enabled + * 2) Extract key information from inode + * 3) Load and manage various keys in ICE HW engine + * 4) It should be invoked from various layers in FS/BLOCK/STORAGE DRIVER + * that need to take decision on HW encryption management of the data + * Some examples: + * BLOCK LAYER: when it takes decision on whether 2 chunks can be united + * to one encryption / decryption request sent to the HW + * + * UFS DRIVER: when it need to configure ICE HW with a particular key slot + * to be used for encryption / decryption + * + * PFE variants can differ on particular way of storing the cryptographic info + * inside inode, actions to be taken upon file operations, etc., but the common + * properties are described above + * + */ + +#define pr_fmt(fmt) "pfk [%s]: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ext4.h" +#include "objsec.h" +#include "pfk_kc.h" +#include "pfk_ice.h" +#include "pfk_ext4.h" +#include "pfk_internal.h" + +static bool pfk_ready; + +/* might be replaced by a table when more than one cipher is supported */ +#define PFK_SUPPORTED_KEY_SIZE 32 +#define PFK_SUPPORTED_SALT_SIZE 32 + +/* Various PFE types and function tables to support each one of them */ +enum pfe_type {EXT4_CRYPT_PFE, INVALID_PFE}; + +typedef int (*pfk_parse_inode_type)(const struct bio *bio, + const struct inode *inode, + struct pfk_key_info *key_info, + enum ice_cryto_algo_mode *algo, + bool *is_pfe); + +typedef bool (*pfk_allow_merge_bio_type)(const struct bio *bio1, + const struct bio *bio2, const struct inode *inode1, + const struct inode *inode2); + +static const pfk_parse_inode_type pfk_parse_inode_ftable[] = { + /* EXT4_CRYPT_PFE */ &pfk_ext4_parse_inode, +}; + +static const pfk_allow_merge_bio_type pfk_allow_merge_bio_ftable[] = { + /* EXT4_CRYPT_PFE */ &pfk_ext4_allow_merge_bio, +}; + +static void __exit pfk_exit(void) +{ + pfk_ready = false; + pfk_ext4_deinit(); + pfk_kc_deinit(); +} + +static int __init pfk_init(void) +{ + int ret = 0; + + ret = pfk_ext4_init(); + if (ret != 0) + goto fail; + + ret = pfk_kc_init(); + if (ret != 0) { + pr_err("could init pfk key cache, error %d\n", ret); + pfk_ext4_deinit(); + goto fail; + } + + pfk_ready = true; + pr_info("Driver initialized successfully\n"); + + return 0; + +fail: + pr_err("Failed to init driver\n"); + return -ENODEV; +} + +/* + * If more than one type is supported simultaneously, this function will also + * set the priority between them + */ +static enum pfe_type pfk_get_pfe_type(const struct inode *inode) +{ + if (!inode) + return INVALID_PFE; + + if (pfk_is_ext4_type(inode)) + return EXT4_CRYPT_PFE; + + return INVALID_PFE; +} + +/** + * inode_to_filename() - get the filename from inode pointer. + * @inode: inode pointer + * + * it is used for debug prints. + * + * Return: filename string or "unknown". + */ +char *inode_to_filename(const struct inode *inode) +{ + struct dentry *dentry = NULL; + char *filename = NULL; + + if (hlist_empty(&inode->i_dentry)) + return "unknown"; + + dentry = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); + filename = dentry->d_iname; + + return filename; +} + +/** + * pfk_is_ready() - driver is initialized and ready. + * + * Return: true if the driver is ready. + */ +static inline bool pfk_is_ready(void) +{ + return pfk_ready; +} + +/** + * pfk_bio_get_inode() - get the inode from a bio. + * @bio: Pointer to BIO structure. + * + * Walk the bio struct links to get the inode. + * Please note, that in general bio may consist of several pages from + * several files, but in our case we always assume that all pages come + * from the same file, since our logic ensures it. That is why we only + * walk through the first page to look for inode. + * + * Return: pointer to the inode struct if successful, or NULL otherwise. + * + */ +static struct inode *pfk_bio_get_inode(const struct bio *bio) +{ + struct address_space *mapping; + + if (!bio) + return NULL; + if (!bio->bi_io_vec) + return NULL; + if (!bio->bi_io_vec->bv_page) + return NULL; + if (!bio_has_data((struct bio *)bio)) + return NULL; + + if (PageAnon(bio->bi_io_vec->bv_page)) { + struct inode *inode; + + inode = dio_bio_get_inode((struct bio *)bio); + pr_debug("inode on direct-io, inode = 0x%pK.\n", inode); + return inode; + } + + mapping = page_mapping(bio->bi_io_vec->bv_page); + if (!mapping) + return NULL; + + if (!mapping->host) + return NULL; + + return bio->bi_io_vec->bv_page->mapping->host; +} + +/** + * pfk_key_size_to_key_type() - translate key size to key size enum + * @key_size: key size in bytes + * @key_size_type: pointer to store the output enum (can be null) + * + * return 0 in case of success, error otherwise (i.e not supported key size) + */ +int pfk_key_size_to_key_type(size_t key_size, + enum ice_crpto_key_size *key_size_type) +{ + /* + * currently only 32 bit key size is supported + * in the future, table with supported key sizes might + * be introduced + */ + + if (key_size != PFK_SUPPORTED_KEY_SIZE) { + pr_err("not supported key size %zu\n", key_size); + return -EINVAL; + } + + if (key_size_type) + *key_size_type = ICE_CRYPTO_KEY_SIZE_256; + + return 0; +} + +/* + * Retrieves filesystem type from inode's superblock + */ +bool pfe_is_inode_filesystem_type(const struct inode *inode, + const char *fs_type) +{ + if (!inode || !fs_type) + return false; + + if (!inode->i_sb) + return false; + + if (!inode->i_sb->s_type) + return false; + + return (strcmp(inode->i_sb->s_type->name, fs_type) == 0); +} + + +/** + * pfk_load_key_start() - loads PFE encryption key to the ICE + * Can also be invoked from non + * PFE context, in this case it + * is not relevant and is_pfe + * flag is set to false + * + * @bio: Pointer to the BIO structure + * @ice_setting: Pointer to ice setting structure that will be filled with + * ice configuration values, including the index to which the key was loaded + * @is_pfe: will be false if inode is not relevant to PFE, in such a case + * it should be treated as non PFE by the block layer + * + * Returns the index where the key is stored in encryption hw and additional + * information that will be used later for configuration of the encryption hw. + * + * Must be followed by pfk_load_key_end when key is no longer used by ice + * + */ +int pfk_load_key_start(const struct bio *bio, + struct ice_crypto_setting *ice_setting, bool *is_pfe, + bool async) +{ + int ret = 0; + struct pfk_key_info key_info = {NULL, NULL, 0, 0}; + enum ice_cryto_algo_mode algo_mode = ICE_CRYPTO_ALGO_MODE_AES_XTS; + enum ice_crpto_key_size key_size_type = 0; + u32 key_index = 0; + struct inode *inode = NULL; + enum pfe_type which_pfe = INVALID_PFE; + + if (!is_pfe) { + pr_err("is_pfe is NULL\n"); + return -EINVAL; + } + + /* + * only a few errors below can indicate that + * this function was not invoked within PFE context, + * otherwise we will consider it PFE + */ + *is_pfe = true; + + if (!pfk_is_ready()) + return -ENODEV; + + if (!ice_setting) { + pr_err("ice setting is NULL\n"); + return -EINVAL; + } + inode = pfk_bio_get_inode(bio); + if (!inode) { + *is_pfe = false; + return -EINVAL; + } + which_pfe = pfk_get_pfe_type(inode); + if (which_pfe == INVALID_PFE) { + *is_pfe = false; + return -EPERM; + } + + pr_debug("parsing file %s with PFE %d\n", + inode_to_filename(inode), which_pfe); + ret = (*(pfk_parse_inode_ftable[which_pfe])) + (bio, inode, &key_info, &algo_mode, is_pfe); + if (ret != 0) + return ret; + ret = pfk_key_size_to_key_type(key_info.key_size, &key_size_type); + if (ret != 0) + return ret; + ret = pfk_kc_load_key_start(key_info.key, key_info.key_size, + key_info.salt, key_info.salt_size, &key_index, async); + if (ret) { + if (ret != -EBUSY && ret != -EAGAIN) + pr_err("start: could not load key into pfk key cache, error %d\n", + ret); + + return ret; + } + + ice_setting->key_size = key_size_type; + ice_setting->algo_mode = algo_mode; + /* hardcoded for now */ + ice_setting->key_mode = ICE_CRYPTO_USE_LUT_SW_KEY; + ice_setting->key_index = key_index; + + pr_debug("loaded key for file %s key_index %d\n", + inode_to_filename(inode), key_index); + + return 0; +} + +/** + * pfk_load_key_end() - marks the PFE key as no longer used by ICE + * Can also be invoked from non + * PFE context, in this case it is not + * relevant and is_pfe flag is + * set to false + * + * @bio: Pointer to the BIO structure + * @is_pfe: Pointer to is_pfe flag, which will be true if function was invoked + * from PFE context + */ +int pfk_load_key_end(const struct bio *bio, bool *is_pfe) +{ + int ret = 0; + struct pfk_key_info key_info = {0}; + enum pfe_type which_pfe = INVALID_PFE; + struct inode *inode = NULL; + + if (!is_pfe) { + pr_err("is_pfe is NULL\n"); + return -EINVAL; + } + + /* only a few errors below can indicate that + * this function was not invoked within PFE context, + * otherwise we will consider it PFE + */ + *is_pfe = true; + + if (!pfk_is_ready()) + return -ENODEV; + + inode = pfk_bio_get_inode(bio); + if (!inode) { + *is_pfe = false; + return -EINVAL; + } + + which_pfe = pfk_get_pfe_type(inode); + if (which_pfe == INVALID_PFE) { + *is_pfe = false; + return -EPERM; + } + + ret = (*(pfk_parse_inode_ftable[which_pfe])) + (bio, inode, &key_info, NULL, is_pfe); + if (ret != 0) + return ret; + + pfk_kc_load_key_end(key_info.key, key_info.key_size, + key_info.salt, key_info.salt_size); + + pr_debug("finished using key for file %s\n", + inode_to_filename(inode)); + + return 0; +} + +/** + * pfk_allow_merge_bio() - Check if 2 BIOs can be merged. + * @bio1: Pointer to first BIO structure. + * @bio2: Pointer to second BIO structure. + * + * Prevent merging of BIOs from encrypted and non-encrypted + * files, or files encrypted with different key. + * Also prevent non encrypted and encrypted data from the same file + * to be merged (ecryptfs header if stored inside file should be non + * encrypted) + * This API is called by the file system block layer. + * + * Return: true if the BIOs allowed to be merged, false + * otherwise. + */ +bool pfk_allow_merge_bio(const struct bio *bio1, const struct bio *bio2) +{ + struct inode *inode1 = NULL; + struct inode *inode2 = NULL; + enum pfe_type which_pfe1 = INVALID_PFE; + enum pfe_type which_pfe2 = INVALID_PFE; + + if (!pfk_is_ready()) + return false; + + if (!bio1 || !bio2) + return false; + + if (bio1 == bio2) + return true; + + inode1 = pfk_bio_get_inode(bio1); + inode2 = pfk_bio_get_inode(bio2); + + + which_pfe1 = pfk_get_pfe_type(inode1); + which_pfe2 = pfk_get_pfe_type(inode2); + + /* nodes with different encryption, do not merge */ + if (which_pfe1 != which_pfe2) + return false; + + /* both nodes do not have encryption, allow merge */ + if (which_pfe1 == INVALID_PFE) + return true; + + return (*(pfk_allow_merge_bio_ftable[which_pfe1]))(bio1, bio2, + inode1, inode2); +} +/** + * Flush key table on storage core reset. During core reset key configuration + * is lost in ICE. We need to flash the cache, so that the keys will be + * reconfigured again for every subsequent transaction + */ +void pfk_clear_on_reset(void) +{ + if (!pfk_is_ready()) + return; + + pfk_kc_clear_on_reset(); +} + +module_init(pfk_init); +module_exit(pfk_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Per-File-Key driver"); diff --git a/security/pfe/pfk_ext4.c b/security/pfe/pfk_ext4.c new file mode 100644 index 000000000000..05a8628e34b8 --- /dev/null +++ b/security/pfe/pfk_ext4.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * Per-File-Key (PFK) - EXT4 + * + * This driver is used for working with EXT4 crypt extension + * + * The key information is stored in node by EXT4 when file is first opened + * and will be later accessed by Block Device Driver to actually load the key + * to encryption hw. + * + * PFK exposes API's for loading and removing keys from encryption hw + * and also API to determine whether 2 adjacent blocks can be agregated by + * Block Layer in one request to encryption hw. + * + */ + +#define pr_fmt(fmt) "pfk_ext4 [%s]: " fmt, __func__ + +#include +#include +#include +#include + +#include "ext4_ice.h" +#include "pfk_ext4.h" + +static bool pfk_ext4_ready; + +/* + * pfk_ext4_deinit() - Deinit function, should be invoked by upper PFK layer + */ +void pfk_ext4_deinit(void) +{ + pfk_ext4_ready = false; +} + +/* + * pfk_ecryptfs_init() - Init function, should be invoked by upper PFK layer + */ +int __init pfk_ext4_init(void) +{ + pfk_ext4_ready = true; + pr_info("PFK EXT4 inited successfully\n"); + + return 0; +} + +/** + * pfk_ecryptfs_is_ready() - driver is initialized and ready. + * + * Return: true if the driver is ready. + */ +static inline bool pfk_ext4_is_ready(void) +{ + return pfk_ext4_ready; +} + +/** + * pfk_is_ext4_type() - return true if inode belongs to ICE EXT4 PFE + * @inode: inode pointer + */ +bool pfk_is_ext4_type(const struct inode *inode) +{ + if (!pfe_is_inode_filesystem_type(inode, "ext4")) + return false; + + return ext4_should_be_processed_by_ice(inode); +} + +/** + * pfk_ext4_parse_cipher() - parse cipher from inode to enum + * @inode: inode + * @algo: pointer to store the output enum (can be null) + * + * return 0 in case of success, error otherwise (i.e not supported cipher) + */ +static int pfk_ext4_parse_cipher(const struct inode *inode, + enum ice_cryto_algo_mode *algo) +{ + /* + * currently only AES XTS algo is supported + * in the future, table with supported ciphers might + * be introduced + */ + + if (!inode) + return -EINVAL; + + if (!ext4_is_aes_xts_cipher(inode)) { + pr_err("ext4 alghoritm is not supported by pfk\n"); + return -EINVAL; + } + + if (algo) + *algo = ICE_CRYPTO_ALGO_MODE_AES_XTS; + + return 0; +} + +int pfk_ext4_parse_inode(const struct bio *bio, + const struct inode *inode, + struct pfk_key_info *key_info, + enum ice_cryto_algo_mode *algo, + bool *is_pfe) +{ + int ret = 0; + + if (!is_pfe) + return -EINVAL; + + /* + * only a few errors below can indicate that + * this function was not invoked within PFE context, + * otherwise we will consider it PFE + */ + *is_pfe = true; + + if (!pfk_ext4_is_ready()) + return -ENODEV; + + if (!inode) + return -EINVAL; + + if (!key_info) + return -EINVAL; + + key_info->key = ext4_get_ice_encryption_key(inode); + if (!key_info->key) { + pr_err("could not parse key from ext4\n"); + return -EINVAL; + } + + key_info->key_size = ext4_get_ice_encryption_key_size(inode); + if (!key_info->key_size) { + pr_err("could not parse key size from ext4\n"); + return -EINVAL; + } + + key_info->salt = ext4_get_ice_encryption_salt(inode); + if (!key_info->salt) { + pr_err("could not parse salt from ext4\n"); + return -EINVAL; + } + + key_info->salt_size = ext4_get_ice_encryption_salt_size(inode); + if (!key_info->salt_size) { + pr_err("could not parse salt size from ext4\n"); + return -EINVAL; + } + + ret = pfk_ext4_parse_cipher(inode, algo); + if (ret != 0) { + pr_err("not supported cipher\n"); + return ret; + } + + return 0; +} + +bool pfk_ext4_allow_merge_bio(const struct bio *bio1, + const struct bio *bio2, const struct inode *inode1, + const struct inode *inode2) +{ + /* if there is no ext4 pfk, don't disallow merging blocks */ + if (!pfk_ext4_is_ready()) + return true; + + if (!inode1 || !inode2) + return false; + + return ext4_is_ice_encryption_info_equal(inode1, inode2); +} diff --git a/security/pfe/pfk_ext4.h b/security/pfe/pfk_ext4.h new file mode 100644 index 000000000000..c33232f35a14 --- /dev/null +++ b/security/pfe/pfk_ext4.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _PFK_EXT4_H_ +#define _PFK_EXT4_H_ + +#include +#include +#include +#include "pfk_internal.h" + +bool pfk_is_ext4_type(const struct inode *inode); + +int pfk_ext4_parse_inode(const struct bio *bio, + const struct inode *inode, + struct pfk_key_info *key_info, + enum ice_cryto_algo_mode *algo, + bool *is_pfe); + +bool pfk_ext4_allow_merge_bio(const struct bio *bio1, + const struct bio *bio2, const struct inode *inode1, + const struct inode *inode2); + +int __init pfk_ext4_init(void); + +void pfk_ext4_deinit(void); + +#endif /* _PFK_EXT4_H_ */ diff --git a/security/pfe/pfk_ice.c b/security/pfe/pfk_ice.c new file mode 100644 index 000000000000..bf60dd18dd76 --- /dev/null +++ b/security/pfe/pfk_ice.c @@ -0,0 +1,181 @@ +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pfk_ice.h" + + +/**********************************/ +/** global definitions **/ +/**********************************/ + +#define TZ_ES_SET_ICE_KEY 0x2 +#define TZ_ES_INVALIDATE_ICE_KEY 0x3 + +/* index 0 and 1 is reserved for FDE */ +#define MIN_ICE_KEY_INDEX 2 + +#define MAX_ICE_KEY_INDEX 31 + +#define TZ_ES_SET_ICE_KEY_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_ES, TZ_ES_SET_ICE_KEY) + +#define TZ_ES_INVALIDATE_ICE_KEY_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, \ + TZ_SVC_ES, TZ_ES_INVALIDATE_ICE_KEY) + +#define TZ_ES_SET_ICE_KEY_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_5( \ + TZ_SYSCALL_PARAM_TYPE_VAL, \ + TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL, \ + TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL) + +#define TZ_ES_INVALIDATE_ICE_KEY_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_1( \ + TZ_SYSCALL_PARAM_TYPE_VAL) + +#define ICE_KEY_SIZE 32 +#define ICE_SALT_SIZE 32 + +static uint8_t ice_key[ICE_KEY_SIZE]; +static uint8_t ice_salt[ICE_KEY_SIZE]; + +int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt, + char *storage_type) +{ + struct scm_desc desc = {0}; + int ret, ret1; + char *tzbuf_key = (char *)ice_key; + char *tzbuf_salt = (char *)ice_salt; + char *s_type = storage_type; + uint32_t smc_id = 0; + u32 tzbuflen_key = sizeof(ice_key); + u32 tzbuflen_salt = sizeof(ice_salt); + + if (index < MIN_ICE_KEY_INDEX || index > MAX_ICE_KEY_INDEX) { + pr_err("%s Invalid index %d\n", __func__, index); + return -EINVAL; + } + if (!key || !salt) { + pr_err("%s Invalid key/salt\n", __func__); + return -EINVAL; + } + + if (!tzbuf_key || !tzbuf_salt) { + pr_err("%s No Memory\n", __func__); + return -ENOMEM; + } + + if (s_type == NULL) { + pr_err("%s Invalid Storage type\n", __func__); + return -EINVAL; + } + + memset(tzbuf_key, 0, tzbuflen_key); + memset(tzbuf_salt, 0, tzbuflen_salt); + + memcpy(ice_key, key, tzbuflen_key); + memcpy(ice_salt, salt, tzbuflen_salt); + + dmac_flush_range(tzbuf_key, tzbuf_key + tzbuflen_key); + dmac_flush_range(tzbuf_salt, tzbuf_salt + tzbuflen_salt); + + smc_id = TZ_ES_SET_ICE_KEY_ID; + + desc.arginfo = TZ_ES_SET_ICE_KEY_PARAM_ID; + desc.args[0] = index; + desc.args[1] = virt_to_phys(tzbuf_key); + desc.args[2] = tzbuflen_key; + desc.args[3] = virt_to_phys(tzbuf_salt); + desc.args[4] = tzbuflen_salt; + + ret = qcom_ice_setup_ice_hw((const char *)s_type, true); + if (ret) { + pr_err("%s: could not enable clocks: %d\n", __func__, ret); + goto out; + } + + ret = scm_call2(smc_id, &desc); + if (ret) { + pr_err("%s: Set Key Error: %d\n", __func__, ret); + if (ret == -EBUSY) { + if (qcom_ice_setup_ice_hw((const char *)s_type, false)) + pr_err("%s: clock disable failed\n", __func__); + goto out; + } + /* Try to invalidate the key to keep ICE in proper state */ + smc_id = TZ_ES_INVALIDATE_ICE_KEY_ID; + desc.arginfo = TZ_ES_INVALIDATE_ICE_KEY_PARAM_ID; + desc.args[0] = index; + ret1 = scm_call2(smc_id, &desc); + if (ret1) + pr_err("%s: Invalidate Key Error: %d\n", __func__, + ret1); + } + + ret1 = qcom_ice_setup_ice_hw((const char *)s_type, false); + if (ret1) + pr_err("%s: Error %d disabling clocks\n", __func__, ret1); + +out: + return ret; +} + +int qti_pfk_ice_invalidate_key(uint32_t index, char *storage_type) +{ + struct scm_desc desc = {0}; + int ret = 0; + + uint32_t smc_id = 0; + + if (index < MIN_ICE_KEY_INDEX || index > MAX_ICE_KEY_INDEX) { + pr_err("%s Invalid index %d\n", __func__, index); + return -EINVAL; + } + + if (storage_type == NULL) { + pr_err("%s Invalid Storage type\n", __func__); + return -EINVAL; + } + + smc_id = TZ_ES_INVALIDATE_ICE_KEY_ID; + + desc.arginfo = TZ_ES_INVALIDATE_ICE_KEY_PARAM_ID; + desc.args[0] = index; + + ret = qcom_ice_setup_ice_hw((const char *)storage_type, true); + if (ret) { + pr_err("%s: could not enable clocks: 0x%x\n", __func__, ret); + return ret; + } + + ret = scm_call2(smc_id, &desc); + if (ret) + pr_err("%s: Error: 0x%x\n", __func__, ret); + + if (qcom_ice_setup_ice_hw((const char *)storage_type, false)) + pr_err("%s: could not disable clocks\n", __func__); + + return ret; +} diff --git a/security/pfe/pfk_ice.h b/security/pfe/pfk_ice.h new file mode 100644 index 000000000000..a00193919116 --- /dev/null +++ b/security/pfe/pfk_ice.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef PFK_ICE_H_ +#define PFK_ICE_H_ + +/* + * PFK ICE + * + * ICE keys configuration through scm calls. + * + */ + +#include + +int pfk_ice_init(void); +int pfk_ice_deinit(void); + +int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt, + char *storage_type); +int qti_pfk_ice_invalidate_key(uint32_t index, char *storage_type); + +#endif /* PFK_ICE_H_ */ diff --git a/security/pfe/pfk_internal.h b/security/pfe/pfk_internal.h new file mode 100644 index 000000000000..3214327b8bcd --- /dev/null +++ b/security/pfe/pfk_internal.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _PFK_INTERNAL_H_ +#define _PFK_INTERNAL_H_ + +#include +#include + +struct pfk_key_info { + const unsigned char *key; + const unsigned char *salt; + size_t key_size; + size_t salt_size; +}; + +int pfk_key_size_to_key_type(size_t key_size, + enum ice_crpto_key_size *key_size_type); + +bool pfe_is_inode_filesystem_type(const struct inode *inode, + const char *fs_type); + +char *inode_to_filename(const struct inode *inode); + +#endif /* _PFK_INTERNAL_H_ */ diff --git a/security/pfe/pfk_kc.c b/security/pfe/pfk_kc.c new file mode 100644 index 000000000000..6ccfbd1a5484 --- /dev/null +++ b/security/pfe/pfk_kc.c @@ -0,0 +1,905 @@ +/* + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * PFK Key Cache + * + * Key Cache used internally in PFK. + * The purpose of the cache is to save access time to QSEE when loading keys. + * Currently the cache is the same size as the total number of keys that can + * be loaded to ICE. Since this number is relatively small, the algorithms for + * cache eviction are simple, linear and based on last usage timestamp, i.e + * the node that will be evicted is the one with the oldest timestamp. + * Empty entries always have the oldest timestamp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pfk_kc.h" +#include "pfk_ice.h" + + +/** the first available index in ice engine */ +#define PFK_KC_STARTING_INDEX 2 + +/** currently the only supported key and salt sizes */ +#define PFK_KC_KEY_SIZE 32 +#define PFK_KC_SALT_SIZE 32 + +/** Table size */ +/* TODO replace by some constant from ice.h */ +#define PFK_KC_TABLE_SIZE ((32) - (PFK_KC_STARTING_INDEX)) + +/** The maximum key and salt size */ +#define PFK_MAX_KEY_SIZE PFK_KC_KEY_SIZE +#define PFK_MAX_SALT_SIZE PFK_KC_SALT_SIZE +#define PFK_UFS "ufs" + +static DEFINE_SPINLOCK(kc_lock); +static unsigned long flags; +static bool kc_ready; +static char *s_type = "sdcc"; + +/** + * enum pfk_kc_entry_state - state of the entry inside kc table + * + * @FREE: entry is free + * @ACTIVE_ICE_PRELOAD: entry is actively used by ICE engine + and cannot be used by others. SCM call + to load key to ICE is pending to be performed + * @ACTIVE_ICE_LOADED: entry is actively used by ICE engine and + cannot be used by others. SCM call to load the + key to ICE was successfully executed and key is + now loaded + * @INACTIVE_INVALIDATING: entry is being invalidated during file close + and cannot be used by others until invalidation + is complete + * @INACTIVE: entry's key is already loaded, but is not + currently being used. It can be re-used for + optimization and to avoid SCM call cost or + it can be taken by another key if there are + no FREE entries + * @SCM_ERROR: error occurred while scm call was performed to + load the key to ICE + */ +enum pfk_kc_entry_state { + FREE, + ACTIVE_ICE_PRELOAD, + ACTIVE_ICE_LOADED, + INACTIVE_INVALIDATING, + INACTIVE, + SCM_ERROR +}; + +struct kc_entry { + unsigned char key[PFK_MAX_KEY_SIZE]; + size_t key_size; + + unsigned char salt[PFK_MAX_SALT_SIZE]; + size_t salt_size; + + u64 time_stamp; + u32 key_index; + + struct task_struct *thread_pending; + + enum pfk_kc_entry_state state; + + /* ref count for the number of requests in the HW queue for this key */ + int loaded_ref_cnt; + int scm_error; +}; + +static struct kc_entry kc_table[PFK_KC_TABLE_SIZE]; + +/** + * kc_is_ready() - driver is initialized and ready. + * + * Return: true if the key cache is ready. + */ +static inline bool kc_is_ready(void) +{ + return kc_ready; +} + +static inline void kc_spin_lock(void) +{ + spin_lock_irqsave(&kc_lock, flags); +} + +static inline void kc_spin_unlock(void) +{ + spin_unlock_irqrestore(&kc_lock, flags); +} + +/** + * kc_entry_is_available() - checks whether the entry is available + * + * Return true if it is , false otherwise or if invalid + * Should be invoked under spinlock + */ +static bool kc_entry_is_available(const struct kc_entry *entry) +{ + if (!entry) + return false; + + return (entry->state == FREE || entry->state == INACTIVE); +} + +/** + * kc_entry_wait_till_available() - waits till entry is available + * + * Returns 0 in case of success or -ERESTARTSYS if the wait was interrupted + * by signal + * + * Should be invoked under spinlock + */ +static int kc_entry_wait_till_available(struct kc_entry *entry) +{ + int res = 0; + + while (!kc_entry_is_available(entry)) { + set_current_state(TASK_INTERRUPTIBLE); + if (signal_pending(current)) { + res = -ERESTARTSYS; + break; + } + /* assuming only one thread can try to invalidate + * the same entry + */ + entry->thread_pending = current; + kc_spin_unlock(); + schedule(); + kc_spin_lock(); + } + set_current_state(TASK_RUNNING); + + return res; +} + +/** + * kc_entry_start_invalidating() - moves entry to state + * INACTIVE_INVALIDATING + * If entry is in use, waits till + * it gets available + * @entry: pointer to entry + * + * Return 0 in case of success, otherwise error + * Should be invoked under spinlock + */ +static int kc_entry_start_invalidating(struct kc_entry *entry) +{ + int res; + + res = kc_entry_wait_till_available(entry); + if (res) + return res; + + entry->state = INACTIVE_INVALIDATING; + + return 0; +} + +/** + * kc_entry_finish_invalidating() - moves entry to state FREE + * wakes up all the tasks waiting + * on it + * + * @entry: pointer to entry + * + * Return 0 in case of success, otherwise error + * Should be invoked under spinlock + */ +static void kc_entry_finish_invalidating(struct kc_entry *entry) +{ + if (!entry) + return; + + if (entry->state != INACTIVE_INVALIDATING) + return; + + entry->state = FREE; +} + +/** + * kc_min_entry() - compare two entries to find one with minimal time + * @a: ptr to the first entry. If NULL the other entry will be returned + * @b: pointer to the second entry + * + * Return the entry which timestamp is the minimal, or b if a is NULL + */ +static inline struct kc_entry *kc_min_entry(struct kc_entry *a, + struct kc_entry *b) +{ + if (!a) + return b; + + if (time_before64(b->time_stamp, a->time_stamp)) + return b; + + return a; +} + +/** + * kc_entry_at_index() - return entry at specific index + * @index: index of entry to be accessed + * + * Return entry + * Should be invoked under spinlock + */ +static struct kc_entry *kc_entry_at_index(int index) +{ + return &(kc_table[index]); +} + +/** + * kc_find_key_at_index() - find kc entry starting at specific index + * @key: key to look for + * @key_size: the key size + * @salt: salt to look for + * @salt_size: the salt size + * @sarting_index: index to start search with, if entry found, updated with + * index of that entry + * + * Return entry or NULL in case of error + * Should be invoked under spinlock + */ +static struct kc_entry *kc_find_key_at_index(const unsigned char *key, + size_t key_size, const unsigned char *salt, size_t salt_size, + int *starting_index) +{ + struct kc_entry *entry = NULL; + int i = 0; + + for (i = *starting_index; i < PFK_KC_TABLE_SIZE; i++) { + entry = kc_entry_at_index(i); + + if (salt != NULL) { + if (entry->salt_size != salt_size) + continue; + + if (memcmp(entry->salt, salt, salt_size) != 0) + continue; + } + + if (entry->key_size != key_size) + continue; + + if (memcmp(entry->key, key, key_size) == 0) { + *starting_index = i; + return entry; + } + } + + return NULL; +} + +/** + * kc_find_key() - find kc entry + * @key: key to look for + * @key_size: the key size + * @salt: salt to look for + * @salt_size: the salt size + * + * Return entry or NULL in case of error + * Should be invoked under spinlock + */ +static struct kc_entry *kc_find_key(const unsigned char *key, size_t key_size, + const unsigned char *salt, size_t salt_size) +{ + int index = 0; + + return kc_find_key_at_index(key, key_size, salt, salt_size, &index); +} + +/** + * kc_find_oldest_entry_non_locked() - finds the entry with minimal timestamp + * that is not locked + * + * Returns entry with minimal timestamp. Empty entries have timestamp + * of 0, therefore they are returned first. + * If all the entries are locked, will return NULL + * Should be invoked under spin lock + */ +static struct kc_entry *kc_find_oldest_entry_non_locked(void) +{ + struct kc_entry *curr_min_entry = NULL; + struct kc_entry *entry = NULL; + int i = 0; + + for (i = 0; i < PFK_KC_TABLE_SIZE; i++) { + entry = kc_entry_at_index(i); + + if (entry->state == FREE) + return entry; + + if (entry->state == INACTIVE) + curr_min_entry = kc_min_entry(curr_min_entry, entry); + } + + return curr_min_entry; +} + +/** + * kc_update_timestamp() - updates timestamp of entry to current + * + * @entry: entry to update + * + */ +static void kc_update_timestamp(struct kc_entry *entry) +{ + if (!entry) + return; + + entry->time_stamp = get_jiffies_64(); +} + +/** + * kc_clear_entry() - clear the key from entry and mark entry not in use + * + * @entry: pointer to entry + * + * Should be invoked under spinlock + */ +static void kc_clear_entry(struct kc_entry *entry) +{ + if (!entry) + return; + + memset(entry->key, 0, entry->key_size); + memset(entry->salt, 0, entry->salt_size); + + entry->key_size = 0; + entry->salt_size = 0; + + entry->time_stamp = 0; + entry->scm_error = 0; + + entry->state = FREE; + + entry->loaded_ref_cnt = 0; + entry->thread_pending = NULL; +} + +/** + * kc_update_entry() - replaces the key in given entry and + * loads the new key to ICE + * + * @entry: entry to replace key in + * @key: key + * @key_size: key_size + * @salt: salt + * @salt_size: salt_size + * + * The previous key is securely released and wiped, the new one is loaded + * to ICE. + * Should be invoked under spinlock + */ +static int kc_update_entry(struct kc_entry *entry, const unsigned char *key, + size_t key_size, const unsigned char *salt, size_t salt_size) +{ + int ret; + + kc_clear_entry(entry); + + memcpy(entry->key, key, key_size); + entry->key_size = key_size; + + memcpy(entry->salt, salt, salt_size); + entry->salt_size = salt_size; + + /* Mark entry as no longer free before releasing the lock */ + entry->state = ACTIVE_ICE_PRELOAD; + kc_spin_unlock(); + + ret = qti_pfk_ice_set_key(entry->key_index, entry->key, + entry->salt, s_type); + + kc_spin_lock(); + return ret; +} + +/** + * pfk_kc_init() - init function + * + * Return 0 in case of success, error otherwise + */ +int pfk_kc_init(void) +{ + int i = 0; + struct kc_entry *entry = NULL; + + kc_spin_lock(); + for (i = 0; i < PFK_KC_TABLE_SIZE; i++) { + entry = kc_entry_at_index(i); + entry->key_index = PFK_KC_STARTING_INDEX + i; + } + kc_ready = true; + kc_spin_unlock(); + return 0; +} + +/** + * pfk_kc_denit() - deinit function + * + * Return 0 in case of success, error otherwise + */ +int pfk_kc_deinit(void) +{ + int res = pfk_kc_clear(); + + kc_ready = false; + return res; +} + +/** + * pfk_kc_load_key_start() - retrieve the key from cache or add it if + * it's not there and return the ICE hw key index in @key_index. + * @key: pointer to the key + * @key_size: the size of the key + * @salt: pointer to the salt + * @salt_size: the size of the salt + * @key_index: the pointer to key_index where the output will be stored + * @async: whether scm calls are allowed in the caller context + * + * If key is present in cache, than the key_index will be retrieved from cache. + * If it is not present, the oldest entry from kc table will be evicted, + * the key will be loaded to ICE via QSEE to the index that is the evicted + * entry number and stored in cache. + * Entry that is going to be used is marked as being used, it will mark + * as not being used when ICE finishes using it and pfk_kc_load_key_end + * will be invoked. + * As QSEE calls can only be done from a non-atomic context, when @async flag + * is set to 'false', it specifies that it is ok to make the calls in the + * current context. Otherwise, when @async is set, the caller should retry the + * call again from a different context, and -EAGAIN error will be returned. + * + * Return 0 in case of success, error otherwise + */ +int pfk_kc_load_key_start(const unsigned char *key, size_t key_size, + const unsigned char *salt, size_t salt_size, u32 *key_index, + bool async) +{ + int ret = 0; + struct kc_entry *entry = NULL; + bool entry_exists = false; + + if (!kc_is_ready()) + return -ENODEV; + + if (!key || !salt || !key_index) { + pr_err("%s key/salt/key_index NULL\n", __func__); + return -EINVAL; + } + + if (key_size != PFK_KC_KEY_SIZE) { + pr_err("unsupported key size %zu\n", key_size); + return -EINVAL; + } + + if (salt_size != PFK_KC_SALT_SIZE) { + pr_err("unsupported salt size %zu\n", salt_size); + return -EINVAL; + } + + kc_spin_lock(); + + entry = kc_find_key(key, key_size, salt, salt_size); + if (!entry) { + if (async) { + pr_debug("%s task will populate entry\n", __func__); + kc_spin_unlock(); + return -EAGAIN; + } + + entry = kc_find_oldest_entry_non_locked(); + if (!entry) { + /* could not find a single non locked entry, + * return EBUSY to upper layers so that the + * request will be rescheduled + */ + kc_spin_unlock(); + return -EBUSY; + } + } else { + entry_exists = true; + } + + pr_debug("entry with index %d is in state %d\n", + entry->key_index, entry->state); + + switch (entry->state) { + case (INACTIVE): + if (entry_exists) { + kc_update_timestamp(entry); + entry->state = ACTIVE_ICE_LOADED; + + if (!strcmp(s_type, (char *)PFK_UFS)) { + if (async) + entry->loaded_ref_cnt++; + } else { + entry->loaded_ref_cnt++; + } + break; + } + case (FREE): + ret = kc_update_entry(entry, key, key_size, salt, salt_size); + if (ret) { + entry->state = SCM_ERROR; + entry->scm_error = ret; + pr_err("%s: key load error (%d)\n", __func__, ret); + } else { + kc_update_timestamp(entry); + entry->state = ACTIVE_ICE_LOADED; + + /* + * In case of UFS only increase ref cnt for async calls, + * sync calls from within work thread do not pass + * requests further to HW + */ + if (!strcmp(s_type, (char *)PFK_UFS)) { + if (async) + entry->loaded_ref_cnt++; + } else { + entry->loaded_ref_cnt++; + } + } + break; + case (ACTIVE_ICE_PRELOAD): + case (INACTIVE_INVALIDATING): + ret = -EAGAIN; + break; + case (ACTIVE_ICE_LOADED): + kc_update_timestamp(entry); + + if (!strcmp(s_type, (char *)PFK_UFS)) { + if (async) + entry->loaded_ref_cnt++; + } else { + entry->loaded_ref_cnt++; + } + break; + case(SCM_ERROR): + ret = entry->scm_error; + kc_clear_entry(entry); + entry->state = FREE; + break; + default: + pr_err("invalid state %d for entry with key index %d\n", + entry->state, entry->key_index); + ret = -EINVAL; + } + + *key_index = entry->key_index; + kc_spin_unlock(); + + return ret; +} + +/** + * pfk_kc_load_key_end() - finish the process of key loading that was started + * by pfk_kc_load_key_start + * by marking the entry as not + * being in use + * @key: pointer to the key + * @key_size: the size of the key + * @salt: pointer to the salt + * @salt_size: the size of the salt + * + */ +void pfk_kc_load_key_end(const unsigned char *key, size_t key_size, + const unsigned char *salt, size_t salt_size) +{ + struct kc_entry *entry = NULL; + struct task_struct *tmp_pending = NULL; + int ref_cnt = 0; + + if (!kc_is_ready()) + return; + + if (!key || !salt) + return; + + if (key_size != PFK_KC_KEY_SIZE) + return; + + if (salt_size != PFK_KC_SALT_SIZE) + return; + + kc_spin_lock(); + + entry = kc_find_key(key, key_size, salt, salt_size); + if (!entry) { + kc_spin_unlock(); + pr_err("internal error, there should an entry to unlock\n"); + + return; + } + ref_cnt = --entry->loaded_ref_cnt; + + if (ref_cnt < 0) + pr_err("internal error, ref count should never be negative\n"); + + if (!ref_cnt) { + entry->state = INACTIVE; + /* + * wake-up invalidation if it's waiting + * for the entry to be released + */ + if (entry->thread_pending) { + tmp_pending = entry->thread_pending; + entry->thread_pending = NULL; + + kc_spin_unlock(); + wake_up_process(tmp_pending); + return; + } + } + + kc_spin_unlock(); +} + +/** + * pfk_kc_remove_key() - remove the key from cache and from ICE engine + * @key: pointer to the key + * @key_size: the size of the key + * @salt: pointer to the key + * @salt_size: the size of the key + * + * Return 0 in case of success, error otherwise (also in case of non + * (existing key) + */ +int pfk_kc_remove_key_with_salt(const unsigned char *key, size_t key_size, + const unsigned char *salt, size_t salt_size) +{ + struct kc_entry *entry = NULL; + int res = 0; + + if (!kc_is_ready()) + return -ENODEV; + + if (!key) + return -EINVAL; + + if (!salt) + return -EINVAL; + + if (key_size != PFK_KC_KEY_SIZE) + return -EINVAL; + + if (salt_size != PFK_KC_SALT_SIZE) + return -EINVAL; + + kc_spin_lock(); + + entry = kc_find_key(key, key_size, salt, salt_size); + if (!entry) { + pr_debug("%s: key does not exist\n", __func__); + kc_spin_unlock(); + return -EINVAL; + } + + res = kc_entry_start_invalidating(entry); + if (res != 0) { + kc_spin_unlock(); + return res; + } + kc_clear_entry(entry); + + kc_spin_unlock(); + + qti_pfk_ice_invalidate_key(entry->key_index, s_type); + + kc_spin_lock(); + kc_entry_finish_invalidating(entry); + kc_spin_unlock(); + + return 0; +} + +/** + * pfk_kc_remove_key() - remove the key from cache and from ICE engine + * when no salt is available. Will only search key part, if there are several, + * all will be removed + * + * @key: pointer to the key + * @key_size: the size of the key + * + * Return 0 in case of success, error otherwise (also for non-existing key) + */ +int pfk_kc_remove_key(const unsigned char *key, size_t key_size) +{ + struct kc_entry *entry = NULL; + int index = 0; + int temp_indexes[PFK_KC_TABLE_SIZE] = {0}; + int temp_indexes_size = 0; + int i = 0; + int res = 0; + + if (!kc_is_ready()) + return -ENODEV; + + if (!key) + return -EINVAL; + + if (key_size != PFK_KC_KEY_SIZE) + return -EINVAL; + + memset(temp_indexes, -1, sizeof(temp_indexes)); + + kc_spin_lock(); + + entry = kc_find_key_at_index(key, key_size, NULL, 0, &index); + if (!entry) { + pr_err("%s: key does not exist\n", __func__); + kc_spin_unlock(); + return -EINVAL; + } + + res = kc_entry_start_invalidating(entry); + if (res != 0) { + kc_spin_unlock(); + return res; + } + + temp_indexes[temp_indexes_size++] = index; + kc_clear_entry(entry); + + /* let's clean additional entries with the same key if there are any */ + do { + index++; + entry = kc_find_key_at_index(key, key_size, NULL, 0, &index); + if (!entry) + break; + + res = kc_entry_start_invalidating(entry); + if (res != 0) { + kc_spin_unlock(); + goto out; + } + + temp_indexes[temp_indexes_size++] = index; + + kc_clear_entry(entry); + + + } while (true); + + kc_spin_unlock(); + + temp_indexes_size--; + for (i = temp_indexes_size; i >= 0 ; i--) + qti_pfk_ice_invalidate_key( + kc_entry_at_index(temp_indexes[i])->key_index, + s_type); + + /* fall through */ + res = 0; + +out: + kc_spin_lock(); + for (i = temp_indexes_size; i >= 0 ; i--) + kc_entry_finish_invalidating( + kc_entry_at_index(temp_indexes[i])); + kc_spin_unlock(); + + return res; +} + +/** + * pfk_kc_clear() - clear the table and remove all keys from ICE + * + * Return 0 on success, error otherwise + * + */ +int pfk_kc_clear(void) +{ + struct kc_entry *entry = NULL; + int i = 0; + int res = 0; + + if (!kc_is_ready()) + return -ENODEV; + + kc_spin_lock(); + for (i = 0; i < PFK_KC_TABLE_SIZE; i++) { + entry = kc_entry_at_index(i); + res = kc_entry_start_invalidating(entry); + if (res != 0) { + kc_spin_unlock(); + goto out; + } + kc_clear_entry(entry); + } + kc_spin_unlock(); + + for (i = 0; i < PFK_KC_TABLE_SIZE; i++) + qti_pfk_ice_invalidate_key(kc_entry_at_index(i)->key_index, + s_type); + + /* fall through */ + res = 0; +out: + kc_spin_lock(); + for (i = 0; i < PFK_KC_TABLE_SIZE; i++) + kc_entry_finish_invalidating(kc_entry_at_index(i)); + kc_spin_unlock(); + + return res; +} + +/** + * pfk_kc_clear_on_reset() - clear the table and remove all keys from ICE + * The assumption is that at this point we don't have any pending transactions + * Also, there is no need to clear keys from ICE + * + * Return 0 on success, error otherwise + * + */ +void pfk_kc_clear_on_reset(void) +{ + struct kc_entry *entry = NULL; + int i = 0; + + if (!kc_is_ready()) + return; + + kc_spin_lock(); + for (i = 0; i < PFK_KC_TABLE_SIZE; i++) { + entry = kc_entry_at_index(i); + kc_clear_entry(entry); + } + kc_spin_unlock(); +} + +static int pfk_kc_find_storage_type(char **device) +{ + char boot[20] = {'\0'}; + char *match = (char *)strnstr(saved_command_line, + "androidboot.bootdevice=", + strlen(saved_command_line)); + if (match) { + memcpy(boot, (match + strlen("androidboot.bootdevice=")), + sizeof(boot) - 1); + if (strnstr(boot, PFK_UFS, strlen(boot))) + *device = PFK_UFS; + + return 0; + } + return -EINVAL; +} + +static int __init pfk_kc_pre_init(void) +{ + return pfk_kc_find_storage_type(&s_type); +} + +static void __exit pfk_kc_exit(void) +{ + s_type = NULL; +} + +module_init(pfk_kc_pre_init); +module_exit(pfk_kc_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Per-File-Key-KC driver"); diff --git a/security/pfe/pfk_kc.h b/security/pfe/pfk_kc.h new file mode 100644 index 000000000000..6adeee2259cd --- /dev/null +++ b/security/pfe/pfk_kc.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef PFK_KC_H_ +#define PFK_KC_H_ + +#include + +int pfk_kc_init(void); +int pfk_kc_deinit(void); +int pfk_kc_load_key_start(const unsigned char *key, size_t key_size, + const unsigned char *salt, size_t salt_size, u32 *key_index, + bool async); +void pfk_kc_load_key_end(const unsigned char *key, size_t key_size, + const unsigned char *salt, size_t salt_size); +int pfk_kc_remove_key_with_salt(const unsigned char *key, size_t key_size, + const unsigned char *salt, size_t salt_size); +int pfk_kc_remove_key(const unsigned char *key, size_t key_size); +int pfk_kc_clear(void); +void pfk_kc_clear_on_reset(void); +extern char *saved_command_line; + + +#endif /* PFK_KC_H_ */ diff --git a/security/security.c b/security/security.c index 264a5e5a0595..d0d99921b751 100644 --- a/security/security.c +++ b/security/security.c @@ -612,6 +612,14 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode } EXPORT_SYMBOL_GPL(security_inode_create); +int security_inode_post_create(struct inode *dir, struct dentry *dentry, + umode_t mode) +{ + if (unlikely(IS_PRIVATE(dir))) + return 0; + return call_int_hook(inode_post_create, 0, dir, dentry, mode); +} + int security_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) { diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 3d54468ce334..af8582501f93 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -26,8 +26,9 @@ #include #include #include -#include "flask.h" -#include "avc.h" +//#include "flask.h" +//#include "avc.h" +#include "security.h" struct task_security_struct { u32 osid; /* SID prior to last execve */ @@ -64,6 +65,8 @@ struct inode_security_struct { u32 sid; /* SID of this object */ u16 sclass; /* security class of this object */ unsigned char initialized; /* initialization flag */ + u32 tag; /* Per-File-Encryption tag */ + void *pfk_data; /* Per-File-Key data from ecryptfs */ spinlock_t lock; }; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 02f0412d42f2..de4c7d32b955 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -13,7 +13,6 @@ #include #include #include -#include "flask.h" #define SECSID_NULL 0x00000000 /* unspecified SID */ #define SECSID_WILD 0xffffffff /* wildcard SID */ -- GitLab From 79700f5ae9ba410fde2e341852e4731b1cd3b50b Mon Sep 17 00:00:00 2001 From: Dinesh K Garg Date: Wed, 23 May 2018 16:42:42 -0700 Subject: [PATCH 0154/1299] defconfig: arm64: Enable ICE based HW FBE on sm8150 Enable following configurations to enable ICE based HW FBE 1. CONFIG_PFK=y 2. CONFIG_SCSI_UFS_QCOM_ICE=y 3. CONFIG_CRYPTO_DEV_QCOM_ICE=y 4. CONFIG_EXT4_FS_ENCRYPTION=y 5. CONFIG_EXT4_FS_ICE_ENCRYPTION=y Change-Id: I6a42d8bd94aead423ae082869697d5e5155a15fb Signed-off-by: Dinesh K Garg --- arch/arm64/configs/sm8150-perf_defconfig | 5 +++++ arch/arm64/configs/sm8150_defconfig | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm64/configs/sm8150-perf_defconfig b/arch/arm64/configs/sm8150-perf_defconfig index c7766f76da7c..3eaec7205a6a 100644 --- a/arch/arm64/configs/sm8150-perf_defconfig +++ b/arch/arm64/configs/sm8150-perf_defconfig @@ -264,6 +264,7 @@ CONFIG_SCSI_SCAN_ASYNC=y CONFIG_SCSI_UFSHCD=y CONFIG_SCSI_UFSHCD_PLATFORM=y CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y CONFIG_MD=y CONFIG_BLK_DEV_DM=y CONFIG_DM_UEVENT=y @@ -576,6 +577,8 @@ CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y +CONFIG_EXT4_FS_ENCRYPTION=y +CONFIG_EXT4_FS_ICE_ENCRYPTION=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_FUSE_FS=y @@ -608,6 +611,7 @@ CONFIG_CORESIGHT_REMOTE_ETM=y CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 CONFIG_CORESIGHT_TGU=y CONFIG_CORESIGHT_EVENT=y +CONFIG_PFK=y CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y @@ -621,6 +625,7 @@ CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y CONFIG_CRYPTO_DEV_QCRYPTO=y CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y CONFIG_ARM64_CRYPTO=y CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_CRYPTO_SHA2_ARM64_CE=y diff --git a/arch/arm64/configs/sm8150_defconfig b/arch/arm64/configs/sm8150_defconfig index 26255237ae9c..92c9a9bc7692 100644 --- a/arch/arm64/configs/sm8150_defconfig +++ b/arch/arm64/configs/sm8150_defconfig @@ -275,6 +275,7 @@ CONFIG_SCSI_SCAN_ASYNC=y CONFIG_SCSI_UFSHCD=y CONFIG_SCSI_UFSHCD_PLATFORM=y CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y CONFIG_SCSI_UFSHCD_CMD_LOGGING=y CONFIG_MD=y CONFIG_BLK_DEV_DM=y @@ -602,6 +603,8 @@ CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y +CONFIG_EXT4_FS_ENCRYPTION=y +CONFIG_EXT4_FS_ICE_ENCRYPTION=y CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_FUSE_FS=y @@ -688,6 +691,7 @@ CONFIG_CORESIGHT_REMOTE_ETM=y CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 CONFIG_CORESIGHT_TGU=y CONFIG_CORESIGHT_EVENT=y +CONFIG_PFK=y CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y @@ -702,6 +706,7 @@ CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y CONFIG_CRYPTO_DEV_QCRYPTO=y CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y CONFIG_ARM64_CRYPTO=y CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_CRYPTO_SHA2_ARM64_CE=y -- GitLab From 7fe923ac4210e3b5890da885d75d38b840e4d6c8 Mon Sep 17 00:00:00 2001 From: Dinesh K Garg Date: Wed, 23 May 2018 16:37:19 -0700 Subject: [PATCH 0155/1299] ARM: dts: msm: Add ICE node for SM8150 Add ICE device node to support ICE based FBE. Change-Id: Ib3f52329f7d8c71fdb4d10288161972b71695d1d Signed-off-by: Dinesh K Garg --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index ca1ee3cfbc83..ed4a0eb26ec2 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -2127,10 +2127,34 @@ reg = <0x17c0000c 0x4>; }; + ufs_ice: ufsice@1d90000 { + compatible = "qcom,ice"; + reg = <0x1d90000 0x8000>; + qcom,enable-ice-clk; + clock-names = "ufs_core_clk", "bus_clk", + "iface_clk", "ice_core_clk"; + clocks = <&clock_gcc GCC_UFS_PHY_AXI_CLK>, + <&clock_gcc GCC_UFS_MEM_CLKREF_CLK>, + <&clock_gcc GCC_UFS_PHY_AHB_CLK>, + <&clock_gcc GCC_UFS_PHY_ICE_CORE_CLK>; + qcom,op-freq-hz = <0>, <0>, <0>, <300000000>; + vdd-hba-supply = <&ufs_phy_gdsc>; + qcom,msm-bus,name = "ufs_ice_noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <1 650 0 0>, /* No vote */ + <1 650 1000 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", + "MAX"; + qcom,instance-type = "ufs"; + }; + ufsphy_mem: ufsphy_mem@1d87000 { reg = <0x1d87000 0xda8>; /* PHY regs */ reg-names = "phy_mem"; #phy-cells = <0>; + ufs-qcom-crypto = <&ufs_ice>; lanes-per-direction = <2>; @@ -2150,6 +2174,7 @@ interrupts = <0 265 0>; phys = <&ufsphy_mem>; phy-names = "ufsphy"; + ufs-qcom-crypto = <&ufs_ice>; lanes-per-direction = <2>; dev-ref-clk-freq = <0>; /* 19.2 MHz */ -- GitLab From 43e46d243918da5dd7ccf569b2fec9db1bf4dbeb Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Fri, 1 Jun 2018 16:25:10 -0700 Subject: [PATCH 0156/1299] power: smb5: support connector_temp_health property PM8150B's AUX_THM3_PU2 input is connected to its VADC. Expose connector temp status via usb psy connector_temp_health property. Change-Id: Idcc4360074ef3d67bf873941504f2c6dedb0e52d Signed-off-by: Harry Yang --- drivers/power/supply/qcom/qpnp-smb5.c | 13 ++++++++++ drivers/power/supply/qcom/smb5-lib.c | 34 +++++++++++++++++++++++++++ drivers/power/supply/qcom/smb5-lib.h | 3 +++ drivers/power/supply/qcom/smb5-reg.h | 6 +++++ 4 files changed, 56 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index e1cdf902097f..7d780aede22a 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -482,6 +482,7 @@ static enum power_supply_property smb5_usb_props[] = { POWER_SUPPLY_PROP_PD_VOLTAGE_MIN, POWER_SUPPLY_PROP_SDP_CURRENT_MAX, POWER_SUPPLY_PROP_CONNECTOR_TYPE, + POWER_SUPPLY_PROP_CONNECTOR_HEALTH, POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_SMB_EN_MODE, POWER_SUPPLY_PROP_SCOPE, @@ -594,6 +595,12 @@ static int smb5_usb_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CONNECTOR_TYPE: val->intval = chg->connector_type; break; + case POWER_SUPPLY_PROP_CONNECTOR_HEALTH: + if (chg->connector_health == -EINVAL) + rc = smblib_get_prop_connector_health(chg, val); + else + val->intval = chg->connector_health; + break; case POWER_SUPPLY_PROP_SCOPE: val->intval = POWER_SUPPLY_SCOPE_UNKNOWN; rc = smblib_get_prop_usb_present(chg, &pval); @@ -663,6 +670,10 @@ static int smb5_usb_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_SDP_CURRENT_MAX: rc = smblib_set_prop_sdp_current_max(chg, val); break; + case POWER_SUPPLY_PROP_CONNECTOR_HEALTH: + chg->connector_health = val->intval; + power_supply_changed(chg->usb_psy); + break; default: pr_err("set prop %d is not supported\n", psp); rc = -EINVAL; @@ -677,6 +688,7 @@ static int smb5_usb_prop_is_writeable(struct power_supply *psy, { switch (psp) { case POWER_SUPPLY_PROP_CTM_CURRENT_MAX: + case POWER_SUPPLY_PROP_CONNECTOR_HEALTH: return 1; default: break; @@ -2398,6 +2410,7 @@ static int smb5_probe(struct platform_device *pdev) chg->mode = PARALLEL_MASTER; chg->irq_info = smb5_irqs; chg->die_health = -EINVAL; + chg->connector_health = -EINVAL; chg->otg_present = false; chg->regmap = dev_get_regmap(chg->dev->parent, NULL); diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 37b2ba782ae0..ff7c5cfa88a8 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -2245,6 +2245,40 @@ int smblib_get_prop_die_health(struct smb_charger *chg, return 0; } +int smblib_get_prop_connector_health(struct smb_charger *chg, + union power_supply_propval *val) +{ + int rc; + u8 stat; + + rc = smblib_read(chg, CONNECTOR_TEMP_STATUS_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read CONNECTOR_TEMP_STATUS_REG, rc=%d\n", + rc); + return rc; + } + + /* Thermal status bits are mutually exclusive */ + switch (stat) { + case CONNECTOR_TEMP_LB_BIT: + val->intval = POWER_SUPPLY_HEALTH_COOL; + break; + case CONNECTOR_TEMP_UB_BIT: + val->intval = POWER_SUPPLY_HEALTH_WARM; + break; + case CONNECTOR_TEMP_RST_BIT: + val->intval = POWER_SUPPLY_HEALTH_HOT; + break; + case CONNECTOR_TEMP_SHDN_BIT: + val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; + break; + default: + val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; + } + + return 0; +} + #define SDP_CURRENT_UA 500000 #define CDP_CURRENT_UA 1500000 #define DCP_CURRENT_UA 1500000 diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 9050c7ca34e5..7574c583534c 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -376,6 +376,7 @@ struct smb_charger { int pulse_cnt; int die_health; + int connector_health; /* flash */ u32 flash_derating_soc; @@ -514,6 +515,8 @@ int smblib_get_prop_charger_temp(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_die_health(struct smb_charger *chg, union power_supply_propval *val); +int smblib_get_prop_connector_health(struct smb_charger *chg, + union power_supply_propval *val); int smblib_set_prop_pd_current_max(struct smb_charger *chg, const union power_supply_propval *val); int smblib_set_prop_sdp_current_max(struct smb_charger *chg, diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h index 20a864e513e6..20ac2897c03a 100644 --- a/drivers/power/supply/qcom/smb5-reg.h +++ b/drivers/power/supply/qcom/smb5-reg.h @@ -353,6 +353,12 @@ enum { #define TEMP_BELOW_RANGE_BIT BIT(1) #define THERMREG_DISABLED_BIT BIT(0) +#define CONNECTOR_TEMP_STATUS_REG (MISC_BASE + 0x09) +#define CONNECTOR_TEMP_SHDN_BIT BIT(3) +#define CONNECTOR_TEMP_RST_BIT BIT(2) +#define CONNECTOR_TEMP_UB_BIT BIT(1) +#define CONNECTOR_TEMP_LB_BIT BIT(0) + #define BARK_BITE_WDOG_PET_REG (MISC_BASE + 0x43) #define BARK_BITE_WDOG_PET_BIT BIT(0) -- GitLab From c0e6e7cb16a61fca55c717bc198d171d4e2d0bd8 Mon Sep 17 00:00:00 2001 From: Zhongbo Shi Date: Tue, 29 May 2018 15:20:54 +0800 Subject: [PATCH 0157/1299] msm: vidc: Add uncompressed format constraint setting Add uncompressed format constraint property setting especially for 10bit P010 format. The stride of P010 moves from 128 to 256 now. Change-Id: I451fcb6d5979b904ce550c04e5b9e0c11bd5d4ed Signed-off-by: Zhongbo Shi --- .../platform/msm/vidc/hfi_packetization.c | 28 ++++++ drivers/media/platform/msm/vidc/msm_vdec.c | 38 ++++++++ drivers/media/platform/msm/vidc/msm_venc.c | 40 +++++++++ .../media/platform/msm/vidc/msm_vidc_common.c | 90 +++++++++++++++++++ .../media/platform/msm/vidc/msm_vidc_common.h | 5 ++ .../platform/msm/vidc/msm_vidc_internal.h | 13 +++ 6 files changed, 214 insertions(+) diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c index 2e335fdf6552..dc2015db1b41 100644 --- a/drivers/media/platform/msm/vidc/hfi_packetization.c +++ b/drivers/media/platform/msm/vidc/hfi_packetization.c @@ -1025,7 +1025,35 @@ int create_pkt_cmd_session_set_property( break; } case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO: + { + struct hfi_uncompressed_plane_actual_constraints_info *hfi; + struct hal_uncompressed_plane_actual_constraints_info *prop = + (struct hal_uncompressed_plane_actual_constraints_info *) pdata; + u32 buffer_type; + u32 num_plane = prop->num_planes; + u32 hfi_pkt_size = + 2 * sizeof(u32) + + num_plane + * sizeof(struct hal_uncompressed_plane_constraints); + + pkt->rg_property_data[0] = + HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO; + + hfi = (struct hfi_uncompressed_plane_actual_constraints_info *) + &pkt->rg_property_data[1]; + buffer_type = get_hfi_buffer(prop->buffer_type); + if (buffer_type) + hfi->buffer_type = buffer_type; + else + return -EINVAL; + + hfi->num_planes = prop->num_planes; + memcpy(hfi->rg_plane_format, prop->rg_plane_format, + hfi->num_planes + *sizeof(struct hal_uncompressed_plane_constraints)); + pkt->size += hfi_pkt_size; break; + } case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO: break; case HAL_PARAM_FRAME_SIZE: diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c index 5044fbf7c2ce..e3dace2a381e 100644 --- a/drivers/media/platform/msm/vidc/msm_vdec.c +++ b/drivers/media/platform/msm/vidc/msm_vdec.c @@ -511,6 +511,21 @@ struct msm_vidc_format vdec_formats[] = { }, }; +struct msm_vidc_format_constraint dec_pix_format_constraints[] = { + { + .fourcc = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS, + .num_planes = 2, + .y_stride_multiples = 256, + .y_max_stride = 8192, + .y_min_plane_buffer_height_multiple = 32, + .y_buffer_alignment = 256, + .uv_stride_multiples = 256, + .uv_max_stride = 8192, + .uv_min_plane_buffer_height_multiple = 16, + .uv_buffer_alignment = 256, + }, +}; + static bool msm_vidc_check_for_vp9d_overload(struct msm_vidc_core *core) { u32 vp9d_instance_count = 0; @@ -532,6 +547,7 @@ static bool msm_vidc_check_for_vp9d_overload(struct msm_vidc_core *core) int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) { struct msm_vidc_format *fmt = NULL; + struct msm_vidc_format_constraint *fmt_constraint = NULL; struct hal_frame_size frame_sz; unsigned int extra_idx = 0; int rc = 0; @@ -579,6 +595,28 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) msm_comm_get_hal_output_buffer(inst), f->fmt.pix_mp.pixelformat); + fmt_constraint = + msm_comm_get_pixel_fmt_constraints(dec_pix_format_constraints, + ARRAY_SIZE(dec_pix_format_constraints), + f->fmt.pix_mp.pixelformat); + + if (!fmt_constraint) { + dprintk(VIDC_INFO, + "Format constraint not required for %d on CAPTURE port\n", + f->fmt.pix_mp.pixelformat); + } else { + rc = msm_comm_set_color_format_constraints(inst, + msm_comm_get_hal_output_buffer(inst), + fmt_constraint); + if (rc) { + dprintk(VIDC_ERR, + "Set constraint for %d failed on CAPTURE port\n", + f->fmt.pix_mp.pixelformat); + rc = -EINVAL; + goto err_invalid_fmt; + } + } + inst->clk_data.opb_fourcc = f->fmt.pix_mp.pixelformat; if (msm_comm_get_stream_output_mode(inst) == HAL_VIDEO_DECODER_SECONDARY) { diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 9d3fb6705cca..9faf1d6b2953 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -1205,6 +1205,22 @@ static struct msm_vidc_format venc_formats[] = { }, }; +struct msm_vidc_format_constraint enc_pix_format_constraints[] = { + { + .fourcc = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS, + .num_planes = 2, + .y_stride_multiples = 256, + .y_max_stride = 8192, + .y_min_plane_buffer_height_multiple = 32, + .y_buffer_alignment = 256, + .uv_stride_multiples = 256, + .uv_max_stride = 8192, + .uv_min_plane_buffer_height_multiple = 16, + .uv_buffer_alignment = 256, + }, +}; + + static int msm_venc_set_csc(struct msm_vidc_inst *inst, u32 color_primaries, u32 custom_matrix); @@ -2506,6 +2522,7 @@ static int msm_venc_set_csc(struct msm_vidc_inst *inst, int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) { struct msm_vidc_format *fmt = NULL; + struct msm_vidc_format_constraint *fmt_constraint = NULL; int rc = 0; struct hfi_device *hdev; int extra_idx = 0, i = 0; @@ -2693,6 +2710,29 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) } msm_comm_set_color_format(inst, HAL_BUFFER_INPUT, fmt->fourcc); + + fmt_constraint = + msm_comm_get_pixel_fmt_constraints(enc_pix_format_constraints, + ARRAY_SIZE(enc_pix_format_constraints), + f->fmt.pix_mp.pixelformat); + + if (!fmt_constraint) { + dprintk(VIDC_ERR, + "Format constraint not required for %d on OUTPUT port\n", + f->fmt.pix_mp.pixelformat); + } else { + rc = msm_comm_set_color_format_constraints(inst, + HAL_BUFFER_INPUT, + fmt_constraint); + if (rc) { + dprintk(VIDC_ERR, + "Set constraint for %d failed on CAPTURE port\n", + f->fmt.pix_mp.pixelformat); + rc = -EINVAL; + goto exit; + } + } + } else { dprintk(VIDC_ERR, "%s - Unsupported buf type: %d\n", __func__, f->type); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 455d4ce648f1..e955166ccddc 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -991,6 +991,26 @@ struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc( return &fmt[i]; } +struct msm_vidc_format_constraint *msm_comm_get_pixel_fmt_constraints( + struct msm_vidc_format_constraint fmt[], int size, int fourcc) +{ + int i; + + if (!fmt) { + dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK\n", fmt); + return NULL; + } + for (i = 0; i < size; i++) { + if (fmt[i].fourcc == fourcc) + break; + } + if (i == size) { + dprintk(VIDC_INFO, "Format constraint not found.\n"); + return NULL; + } + return &fmt[i]; +} + struct buf_queue *msm_comm_get_vb2q( struct msm_vidc_inst *inst, enum v4l2_buf_type type) { @@ -6518,3 +6538,73 @@ int msm_comm_release_mark_data(struct msm_vidc_inst *inst) return 0; } +int msm_comm_set_color_format_constraints(struct msm_vidc_inst *inst, + enum hal_buffer buffer_type, + struct msm_vidc_format_constraint *pix_constraint) +{ + struct hal_uncompressed_plane_actual_constraints_info + *pconstraint = NULL; + u32 num_planes = 2; + u32 size = 0; + int rc = 0; + struct hfi_device *hdev; + + if (!inst || !inst->core || !inst->core->device) { + dprintk(VIDC_ERR, "%s - invalid param\n", __func__); + return -EINVAL; + } + + hdev = inst->core->device; + + size = sizeof(buffer_type) + + sizeof(u32) + + num_planes + * sizeof(struct hal_uncompressed_plane_constraints); + + pconstraint = kzalloc(size, GFP_KERNEL); + if (!pconstraint) { + dprintk(VIDC_ERR, "No memory cannot alloc constrain\n"); + rc = -ENOMEM; + goto exit; + } + + pconstraint->buffer_type = buffer_type; + pconstraint->num_planes = pix_constraint->num_planes; + //set Y plan constraints + dprintk(VIDC_INFO, "Set Y plan constraints.\n"); + pconstraint->rg_plane_format[0].stride_multiples = + pix_constraint->y_stride_multiples; + pconstraint->rg_plane_format[0].max_stride = + pix_constraint->y_max_stride; + pconstraint->rg_plane_format[0].min_plane_buffer_height_multiple = + pix_constraint->y_min_plane_buffer_height_multiple; + pconstraint->rg_plane_format[0].buffer_alignment = + pix_constraint->y_buffer_alignment; + + //set UV plan constraints + dprintk(VIDC_INFO, "Set UV plan constraints.\n"); + pconstraint->rg_plane_format[1].stride_multiples = + pix_constraint->uv_stride_multiples; + pconstraint->rg_plane_format[1].max_stride = + pix_constraint->uv_max_stride; + pconstraint->rg_plane_format[1].min_plane_buffer_height_multiple = + pix_constraint->uv_min_plane_buffer_height_multiple; + pconstraint->rg_plane_format[1].buffer_alignment = + pix_constraint->uv_buffer_alignment; + + rc = call_hfi_op(hdev, + session_set_property, + inst->session, + HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO, + pconstraint); + if (rc) + dprintk(VIDC_ERR, + "Failed to set input color format constraint\n"); + else + dprintk(VIDC_DBG, "Set color format constraint success\n"); + +exit: + if (!pconstraint) + kfree(pconstraint); + return rc; +} diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h index d73da96f89b6..36505649e611 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h @@ -92,6 +92,11 @@ const struct msm_vidc_format *msm_comm_get_pixel_fmt_index( const struct msm_vidc_format fmt[], int size, int index, int fmt_type); struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc( struct msm_vidc_format fmt[], int size, int fourcc, int fmt_type); +struct msm_vidc_format_constraint *msm_comm_get_pixel_fmt_constraints( + struct msm_vidc_format_constraint fmt[], int size, int fourcc); +int msm_comm_set_color_format_constraints(struct msm_vidc_inst *inst, + enum hal_buffer buffer_type, + struct msm_vidc_format_constraint *pix_constraint); struct buf_queue *msm_comm_get_vb2q( struct msm_vidc_inst *inst, enum v4l2_buf_type type); int msm_comm_try_state(struct msm_vidc_inst *inst, int state); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index 29b4d821e52d..095a8cfc38bb 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -235,6 +235,19 @@ struct msm_vidc_format { bool defer_outputs; }; +struct msm_vidc_format_constraint { + u32 fourcc; + u32 num_planes; + u32 y_stride_multiples; + u32 y_max_stride; + u32 y_min_plane_buffer_height_multiple; + u32 y_buffer_alignment; + u32 uv_stride_multiples; + u32 uv_max_stride; + u32 uv_min_plane_buffer_height_multiple; + u32 uv_buffer_alignment; +}; + struct msm_vidc_drv { struct mutex lock; struct list_head cores; -- GitLab From a65478df351382d255d293d745aee9bae3a3a741 Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Tue, 12 Jun 2018 14:50:30 +0530 Subject: [PATCH 0158/1299] ARM: dts: msm: Update CPU frequency for QCS405 The frequency table needs to be updated as per latest HW recommendation, so update the same. Change-Id: I5f9e2d3b83e45a213942d867ff41b2b0ddb08359 Signed-off-by: Shefali Jain --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 4d07feade11a..275710a6cdf4 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -278,10 +278,9 @@ vdd_dig_ao-supply = <&pms405_s1_level>; qcom,speed0-bin-v0 = < 0 0>, - < 960000000 1>, - < 1113600000 2>, - < 1267200000 3>, - < 1382400000 4>; + < 1113600000 1>, + < 1267200000 2>, + < 1401600000 3>; #clock-cells = <1>; }; -- GitLab From cba44bdd1ea30804d8c697c2bc3cbe43898dfd51 Mon Sep 17 00:00:00 2001 From: Amit Nischal Date: Thu, 8 Mar 2018 16:05:46 +0530 Subject: [PATCH 0159/1299] clk: qcom: Add GCC clock driver for SM6150 Add support for peripheral clocks controlled by global clock controller. Change-Id: Iaae6267de7b56f830a02eed054b134f207e26339 Signed-off-by: Amit Nischal --- .../devicetree/bindings/clock/qcom,gcc.txt | 1 + drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gcc-sm6150.c | 3501 +++++++++++++++++ drivers/clk/qcom/vdd-level-sm6150.h | 67 + include/dt-bindings/clock/qcom,gcc-sm6150.h | 394 +- 6 files changed, 3765 insertions(+), 208 deletions(-) create mode 100644 drivers/clk/qcom/gcc-sm6150.c create mode 100644 drivers/clk/qcom/vdd-level-sm6150.h diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt index d238475136be..23e542e7b3a2 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt @@ -23,6 +23,7 @@ Required properties : "qcom,gcc-sdmshrike" "qcom,gcc-qcs405" "qcom,gcc-mdss-qcs405" + "qcom,gcc-sm6150" - reg : shall contain base register location and length - #clock-cells : shall contain 1 diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 646565f68e9a..8736a0153e02 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -341,3 +341,12 @@ config CLOCK_CPU_QCS405 based devices. Say Y if you want to support CPU clock scaling using CPUfreq drivers for dynamic power management. + +config MSM_GCC_SM6150 + tristate "SM6150 Global Clock Controller" + depends on COMMON_CLK_QCOM + help + Support for the global clock controller on Qualcomm Technologies, Inc + SM6150 devices. + Say Y if you want to use peripheral devices such as UART, SPI, I2C, + USB, UFS, SD/eMMC, PCIe, etc. diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index b7efc3c1e3b0..eae763bb9a7e 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o +obj-$(CONFIG_MSM_GCC_SM6150) += gcc-sm6150.o obj-$(CONFIG_MSM_GCC_SM8150) += gcc-sm8150.o obj-$(CONFIG_MSM_GCC_SDMSHRIKE) += gcc-sdmshrike.o obj-$(CONFIG_MSM_GPUCC_SM8150) += gpucc-sm8150.o diff --git a/drivers/clk/qcom/gcc-sm6150.c b/drivers/clk/qcom/gcc-sm6150.c new file mode 100644 index 000000000000..8e9b98f398c2 --- /dev/null +++ b/drivers/clk/qcom/gcc-sm6150.c @@ -0,0 +1,3501 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "clk: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "common.h" +#include "reset.h" +#include "vdd-level-sm6150.h" + +#define GCC_DISPLAY_MISC 0x0b080 +#define GCC_CAMERA_MISC 0x0b084 +#define GCC_VIDEO_MISC 0x9b000 +#define GCC_GPU_MISC 0x71028 +#define GCC_EMAC_MISC 0x06040 + +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } + +static DEFINE_VDD_REGULATORS(vdd_cx, VDD_NUM, 1, vdd_corner); +static DEFINE_VDD_REGULATORS(vdd_cx_ao, VDD_NUM, 1, vdd_corner); + +enum { + P_BI_TCXO, + P_CORE_BI_PLL_TEST_SE, + P_GPLL0_OUT_AUX2, + P_GPLL0_OUT_MAIN, + P_GPLL3_OUT_MAIN, + P_GPLL4_OUT_MAIN, + P_GPLL6_OUT_MAIN, + P_GPLL7_OUT_MAIN, + P_GPLL8_OUT_MAIN, + P_SLEEP_CLK, +}; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL0_OUT_AUX2, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_0[] = { + "bi_tcxo", + "gpll0_out_main", + "gpll0_out_aux2", + "core_bi_pll_test_se", +}; +static const char * const gcc_parent_names_0_ao[] = { + "bi_tcxo_ao", + "gpll0_out_main", + "gpll0_out_aux2", + "core_bi_pll_test_se", +}; + +static const struct parent_map gcc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL6_OUT_MAIN, 2 }, + { P_GPLL0_OUT_AUX2, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_1[] = { + "bi_tcxo", + "gpll0_out_main", + "gpll6_out_main", + "gpll0_out_aux2", + "core_bi_pll_test_se", +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_SLEEP_CLK, 5 }, + { P_GPLL0_OUT_AUX2, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_2[] = { + "bi_tcxo", + "gpll0_out_main", + "sleep_clk", + "gpll0_out_aux2", + "core_bi_pll_test_se", +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_SLEEP_CLK, 5 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_3[] = { + "bi_tcxo", + "sleep_clk", + "core_bi_pll_test_se", +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_4[] = { + "bi_tcxo", + "core_bi_pll_test_se", +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL7_OUT_MAIN, 3 }, + { P_GPLL4_OUT_MAIN, 5 }, + { P_GPLL0_OUT_AUX2, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_5[] = { + "bi_tcxo", + "gpll0_out_main", + "gpll7_out_main", + "gpll4_out_main", + "gpll0_out_aux2", + "core_bi_pll_test_se", +}; + +static const struct parent_map gcc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL7_OUT_MAIN, 3 }, + { P_GPLL0_OUT_AUX2, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_6[] = { + "bi_tcxo", + "gpll0_out_main", + "gpll7_out_main", + "gpll0_out_aux2", + "core_bi_pll_test_se", +}; + +static const struct parent_map gcc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL8_OUT_MAIN, 2 }, + { P_GPLL4_OUT_MAIN, 5 }, + { P_GPLL0_OUT_AUX2, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_7[] = { + "bi_tcxo", + "gpll0_out_main", + "gpll8_out_main", + "gpll4_out_main", + "gpll0_out_aux2", + "core_bi_pll_test_se", +}; + +static const struct parent_map gcc_parent_map_8[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_8[] = { + "bi_tcxo", + "gpll0_out_main", + "core_bi_pll_test_se", +}; + +static const struct parent_map gcc_parent_map_9[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL3_OUT_MAIN, 4 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_9[] = { + "bi_tcxo", + "gpll0_out_main", + "gpll3_out_main", + "core_bi_pll_test_se", +}; + +static struct clk_alpha_pll gpll0_out_main = { + .offset = 0x0, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpll0_out_main", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll0_out_aux2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll0_out_aux2", + .parent_names = (const char *[]){ "gpll0_out_main" }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll6_out_main = { + .offset = 0x13000, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gpll6_out_main", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll7_out_main = { + .offset = 0x1a000, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gpll7_out_main", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll8_out_main = { + .offset = 0x1b000, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gpll8_out_main", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_cpuss_ahb_clk_src = { + .cmd_rcgr = 0x48014, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_cpuss_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_ahb_clk_src", + .parent_names = gcc_parent_names_0_ao, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx_ao, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac_ptp_clk_src[] = { + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(125000000, P_GPLL7_OUT_MAIN, 4, 0, 0), + F(250000000, P_GPLL7_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac_ptp_clk_src = { + .cmd_rcgr = 0x6038, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_emac_ptp_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_emac_ptp_clk_src", + .parent_names = gcc_parent_names_5, + .num_parents = 6, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 50000000, + [VDD_LOW] = 230400000}, + }, +}; + +static struct clk_rcg2 gcc_emac_rgmii_clk_src = { + .cmd_rcgr = 0x601c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_emac_ptp_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_emac_rgmii_clk_src", + .parent_names = gcc_parent_names_6, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 50000000, + [VDD_LOW] = 125000000, + [VDD_NOMINAL] = 250000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x64004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk_src", + .parent_names = gcc_parent_names_2, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 50000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 200000000}, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x65004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk_src", + .parent_names = gcc_parent_names_2, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 50000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 200000000}, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x66004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk_src", + .parent_names = gcc_parent_names_2, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 50000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 200000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_0_aux_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_0_aux_clk_src = { + .cmd_rcgr = 0x6b02c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_aux_clk_src", + .parent_names = gcc_parent_names_3, + .num_parents = 3, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 9600000, + [VDD_LOW] = 19200000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_phy_refgen_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_phy_refgen_clk_src = { + .cmd_rcgr = 0x6f014, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_phy_refgen_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_phy_refgen_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000, + [VDD_LOW] = 100000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x33010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000, + [VDD_LOW] = 60000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_qspi_core_clk_src[] = { + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_qspi_core_clk_src = { + .cmd_rcgr = 0x4b008, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qspi_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qspi_core_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 150000000, + [VDD_NOMINAL] = 300000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, P_GPLL0_OUT_AUX2, 1, 384, 15625), + F(14745600, P_GPLL0_OUT_AUX2, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GPLL0_OUT_AUX2, 1, 1536, 15625), + F(32000000, P_GPLL0_OUT_AUX2, 1, 8, 75), + F(48000000, P_GPLL0_OUT_AUX2, 1, 4, 25), + F(64000000, P_GPLL0_OUT_AUX2, 1, 16, 75), + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(80000000, P_GPLL0_OUT_AUX2, 1, 4, 15), + F(96000000, P_GPLL0_OUT_AUX2, 1, 8, 25), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(102400000, P_GPLL0_OUT_AUX2, 1, 128, 375), + F(112000000, P_GPLL0_OUT_AUX2, 1, 28, 75), + F(117964800, P_GPLL0_OUT_AUX2, 1, 6144, 15625), + F(120000000, P_GPLL0_OUT_AUX2, 2.5, 0, 0), + F(128000000, P_GPLL6_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { + .cmd_rcgr = 0x17148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s0_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { + .cmd_rcgr = 0x17278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s1_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { + .cmd_rcgr = 0x173a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s2_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { + .cmd_rcgr = 0x174d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s3_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { + .cmd_rcgr = 0x17608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s4_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { + .cmd_rcgr = 0x17738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s5_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = { + .cmd_rcgr = 0x18148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s0_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = { + .cmd_rcgr = 0x18278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s1_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = { + .cmd_rcgr = 0x183a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s2_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = { + .cmd_rcgr = 0x184d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s3_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = { + .cmd_rcgr = 0x18608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s4_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = { + .cmd_rcgr = 0x18738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s5_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 128000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, P_BI_TCXO, 16, 3, 25), + F(400000, P_BI_TCXO, 12, 1, 4), + F(20000000, P_GPLL0_OUT_AUX2, 5, 1, 3), + F(25000000, P_GPLL0_OUT_AUX2, 6, 1, 2), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0), + F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .cmd_rcgr = 0x12028, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk_src", + .parent_names = gcc_parent_names_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 100000000, + [VDD_NOMINAL] = 384000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = { + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { + .cmd_rcgr = 0x12010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ice_core_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 150000000, + [VDD_NOMINAL] = 300000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(52000000, P_GPLL8_OUT_MAIN, 8, 0, 0), + F(208000000, P_GPLL8_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .cmd_rcgr = 0x1400c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk_src", + .parent_names = gcc_parent_names_7, + .num_parents = 6, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 52000000, + [VDD_LOW] = 208000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_axi_clk_src[] = { + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = { + .cmd_rcgr = 0x77020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src, + .flags = FORCE_ENABLE_RCG, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 50000000, + [VDD_LOW] = 100000000, + [VDD_NOMINAL] = 200000000, + [VDD_HIGH] = 240000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = { + F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0), + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = { + .cmd_rcgr = 0x77048, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src, + .flags = FORCE_ENABLE_RCG, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 75000000, + [VDD_LOW] = 150000000, + [VDD_NOMINAL] = 300000000}, + }, +}; + +static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = { + .cmd_rcgr = 0x7707c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .flags = FORCE_ENABLE_RCG, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_clk_src", + .parent_names = gcc_parent_names_4, + .num_parents = 2, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_unipro_core_clk_src[] = { + F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0), + F(75000000, P_GPLL0_OUT_MAIN, 8, 0, 0), + F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = { + .cmd_rcgr = 0x77060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_unipro_core_clk_src, + .flags = FORCE_ENABLE_RCG, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 37500000, + [VDD_LOW] = 75000000, + [VDD_NOMINAL] = 150000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb20_sec_master_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0), + F(120000000, P_GPLL0_OUT_MAIN, 5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb20_sec_master_clk_src = { + .cmd_rcgr = 0xa601c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb20_sec_master_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb20_sec_master_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000, + [VDD_LOW] = 60000000, + [VDD_NOMINAL] = 120000000}, + }, +}; + +static struct clk_rcg2 gcc_usb20_sec_mock_utmi_clk_src = { + .cmd_rcgr = 0xa6034, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb20_sec_mock_utmi_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000, + [VDD_LOW] = 60000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb2_sec_phy_aux_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb2_sec_phy_aux_clk_src = { + .cmd_rcgr = 0xa6060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_usb2_sec_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb2_sec_phy_aux_clk_src", + .parent_names = gcc_parent_names_3, + .num_parents = 3, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(66666667, P_GPLL0_OUT_AUX2, 4.5, 0, 0), + F(133333333, P_GPLL0_OUT_MAIN, 4.5, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { + .cmd_rcgr = 0xf01c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_master_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 66666667, + [VDD_LOW] = 133333333, + [VDD_NOMINAL] = 200000000, + [VDD_HIGH] = 240000000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = { + F(20000000, P_GPLL0_OUT_AUX2, 15, 0, 0), + F(40000000, P_GPLL0_OUT_AUX2, 7.5, 0, 0), + F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { + .cmd_rcgr = 0xf034, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_mock_utmi_clk_src", + .parent_names = gcc_parent_names_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 40000000, + [VDD_LOW] = 60000000}, + }, +}; + +static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { + .cmd_rcgr = 0xf060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_usb2_sec_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_aux_clk_src", + .parent_names = gcc_parent_names_3, + .num_parents = 3, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000}, + }, +}; + +static struct clk_rcg2 gcc_vs_ctrl_clk_src = { + .cmd_rcgr = 0x7a030, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_8, + .freq_tbl = ftbl_gcc_usb2_sec_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_vs_ctrl_clk_src", + .parent_names = gcc_parent_names_8, + .num_parents = 3, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000}, + }, +}; + +static const struct freq_tbl ftbl_gcc_vsensor_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0), + F(600000000, P_GPLL0_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_vsensor_clk_src = { + .cmd_rcgr = 0x7a018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_9, + .freq_tbl = ftbl_gcc_vsensor_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_vsensor_clk_src", + .parent_names = gcc_parent_names_9, + .num_parents = 4, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000, + [VDD_LOW] = 600000000}, + }, +}; + +static struct clk_branch gcc_aggre_ufs_phy_axi_clk = { + .halt_reg = 0x770c0, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x770c0, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x770c0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_ufs_phy_axi_clk", + .parent_names = (const char *[]){ + "gcc_ufs_phy_axi_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_ufs_phy_axi_hw_ctl_clk = { + .halt_reg = 0x770c0, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x770c0, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x770c0, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_ufs_phy_axi_hw_ctl_clk", + .parent_names = (const char *[]){ + "gcc_aggre_ufs_phy_axi_clk", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_hw_ctl_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb2_sec_axi_clk = { + .halt_reg = 0xa6084, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa6084, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_usb2_sec_axi_clk", + .parent_names = (const char *[]){ + "gcc_usb20_sec_master_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb3_prim_axi_clk = { + .halt_reg = 0xf07c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf07c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_usb3_prim_axi_clk", + .parent_names = (const char *[]){ + "gcc_usb30_prim_master_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ahb2phy_east_clk = { + .halt_reg = 0x6a008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x6a008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6a008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ahb2phy_east_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ahb2phy_west_clk = { + .halt_reg = 0x6a004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x6a004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6a004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ahb2phy_west_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_apc_vs_clk = { + .halt_reg = 0x7a04c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7a04c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_apc_vs_clk", + .parent_names = (const char *[]){ + "gcc_vsensor_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x38004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x38004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_ahb_clk = { + .halt_reg = 0xb008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xb008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_hf_axi_clk = { + .halt_reg = 0xb030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_xo_clk = { + .halt_reg = 0xb044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_xo_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_ahb_clk = { + .halt_reg = 0x4100c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x4100c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_axi_clk = { + .halt_reg = 0x41008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_clk = { + .halt_reg = 0x41004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb2_sec_axi_clk = { + .halt_reg = 0xa609c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa609c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cfg_noc_usb2_sec_axi_clk", + .parent_names = (const char *[]){ + "gcc_usb20_sec_master_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { + .halt_reg = 0xf078, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cfg_noc_usb3_prim_axi_clk", + .parent_names = (const char *[]){ + "gcc_usb30_prim_master_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cpuss_ahb_clk = { + .halt_reg = 0x48000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(21), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_ahb_clk", + .parent_names = (const char *[]){ + "gcc_cpuss_ahb_clk_src", + }, + .num_parents = 1, + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cpuss_gnoc_clk = { + .halt_reg = 0x48004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x48004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(22), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_gnoc_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_gpu_axi_clk = { + .halt_reg = 0x71154, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x71154, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ddrss_gpu_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_ahb_clk = { + .halt_reg = 0xb00c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xb00c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb00c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(20), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_gpll0_div_clk_src", + .parent_names = (const char *[]){ + "gpll0_out_aux2", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_hf_axi_clk = { + .halt_reg = 0xb038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_xo_clk = { + .halt_reg = 0xb048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_xo_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac_axi_clk = { + .halt_reg = 0x6010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_emac_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac_ptp_clk = { + .halt_reg = 0x6034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_emac_ptp_clk", + .parent_names = (const char *[]){ + "gcc_emac_ptp_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac_rgmii_clk = { + .halt_reg = 0x6018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_emac_rgmii_clk", + .parent_names = (const char *[]){ + "gcc_emac_rgmii_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac_slv_ahb_clk = { + .halt_reg = 0x6014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x6014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_emac_slv_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x64000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x64000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk", + .parent_names = (const char *[]){ + "gcc_gp1_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x65000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x65000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk", + .parent_names = (const char *[]){ + "gcc_gp2_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x66000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x66000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk", + .parent_names = (const char *[]){ + "gcc_gp3_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_cfg_ahb_clk = { + .halt_reg = 0x71004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x71004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x71004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_cfg_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_gpll0_clk_src", + .parent_names = (const char *[]){ + "gpll0_out_main", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(16), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_gpll0_div_clk_src", + .parent_names = (const char *[]){ + "gpll0_out_aux2", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_iref_clk = { + .halt_reg = 0x8c010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_iref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_memnoc_gfx_clk = { + .halt_reg = 0x7100c, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x7100c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_memnoc_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = { + .halt_reg = 0x71018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x71018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_snoc_dvm_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_axis2_clk = { + .halt_reg = 0x8a00c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8a00c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_axis2_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_cfg_ahb_clk = { + .halt_reg = 0x8a000, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x8a000, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x8a000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(17), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_gpll0_div_clk_src", + .parent_names = (const char *[]){ + "gpll0_out_main", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_mfab_axis_clk = { + .halt_reg = 0x8a004, + .halt_check = BRANCH_VOTED, + .hwcg_reg = 0x8a004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x8a004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_mfab_axis_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_q6_memnoc_axi_clk = { + .halt_reg = 0x8a154, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x8a154, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_q6_memnoc_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_snoc_axi_clk = { + .halt_reg = 0x8a150, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8a150, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_snoc_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_vs_clk = { + .halt_reg = 0x7a048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7a048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_vs_clk", + .parent_names = (const char *[]){ + "gcc_vsensor_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie0_phy_refgen_clk = { + .halt_reg = 0x6f02c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6f02c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie0_phy_refgen_clk", + .parent_names = (const char *[]){ + "gcc_pcie_phy_refgen_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_aux_clk = { + .halt_reg = 0x6b020, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_aux_clk", + .parent_names = (const char *[]){ + "gcc_pcie_0_aux_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_cfg_ahb_clk = { + .halt_reg = 0x6b01c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6b01c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_clkref_clk = { + .halt_reg = 0x8c00c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c00c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_mstr_axi_clk = { + .halt_reg = 0x6b018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_pipe_clk = { + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_slv_axi_clk = { + .halt_reg = 0x6b014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6b014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_slv_q2a_axi_clk = { + .halt_reg = 0x6b010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_phy_aux_clk = { + .halt_reg = 0x6f004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6f004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_phy_aux_clk", + .parent_names = (const char *[]){ + "gcc_pcie_0_aux_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x3300c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x3300c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk", + .parent_names = (const char *[]){ + "gcc_pdm2_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x33004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x33004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x33004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x33008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x33008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_prng_ahb_clk = { + .halt_reg = 0x34004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x34004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_prng_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = { + .halt_reg = 0xb018, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xb018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_camera_nrt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_disp_ahb_clk = { + .halt_reg = 0xb020, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xb020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_disp_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_pcie_ahb_clk = { + .halt_reg = 0x6b044, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6b044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(28), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_pcie_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = { + .halt_reg = 0xb014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xb014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_video_vcodec_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qspi_cnoc_periph_ahb_clk = { + .halt_reg = 0x4b000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4b000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qspi_cnoc_periph_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qspi_core_clk = { + .halt_reg = 0x4b004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4b004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qspi_core_clk", + .parent_names = (const char *[]){ + "gcc_qspi_core_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = { + .halt_reg = 0x17014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_clk = { + .halt_reg = 0x1700c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s0_clk = { + .halt_reg = 0x17144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s0_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap0_s0_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s1_clk = { + .halt_reg = 0x17274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s1_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap0_s1_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s2_clk = { + .halt_reg = 0x173a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(12), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s2_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap0_s2_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s3_clk = { + .halt_reg = 0x174d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s3_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap0_s3_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s4_clk = { + .halt_reg = 0x17604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(14), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s4_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap0_s4_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s5_clk = { + .halt_reg = 0x17734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s5_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap0_s5_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = { + .halt_reg = 0x18014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(18), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_clk = { + .halt_reg = 0x1800c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(19), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s0_clk = { + .halt_reg = 0x18144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(22), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s0_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap1_s0_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s1_clk = { + .halt_reg = 0x18274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(23), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s1_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap1_s1_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s2_clk = { + .halt_reg = 0x183a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(24), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s2_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap1_s2_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s3_clk = { + .halt_reg = 0x184d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(25), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s3_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap1_s3_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s4_clk = { + .halt_reg = 0x18604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(26), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s4_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap1_s4_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s5_clk = { + .halt_reg = 0x18734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(27), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s5_clk", + .parent_names = (const char *[]){ + "gcc_qupv3_wrap1_s5_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = { + .halt_reg = 0x17004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_0_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = { + .halt_reg = 0x17008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_0_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = { + .halt_reg = 0x18004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(20), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_1_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_s_ahb_clk = { + .halt_reg = 0x18008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x18008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(21), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_1_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0x12008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0x12004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk", + .parent_names = (const char *[]){ + "gcc_sdcc1_apps_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ice_core_clk = { + .halt_reg = 0x1200c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1200c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ice_core_clk", + .parent_names = (const char *[]){ + "gcc_sdcc1_ice_core_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x14008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x14004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk", + .parent_names = (const char *[]){ + "gcc_sdcc2_apps_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_cpuss_ahb_clk = { + .halt_reg = 0x4819c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_cpuss_ahb_clk", + .parent_names = (const char *[]){ + "gcc_cpuss_ahb_clk_src", + }, + .num_parents = 1, + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_clkref_clk = { + .halt_reg = 0x8c004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_card_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_mem_clkref_clk = { + .halt_reg = 0x8c000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_mem_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ahb_clk = { + .halt_reg = 0x77014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_axi_clk = { + .halt_reg = 0x77010, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_clk", + .parent_names = (const char *[]){ + "gcc_ufs_phy_axi_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_axi_hw_ctl_clk = { + .halt_reg = 0x77010, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77010, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_hw_ctl_clk", + .parent_names = (const char *[]){ + "gcc_ufs_phy_axi_clk", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_hw_ctl_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ice_core_clk = { + .halt_reg = 0x77044, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_clk", + .parent_names = (const char *[]){ + "gcc_ufs_phy_ice_core_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ice_core_hw_ctl_clk = { + .halt_reg = 0x77044, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77044, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_hw_ctl_clk", + .parent_names = (const char *[]){ + "gcc_ufs_phy_ice_core_clk", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_hw_ctl_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_phy_aux_clk = { + .halt_reg = 0x77078, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77078, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_clk", + .parent_names = (const char *[]){ + "gcc_ufs_phy_phy_aux_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_phy_aux_hw_ctl_clk = { + .halt_reg = 0x77078, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77078, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77078, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_hw_ctl_clk", + .parent_names = (const char *[]){ + "gcc_ufs_phy_phy_aux_clk", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_hw_ctl_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = { + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x7701c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_rx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = { + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x77018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_tx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_unipro_core_clk = { + .halt_reg = 0x77040, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_clk", + .parent_names = (const char *[]){ + "gcc_ufs_phy_unipro_core_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_unipro_core_hw_ctl_clk = { + .halt_reg = 0x77040, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77040, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_hw_ctl_clk", + .parent_names = (const char *[]){ + "gcc_ufs_phy_unipro_core_clk", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_hw_ctl_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_sec_master_clk = { + .halt_reg = 0xa6010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa6010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb20_sec_master_clk", + .parent_names = (const char *[]){ + "gcc_usb20_sec_master_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_sec_mock_utmi_clk = { + .halt_reg = 0xa6018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa6018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb20_sec_mock_utmi_clk", + .parent_names = (const char *[]){ + "gcc_usb20_sec_mock_utmi_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_sec_sleep_clk = { + .halt_reg = 0xa6014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa6014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb20_sec_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_sec_phy_aux_clk = { + .halt_reg = 0xa6050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa6050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb2_sec_phy_aux_clk", + .parent_names = (const char *[]){ + "gcc_usb2_sec_phy_aux_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_sec_phy_com_aux_clk = { + .halt_reg = 0xa6054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa6054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb2_sec_phy_com_aux_clk", + .parent_names = (const char *[]){ + "gcc_usb2_sec_phy_aux_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_sec_phy_pipe_clk = { + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0xa6058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb2_sec_phy_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_master_clk = { + .halt_reg = 0xf010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_master_clk", + .parent_names = (const char *[]){ + "gcc_usb30_prim_master_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_mock_utmi_clk = { + .halt_reg = 0xf018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_mock_utmi_clk", + .parent_names = (const char *[]){ + "gcc_usb30_prim_mock_utmi_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_sleep_clk = { + .halt_reg = 0xf014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_clkref_clk = { + .halt_reg = 0x8c008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_aux_clk = { + .halt_reg = 0xf050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_aux_clk", + .parent_names = (const char *[]){ + "gcc_usb3_prim_phy_aux_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = { + .halt_reg = 0xf054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_com_aux_clk", + .parent_names = (const char *[]){ + "gcc_usb3_prim_phy_aux_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0xf058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_sec_clkref_clk = { + .halt_reg = 0x8c014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_sec_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vdda_vs_clk = { + .halt_reg = 0x7a00c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7a00c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vdda_vs_clk", + .parent_names = (const char *[]){ + "gcc_vsensor_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vddcx_vs_clk = { + .halt_reg = 0x7a004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7a004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vddcx_vs_clk", + .parent_names = (const char *[]){ + "gcc_vsensor_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vddmx_vs_clk = { + .halt_reg = 0x7a008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7a008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vddmx_vs_clk", + .parent_names = (const char *[]){ + "gcc_vsensor_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_ahb_clk = { + .halt_reg = 0xb004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xb004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_axi0_clk = { + .halt_reg = 0xb024, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_axi0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_xo_clk = { + .halt_reg = 0xb040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_xo_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vs_ctrl_ahb_clk = { + .halt_reg = 0x7a014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x7a014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7a014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vs_ctrl_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vs_ctrl_clk = { + .halt_reg = 0x7a010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7a010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vs_ctrl_clk", + .parent_names = (const char *[]){ + "gcc_vs_ctrl_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_wcss_vs_clk = { + .halt_reg = 0x7a054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7a054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_wcss_vs_clk", + .parent_names = (const char *[]){ + "gcc_vsensor_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +/* Measure-only clock for ddrss_gcc_debug_clk. */ +static struct clk_dummy measure_only_bimc_clk = { + .rrate = 1000, + .hw.init = &(struct clk_init_data){ + .name = "measure_only_bimc_clk", + .ops = &clk_dummy_ops, + }, +}; + +/* Measure-only clock for gcc_cfg_noc_ahb_clk. */ +static struct clk_dummy measure_only_cnoc_clk = { + .rrate = 1000, + .hw.init = &(struct clk_init_data){ + .name = "measure_only_cnoc_clk", + .ops = &clk_dummy_ops, + }, +}; + +/* Measure-only clock for gcc_ipa_2x_clk. */ +static struct clk_dummy measure_only_ipa_2x_clk = { + .rrate = 1000, + .hw.init = &(struct clk_init_data){ + .name = "measure_only_ipa_2x_clk", + .ops = &clk_dummy_ops, + }, +}; + +/* Measure-only clock for gcc_sys_noc_axi_clk. */ +static struct clk_dummy measure_only_snoc_clk = { + .rrate = 1000, + .hw.init = &(struct clk_init_data){ + .name = "measure_only_snoc_clk", + .ops = &clk_dummy_ops, + }, +}; + +struct clk_hw *gcc_sm6150_hws[] = { + [GPLL0_OUT_AUX2] = &gpll0_out_aux2.hw, + [MEASURE_ONLY_BIMC_CLK] = &measure_only_bimc_clk.hw, + [MEASURE_ONLY_CNOC_CLK] = &measure_only_cnoc_clk.hw, + [MEASURE_ONLY_IPA_2X_CLK] = &measure_only_ipa_2x_clk.hw, + [MEASURE_ONLY_SNOC_CLK] = &measure_only_snoc_clk.hw, +}; + +static struct clk_regmap *gcc_sm6150_clocks[] = { + [GCC_AGGRE_UFS_PHY_AXI_CLK] = &gcc_aggre_ufs_phy_axi_clk.clkr, + [GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK] = + &gcc_aggre_ufs_phy_axi_hw_ctl_clk.clkr, + [GCC_AGGRE_USB2_SEC_AXI_CLK] = &gcc_aggre_usb2_sec_axi_clk.clkr, + [GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.clkr, + [GCC_AHB2PHY_EAST_CLK] = &gcc_ahb2phy_east_clk.clkr, + [GCC_AHB2PHY_WEST_CLK] = &gcc_ahb2phy_west_clk.clkr, + [GCC_APC_VS_CLK] = &gcc_apc_vs_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CAMERA_AHB_CLK] = &gcc_camera_ahb_clk.clkr, + [GCC_CAMERA_HF_AXI_CLK] = &gcc_camera_hf_axi_clk.clkr, + [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr, + [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr, + [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr, + [GCC_CE1_CLK] = &gcc_ce1_clk.clkr, + [GCC_CFG_NOC_USB2_SEC_AXI_CLK] = &gcc_cfg_noc_usb2_sec_axi_clk.clkr, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, + [GCC_CPUSS_AHB_CLK] = &gcc_cpuss_ahb_clk.clkr, + [GCC_CPUSS_AHB_CLK_SRC] = &gcc_cpuss_ahb_clk_src.clkr, + [GCC_CPUSS_GNOC_CLK] = &gcc_cpuss_gnoc_clk.clkr, + [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr, + [GCC_DISP_AHB_CLK] = &gcc_disp_ahb_clk.clkr, + [GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr, + [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, + [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr, + [GCC_EMAC_AXI_CLK] = &gcc_emac_axi_clk.clkr, + [GCC_EMAC_PTP_CLK] = &gcc_emac_ptp_clk.clkr, + [GCC_EMAC_PTP_CLK_SRC] = &gcc_emac_ptp_clk_src.clkr, + [GCC_EMAC_RGMII_CLK] = &gcc_emac_rgmii_clk.clkr, + [GCC_EMAC_RGMII_CLK_SRC] = &gcc_emac_rgmii_clk_src.clkr, + [GCC_EMAC_SLV_AHB_CLK] = &gcc_emac_slv_ahb_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, + [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr, + [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr, + [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr, + [GCC_GPU_IREF_CLK] = &gcc_gpu_iref_clk.clkr, + [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, + [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr, + [GCC_MSS_AXIS2_CLK] = &gcc_mss_axis2_clk.clkr, + [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr, + [GCC_MSS_GPLL0_DIV_CLK_SRC] = &gcc_mss_gpll0_div_clk_src.clkr, + [GCC_MSS_MFAB_AXIS_CLK] = &gcc_mss_mfab_axis_clk.clkr, + [GCC_MSS_Q6_MEMNOC_AXI_CLK] = &gcc_mss_q6_memnoc_axi_clk.clkr, + [GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr, + [GCC_MSS_VS_CLK] = &gcc_mss_vs_clk.clkr, + [GCC_PCIE0_PHY_REFGEN_CLK] = &gcc_pcie0_phy_refgen_clk.clkr, + [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr, + [GCC_PCIE_0_AUX_CLK_SRC] = &gcc_pcie_0_aux_clk_src.clkr, + [GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr, + [GCC_PCIE_0_CLKREF_CLK] = &gcc_pcie_0_clkref_clk.clkr, + [GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr, + [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr, + [GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr, + [GCC_PCIE_0_SLV_Q2A_AXI_CLK] = &gcc_pcie_0_slv_q2a_axi_clk.clkr, + [GCC_PCIE_PHY_AUX_CLK] = &gcc_pcie_phy_aux_clk.clkr, + [GCC_PCIE_PHY_REFGEN_CLK_SRC] = &gcc_pcie_phy_refgen_clk_src.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, + [GCC_QMIP_CAMERA_NRT_AHB_CLK] = &gcc_qmip_camera_nrt_ahb_clk.clkr, + [GCC_QMIP_DISP_AHB_CLK] = &gcc_qmip_disp_ahb_clk.clkr, + [GCC_QMIP_PCIE_AHB_CLK] = &gcc_qmip_pcie_ahb_clk.clkr, + [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr, + [GCC_QSPI_CNOC_PERIPH_AHB_CLK] = &gcc_qspi_cnoc_periph_ahb_clk.clkr, + [GCC_QSPI_CORE_CLK] = &gcc_qspi_core_clk.clkr, + [GCC_QSPI_CORE_CLK_SRC] = &gcc_qspi_core_clk_src.clkr, + [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr, + [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr, + [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr, + [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr, + [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr, + [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr, + [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr, + [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr, + [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr, + [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr, + [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr, + [GCC_QUPV3_WRAP1_CORE_2X_CLK] = &gcc_qupv3_wrap1_core_2x_clk.clkr, + [GCC_QUPV3_WRAP1_CORE_CLK] = &gcc_qupv3_wrap1_core_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK_SRC] = &gcc_qupv3_wrap1_s0_clk_src.clkr, + [GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.clkr, + [GCC_QUPV3_WRAP1_S1_CLK_SRC] = &gcc_qupv3_wrap1_s1_clk_src.clkr, + [GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.clkr, + [GCC_QUPV3_WRAP1_S2_CLK_SRC] = &gcc_qupv3_wrap1_s2_clk_src.clkr, + [GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.clkr, + [GCC_QUPV3_WRAP1_S3_CLK_SRC] = &gcc_qupv3_wrap1_s3_clk_src.clkr, + [GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.clkr, + [GCC_QUPV3_WRAP1_S4_CLK_SRC] = &gcc_qupv3_wrap1_s4_clk_src.clkr, + [GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.clkr, + [GCC_QUPV3_WRAP1_S5_CLK_SRC] = &gcc_qupv3_wrap1_s5_clk_src.clkr, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr, + [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr, + [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, + [GCC_SYS_NOC_CPUSS_AHB_CLK] = &gcc_sys_noc_cpuss_ahb_clk.clkr, + [GCC_UFS_CARD_CLKREF_CLK] = &gcc_ufs_card_clkref_clk.clkr, + [GCC_UFS_MEM_CLKREF_CLK] = &gcc_ufs_mem_clkref_clk.clkr, + [GCC_UFS_PHY_AHB_CLK] = &gcc_ufs_phy_ahb_clk.clkr, + [GCC_UFS_PHY_AXI_CLK] = &gcc_ufs_phy_axi_clk.clkr, + [GCC_UFS_PHY_AXI_CLK_SRC] = &gcc_ufs_phy_axi_clk_src.clkr, + [GCC_UFS_PHY_AXI_HW_CTL_CLK] = &gcc_ufs_phy_axi_hw_ctl_clk.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK] = &gcc_ufs_phy_ice_core_clk.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK_SRC] = &gcc_ufs_phy_ice_core_clk_src.clkr, + [GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK] = + &gcc_ufs_phy_ice_core_hw_ctl_clk.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr, + [GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK] = &gcc_ufs_phy_phy_aux_hw_ctl_clk.clkr, + [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr, + [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] = + &gcc_ufs_phy_unipro_core_clk_src.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK] = + &gcc_ufs_phy_unipro_core_hw_ctl_clk.clkr, + [GCC_USB20_SEC_MASTER_CLK] = &gcc_usb20_sec_master_clk.clkr, + [GCC_USB20_SEC_MASTER_CLK_SRC] = &gcc_usb20_sec_master_clk_src.clkr, + [GCC_USB20_SEC_MOCK_UTMI_CLK] = &gcc_usb20_sec_mock_utmi_clk.clkr, + [GCC_USB20_SEC_MOCK_UTMI_CLK_SRC] = + &gcc_usb20_sec_mock_utmi_clk_src.clkr, + [GCC_USB20_SEC_SLEEP_CLK] = &gcc_usb20_sec_sleep_clk.clkr, + [GCC_USB2_SEC_PHY_AUX_CLK] = &gcc_usb2_sec_phy_aux_clk.clkr, + [GCC_USB2_SEC_PHY_AUX_CLK_SRC] = &gcc_usb2_sec_phy_aux_clk_src.clkr, + [GCC_USB2_SEC_PHY_COM_AUX_CLK] = &gcc_usb2_sec_phy_com_aux_clk.clkr, + [GCC_USB2_SEC_PHY_PIPE_CLK] = &gcc_usb2_sec_phy_pipe_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] = + &gcc_usb30_prim_mock_utmi_clk_src.clkr, + [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr, + [GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK] = &gcc_usb3_prim_phy_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr, + [GCC_USB3_SEC_CLKREF_CLK] = &gcc_usb3_sec_clkref_clk.clkr, + [GCC_VDDA_VS_CLK] = &gcc_vdda_vs_clk.clkr, + [GCC_VDDCX_VS_CLK] = &gcc_vddcx_vs_clk.clkr, + [GCC_VDDMX_VS_CLK] = &gcc_vddmx_vs_clk.clkr, + [GCC_VIDEO_AHB_CLK] = &gcc_video_ahb_clk.clkr, + [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr, + [GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr, + [GCC_VS_CTRL_AHB_CLK] = &gcc_vs_ctrl_ahb_clk.clkr, + [GCC_VS_CTRL_CLK] = &gcc_vs_ctrl_clk.clkr, + [GCC_VS_CTRL_CLK_SRC] = &gcc_vs_ctrl_clk_src.clkr, + [GCC_VSENSOR_CLK_SRC] = &gcc_vsensor_clk_src.clkr, + [GCC_WCSS_VS_CLK] = &gcc_wcss_vs_clk.clkr, + [GPLL0_OUT_MAIN] = &gpll0_out_main.clkr, + [GPLL6_OUT_MAIN] = &gpll6_out_main.clkr, + [GPLL7_OUT_MAIN] = &gpll7_out_main.clkr, + [GPLL8_OUT_MAIN] = &gpll8_out_main.clkr, +}; + +static const struct qcom_reset_map gcc_sm6150_resets[] = { + [GCC_QUSB2PHY_PRIM_BCR] = { 0xd000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0xd004 }, + [GCC_USB30_PRIM_BCR] = { 0xf000 }, + [GCC_USB2_PHY_SEC_BCR] = { 0x50018 }, + [GCC_USB3_DP_PHY_SEC_BCR] = { 0x50020 }, + [GCC_USB3PHY_PHY_SEC_BCR] = { 0x5001c }, + [GCC_PCIE_0_BCR] = { 0x6b000 }, + [GCC_PCIE_0_PHY_BCR] = { 0x6c01c }, + [GCC_PCIE_PHY_BCR] = { 0x6f000 }, + [GCC_PCIE_PHY_COM_BCR] = { 0x6f010 }, + [GCC_UFS_PHY_BCR] = { 0x77000 }, + [GCC_USB20_SEC_BCR] = { 0xa6000 }, +}; + +static struct clk_dfs gcc_dfs_clocks[] = { + { &gcc_qupv3_wrap0_s0_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap0_s1_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap0_s2_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap0_s3_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap0_s4_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap0_s5_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap1_s0_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap1_s1_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap1_s2_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap1_s3_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap1_s4_clk_src, DFS_ENABLE_RCG }, + { &gcc_qupv3_wrap1_s5_clk_src, DFS_ENABLE_RCG }, +}; + +static const struct qcom_cc_dfs_desc gcc_sm6150_dfs_desc = { + .clks = gcc_dfs_clocks, + .num_clks = ARRAY_SIZE(gcc_dfs_clocks), +}; + +static const struct regmap_config gcc_sm6150_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xa609c, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_sm6150_desc = { + .config = &gcc_sm6150_regmap_config, + .clks = gcc_sm6150_clocks, + .num_clks = ARRAY_SIZE(gcc_sm6150_clocks), + .hwclks = gcc_sm6150_hws, + .num_hwclks = ARRAY_SIZE(gcc_sm6150_hws), + .resets = gcc_sm6150_resets, + .num_resets = ARRAY_SIZE(gcc_sm6150_resets), +}; + +static const struct of_device_id gcc_sm6150_match_table[] = { + { .compatible = "qcom,gcc-sm6150" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_sm6150_match_table); + +static int gcc_sm6150_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + vdd_cx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_cx"); + if (IS_ERR(vdd_cx.regulator[0])) { + if (!(PTR_ERR(vdd_cx.regulator[0]) == -EPROBE_DEFER)) + dev_err(&pdev->dev, + "Unable to get vdd_cx regulator\n"); + return PTR_ERR(vdd_cx.regulator[0]); + } + + vdd_cx_ao.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_cx_ao"); + if (IS_ERR(vdd_cx_ao.regulator[0])) { + if (!(PTR_ERR(vdd_cx_ao.regulator[0]) == -EPROBE_DEFER)) + dev_err(&pdev->dev, + "Unable to get vdd_cx_ao regulator\n"); + return PTR_ERR(vdd_cx_ao.regulator[0]); + } + + regmap = qcom_cc_map(pdev, &gcc_sm6150_desc); + if (IS_ERR(regmap)) { + pr_err("Failed to map the gcc registers\n"); + return PTR_ERR(regmap); + } + + /* + * Disable the GPLL0 active input to MM blocks and GPU + * via MISC registers. + */ + regmap_update_bits(regmap, GCC_DISPLAY_MISC, 0x3, 0x3); + regmap_update_bits(regmap, GCC_CAMERA_MISC, 0x3, 0x3); + regmap_update_bits(regmap, GCC_VIDEO_MISC, 0x3, 0x3); + regmap_update_bits(regmap, GCC_GPU_MISC, 0x3, 0x3); + regmap_update_bits(regmap, GCC_EMAC_MISC, 0x3, 0x3); + + ret = qcom_cc_really_probe(pdev, &gcc_sm6150_desc, regmap); + if (ret) { + dev_err(&pdev->dev, "Failed to register GCC clocks\n"); + return ret; + } + + /* DFS clock registration */ + ret = qcom_cc_register_rcg_dfs(pdev, &gcc_sm6150_dfs_desc); + if (ret) + dev_err(&pdev->dev, "Failed to register with DFS!\n"); + + dev_info(&pdev->dev, "Registered GCC clocks\n"); + + return 0; +} + +static struct platform_driver gcc_sm6150_driver = { + .probe = gcc_sm6150_probe, + .driver = { + .name = "gcc-sm6150", + .of_match_table = gcc_sm6150_match_table, + }, +}; + +static int __init gcc_sm6150_init(void) +{ + return platform_driver_register(&gcc_sm6150_driver); +} +subsys_initcall(gcc_sm6150_init); + +static void __exit gcc_sm6150_exit(void) +{ + platform_driver_unregister(&gcc_sm6150_driver); +} +module_exit(gcc_sm6150_exit); + +MODULE_DESCRIPTION("QTI GCC SM6150 Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:gcc-sm6150"); diff --git a/drivers/clk/qcom/vdd-level-sm6150.h b/drivers/clk/qcom/vdd-level-sm6150.h new file mode 100644 index 000000000000..88397238c7c1 --- /dev/null +++ b/drivers/clk/qcom/vdd-level-sm6150.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __DRIVERS_CLK_QCOM_VDD_LEVEL_SM6150_H +#define __DRIVERS_CLK_QCOM_VDD_LEVEL_SM6150_H + +#include +#include + +enum vdd_mx_levels { + VDD_MX_NONE, + VDD_MX_MIN, /* MIN SVS */ + VDD_MX_LOWER, /* SVS2 */ + VDD_MX_LOW, /* SVS */ + VDD_MX_LOW_L1, /* SVSL1 */ + VDD_MX_NOMINAL, /* NOM */ + VDD_MX_HIGH, /* TURBO */ + VDD_MX_NUM, +}; + +static int vdd_mx_corner[] = { + RPMH_REGULATOR_LEVEL_OFF, /* VDD_NONE */ + RPMH_REGULATOR_LEVEL_MIN_SVS, /* VDD_MIN */ + RPMH_REGULATOR_LEVEL_LOW_SVS, /* VDD_LOWER */ + RPMH_REGULATOR_LEVEL_SVS, /* VDD_LOW */ + RPMH_REGULATOR_LEVEL_SVS_L1, /* VDD_LOW_L1 */ + RPMH_REGULATOR_LEVEL_NOM, /* VDD_NOMINAL */ + RPMH_REGULATOR_LEVEL_TURBO, /* VDD_HIGH */ +}; + +enum vdd_levels { + VDD_NONE, + VDD_MIN, /* MIN SVS */ + VDD_LOWER, /* SVS2 */ + VDD_LOW, /* SVS */ + VDD_LOW_L1, /* SVSL1 */ + VDD_NOMINAL, /* NOM */ + VDD_NOMINAL_L1, /* NOM1 */ + VDD_HIGH, /* TURBO */ + VDD_HIGH_L1, /* TURBO1 */ + VDD_NUM, +}; + +static int vdd_corner[] = { + RPMH_REGULATOR_LEVEL_OFF, /* VDD_NONE */ + RPMH_REGULATOR_LEVEL_MIN_SVS, /* VDD_MIN */ + RPMH_REGULATOR_LEVEL_LOW_SVS, /* VDD_LOWER */ + RPMH_REGULATOR_LEVEL_SVS, /* VDD_LOW */ + RPMH_REGULATOR_LEVEL_SVS_L1, /* VDD_LOW_L1 */ + RPMH_REGULATOR_LEVEL_NOM, /* VDD_NOMINAL */ + RPMH_REGULATOR_LEVEL_NOM_L1, /* VDD_NOMINAL_L1 */ + RPMH_REGULATOR_LEVEL_TURBO, /* VDD_HIGH */ + RPMH_REGULATOR_LEVEL_TURBO_L1, /* VDD_HIGH_L1 */ + RPMH_REGULATOR_LEVEL_MAX, /* VDD_MAX */ +}; + +#endif diff --git a/include/dt-bindings/clock/qcom,gcc-sm6150.h b/include/dt-bindings/clock/qcom,gcc-sm6150.h index 711f19c1d55d..cf08a333002d 100644 --- a/include/dt-bindings/clock/qcom,gcc-sm6150.h +++ b/include/dt-bindings/clock/qcom,gcc-sm6150.h @@ -14,214 +14,192 @@ #ifndef _DT_BINDINGS_CLK_QCOM_GCC_SM6150_H #define _DT_BINDINGS_CLK_QCOM_GCC_SM6150_H -#define GCC_AGGRE_UFS_PHY_AXI_CLK 0 -#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK 1 -#define GCC_AGGRE_USB2_SEC_AXI_CLK 2 -#define GCC_AGGRE_USB3_PRIM_AXI_CLK 3 -#define GCC_AHB2PHY_EAST_CLK 4 -#define GCC_AHB2PHY_WEST_CLK 5 -#define GCC_APC_VS_CLK 6 -#define GCC_BOOT_ROM_AHB_CLK 7 -#define GCC_CAMERA_AHB_CLK 8 -#define GCC_CAMERA_HF_AXI_CLK 9 -#define GCC_CAMERA_XO_CLK 10 -#define GCC_CE1_AHB_CLK 11 -#define GCC_CE1_AXI_CLK 12 -#define GCC_CE1_CLK 13 -#define GCC_CFG_NOC_USB2_SEC_AXI_CLK 14 -#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 15 -#define GCC_CPUSS_AHB_CLK 16 -#define GCC_CPUSS_AHB_CLK_SRC 17 -#define GCC_CPUSS_GNOC_CLK 18 -#define GCC_DDRSS_GPU_AXI_CLK 19 -#define GCC_DISP_AHB_CLK 20 -#define GCC_DISP_GPLL0_DIV_CLK_SRC 21 -#define GCC_DISP_HF_AXI_CLK 22 -#define GCC_DISP_XO_CLK 23 -#define GCC_EMAC_AXI_CLK 24 -#define GCC_EMAC_PTP_CLK 25 -#define GCC_EMAC_PTP_CLK_SRC 26 -#define GCC_EMAC_RGMII_CLK 27 -#define GCC_EMAC_RGMII_CLK_SRC 28 -#define GCC_EMAC_SLV_AHB_CLK 29 -#define GCC_GP1_CLK 30 -#define GCC_GP1_CLK_SRC 31 -#define GCC_GP2_CLK 32 -#define GCC_GP2_CLK_SRC 33 -#define GCC_GP3_CLK 34 -#define GCC_GP3_CLK_SRC 35 -#define GCC_GPU_CFG_AHB_CLK 36 -#define GCC_GPU_GPLL0_CLK_SRC 37 -#define GCC_GPU_GPLL0_DIV_CLK_SRC 38 -#define GCC_GPU_IREF_CLK 39 -#define GCC_GPU_MEMNOC_GFX_CLK 40 -#define GCC_GPU_SNOC_DVM_GFX_CLK 41 -#define GCC_MSS_AXIS2_CLK 42 -#define GCC_MSS_CFG_AHB_CLK 43 -#define GCC_MSS_GPLL0_DIV_CLK_SRC 44 -#define GCC_MSS_MFAB_AXIS_CLK 45 -#define GCC_MSS_Q6_MEMNOC_AXI_CLK 46 -#define GCC_MSS_SNOC_AXI_CLK 47 -#define GCC_MSS_VS_CLK 48 -#define GCC_PCIE0_PHY_REFGEN_CLK 49 -#define GCC_PCIE_0_AUX_CLK 50 -#define GCC_PCIE_0_AUX_CLK_SRC 51 -#define GCC_PCIE_0_CFG_AHB_CLK 52 -#define GCC_PCIE_0_CLKREF_CLK 53 -#define GCC_PCIE_0_MSTR_AXI_CLK 54 -#define GCC_PCIE_0_PIPE_CLK 55 -#define GCC_PCIE_0_SLV_AXI_CLK 56 -#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 57 -#define GCC_PCIE_PHY_AUX_CLK 58 -#define GCC_PCIE_PHY_REFGEN_CLK_SRC 59 -#define GCC_PDM2_CLK 60 -#define GCC_PDM2_CLK_SRC 61 -#define GCC_PDM_AHB_CLK 62 -#define GCC_PDM_XO4_CLK 63 -#define GCC_PRNG_AHB_CLK 64 -#define GCC_QMIP_CAMERA_NRT_AHB_CLK 65 -#define GCC_QMIP_DISP_AHB_CLK 66 -#define GCC_QMIP_PCIE_AHB_CLK 67 -#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 68 -#define GCC_QSPI_CNOC_PERIPH_AHB_CLK 69 -#define GCC_QSPI_CORE_CLK 70 -#define GCC_QSPI_CORE_CLK_SRC 71 -#define GCC_QUPV3_WRAP0_CORE_2X_CLK 72 -#define GCC_QUPV3_WRAP0_CORE_CLK 73 -#define GCC_QUPV3_WRAP0_S0_CLK 74 -#define GCC_QUPV3_WRAP0_S0_CLK_SRC 75 -#define GCC_QUPV3_WRAP0_S1_CLK 76 -#define GCC_QUPV3_WRAP0_S1_CLK_SRC 77 -#define GCC_QUPV3_WRAP0_S2_CLK 78 -#define GCC_QUPV3_WRAP0_S2_CLK_SRC 79 -#define GCC_QUPV3_WRAP0_S3_CLK 80 -#define GCC_QUPV3_WRAP0_S3_CLK_SRC 81 -#define GCC_QUPV3_WRAP0_S4_CLK 82 -#define GCC_QUPV3_WRAP0_S4_CLK_SRC 83 -#define GCC_QUPV3_WRAP0_S5_CLK 84 -#define GCC_QUPV3_WRAP0_S5_CLK_SRC 85 -#define GCC_QUPV3_WRAP1_CORE_2X_CLK 86 -#define GCC_QUPV3_WRAP1_CORE_CLK 87 -#define GCC_QUPV3_WRAP1_S0_CLK 88 -#define GCC_QUPV3_WRAP1_S0_CLK_SRC 89 -#define GCC_QUPV3_WRAP1_S1_CLK 90 -#define GCC_QUPV3_WRAP1_S1_CLK_SRC 91 -#define GCC_QUPV3_WRAP1_S2_CLK 92 -#define GCC_QUPV3_WRAP1_S2_CLK_SRC 93 -#define GCC_QUPV3_WRAP1_S3_CLK 94 -#define GCC_QUPV3_WRAP1_S3_CLK_SRC 95 -#define GCC_QUPV3_WRAP1_S4_CLK 96 -#define GCC_QUPV3_WRAP1_S4_CLK_SRC 97 -#define GCC_QUPV3_WRAP1_S5_CLK 98 -#define GCC_QUPV3_WRAP1_S5_CLK_SRC 99 -#define GCC_QUPV3_WRAP_0_M_AHB_CLK 100 -#define GCC_QUPV3_WRAP_0_S_AHB_CLK 101 -#define GCC_QUPV3_WRAP_1_M_AHB_CLK 102 -#define GCC_QUPV3_WRAP_1_S_AHB_CLK 103 -#define GCC_SDCC1_AHB_CLK 104 -#define GCC_SDCC1_APPS_CLK 105 -#define GCC_SDCC1_APPS_CLK_SRC 106 -#define GCC_SDCC1_ICE_CORE_CLK 107 -#define GCC_SDCC1_ICE_CORE_CLK_SRC 108 -#define GCC_SDCC2_AHB_CLK 109 -#define GCC_SDCC2_APPS_CLK 110 -#define GCC_SDCC2_APPS_CLK_SRC 111 -#define GCC_SYS_NOC_CPUSS_AHB_CLK 112 -#define GCC_UFS_CARD_CLKREF_CLK 113 -#define GCC_UFS_MEM_CLKREF_CLK 114 -#define GCC_UFS_PHY_AHB_CLK 115 -#define GCC_UFS_PHY_AXI_CLK 116 -#define GCC_UFS_PHY_AXI_CLK_SRC 117 -#define GCC_UFS_PHY_AXI_HW_CTL_CLK 118 -#define GCC_UFS_PHY_ICE_CORE_CLK 119 -#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 120 -#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK 121 -#define GCC_UFS_PHY_PHY_AUX_CLK 122 -#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 123 -#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK 124 -#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 125 -#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 126 -#define GCC_UFS_PHY_UNIPRO_CORE_CLK 127 -#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 128 -#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK 129 -#define GCC_USB20_SEC_MASTER_CLK 130 -#define GCC_USB20_SEC_MASTER_CLK_SRC 131 -#define GCC_USB20_SEC_MOCK_UTMI_CLK 132 -#define GCC_USB20_SEC_MOCK_UTMI_CLK_SRC 133 -#define GCC_USB20_SEC_SLEEP_CLK 134 -#define GCC_USB2_SEC_PHY_AUX_CLK 135 -#define GCC_USB2_SEC_PHY_AUX_CLK_SRC 136 -#define GCC_USB2_SEC_PHY_COM_AUX_CLK 137 -#define GCC_USB2_SEC_PHY_PIPE_CLK 138 -#define GCC_USB30_PRIM_MASTER_CLK 139 -#define GCC_USB30_PRIM_MASTER_CLK_SRC 140 -#define GCC_USB30_PRIM_MOCK_UTMI_CLK 141 -#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 142 -#define GCC_USB30_PRIM_SLEEP_CLK 143 -#define GCC_USB3_PRIM_CLKREF_CLK 144 -#define GCC_USB3_PRIM_PHY_AUX_CLK 145 -#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 146 -#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 147 -#define GCC_USB3_PRIM_PHY_PIPE_CLK 148 -#define GCC_USB3_SEC_CLKREF_CLK 149 -#define GCC_VDDA_VS_CLK 150 -#define GCC_VDDCX_VS_CLK 151 -#define GCC_VDDMX_VS_CLK 152 -#define GCC_VIDEO_AHB_CLK 153 -#define GCC_VIDEO_AXI0_CLK 154 -#define GCC_VIDEO_XO_CLK 155 -#define GCC_VS_CTRL_AHB_CLK 156 -#define GCC_VS_CTRL_CLK 157 -#define GCC_VS_CTRL_CLK_SRC 158 -#define GCC_VSENSOR_CLK_SRC 159 -#define GCC_WCSS_VS_CLK 160 -#define GPLL0 161 -#define GPLL0_OUT_AUX2 162 -#define GPLL0_OUT_MAIN 163 -#define GPLL6 164 -#define GPLL6_OUT_MAIN 165 -#define GPLL7 166 -#define GPLL7_OUT_MAIN 167 -#define GPLL8 168 -#define GPLL8_OUT_MAIN 169 +/* Hardware and dummy clocks for rate measurement */ +#define GPLL0_OUT_AUX2 0 +#define MEASURE_ONLY_SNOC_CLK 1 +#define MEASURE_ONLY_CNOC_CLK 2 +#define MEASURE_ONLY_BIMC_CLK 3 +#define MEASURE_ONLY_IPA_2X_CLK 4 -#define GCC_EMAC_BCR 0 -#define GCC_GPU_BCR 1 -#define GCC_MMSS_BCR 2 -#define GCC_PCIE_0_BCR 3 -#define GCC_PCIE_0_LINK_DOWN_BCR 4 -#define GCC_PCIE_0_NOCSR_COM_PHY_BCR 5 -#define GCC_PCIE_0_PHY_BCR 6 -#define GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR 7 -#define GCC_PCIE_PHY_BCR 8 -#define GCC_PCIE_PHY_CFG_AHB_BCR 9 -#define GCC_PCIE_PHY_COM_BCR 10 -#define GCC_PDM_BCR 11 -#define GCC_PRNG_BCR 12 -#define GCC_QSPI_BCR 13 -#define GCC_QUPV3_WRAPPER_0_BCR 14 -#define GCC_QUPV3_WRAPPER_1_BCR 15 -#define GCC_QUSB2PHY_PRIM_BCR 16 -#define GCC_QUSB2PHY_SEC_BCR 17 -#define GCC_SDCC1_BCR 18 -#define GCC_SDCC2_BCR 19 -#define GCC_UFS_PHY_BCR 20 -#define GCC_USB20_SEC_BCR 21 -#define GCC_USB2_PHY_SEC_BCR 22 -#define GCC_USB30_PRIM_BCR 23 -#define GCC_USB3_DP_PHY_PRIM_SP0_BCR 24 -#define GCC_USB3_DP_PHY_PRIM_SP1_BCR 25 -#define GCC_USB3_DP_PHY_SEC_BCR 26 -#define GCC_USB3_PHY_PRIM_SP0_BCR 27 -#define GCC_USB3_PHY_PRIM_SP1_BCR 28 -#define GCC_USB3_UNIPHY_MP0_BCR 29 -#define GCC_USB3_UNIPHY_MP1_BCR 30 -#define GCC_USB3PHY_PHY_PRIM_SP0_BCR 31 -#define GCC_USB3PHY_PHY_PRIM_SP1_BCR 32 -#define GCC_USB3PHY_PHY_SEC_BCR 33 -#define GCC_USB3UNIPHY_PHY_MP0_BCR 34 -#define GCC_USB3UNIPHY_PHY_MP1_BCR 35 -#define GCC_USB_PHY_CFG_AHB2PHY_BCR 36 -#define GCC_VS_BCR 37 +/* GCC clock registers */ +#define GCC_AGGRE_UFS_PHY_AXI_CLK 5 +#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK 6 +#define GCC_AGGRE_USB2_SEC_AXI_CLK 7 +#define GCC_AGGRE_USB3_PRIM_AXI_CLK 8 +#define GCC_AHB2PHY_EAST_CLK 9 +#define GCC_AHB2PHY_WEST_CLK 10 +#define GCC_APC_VS_CLK 11 +#define GCC_BOOT_ROM_AHB_CLK 12 +#define GCC_CAMERA_AHB_CLK 13 +#define GCC_CAMERA_HF_AXI_CLK 14 +#define GCC_CE1_AHB_CLK 15 +#define GCC_CE1_AXI_CLK 16 +#define GCC_CE1_CLK 17 +#define GCC_CFG_NOC_USB2_SEC_AXI_CLK 18 +#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 19 +#define GCC_CPUSS_AHB_CLK 20 +#define GCC_CPUSS_AHB_CLK_SRC 21 +#define GCC_DDRSS_GPU_AXI_CLK 22 +#define GCC_DISP_AHB_CLK 23 +#define GCC_DISP_GPLL0_DIV_CLK_SRC 24 +#define GCC_DISP_HF_AXI_CLK 25 +#define GCC_EMAC_AXI_CLK 26 +#define GCC_EMAC_PTP_CLK 27 +#define GCC_EMAC_PTP_CLK_SRC 28 +#define GCC_EMAC_RGMII_CLK 29 +#define GCC_EMAC_RGMII_CLK_SRC 30 +#define GCC_EMAC_SLV_AHB_CLK 31 +#define GCC_GP1_CLK 32 +#define GCC_GP1_CLK_SRC 33 +#define GCC_GP2_CLK 34 +#define GCC_GP2_CLK_SRC 35 +#define GCC_GP3_CLK 36 +#define GCC_GP3_CLK_SRC 37 +#define GCC_GPU_CFG_AHB_CLK 38 +#define GCC_GPU_GPLL0_CLK_SRC 39 +#define GCC_GPU_GPLL0_DIV_CLK_SRC 40 +#define GCC_GPU_IREF_CLK 41 +#define GCC_GPU_MEMNOC_GFX_CLK 42 +#define GCC_GPU_SNOC_DVM_GFX_CLK 43 +#define GCC_MSS_AXIS2_CLK 44 +#define GCC_MSS_CFG_AHB_CLK 45 +#define GCC_MSS_GPLL0_DIV_CLK_SRC 46 +#define GCC_MSS_MFAB_AXIS_CLK 47 +#define GCC_MSS_Q6_MEMNOC_AXI_CLK 48 +#define GCC_MSS_SNOC_AXI_CLK 49 +#define GCC_MSS_VS_CLK 50 +#define GCC_PCIE0_PHY_REFGEN_CLK 51 +#define GCC_PCIE_0_AUX_CLK 52 +#define GCC_PCIE_0_AUX_CLK_SRC 53 +#define GCC_PCIE_0_CFG_AHB_CLK 54 +#define GCC_PCIE_0_CLKREF_CLK 55 +#define GCC_PCIE_0_MSTR_AXI_CLK 56 +#define GCC_PCIE_0_PIPE_CLK 57 +#define GCC_PCIE_0_SLV_AXI_CLK 58 +#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 59 +#define GCC_PCIE_PHY_AUX_CLK 60 +#define GCC_PCIE_PHY_REFGEN_CLK_SRC 61 +#define GCC_PDM2_CLK 62 +#define GCC_PDM2_CLK_SRC 63 +#define GCC_PDM_AHB_CLK 64 +#define GCC_PDM_XO4_CLK 65 +#define GCC_PRNG_AHB_CLK 66 +#define GCC_QMIP_CAMERA_NRT_AHB_CLK 67 +#define GCC_QMIP_DISP_AHB_CLK 68 +#define GCC_QMIP_PCIE_AHB_CLK 69 +#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 70 +#define GCC_QSPI_CNOC_PERIPH_AHB_CLK 71 +#define GCC_QSPI_CORE_CLK 72 +#define GCC_QSPI_CORE_CLK_SRC 73 +#define GCC_QUPV3_WRAP0_CORE_2X_CLK 74 +#define GCC_QUPV3_WRAP0_CORE_CLK 75 +#define GCC_QUPV3_WRAP0_S0_CLK 76 +#define GCC_QUPV3_WRAP0_S0_CLK_SRC 77 +#define GCC_QUPV3_WRAP0_S1_CLK 78 +#define GCC_QUPV3_WRAP0_S1_CLK_SRC 79 +#define GCC_QUPV3_WRAP0_S2_CLK 80 +#define GCC_QUPV3_WRAP0_S2_CLK_SRC 81 +#define GCC_QUPV3_WRAP0_S3_CLK 82 +#define GCC_QUPV3_WRAP0_S3_CLK_SRC 83 +#define GCC_QUPV3_WRAP0_S4_CLK 84 +#define GCC_QUPV3_WRAP0_S4_CLK_SRC 85 +#define GCC_QUPV3_WRAP0_S5_CLK 86 +#define GCC_QUPV3_WRAP0_S5_CLK_SRC 87 +#define GCC_QUPV3_WRAP1_CORE_2X_CLK 88 +#define GCC_QUPV3_WRAP1_CORE_CLK 89 +#define GCC_QUPV3_WRAP1_S0_CLK 90 +#define GCC_QUPV3_WRAP1_S0_CLK_SRC 91 +#define GCC_QUPV3_WRAP1_S1_CLK 92 +#define GCC_QUPV3_WRAP1_S1_CLK_SRC 93 +#define GCC_QUPV3_WRAP1_S2_CLK 94 +#define GCC_QUPV3_WRAP1_S2_CLK_SRC 95 +#define GCC_QUPV3_WRAP1_S3_CLK 96 +#define GCC_QUPV3_WRAP1_S3_CLK_SRC 97 +#define GCC_QUPV3_WRAP1_S4_CLK 98 +#define GCC_QUPV3_WRAP1_S4_CLK_SRC 99 +#define GCC_QUPV3_WRAP1_S5_CLK 100 +#define GCC_QUPV3_WRAP1_S5_CLK_SRC 101 +#define GCC_QUPV3_WRAP_0_M_AHB_CLK 102 +#define GCC_QUPV3_WRAP_0_S_AHB_CLK 103 +#define GCC_QUPV3_WRAP_1_M_AHB_CLK 104 +#define GCC_QUPV3_WRAP_1_S_AHB_CLK 105 +#define GCC_SDCC1_AHB_CLK 106 +#define GCC_SDCC1_APPS_CLK 107 +#define GCC_SDCC1_APPS_CLK_SRC 108 +#define GCC_SDCC1_ICE_CORE_CLK 109 +#define GCC_SDCC1_ICE_CORE_CLK_SRC 110 +#define GCC_SDCC2_AHB_CLK 111 +#define GCC_SDCC2_APPS_CLK 112 +#define GCC_SDCC2_APPS_CLK_SRC 113 +#define GCC_SYS_NOC_CPUSS_AHB_CLK 114 +#define GCC_UFS_CARD_CLKREF_CLK 115 +#define GCC_UFS_MEM_CLKREF_CLK 116 +#define GCC_UFS_PHY_AHB_CLK 117 +#define GCC_UFS_PHY_AXI_CLK 118 +#define GCC_UFS_PHY_AXI_CLK_SRC 119 +#define GCC_UFS_PHY_AXI_HW_CTL_CLK 120 +#define GCC_UFS_PHY_ICE_CORE_CLK 121 +#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 122 +#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK 123 +#define GCC_UFS_PHY_PHY_AUX_CLK 124 +#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 125 +#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK 126 +#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 127 +#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 128 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK 129 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 130 +#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK 131 +#define GCC_USB20_SEC_MASTER_CLK 132 +#define GCC_USB20_SEC_MASTER_CLK_SRC 133 +#define GCC_USB20_SEC_MOCK_UTMI_CLK 134 +#define GCC_USB20_SEC_MOCK_UTMI_CLK_SRC 135 +#define GCC_USB20_SEC_SLEEP_CLK 136 +#define GCC_USB2_SEC_PHY_AUX_CLK 137 +#define GCC_USB2_SEC_PHY_AUX_CLK_SRC 138 +#define GCC_USB2_SEC_PHY_COM_AUX_CLK 139 +#define GCC_USB2_SEC_PHY_PIPE_CLK 140 +#define GCC_USB30_PRIM_MASTER_CLK 141 +#define GCC_USB30_PRIM_MASTER_CLK_SRC 142 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK 143 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 144 +#define GCC_USB30_PRIM_SLEEP_CLK 145 +#define GCC_USB3_PRIM_CLKREF_CLK 146 +#define GCC_USB3_PRIM_PHY_AUX_CLK 147 +#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 148 +#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 149 +#define GCC_USB3_PRIM_PHY_PIPE_CLK 150 +#define GCC_USB3_SEC_CLKREF_CLK 151 +#define GCC_VDDA_VS_CLK 152 +#define GCC_VDDCX_VS_CLK 153 +#define GCC_VDDMX_VS_CLK 154 +#define GCC_VIDEO_AHB_CLK 155 +#define GCC_VIDEO_AXI0_CLK 156 +#define GCC_VS_CTRL_AHB_CLK 157 +#define GCC_VS_CTRL_CLK 158 +#define GCC_VS_CTRL_CLK_SRC 159 +#define GCC_VSENSOR_CLK_SRC 160 +#define GCC_WCSS_VS_CLK 161 +#define GPLL0_OUT_MAIN 162 +#define GPLL6_OUT_MAIN 163 +#define GPLL7_OUT_MAIN 164 +#define GPLL8_OUT_MAIN 165 +#define GCC_CAMERA_XO_CLK 166 +#define GCC_CPUSS_GNOC_CLK 167 +#define GCC_DISP_XO_CLK 166 +#define GCC_VIDEO_XO_CLK 166 + +/* GCC Resets */ +#define GCC_QUSB2PHY_PRIM_BCR 0 +#define GCC_QUSB2PHY_SEC_BCR 1 +#define GCC_USB30_PRIM_BCR 2 +#define GCC_USB2_PHY_SEC_BCR 3 +#define GCC_USB3_DP_PHY_SEC_BCR 4 +#define GCC_USB3PHY_PHY_SEC_BCR 5 +#define GCC_PCIE_0_BCR 6 +#define GCC_PCIE_0_PHY_BCR 7 +#define GCC_PCIE_PHY_BCR 8 +#define GCC_PCIE_PHY_COM_BCR 9 +#define GCC_UFS_PHY_BCR 10 +#define GCC_USB20_SEC_BCR 11 #endif -- GitLab From c10d342fc164f89807dd8f87fdcc2b9ea4d6664e Mon Sep 17 00:00:00 2001 From: Amit Nischal Date: Mon, 23 Apr 2018 18:24:33 +0530 Subject: [PATCH 0160/1299] ARM: dts: msm: Update the clock_gcc node on SM6150 Update the GCC clock controller device node to register to actual GCC driver. Also update the GCC GDSCs by replacing the dummy nodes with actual GDSC regulator driver. Change-Id: I15197e2d84a8ae4497020e3aff9252c0e02ef9e2 Signed-off-by: Amit Nischal --- arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi | 42 +++++++---------------- arch/arm64/boot/dts/qcom/sm6150.dtsi | 15 +++----- 2 files changed, 17 insertions(+), 40 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi b/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi index 5548c3c0c9ea..143441013e52 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi @@ -14,7 +14,7 @@ &soc { /* GDSCs in Global CC */ emac_gdsc: qcom,gdsc@106004 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "emac_gdsc"; reg = <0x106004 0x4>; qcom,poll-cfg-gdscr; @@ -22,7 +22,7 @@ }; pcie_0_gdsc: qcom,gdsc@16b004 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "pcie_0_gdsc"; reg = <0x16b004 0x4>; qcom,poll-cfg-gdscr; @@ -30,7 +30,7 @@ }; ufs_phy_gdsc: qcom,gdsc@177004 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "ufs_phy_gdsc"; reg = <0x177004 0x4>; qcom,poll-cfg-gdscr; @@ -38,7 +38,7 @@ }; usb20_sec_gdsc: qcom,gdsc@1a6004 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "usb20_sec_gdsc"; reg = <0x1a6004 0x4>; qcom,poll-cfg-gdscr; @@ -46,7 +46,7 @@ }; usb30_prim_gdsc: qcom,gdsc@10f004 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "usb30_prim_gdsc"; reg = <0x10f004 0x4>; qcom,poll-cfg-gdscr; @@ -54,7 +54,7 @@ }; hlos1_vote_aggre_noc_mmu_audio_tbu_gdsc: qcom,gdsc@17d040 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "hlos1_vote_aggre_noc_mmu_audio_tbu_gdsc"; reg = <0x17d040 0x4>; qcom,no-status-check-on-disable; @@ -63,7 +63,7 @@ }; hlos1_vote_aggre_noc_mmu_tbu1_gdsc: qcom,gdsc@17d044 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "hlos1_vote_aggre_noc_mmu_tbu1_gdsc"; reg = <0x17d044 0x4>; qcom,no-status-check-on-disable; @@ -72,7 +72,7 @@ }; hlos1_vote_aggre_noc_mmu_tbu2_gdsc: qcom,gdsc@17d048 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "hlos1_vote_aggre_noc_mmu_tbu2_gdsc"; reg = <0x17d048 0x4>; qcom,no-status-check-on-disable; @@ -81,7 +81,7 @@ }; hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc: qcom,gdsc@17d04c { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc"; reg = <0x17d04c 0x4>; qcom,no-status-check-on-disable; @@ -90,7 +90,7 @@ }; hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc: qcom,gdsc@17d050 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc"; reg = <0x17d050 0x4>; qcom,no-status-check-on-disable; @@ -99,7 +99,7 @@ }; hlos1_vote_mmnoc_mmu_tbu_sf_gdsc: qcom,gdsc@17d054 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "hlos1_vote_mmnoc_mmu_tbu_sf_gdsc"; reg = <0x17d054 0x4>; qcom,no-status-check-on-disable; @@ -108,7 +108,7 @@ }; hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc: qcom,gdsc@17d058 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc"; reg = <0x17d058 0x4>; qcom,no-status-check-on-disable; @@ -116,24 +116,6 @@ status = "disabled"; }; - hlos1_vote_turing_mmu_tbu0_gdsc: qcom,gdsc@17d05c { - compatible = "regulator-fixed"; - regulator-name = "hlos1_vote_turing_mmu_tbu0_gdsc"; - reg = <0x17d05c 0x4>; - qcom,no-status-check-on-disable; - qcom,gds-timeout = <500>; - status = "disabled"; - }; - - hlos1_vote_turing_mmu_tbu1_gdsc: qcom,gdsc@17d060 { - compatible = "regulator-fixed"; - regulator-name = "hlos1_vote_turing_mmu_tbu1_gdsc"; - reg = <0x17d060 0x4>; - qcom,no-status-check-on-disable; - qcom,gds-timeout = <500>; - status = "disabled"; - }; - /* GDSCs in Camera CC */ bps_gdsc: qcom,gdsc@ad06004 { compatible = "regulator-fixed"; diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index f7447988e266..c6b277f9797a 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -609,8 +609,11 @@ }; clock_gcc: qcom,gcc { - compatible = "qcom,dummycc"; - clock-output-names = "gcc_clocks"; + compatible = "qcom,gcc-sm6150", "syscon"; + reg = <0x100000 0x1f0000>; + reg-names = "cc_base"; + vdd_cx-supply = <&pm6150_s1_level>; + vdd_cx_ao-supply = <&pm6150_s1_level_ao>; #clock-cells = <1>; #reset-cells = <1>; }; @@ -1577,14 +1580,6 @@ status = "ok"; }; -&hlos1_vote_turing_mmu_tbu0_gdsc { - status = "ok"; -}; - -&hlos1_vote_turing_mmu_tbu1_gdsc { - status = "ok"; -}; - &bps_gdsc { status = "ok"; }; -- GitLab From 1acf1a1a1ab07fab6d985aaad4c9fde72847ccb1 Mon Sep 17 00:00:00 2001 From: Amit Nischal Date: Mon, 23 Apr 2018 17:00:09 +0530 Subject: [PATCH 0161/1299] clk: qcom: Add GPU clock driver for SM6150 Add support for the graphics clock controller found on SM6150 based devices. This should allow GPU device drivers to probe and control their clocks. Change-Id: Id9fa12a3521462ddef34eb1a0a91f14c2f558a67 Signed-off-by: Amit Nischal --- .../devicetree/bindings/clock/qcom,gpucc.txt | 11 +- drivers/clk/qcom/Kconfig | 8 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gpucc-sm6150.c | 522 ++++++++++++++++++ include/dt-bindings/clock/qcom,gpucc-sm6150.h | 52 +- 5 files changed, 555 insertions(+), 39 deletions(-) create mode 100644 drivers/clk/qcom/gpucc-sm6150.c diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.txt b/Documentation/devicetree/bindings/clock/qcom,gpucc.txt index 129e3a79fbb9..c05328047241 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gpucc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.txt @@ -4,21 +4,22 @@ Qualcomm Technologies, Inc. Graphics Clock & Reset Controller Binding Required properties : - compatible : shall contain one of the following: "qcom,gpucc-sm8150", - "qcom,gpucc-sdmshrike". + "qcom,gpucc-sdmshrike", + "qcom,gpucc-sm6150". - reg : shall contain base register offset and size. - reg-names: names of registers listed in the same order as in the reg property. Must contain "cc_base". -- #clock-cells : shall contain 1. -- #reset-cells : shall contain 1. +- #clock-cells : from common clock binding, shall contain 1. +- #reset-cells : from common reset binding, shall contain 1. - vdd_cx-supply : The vdd_cx logic rail supply. - vdd_mx-supply : The vdd_mx logic rail supply. Optional properties : -- #power-domain-cells : shall contain 1. +- #power-domain-cells : from generic power domain binding, shall contain 1. Example: - clock_gpucc: qcom,gpucc { + clock_gpucc: clock-controller@0x2c90000 { compatible = "qcom,gpucc-sm8150"; reg = <0x2c90000 0x9000>; reg-names = "cc_base"; diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 8736a0153e02..bc4778ffd09e 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -350,3 +350,11 @@ config MSM_GCC_SM6150 SM6150 devices. Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, UFS, SD/eMMC, PCIe, etc. + +config MSM_GPUCC_SM6150 + tristate "SM6150 graphics Clock Controller" + depends on COMMON_CLK_QCOM + help + Support for the graphics clock controller on Qualcomm Technologies, Inc. + SM6150 devices. + Say Y if you want to support graphics clocks. diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index eae763bb9a7e..24d49dbf84ad 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o obj-$(CONFIG_MSM_GCC_SM6150) += gcc-sm6150.o obj-$(CONFIG_MSM_GCC_SM8150) += gcc-sm8150.o obj-$(CONFIG_MSM_GCC_SDMSHRIKE) += gcc-sdmshrike.o +obj-$(CONFIG_MSM_GPUCC_SM6150) += gpucc-sm6150.o obj-$(CONFIG_MSM_GPUCC_SM8150) += gpucc-sm8150.o obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o diff --git a/drivers/clk/qcom/gpucc-sm6150.c b/drivers/clk/qcom/gpucc-sm6150.c new file mode 100644 index 000000000000..eaf4e0a38dbc --- /dev/null +++ b/drivers/clk/qcom/gpucc-sm6150.c @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "clk: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "common.h" +#include "reset.h" +#include "vdd-level-sm6150.h" + +#define CX_GMU_CBCR_SLEEP_MASK 0xf +#define CX_GMU_CBCR_SLEEP_SHIFT 4 +#define CX_GMU_CBCR_WAKE_MASK 0xf +#define CX_GMU_CBCR_WAKE_SHIFT 8 + +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } + +static DEFINE_VDD_REGULATORS(vdd_cx, VDD_NUM, 1, vdd_corner); +static DEFINE_VDD_REGULATORS(vdd_mx, VDD_MX_NUM, 1, vdd_mx_corner); + +enum { + P_BI_TCXO, + P_CORE_BI_PLL_TEST_SE, + P_GPLL0_OUT_MAIN, + P_GPLL0_OUT_MAIN_DIV, + P_GPU_CC_PLL0_2X_CLK, + P_GPU_CC_PLL0_OUT_AUX2, + P_GPU_CC_PLL0_OUT_MAIN, + P_GPU_CC_PLL1_OUT_AUX, + P_GPU_CC_PLL1_OUT_AUX2, + P_GPU_CC_PLL1_OUT_MAIN, +}; + +static const struct parent_map gpu_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL0_OUT_MAIN, 1 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gpu_cc_parent_names_0[] = { + "bi_tcxo", + "gpu_cc_pll0_out_main", + "gpu_cc_pll1_out_main", + "gpll0_out_main", + "gpll0_out_main_div", + "core_bi_pll_test_se", +}; + +static const struct parent_map gpu_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL0_2X_CLK, 1 }, + { P_GPU_CC_PLL0_OUT_AUX2, 2 }, + { P_GPU_CC_PLL1_OUT_AUX, 3 }, + { P_GPU_CC_PLL1_OUT_AUX2, 4 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gpu_cc_parent_names_1[] = { + "bi_tcxo", + "gpu_cc_pll0_out_aux", + "gpu_cc_pll0_out_aux2", + "gpu_cc_pll1_out_aux", + "gpu_cc_pll1_out_aux2", + "gpll0_out_main", + "core_bi_pll_test_se", +}; + +static struct pll_vco gpu_cc_pll_vco[] = { + { 1000000000, 2000000000, 0 }, + { 500000000, 1000000000, 2 }, +}; + +/* 1020MHz configuration */ +static const struct alpha_pll_config gpu_pll0_config = { + .l = 0x35, + .config_ctl_val = 0x4001055b, + .alpha_u = 0x20, + .alpha = 0x00, + .alpha_en_mask = BIT(24), + .vco_val = 0x0 << 20, + .vco_mask = 0x3 << 20, + .aux2_output_mask = BIT(2), +}; + +/* 930MHz configuration */ +static const struct alpha_pll_config gpu_pll1_config = { + .l = 0x30, + .config_ctl_val = 0x4001055b, + .alpha_u = 0x70, + .alpha = 0x00, + .alpha_en_mask = BIT(24), + .vco_val = 0x2 << 20, + .vco_mask = 0x3 << 20, + .aux2_output_mask = BIT(2), +}; + +static struct clk_alpha_pll gpu_cc_pll0_out_aux2 = { + .offset = 0x0, + .vco_table = gpu_cc_pll_vco, + .num_vco = ARRAY_SIZE(gpu_cc_pll_vco), + .flags = SUPPORTS_DYNAMIC_UPDATE, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_pll0_out_aux2", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + .vdd_class = &vdd_mx, + .num_rate_max = VDD_MX_NUM, + .rate_max = (unsigned long[VDD_MX_NUM]) { + [VDD_MX_MIN] = 1000000000, + [VDD_MX_NOMINAL] = 2000000000}, + }, + }, +}; + +static struct clk_alpha_pll gpu_cc_pll1_out_aux2 = { + .offset = 0x100, + .vco_table = gpu_cc_pll_vco, + .num_vco = ARRAY_SIZE(gpu_cc_pll_vco), + .flags = SUPPORTS_DYNAMIC_UPDATE, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_pll1_out_aux2", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + .vdd_class = &vdd_mx, + .num_rate_max = VDD_MX_NUM, + .rate_max = (unsigned long[VDD_MX_NUM]) { + [VDD_MX_MIN] = 1000000000, + [VDD_MX_NOMINAL] = 2000000000}, + }, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_gmu_clk_src = { + .cmd_rcgr = 0x1120, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_0, + .freq_tbl = ftbl_gpu_cc_gmu_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gmu_clk_src", + .parent_names = gpu_cc_parent_names_0, + .num_parents = 6, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 200000000}, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { + F(290000000, P_GPU_CC_PLL1_OUT_AUX2, 2, 0, 0), + F(400000000, P_GPU_CC_PLL1_OUT_AUX2, 2, 0, 0), + F(513000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(645000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(706000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(845000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(895000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { + .cmd_rcgr = 0x101c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_1, + .freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src, + .flags = FORCE_ENABLE_RCG, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gx_gfx3d_clk_src", + .parent_names = gpu_cc_parent_names_1, + .num_parents = 7, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 290000000, + [VDD_LOW] = 400000000, + [VDD_LOW_L1] = 513000000, + [VDD_NOMINAL] = 645000000, + [VDD_NOMINAL_L1] = 706000000, + [VDD_HIGH] = 845000000, + [VDD_HIGH_L1] = 895000000}, + }, +}; + +static struct clk_branch gpu_cc_crc_ahb_clk = { + .halt_reg = 0x107c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x107c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_crc_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_apb_clk = { + .halt_reg = 0x1088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_apb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gfx3d_clk = { + .halt_reg = 0x10a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10a4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_gfx3d_clk", + .parent_names = (const char *[]){ + "gpu_cc_gx_gfx3d_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gfx3d_slv_clk = { + .halt_reg = 0x10a8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10a8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_gfx3d_slv_clk", + .parent_names = (const char *[]){ + "gpu_cc_gx_gfx3d_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gmu_clk = { + .halt_reg = 0x1098, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_gmu_clk", + .parent_names = (const char *[]){ + "gpu_cc_gmu_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { + .halt_reg = 0x108c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x108c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_snoc_dvm_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_aon_clk = { + .halt_reg = 0x1004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cxo_aon_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_clk = { + .halt_reg = 0x109c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x109c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cxo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gx_gfx3d_clk = { + .halt_reg = 0x1054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gx_gfx3d_clk", + .parent_names = (const char *[]){ + "gpu_cc_gx_gfx3d_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gx_gmu_clk = { + .halt_reg = 0x1064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1064, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gx_gmu_clk", + .parent_names = (const char *[]){ + "gpu_cc_gmu_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_sleep_clk = { + .halt_reg = 0x1090, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1090, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_ahb_clk = { + .halt_reg = 0x1078, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap *gpu_cc_sm6150_clocks[] = { + [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, + [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr, + [GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr, + [GPU_CC_CX_GFX3D_SLV_CLK] = &gpu_cc_cx_gfx3d_slv_clk.clkr, + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, + [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, + [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, + [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, + [GPU_CC_PLL0_OUT_AUX2] = &gpu_cc_pll0_out_aux2.clkr, + [GPU_CC_PLL1_OUT_AUX2] = &gpu_cc_pll1_out_aux2.clkr, + [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, + [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, + [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr, + [GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr, + [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, +}; + +static const struct regmap_config gpu_cc_sm6150_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x7008, + .fast_io = true, +}; + +static const struct qcom_cc_desc gpu_cc_sm6150_desc = { + .config = &gpu_cc_sm6150_regmap_config, + .clks = gpu_cc_sm6150_clocks, + .num_clks = ARRAY_SIZE(gpu_cc_sm6150_clocks), +}; + +static const struct of_device_id gpu_cc_sm6150_match_table[] = { + { .compatible = "qcom,gpucc-sm6150" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpu_cc_sm6150_match_table); + +static int gpu_cc_sm6150_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + unsigned int value, mask; + + /* Get CX voltage regulator for CX and GMU clocks. */ + vdd_cx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_cx"); + if (IS_ERR(vdd_cx.regulator[0])) { + if (!(PTR_ERR(vdd_cx.regulator[0]) == -EPROBE_DEFER)) + dev_err(&pdev->dev, + "Unable to get vdd_cx regulator\n"); + return PTR_ERR(vdd_cx.regulator[0]); + } + + /* Get MX voltage regulator for GPU PLL graphic clock. */ + vdd_mx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_mx"); + if (IS_ERR(vdd_mx.regulator[0])) { + if (!(PTR_ERR(vdd_mx.regulator[0]) == -EPROBE_DEFER)) + dev_err(&pdev->dev, + "Unable to get vdd_mx regulator\n"); + return PTR_ERR(vdd_mx.regulator[0]); + } + + regmap = qcom_cc_map(pdev, &gpu_cc_sm6150_desc); + if (IS_ERR(regmap)) { + pr_err("Failed to map the gpu_cc registers\n"); + return PTR_ERR(regmap); + } + + clk_alpha_pll_configure(&gpu_cc_pll0_out_aux2, regmap, + &gpu_pll0_config); + clk_alpha_pll_configure(&gpu_cc_pll1_out_aux2, regmap, + &gpu_pll1_config); + + ret = qcom_cc_really_probe(pdev, &gpu_cc_sm6150_desc, regmap); + if (ret) { + dev_err(&pdev->dev, "Failed to register GPU CC clocks\n"); + return ret; + } + + /* Recommended WAKEUP/SLEEP settings for the gpu_cc_cx_gmu_clk */ + mask = CX_GMU_CBCR_WAKE_MASK << CX_GMU_CBCR_WAKE_SHIFT; + mask |= CX_GMU_CBCR_SLEEP_MASK << CX_GMU_CBCR_SLEEP_SHIFT; + value = 0xf << CX_GMU_CBCR_WAKE_SHIFT | 0xf << CX_GMU_CBCR_SLEEP_SHIFT; + regmap_update_bits(regmap, gpu_cc_cx_gmu_clk.clkr.enable_reg, + mask, value); + + dev_info(&pdev->dev, "Registered GPU CC clocks\n"); + + return ret; +} + +static struct platform_driver gpu_cc_sm6150_driver = { + .probe = gpu_cc_sm6150_probe, + .driver = { + .name = "gpu_cc-sm6150", + .of_match_table = gpu_cc_sm6150_match_table, + }, +}; + +static int __init gpu_cc_sm6150_init(void) +{ + return platform_driver_register(&gpu_cc_sm6150_driver); +} +subsys_initcall(gpu_cc_sm6150_init); + +static void __exit gpu_cc_sm6150_exit(void) +{ + platform_driver_unregister(&gpu_cc_sm6150_driver); +} +module_exit(gpu_cc_sm6150_exit); + +MODULE_DESCRIPTION("QTI GPU_CC SM6150 Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:gpu_cc-sm6150"); diff --git a/include/dt-bindings/clock/qcom,gpucc-sm6150.h b/include/dt-bindings/clock/qcom,gpucc-sm6150.h index 15ad06ad4e7d..33c9975f6838 100644 --- a/include/dt-bindings/clock/qcom,gpucc-sm6150.h +++ b/include/dt-bindings/clock/qcom,gpucc-sm6150.h @@ -14,39 +14,23 @@ #ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_SM6150_H #define _DT_BINDINGS_CLK_QCOM_GPU_CC_SM6150_H -#define GPU_CC_AHB_CLK 0 -#define GPU_CC_CRC_AHB_CLK 1 -#define GPU_CC_CX_APB_CLK 2 -#define GPU_CC_CX_GFX3D_CLK 3 -#define GPU_CC_CX_GFX3D_SLV_CLK 4 -#define GPU_CC_CX_GMU_CLK 5 -#define GPU_CC_CX_QDSS_AT_CLK 6 -#define GPU_CC_CX_QDSS_TRIG_CLK 7 -#define GPU_CC_CX_QDSS_TSCTR_CLK 8 -#define GPU_CC_CX_SNOC_DVM_CLK 9 -#define GPU_CC_CXO_AON_CLK 10 -#define GPU_CC_CXO_CLK 11 -#define GPU_CC_GMU_CLK_SRC 12 -#define GPU_CC_GX_CXO_CLK 13 -#define GPU_CC_GX_GFX3D_CLK 14 -#define GPU_CC_GX_GFX3D_CLK_SRC 15 -#define GPU_CC_GX_GMU_CLK 16 -#define GPU_CC_GX_QDSS_TSCTR_CLK 17 -#define GPU_CC_GX_VSENSE_CLK 18 -#define GPU_CC_PLL0 19 -#define GPU_CC_PLL0_OUT_AUX 20 -#define GPU_CC_PLL1 21 -#define GPU_CC_PLL1_OUT_AUX 22 -#define GPU_CC_PLL_TEST_CLK 23 -#define GPU_CC_SLEEP_CLK 24 - -/* TODO: PLL CLOCK IDs */ - -#define GPUCC_GPU_CC_CX_BCR 0 -#define GPUCC_GPU_CC_GFX3D_AON_BCR 1 -#define GPUCC_GPU_CC_GMU_BCR 2 -#define GPUCC_GPU_CC_GX_BCR 3 -#define GPUCC_GPU_CC_SPDM_BCR 4 -#define GPUCC_GPU_CC_XO_BCR 5 +/* GPUCC clock registers */ +#define GPU_CC_CRC_AHB_CLK 0 +#define GPU_CC_CX_APB_CLK 1 +#define GPU_CC_CX_GFX3D_CLK 2 +#define GPU_CC_CX_GFX3D_SLV_CLK 3 +#define GPU_CC_CX_GMU_CLK 4 +#define GPU_CC_CX_SNOC_DVM_CLK 5 +#define GPU_CC_CXO_AON_CLK 6 +#define GPU_CC_CXO_CLK 7 +#define GPU_CC_GMU_CLK_SRC 8 +#define GPU_CC_PLL0_OUT_AUX2 9 +#define GPU_CC_PLL1_OUT_AUX2 10 +#define GPU_CC_SLEEP_CLK 11 +#define GPU_CC_GX_GMU_CLK 12 +#define GPU_CC_GX_CXO_CLK 13 +#define GPU_CC_GX_GFX3D_CLK 14 +#define GPU_CC_GX_GFX3D_CLK_SRC 15 +#define GPU_CC_AHB_CLK 16 #endif -- GitLab From 0a75c848071df65acdd78051b5d1d4352936318d Mon Sep 17 00:00:00 2001 From: Amit Nischal Date: Tue, 8 May 2018 12:22:33 +0530 Subject: [PATCH 0162/1299] ARM: dts: msm: Update the clock_gpucc node on SM6150 Update the GPUCC clock controller device node to register to actual GPUCC driver. Also update the GPUCC GDSCs by replacing the dummy nodes with actual GDSC regulator driver. Change-Id: If6bfe9e088060f4a4f9c5e0d4241d8f4bfcea89c Signed-off-by: Amit Nischal --- arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi | 4 ++-- arch/arm64/boot/dts/qcom/sm6150.dtsi | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi b/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi index 143441013e52..a566a4facd78 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi @@ -176,7 +176,7 @@ }; gpu_cx_gdsc: qcom,gdsc@509106c { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "gpu_cx_gdsc"; reg = <0x509106c 0x4>; hw-ctrl-addr = <&gpu_cx_hw_ctrl>; @@ -187,7 +187,7 @@ }; gpu_gx_gdsc: qcom,gdsc@509100c { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "gpu_gx_gdsc"; reg = <0x509100c 0x4>; qcom,poll-cfg-gdscr; diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index c6b277f9797a..d0e63a9d5d13 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -640,8 +640,11 @@ }; clock_gpucc: qcom,gpupcc { - compatible = "qcom,dummycc"; - clock-output-names = "gpucc_clocks"; + compatible = "qcom,gpucc-sm6150", "syscon"; + reg = <0x5090000 0x9000>; + reg-names = "cc_base"; + vdd_cx-supply = <&pm6150_s1_level>; + vdd_mx-supply = <&pm6150_s3_level>; #clock-cells = <1>; #reset-cells = <1>; }; @@ -1609,6 +1612,10 @@ }; &gpu_gx_gdsc { + clock-names = "core_root_clk"; + clocks = <&clock_gpucc GPU_CC_GX_GFX3D_CLK_SRC>; + qcom,force-enable-root-clk; + parent-supply = <&pm6150_s1_level>; status = "ok"; }; -- GitLab From 11893153bf9b6461b6a96ee84526c2602298ff8d Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Mon, 4 Jun 2018 17:50:14 -0700 Subject: [PATCH 0163/1299] power: smb5: report charger_temp_max using property The charger temp threshold charger_temp_max is defined in charger peripheral. Expose it in battery power supply. Change-Id: I24c90bfa0bffe10ff316dc673f83596c5ad75527 Signed-off-by: Harry Yang --- drivers/power/supply/qcom/qpnp-smb5.c | 11 ++++++ drivers/power/supply/qcom/smb5-lib.c | 53 +++++++++++++++++++++++++++ drivers/power/supply/qcom/smb5-lib.h | 2 + drivers/power/supply/qcom/smb5-reg.h | 2 + 4 files changed, 68 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index e1cdf902097f..8731c88f1895 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -1049,6 +1049,7 @@ static enum power_supply_property smb5_batt_props[] = { POWER_SUPPLY_PROP_CHARGE_TYPE, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_CHARGER_TEMP, + POWER_SUPPLY_PROP_CHARGER_TEMP_MAX, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_MAX, @@ -1115,6 +1116,9 @@ static int smb5_batt_get_prop(struct power_supply *psy, if (pval.intval) rc = smblib_get_prop_charger_temp(chg, val); break; + case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX: + val->intval = chg->charger_temp_max; + break; case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: rc = smblib_get_prop_input_current_limited(chg, val); break; @@ -1561,6 +1565,13 @@ static int smb5_init_hw(struct smb5 *chip) smblib_get_charge_param(chg, &chg->param.usb_icl, &chg->default_icl_ua); + rc = smblib_get_thermal_threshold(chg, DIE_REG_H_THRESHOLD_MSB_REG, + &chg->charger_temp_max); + if (rc < 0) { + dev_err(chg->dev, "Couldn't get charger_temp_max rc=%d\n", rc); + return rc; + } + /* Use SW based VBUS control, disable HW autonomous mode */ rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 37b2ba782ae0..0f50fe1bc936 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -259,6 +259,59 @@ int smblib_get_usb_suspend(struct smb_charger *chg, int *suspend) return rc; } + +static const s16 therm_lookup_table[] = { + /* Index -30C~85C, ADC raw code */ + 0x6C92, 0x6C43, 0x6BF0, 0x6B98, 0x6B3A, 0x6AD8, 0x6A70, 0x6A03, + 0x6990, 0x6916, 0x6897, 0x6811, 0x6785, 0x66F2, 0x6658, 0x65B7, + 0x650F, 0x6460, 0x63AA, 0x62EC, 0x6226, 0x6159, 0x6084, 0x5FA8, + 0x5EC3, 0x5DD8, 0x5CE4, 0x5BE9, 0x5AE7, 0x59DD, 0x58CD, 0x57B5, + 0x5696, 0x5571, 0x5446, 0x5314, 0x51DD, 0x50A0, 0x4F5E, 0x4E17, + 0x4CCC, 0x4B7D, 0x4A2A, 0x48D4, 0x477C, 0x4621, 0x44C4, 0x4365, + 0x4206, 0x40A6, 0x3F45, 0x3DE6, 0x3C86, 0x3B28, 0x39CC, 0x3872, + 0x3719, 0x35C4, 0x3471, 0x3322, 0x31D7, 0x308F, 0x2F4C, 0x2E0D, + 0x2CD3, 0x2B9E, 0x2A6E, 0x2943, 0x281D, 0x26FE, 0x25E3, 0x24CF, + 0x23C0, 0x22B8, 0x21B5, 0x20B8, 0x1FC2, 0x1ED1, 0x1DE6, 0x1D01, + 0x1C22, 0x1B49, 0x1A75, 0x19A8, 0x18E0, 0x181D, 0x1761, 0x16A9, + 0x15F7, 0x154A, 0x14A2, 0x13FF, 0x1361, 0x12C8, 0x1234, 0x11A4, + 0x1119, 0x1091, 0x100F, 0x0F90, 0x0F15, 0x0E9E, 0x0E2B, 0x0DBC, + 0x0D50, 0x0CE8, 0x0C83, 0x0C21, 0x0BC3, 0x0B67, 0x0B0F, 0x0AB9, + 0x0A66, 0x0A16, 0x09C9, 0x097E, +}; + +int smblib_get_thermal_threshold(struct smb_charger *chg, u16 addr, int *val) +{ + u8 buff[2]; + s16 temp; + int rc = 0; + int i, lower, upper; + + rc = smblib_batch_read(chg, addr, buff, 2); + if (rc < 0) { + pr_err("failed to write to 0x%04X, rc=%d\n", addr, rc); + return rc; + } + + temp = buff[1] | buff[0] << 8; + + lower = 0; + upper = ARRAY_SIZE(therm_lookup_table) - 1; + while (lower <= upper) { + i = (upper + lower) / 2; + if (therm_lookup_table[i] < temp) + upper = i - 1; + else if (therm_lookup_table[i] > temp) + lower = i + 1; + else + break; + } + + /* index 0 corresonds to -30C */ + *val = (i - 30) * 10; + + return rc; +} + struct apsd_result { const char * const name; const u8 bit; diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 9050c7ca34e5..c4d68083f05d 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -360,6 +360,7 @@ struct smb_charger { int auto_recharge_soc; enum sink_src_mode sink_src_mode; bool jeita_configured; + int charger_temp_max; /* workaround flag */ u32 wa_flags; @@ -536,6 +537,7 @@ void smblib_suspend_on_debug_battery(struct smb_charger *chg); int smblib_rerun_apsd_if_required(struct smb_charger *chg); int smblib_get_prop_fcc_delta(struct smb_charger *chg, union power_supply_propval *val); +int smblib_get_thermal_threshold(struct smb_charger *chg, u16 addr, int *val); int smblib_dp_dm(struct smb_charger *chg, int val); int smblib_disable_hw_jeita(struct smb_charger *chg, bool disable); int smblib_rerun_aicl(struct smb_charger *chg); diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h index 20a864e513e6..4afc7cca403f 100644 --- a/drivers/power/supply/qcom/smb5-reg.h +++ b/drivers/power/supply/qcom/smb5-reg.h @@ -386,4 +386,6 @@ enum { #define STAT_FUNCTION_CFG_BIT BIT(1) #define STAT_IRQ_PULSING_EN_BIT BIT(0) +#define DIE_REG_H_THRESHOLD_MSB_REG (MISC_BASE + 0xA0) + #endif /* __SMB5_CHARGER_REG_H */ -- GitLab From 922e636485eca9065dda04dce618cafd612ba299 Mon Sep 17 00:00:00 2001 From: Naresh Maradana Date: Tue, 12 Jun 2018 15:24:04 +0530 Subject: [PATCH 0164/1299] seemp: update to seemp_logk_set_mapping() Updating/interchanging the code in the Lock section to avoid memory leak in race condition in function seemp_logk_set_mapping(). Change-Id: I93fba54444c463f18faf1a2aa8be858a29d94a1b Signed-off-by: Naresh Maradana --- drivers/platform/msm/seemp_core/seemp_logk.c | 26 +++++++++----------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/platform/msm/seemp_core/seemp_logk.c b/drivers/platform/msm/seemp_core/seemp_logk.c index ca7f5e9332df..1a962bb9a013 100644 --- a/drivers/platform/msm/seemp_core/seemp_logk.c +++ b/drivers/platform/msm/seemp_core/seemp_logk.c @@ -472,20 +472,6 @@ static long seemp_logk_set_mapping(unsigned long arg) (UINT_MAX / sizeof(struct seemp_source_mask)))) return -EFAULT; - write_lock(&filter_lock); - if (pmask != NULL) { - /* - * Mask is getting set again. - * seemp_core was probably restarted. - */ - struct seemp_source_mask *ptempmask; - - num_sources = 0; - ptempmask = pmask; - pmask = NULL; - kfree(ptempmask); - } - write_unlock(&filter_lock); pbuffer = kmalloc_array(num_elements, sizeof(struct seemp_source_mask), GFP_KERNEL); if (pbuffer == NULL) @@ -511,6 +497,18 @@ static long seemp_logk_set_mapping(unsigned long arg) pnewmask[i].isOn = 0; } write_lock(&filter_lock); + if (pmask != NULL) { + /* + * Mask is getting set again. + * seemp_core was probably restarted. + */ + struct seemp_source_mask *ptempmask; + + num_sources = 0; + ptempmask = pmask; + pmask = NULL; + kfree(ptempmask); + } pmask = pnewmask; num_sources = num_elements; write_unlock(&filter_lock); -- GitLab From c3b79351665416200716152ec7e1bb035e4b500f Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Tue, 12 Jun 2018 15:35:43 +0530 Subject: [PATCH 0165/1299] clk: smd-rpm: Remove noirq function call from rpm cc Support for noirq is not present in upstraem rpmsg framework. So replace rpm_send_message_noirq() call with rpm_send_message() call. Change-Id: Id1f4e5d3e3ec857cdcc7ecdc183eef4708f014ef Signed-off-by: Shefali Jain --- drivers/clk/qcom/clk-smd-rpm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 79a6975ac5ee..cfac51124578 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -409,7 +409,7 @@ static int clk_smd_rpm_enable_scaling(void) .length = sizeof(value), }; - ret = msm_rpm_send_message_noirq(QCOM_SMD_RPM_SLEEP_STATE, + ret = msm_rpm_send_message(QCOM_SMD_RPM_SLEEP_STATE, QCOM_SMD_RPM_MISC_CLK, QCOM_RPM_SCALING_ENABLE_ID, &req, 1); if (ret) { @@ -417,7 +417,7 @@ static int clk_smd_rpm_enable_scaling(void) return ret; } - ret = msm_rpm_send_message_noirq(QCOM_SMD_RPM_ACTIVE_STATE, + ret = msm_rpm_send_message(QCOM_SMD_RPM_ACTIVE_STATE, QCOM_SMD_RPM_MISC_CLK, QCOM_RPM_SCALING_ENABLE_ID, &req, 1); if (ret) { @@ -439,7 +439,7 @@ static int clk_vote_bimc(struct clk_hw *hw, uint32_t rate) .length = sizeof(rate), }; - ret = msm_rpm_send_message_noirq(QCOM_SMD_RPM_ACTIVE_STATE, + ret = msm_rpm_send_message(QCOM_SMD_RPM_ACTIVE_STATE, r->rpm_res_type, r->rpm_clk_id, &req, 1); if (ret < 0) { if (ret != -EPROBE_DEFER) -- GitLab From 020642e2c4c82dbc714ef69e42cc392d7fab9e42 Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Thu, 12 Apr 2018 23:36:27 +0530 Subject: [PATCH 0166/1299] serial: msm_geni_serial: Remove manual flow control and set as RFR OPEN This patch removes the manual flow control and instead gives the RFR control to the HW depending on the FIFO level. In case of Manual flow control FW introduced a race and caused RFR to remain High at RX shutdown which blocked peer device from sending any data. The latest FW along with this patch makes sure RFR gets configured as an RFR OPEN post RX cancel and removes the need to have any manual flow. Also wait for the RX EOT bit post cancel command as per the suggested sequence. Also Log the GENI FW version for primary and secondary sequencer. Change-Id: Ifc06a3f1c971eb7490ff8e678779e7163008f999 Signed-off-by: Mukesh Kumar Savaliya --- drivers/platform/msm/qcom-geni-se.c | 32 +++++++++++++ drivers/tty/serial/msm_geni_serial.c | 71 +++++++++++++++++----------- include/linux/qcom-geni-se.h | 17 +++++++ 3 files changed, 93 insertions(+), 27 deletions(-) diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c index 4f09e465f23b..89d0a0d24682 100644 --- a/drivers/platform/msm/qcom-geni-se.c +++ b/drivers/platform/msm/qcom-geni-se.c @@ -157,6 +157,38 @@ int get_se_proto(void __iomem *base) } EXPORT_SYMBOL(get_se_proto); +/** + * get_se_m_fw() - Read the Firmware ver for the Main seqeuncer engine + * @base: Base address of the serial engine's register block. + * + * Return: Firmware version for the Main seqeuncer engine + */ +int get_se_m_fw(void __iomem *base) +{ + int fw_ver_m; + + fw_ver_m = ((geni_read_reg(base, GENI_FW_REVISION_RO) + & FW_REV_VERSION_MSK)); + return fw_ver_m; +} +EXPORT_SYMBOL(get_se_m_fw); + +/** + * get_se_s_fw() - Read the Firmware ver for the Secondry seqeuncer engine + * @base: Base address of the serial engine's register block. + * + * Return: Firmware version for the Secondry seqeuncer engine + */ +int get_se_s_fw(void __iomem *base) +{ + int fw_ver_s; + + fw_ver_s = ((geni_read_reg(base, GENI_FW_S_REVISION_RO) + & FW_REV_VERSION_MSK)); + return fw_ver_s; +} +EXPORT_SYMBOL(get_se_s_fw); + static int se_geni_irq_en(void __iomem *base) { unsigned int common_geni_m_irq_en; diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 185a9e2675e2..36e7841e7d9f 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -96,6 +96,7 @@ /* UART S_CMD OP codes */ #define UART_START_READ (0x1) #define UART_PARAM (0x1) +#define UART_PARAM_RFR_OPEN (BIT(7)) /* UART DMA Rx GP_IRQ_BITS */ #define UART_DMA_RX_PARITY_ERR BIT(5) @@ -610,6 +611,27 @@ static void msm_geni_serial_abort_rx(struct uart_port *uport) geni_write_reg(FORCE_DEFAULT, uport->membase, GENI_FORCE_DEFAULT_REG); } +static void msm_geni_serial_complete_rx_eot(struct uart_port *uport) +{ + int poll_done = 0, tries = 0; + u32 geni_status = 0; + struct msm_geni_serial_port *port = GET_DEV_PORT(uport); + + do { + poll_done = msm_geni_serial_poll_bit(uport, SE_DMA_RX_IRQ_STAT, + RX_EOT, true); + tries++; + } while (!poll_done && tries < 5); + + geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); + + if (!poll_done) + IPC_LOG_MSG(port->ipc_log_misc, "%s: RX_EOT, GENI:0x%x\n", + __func__, geni_status); + else + geni_write_reg_nolog(RX_EOT, uport->membase, SE_DMA_RX_IRQ_CLR); +} + #ifdef CONFIG_CONSOLE_POLL static int msm_geni_serial_get_char(struct uart_port *uport) { @@ -996,12 +1018,14 @@ static void start_rx_sequencer(struct uart_port *uport) unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); int ret; + u32 geni_se_param = UART_PARAM_RFR_OPEN; geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); if (geni_status & S_GENI_CMD_ACTIVE) msm_geni_serial_stop_rx(uport); - geni_setup_s_cmd(uport->membase, UART_START_READ, 0); + /* Start RX with the RFR_OPEN to keep RFR in always ready state */ + geni_setup_s_cmd(uport->membase, UART_START_READ, geni_se_param); if (port->xfer_mode == FIFO_MODE) { geni_s_irq_en = geni_read_reg_nolog(uport->membase, @@ -1075,7 +1099,7 @@ static void stop_rx_sequencer(struct uart_port *uport) unsigned int geni_m_irq_en; unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); - u32 irq_clear = S_CMD_DONE_EN; + u32 irq_clear = S_CMD_CANCEL_EN; bool done; IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__); @@ -1097,22 +1121,31 @@ static void stop_rx_sequencer(struct uart_port *uport) /* Possible stop rx is called multiple times. */ if (!(geni_status & S_GENI_CMD_ACTIVE)) goto exit_rx_seq; + geni_cancel_s_cmd(uport->membase); /* * Ensure that the cancel goes through before polling for the * cancel control bit. */ mb(); + msm_geni_serial_complete_rx_eot(uport); done = msm_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, S_GENI_CMD_CANCEL, false); - geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); - if (!done) + if (done) { + geni_write_reg_nolog(irq_clear, uport->membase, + SE_GENI_S_IRQ_CLEAR); + goto exit_rx_seq; + } else { IPC_LOG_MSG(port->ipc_log_misc, "%s Cancel fail 0x%x\n", - __func__, geni_status); + __func__, geni_status); + } - geni_write_reg_nolog(irq_clear, uport->membase, SE_GENI_S_IRQ_CLEAR); - if ((geni_status & S_GENI_CMD_ACTIVE)) + geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); + if ((geni_status & S_GENI_CMD_ACTIVE)) { + IPC_LOG_MSG(port->ipc_log_misc, "%s:Abort Rx, GENI:0x%x\n", + __func__, geni_status); msm_geni_serial_abort_rx(uport); + } exit_rx_seq: if (port->xfer_mode == SE_DMA && port->rx_dma) { msm_geni_serial_rx_fsm_rst(uport); @@ -1690,6 +1723,9 @@ static int msm_geni_serial_startup(struct uart_port *uport) ret = -ENXIO; goto exit_startup; } + IPC_LOG_MSG(msm_port->ipc_log_misc, "%s: FW Ver:0x%x%x\n", + __func__, + get_se_m_fw(uport->membase), get_se_s_fw(uport->membase)); get_tx_fifo_size(msm_port); if (!msm_port->port_setup) { @@ -2514,7 +2550,6 @@ static int msm_geni_serial_runtime_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct msm_geni_serial_port *port = platform_get_drvdata(pdev); int ret = 0; - u32 uart_manual_rfr = 0; u32 geni_status = geni_read_reg_nolog(port->uport.membase, SE_GENI_STATUS); @@ -2526,23 +2561,8 @@ static int msm_geni_serial_runtime_suspend(struct device *dev) * Resources off */ disable_irq(port->uport.irq); - /* - * If the clients haven't done a manual flow on/off then go ahead and - * set this to manual flow on. - */ - if (!port->manual_flow) { - uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_READY); - geni_write_reg_nolog(uart_manual_rfr, port->uport.membase, - SE_UART_MANUAL_RFR); - /* - * Ensure that the manual flow on writes go through before - * doing a stop_rx else we could end up flowing off the peer. - */ - mb(); - IPC_LOG_MSG(port->ipc_log_pwr, "%s: Manual Flow ON 0x%x\n", - __func__, uart_manual_rfr); - } stop_rx_sequencer(&port->uport); + geni_status = geni_read_reg_nolog(port->uport.membase, SE_GENI_STATUS); if ((geni_status & M_GENI_CMD_ACTIVE)) stop_tx_sequencer(&port->uport); ret = se_geni_resources_off(&port->serial_rsc); @@ -2587,9 +2607,6 @@ static int msm_geni_serial_runtime_resume(struct device *dev) goto exit_runtime_resume; } start_rx_sequencer(&port->uport); - if (!port->manual_flow) - geni_write_reg_nolog(0, port->uport.membase, - SE_UART_MANUAL_RFR); /* Ensure that the Rx is running before enabling interrupts */ mb(); if (pm_runtime_enabled(dev)) diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h index 8ff402f20cdd..b8dd63a2614c 100644 --- a/include/linux/qcom-geni-se.h +++ b/include/linux/qcom-geni-se.h @@ -154,6 +154,7 @@ struct se_geni_rsc { /* FW_REVISION_RO fields */ #define FW_REV_PROTOCOL_MSK (GENMASK(15, 8)) #define FW_REV_PROTOCOL_SHFT (8) +#define FW_REV_VERSION_MSK (GENMASK(7, 0)) /* GENI_CLK_SEL fields */ #define CLK_SEL_MSK (GENMASK(2, 0)) @@ -404,6 +405,22 @@ void geni_write_reg(unsigned int value, void __iomem *base, int offset); */ int get_se_proto(void __iomem *base); +/** + * get_se_m_fw() - Read the Firmware ver for the Main seqeuncer engine + * @base: Base address of the serial engine's register block. + * + * Return: Firmware version for the Main seqeuncer engine + */ +int get_se_m_fw(void __iomem *base); + +/** + * get_se_s_fw() - Read the Firmware ver for the Secondry seqeuncer engine + * @base: Base address of the serial engine's register block. + * + * Return: Firmware version for the Secondry seqeuncer engine + */ +int get_se_s_fw(void __iomem *base); + /** * geni_se_init() - Initialize the GENI Serial Engine * @base: Base address of the serial engine's register block. -- GitLab From 006dbe68b841c08fe0492dee4eef6edc8c54fab8 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Mon, 28 May 2018 11:46:12 +0530 Subject: [PATCH 0167/1299] ARM: dts: msm: Add GPI DMA device tree nodes for sdmmagpie Add GPI device tree nodes for GPI DMA driver. The driver provides DMA capabilities for peripheral buses such as I2C, UART, and SPI. Change-Id: I087ee3f8656fff1c62c0a6d902cfd73273abe98f Signed-off-by: Jishnu Prakash --- arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index cb536c68516c..ba6b1de20e20 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -523,6 +523,38 @@ qcom,rtb-size = <0x100000>; }; + gpi_dma0: qcom,gpi-dma@0x800000 { + #dma-cells = <5>; + compatible = "qcom,gpi-dma"; + reg = <0x800000 0x60000>; + reg-names = "gpi-top"; + interrupts = <0 244 0>, <0 245 0>, <0 246 0>, <0 247 0>, + <0 248 0>, <0 249 0>, <0 250 0>, <0 251 0>; + qcom,max-num-gpii = <8>; + qcom,gpii-mask = <0x0f>; + qcom,ev-factor = <2>; + iommus = <&apps_smmu 0x0216 0x0>; + qcom,smmu-cfg = <0x1>; + qcom,iova-range = <0x0 0x100000 0x0 0x100000>; + status = "ok"; + }; + + gpi_dma1: qcom,gpi-dma@0xa00000 { + #dma-cells = <5>; + compatible = "qcom,gpi-dma"; + reg = <0xa00000 0x60000>; + reg-names = "gpi-top"; + interrupts = <0 279 0>, <0 280 0>, <0 281 0>, <0 282 0>, + <0 283 0>, <0 284 0>, <0 293 0>, <0 294 0>; + qcom,max-num-gpii = <8>; + qcom,gpii-mask = <0x0f>; + qcom,ev-factor = <2>; + iommus = <&apps_smmu 0x04d6 0x0>; + qcom,smmu-cfg = <0x1>; + qcom,iova-range = <0x0 0x100000 0x0 0x100000>; + status = "ok"; + }; + wdog: qcom,wdt@17c10000{ compatible = "qcom,msm-watchdog"; reg = <0x17c10000 0x1000>; -- GitLab From 1d68724ec5ad5b83e27d6b924f485e746e42215f Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Mon, 11 Jun 2018 15:49:12 -0700 Subject: [PATCH 0168/1299] mhi: dev: net_dev: add missing alias documentation Updated device tree binding documentation to add missing alias documentation. CRs-Fixed: 2258358 Change-Id: I46094b42f46eb26ecf397d9390c39e334db7b868 Signed-off-by: Sujeev Dias --- Documentation/devicetree/bindings/bus/mhi.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt index a204510a2cf5..0d640144173b 100644 --- a/Documentation/devicetree/bindings/bus/mhi.txt +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -316,11 +316,21 @@ MHI netdev properties Value type: Definition: Set true if interface support recycling buffers. +- aliases + Usage: required + Value type: + Definition: mhi net_device should have numbered alias in the alias node, + in the form of mhi_netdevN, N = 0, 1..n for each network interface. + ======== Example: ======== -mhi_rmnet@0 { +aliases { + mhi_netdev0 = &mhi_netdev_0; +}; + +mhi_netdev_0: mhi_rmnet@0 { mhi,chan = "IP_HW0"; mhi,interface-name = "rmnet_mhi"; mhi,mru = <0x4000>; -- GitLab From 7b8372342921a68fa1065d70bc7abc72d2b25d30 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Mon, 11 Jun 2018 16:25:17 -0700 Subject: [PATCH 0169/1299] mhi: controller: reorganize static symbols reordering static symbols to avoid forward declarations CRs-Fixed: 2258358 Change-Id: Ia03fc0ff914fd34fed589c3380396c0ffbb68289 Signed-off-by: Sujeev Dias --- drivers/bus/mhi/controllers/mhi_qcom.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/bus/mhi/controllers/mhi_qcom.c b/drivers/bus/mhi/controllers/mhi_qcom.c index f97833224b72..03d244e4563a 100644 --- a/drivers/bus/mhi/controllers/mhi_qcom.c +++ b/drivers/bus/mhi/controllers/mhi_qcom.c @@ -24,19 +24,6 @@ #include #include "mhi_qcom.h" -static struct pci_device_id mhi_pcie_device_id[] = { - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0300)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0301)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0302)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0303)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0304)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0305)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, MHI_PCIE_DEBUG_ID)}, - {0}, -}; - -static struct pci_driver mhi_pcie_driver; - void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl) { struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); @@ -497,6 +484,17 @@ static const struct dev_pm_ops pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(mhi_system_suspend, mhi_system_resume) }; +static struct pci_device_id mhi_pcie_device_id[] = { + {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0300)}, + {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0301)}, + {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0302)}, + {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0303)}, + {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0304)}, + {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0305)}, + {PCI_DEVICE(MHI_PCIE_VENDOR_ID, MHI_PCIE_DEBUG_ID)}, + {0}, +}; + static struct pci_driver mhi_pcie_driver = { .name = "mhi", .id_table = mhi_pcie_device_id, -- GitLab From 06d631dcd85c305c8e2f1b0f0c16ffa353ede38b Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Mon, 4 Jun 2018 17:45:40 -0700 Subject: [PATCH 0170/1299] power: smb5-lib: set charger_temp_max in parallel psy The parallel charger temp threshold is defined in PM8150B. Read and update it to parallel charger. Change-Id: I2801e0de4faae160c73518571807fbdd6d7aa7d4 Signed-off-by: Harry Yang --- drivers/power/supply/qcom/smb-lib.c | 2 +- drivers/power/supply/qcom/smb1355-charger.c | 24 +++------- drivers/power/supply/qcom/smb5-lib.c | 49 ++++++++++++++++++--- drivers/power/supply/qcom/smb5-reg.h | 2 + 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index fc0ba98cf341..c61df73d9921 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -350,7 +350,7 @@ static int smblib_set_opt_freq_buck(struct smb_charger *chg, int fsw_khz) * PROP_BUCK_FREQ property - they could be running * with a fixed frequency */ - power_supply_set_property(chg->pl.psy, + rc = power_supply_set_property(chg->pl.psy, POWER_SUPPLY_PROP_BUCK_FREQ, &pval); } diff --git a/drivers/power/supply/qcom/smb1355-charger.c b/drivers/power/supply/qcom/smb1355-charger.c index 59f2466a48ba..0a2f99199134 100644 --- a/drivers/power/supply/qcom/smb1355-charger.c +++ b/drivers/power/supply/qcom/smb1355-charger.c @@ -170,6 +170,7 @@ struct smb1355 { struct pmic_revid_data *pmic_rev_id; int c_health; + int c_charger_temp_max; }; static bool is_secure(struct smb1355 *chip, int addr) @@ -427,23 +428,6 @@ static int smb1355_get_prop_charger_temp(struct smb1355 *chip, return rc; } -static int smb1355_get_prop_charger_temp_max(struct smb1355 *chip, - union power_supply_propval *val) -{ - int rc; - - if (!chip->iio.temp_max_chan || - PTR_ERR(chip->iio.temp_max_chan) == -EPROBE_DEFER) - chip->iio.temp_max_chan = devm_iio_channel_get(chip->dev, - "charger_temp_max"); - if (IS_ERR(chip->iio.temp_max_chan)) - return PTR_ERR(chip->iio.temp_max_chan); - - rc = iio_read_channel_processed(chip->iio.temp_max_chan, &val->intval); - val->intval /= 100; - return rc; -} - static int smb1355_parallel_get_prop(struct power_supply *psy, enum power_supply_property prop, union power_supply_propval *val) @@ -470,7 +454,7 @@ static int smb1355_parallel_get_prop(struct power_supply *psy, rc = smb1355_get_prop_charger_temp(chip, val); break; case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX: - rc = smb1355_get_prop_charger_temp_max(chip, val); + val->intval = chip->c_charger_temp_max; break; case POWER_SUPPLY_PROP_INPUT_SUSPEND: rc = smb1355_get_parallel_charging(chip, &val->intval); @@ -560,6 +544,9 @@ static int smb1355_parallel_set_prop(struct power_supply *psy, chip->c_health = val->intval; power_supply_changed(chip->parallel_psy); break; + case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX: + chip->c_charger_temp_max = val->intval; + break; default: pr_debug("parallel power supply set prop %d not supported\n", prop); @@ -903,6 +890,7 @@ static int smb1355_probe(struct platform_device *pdev) chip->dev = &pdev->dev; chip->param = v1_params; chip->c_health = -EINVAL; + chip->c_charger_temp_max = -EINVAL; chip->name = "smb1355"; mutex_init(&chip->write_lock); diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 0f50fe1bc936..ff4bf871064a 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -3800,8 +3800,26 @@ static void bms_update_work(struct work_struct *work) static void pl_update_work(struct work_struct *work) { + union power_supply_propval prop_val; struct smb_charger *chg = container_of(work, struct smb_charger, pl_update_work); + int rc; + + rc = smblib_get_thermal_threshold(chg, SMB_REG_H_THRESHOLD_MSB_REG, + &prop_val.intval); + if (rc < 0) { + dev_err(chg->dev, "Couldn't get charger_temp_max rc=%d\n", rc); + return; + } + + rc = power_supply_set_property(chg->pl.psy, + POWER_SUPPLY_PROP_CHARGER_TEMP_MAX, + &prop_val); + if (rc < 0) { + dev_err(chg->dev, "Couldn't set POWER_SUPPLY_PROP_CHARGER_TEMP_MAX rc=%d\n", + rc); + return; + } if (chg->sec_chg_selected == POWER_SUPPLY_CHARGER_SEC_CP) return; @@ -4047,6 +4065,7 @@ static void smblib_iio_deinit(struct smb_charger *chg) int smblib_init(struct smb_charger *chg) { + union power_supply_propval prop_val; int rc = 0; mutex_init(&chg->lock); @@ -4093,13 +4112,33 @@ int smblib_init(struct smb_charger *chg) if (chg->sec_pl_present) { chg->pl.psy = power_supply_get_by_name("parallel"); - if (chg->sec_chg_selected != POWER_SUPPLY_CHARGER_SEC_CP - && chg->pl.psy) { - rc = smblib_select_sec_charger(chg, + if (chg->pl.psy) { + if (chg->sec_chg_selected + != POWER_SUPPLY_CHARGER_SEC_CP) { + rc = smblib_select_sec_charger(chg, POWER_SUPPLY_CHARGER_SEC_PL); + if (rc < 0) { + smblib_err(chg, "Couldn't config pl charger rc=%d\n", + rc); + return rc; + } + } + + rc = smblib_get_thermal_threshold(chg, + SMB_REG_H_THRESHOLD_MSB_REG, + &prop_val.intval); if (rc < 0) { - smblib_err(chg, "Couldn't config pl charger rc=%d\n", - rc); + dev_err(chg->dev, "Couldn't get charger_temp_max rc=%d\n", + rc); + return rc; + } + + rc = power_supply_set_property(chg->pl.psy, + POWER_SUPPLY_PROP_CHARGER_TEMP_MAX, + &prop_val); + if (rc < 0) { + dev_err(chg->dev, "Couldn't set POWER_SUPPLY_PROP_CHARGER_TEMP_MAX rc=%d\n", + rc); return rc; } } diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h index 4afc7cca403f..f247d3341e9e 100644 --- a/drivers/power/supply/qcom/smb5-reg.h +++ b/drivers/power/supply/qcom/smb5-reg.h @@ -388,4 +388,6 @@ enum { #define DIE_REG_H_THRESHOLD_MSB_REG (MISC_BASE + 0xA0) +#define SMB_REG_H_THRESHOLD_MSB_REG (MISC_BASE + 0XBC) + #endif /* __SMB5_CHARGER_REG_H */ -- GitLab From 5175e0d3e44edcf1740f486741624852ff234342 Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Thu, 17 May 2018 20:38:00 +0530 Subject: [PATCH 0171/1299] serial: msm_geni_serial: Fix the race between termios and ISR This patch makes sure to process the RX EOT bit post cancel command as part of stop rx sequencer. There could be a race between ISR and userspace thread doing stop rx where ISR clears out the interrupts generated as part of other operations and EOT poll may timeout. Also there are chances that stop_rx can generate an interrupt if the peer device sends data when client hasn't disabled the flow control. This will trigger a call to handle_dma_rx which basically un-maps the rx dma buffer, handles the rx data and remaps the same rx dma buffer. As part of baud change, make sure ISR gets called exclusively against the start_rx call. There is a slight window where dma_map of start_rx sets the iova as DMA_ERROR_CODE for a while before actually mapping to valid dma address and ISR uses this invalid address as part of un-mapping the same buffer address which results into the page fault. Change-Id: I9c69f7f9399aac060188ccee5648b8b7c46a656b Signed-off-by: Mukesh Kumar Savaliya --- drivers/tty/serial/msm_geni_serial.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 36e7841e7d9f..2ec317c1f02f 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -614,7 +614,6 @@ static void msm_geni_serial_abort_rx(struct uart_port *uport) static void msm_geni_serial_complete_rx_eot(struct uart_port *uport) { int poll_done = 0, tries = 0; - u32 geni_status = 0; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); do { @@ -623,11 +622,11 @@ static void msm_geni_serial_complete_rx_eot(struct uart_port *uport) tries++; } while (!poll_done && tries < 5); - geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); - if (!poll_done) - IPC_LOG_MSG(port->ipc_log_misc, "%s: RX_EOT, GENI:0x%x\n", - __func__, geni_status); + IPC_LOG_MSG(port->ipc_log_misc, + "%s: RX_EOT, GENI:0x%x, DMA_DEBUG:0x%x\n", __func__, + geni_read_reg_nolog(uport->membase, SE_GENI_STATUS), + geni_read_reg_nolog(uport->membase, SE_DMA_DEBUG_REG0)); else geni_write_reg_nolog(RX_EOT, uport->membase, SE_DMA_RX_IRQ_CLR); } @@ -1128,7 +1127,9 @@ static void stop_rx_sequencer(struct uart_port *uport) * cancel control bit. */ mb(); - msm_geni_serial_complete_rx_eot(uport); + if (!uart_console(uport)) + msm_geni_serial_complete_rx_eot(uport); + done = msm_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, S_GENI_CMD_CANCEL, false); if (done) { @@ -1853,6 +1854,7 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, unsigned long ser_clk_cfg = 0; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); unsigned long clk_rate; + unsigned long flags; if (!uart_console(uport)) { int ret = msm_geni_serial_power_on(uport); @@ -1864,7 +1866,13 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, return; } } + /* Take a spinlock else stop_rx causes a race with an ISR due to Cancel + * and FSM_RESET. This also has a potential race with the dma_map/unmap + * operations of ISR. + */ + spin_lock_irqsave(&uport->lock, flags); msm_geni_serial_stop_rx(uport); + spin_unlock_irqrestore(&uport->lock, flags); /* baud rate */ baud = uart_get_baud_rate(uport, termios, old, 300, 4000000); port->cur_baud = baud; -- GitLab From b210859e4144eb8231bf7d18b3b70cb2cb7755c5 Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Sun, 10 Jun 2018 20:14:32 -0700 Subject: [PATCH 0172/1299] ARM: dts: msm: specify VADC die temperature channel for smb1355 In SM8150 platforms with SMB1355 configuration, VADC channel ADC_AMUX_THM2 is used for SMB1355 die temperature. Expose it in the name of charger_temp. Change-Id: I32522fcfeed096e09e0cf6ce8cb041d7a8f49737 Signed-off-by: Harry Yang --- arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi | 2 ++ arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi index 50807d9c4ec5..ade27786b84c 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi @@ -590,5 +590,7 @@ }; &smb1355_charger { + io-channels = <&pm8150b_vadc ADC_AMUX_THM2>; + io-channel-names = "charger_temp"; status = "ok"; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi index b617cdc3e70c..caa51c71c686 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi @@ -518,5 +518,7 @@ }; &smb1355_charger { + io-channels = <&pm8150b_vadc ADC_AMUX_THM2>; + io-channel-names = "charger_temp"; status = "ok"; }; -- GitLab From 2bd15e1cd732c64d175ef87714d3212a222013c5 Mon Sep 17 00:00:00 2001 From: Sameer Thalappil Date: Fri, 14 Jun 2013 17:12:12 -0700 Subject: [PATCH 0173/1299] cfg80211: Reset beacon interval when stop AP fails When SSR happens at WLAN driver, the cfg80211 stop AP can fail at driver. Make sure that the beacon interval is reset, even when this API fails. CRs-fixed: 1078172 Change-Id: I459f55ce5f4bc44c4d0e20170bd50a83c2d609b4 Signed-off-by: Sameer Thalappil --- net/wireless/ap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/ap.c b/net/wireless/ap.c index 63682176c96c..882eb864cb44 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c @@ -26,8 +26,8 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, return -ENOENT; err = rdev_stop_ap(rdev, dev); + wdev->beacon_interval = 0; if (!err) { - wdev->beacon_interval = 0; memset(&wdev->chandef, 0, sizeof(wdev->chandef)); wdev->ssid_len = 0; rdev_set_qos_map(rdev, dev, NULL); -- GitLab From 66198289ac92e6b62e38f85123217c62a3e330d0 Mon Sep 17 00:00:00 2001 From: Bryan Huntsman Date: Fri, 25 May 2018 13:05:57 -0700 Subject: [PATCH 0174/1299] scripts/build-all: remove all defconfig manipulation options Simplifiy the script by removing all options and code for manipulating defconfigs. Change-Id: Ic8c583d501165501035c2c43b69e5b5c57b97fb0 Signed-off-by: Bryan Huntsman --- scripts/build-all.py | 73 +++++++++++--------------------------------- 1 file changed, 17 insertions(+), 56 deletions(-) diff --git a/scripts/build-all.py b/scripts/build-all.py index 2f4ad4472762..20adbc5bcf40 100755 --- a/scripts/build-all.py +++ b/scripts/build-all.py @@ -270,36 +270,24 @@ class Builder(): steps.append(ExecStep(['make', 'O=%s' % dest_dir, self.confname], env=self.make_env)) - if not all_options.updateconfigs: - # Build targets can be dependent upon the completion of - # previous build targets, so build them one at a time. - cmd_line = ['make', - 'INSTALL_HDR_PATH=%s' % hdri_dir, - 'INSTALL_MOD_PATH=%s' % modi_dir, - 'O=%s' % dest_dir, - 'REAL_CC=%s' % clang_bin] - build_targets = [] - for c in make_command: - if re.match(r'^-{1,2}\w', c): - cmd_line.append(c) - else: - build_targets.append(c) - for t in build_targets: - steps.append(ExecStep(cmd_line + [t], env=self.make_env)) - - # Copy the defconfig back. - if all_options.configs or all_options.updateconfigs: - steps.append(ExecStep(['make', 'O=%s' % dest_dir, - 'savedefconfig'], env=self.make_env)) - steps.append(CopyfileStep(savedefconfig, defconfig)) + # Build targets can be dependent upon the completion of + # previous build targets, so build them one at a time. + cmd_line = ['make', + 'INSTALL_HDR_PATH=%s' % hdri_dir, + 'INSTALL_MOD_PATH=%s' % modi_dir, + 'O=%s' % dest_dir, + 'REAL_CC=%s' % clang_bin] + build_targets = [] + for c in make_command: + if re.match(r'^-{1,2}\w', c): + cmd_line.append(c) + else: + build_targets.append(c) + for t in build_targets: + steps.append(ExecStep(cmd_line + [t], env=self.make_env)) return steps -def update_config(file, str): - print 'Updating %s with \'%s\'\n' % (file, str) - with open(file, 'a') as defconfig: - defconfig.write(str + '\n') - def scan_configs(): """Get the full list of defconfigs appropriate for this tree.""" names = [] @@ -341,8 +329,6 @@ def build_many(targets): tracker = BuildTracker(parallel) for target in targets: - if all_options.updateconfigs: - update_config(target.defconfig, all_options.updateconfigs) steps = target.build() tracker.add_sequence(target.log_name, target.name, steps) tracker.run() @@ -358,25 +344,14 @@ def main(): usage = (""" %prog [options] all -- Build all targets %prog [options] target target ... -- List specific targets - %prog [options] perf -- Build all perf targets - %prog [options] noperf -- Build all non-perf targets""") + """) parser = OptionParser(usage=usage, version=version) - parser.add_option('--configs', action='store_true', - dest='configs', - help="Copy configs back into tree") parser.add_option('--list', action='store_true', dest='list', help='List available targets') parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='Output to stdout in addition to log file') - parser.add_option('--oldconfig', action='store_true', - dest='oldconfig', - help='Only process "make oldconfig"') - parser.add_option('--updateconfigs', - dest='updateconfigs', - help="Update defconfigs with provided option setting, " - "e.g. --updateconfigs=\'CONFIG_USE_THING=y\'") parser.add_option('-j', '--jobs', type='int', dest="jobs", help="Number of simultaneous jobs") parser.add_option('-l', '--load-average', type='int', @@ -399,25 +374,11 @@ def main(): print " %s" % target.name sys.exit(0) - if options.oldconfig: - make_command = ["oldconfig"] - elif options.make_target: + if options.make_target: make_command = options.make_target if args == ['all']: build_many(configs) - elif args == ['perf']: - targets = [] - for t in configs: - if "perf" in t.name: - targets.append(t) - build_many(targets) - elif args == ['noperf']: - targets = [] - for t in configs: - if "perf" not in t.name: - targets.append(t) - build_many(targets) elif len(args) > 0: all_configs = {} for t in configs: -- GitLab From 39b7c1d4a00acdc79ea18ddb7bceec02cc966d21 Mon Sep 17 00:00:00 2001 From: Bryan Huntsman Date: Mon, 4 Jun 2018 15:11:10 -0700 Subject: [PATCH 0175/1299] scripts/build-all: relax check_kernel() Enforce just that PWD is the top working directory by dropping the hard-coded defconfig lookup. Change-Id: I14404de5e28605c14329768747bb18a49487694f Signed-off-by: Bryan Huntsman --- scripts/build-all.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/scripts/build-all.py b/scripts/build-all.py index 20adbc5bcf40..bb643c1ba6e1 100755 --- a/scripts/build-all.py +++ b/scripts/build-all.py @@ -60,12 +60,8 @@ if not os.environ.get('CROSS_COMPILE'): def check_kernel(): """Ensure that PWD is a kernel directory""" - have_defconfig = any([ - os.path.isfile('arch/arm64/configs/msm_defconfig'), - os.path.isfile('arch/arm64/configs/sm8150_defconfig')]) - - if not all([os.path.isfile('MAINTAINERS'), have_defconfig]): - fail("This doesn't seem to be an MSM kernel dir") + if not os.path.isfile('MAINTAINERS'): + fail("This doesn't seem to be a kernel dir") def check_build(): """Ensure that the build directory is present.""" -- GitLab From 0224904a3cbdad3ba67c31247726e23464d8e7ed Mon Sep 17 00:00:00 2001 From: Bryan Huntsman Date: Mon, 4 Jun 2018 14:18:41 -0700 Subject: [PATCH 0176/1299] scripts/build-all: look for nested vendor/ defconfig directories Look for additional defconfigs in 'arch/arm[64]/configs/vendor/'. Change-Id: I13a1675d8563611eee17a02445e0329ff5f7a215 Signed-off-by: Bryan Huntsman --- scripts/build-all.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/build-all.py b/scripts/build-all.py index bb643c1ba6e1..7f2a2764dc73 100755 --- a/scripts/build-all.py +++ b/scripts/build-all.py @@ -230,7 +230,7 @@ class Builder(): self.name = name self.defconfig = defconfig - self.confname = self.defconfig.split('/')[-1] + self.confname = re.sub('arch/arm[64]*/configs/', '', self.defconfig) # Determine if this is a 64-bit target based on the location # of the defconfig. @@ -310,6 +310,13 @@ def scan_configs(): for n in glob.glob('arch/arm64/configs/' + p): name = os.path.basename(n)[:-10] + "-llvm" + "-64" names.append(Builder(name, n)) + for defconfig in glob.glob('arch/arm*/configs/vendor/*_defconfig'): + target = os.path.basename(defconfig)[:-10] + name = target + "-llvm" + if 'arch/arm64' in defconfig: + name = name + "-64" + names.append(Builder(name, defconfig)) + return names def build_many(targets): -- GitLab From fcd52a098da3b401c95ba2e3de7e0ca1d8c2c8a6 Mon Sep 17 00:00:00 2001 From: Ashay Jaiswal Date: Sun, 27 May 2018 23:59:01 +0530 Subject: [PATCH 0177/1299] power: smb5: add support for ICL override In TypeC mode charger hardware follows a predefined ICL configuration and does not honor input limit configured in ICL configuration register, this limits the ability to control ICL of charger specifically in case of USBIN-USBIN based parallel charging where ICL is split between main and parallel charger or in situation where ICL de-rating is required. Change-Id: I446cf1460169a980c75c1413314fa53d93f7f57d Signed-off-by: Ashay Jaiswal --- drivers/power/supply/qcom/qpnp-smb5.c | 7 +++++++ drivers/power/supply/qcom/smb5-lib.c | 28 ++++++++++++++++++++++++++- drivers/power/supply/qcom/smb5-lib.h | 1 + 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index e1cdf902097f..7b612268a650 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -1624,6 +1624,13 @@ static int smb5_init_hw(struct smb5 *chip) smblib_rerun_apsd_if_required(chg); } + /* clear the ICL override if it is set */ + rc = smblib_icl_override(chg, false); + if (rc < 0) { + pr_err("Couldn't disable ICL override rc=%d\n", rc); + return rc; + } + /* vote 0mA on usb_icl for non battery platforms */ vote(chg->usb_icl_votable, DEFAULT_VOTER, chip->dt.no_battery, 0); diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 37b2ba782ae0..f38db29ccd17 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -117,6 +117,19 @@ int smblib_get_jeita_cc_delta(struct smb_charger *chg, int *cc_delta_ua) return 0; } +int smblib_icl_override(struct smb_charger *chg, bool override) +{ + int rc; + + rc = smblib_masked_write(chg, USBIN_LOAD_CFG_REG, + ICL_OVERRIDE_AFTER_APSD_BIT, + override ? ICL_OVERRIDE_AFTER_APSD_BIT : 0); + if (rc < 0) + smblib_err(chg, "Couldn't override ICL rc=%d\n", rc); + + return rc; +} + static int smblib_select_sec_charger(struct smb_charger *chg, int sec_chg) { int rc; @@ -923,7 +936,7 @@ static int get_sdp_current(struct smb_charger *chg, int *icl_ua) int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) { int rc = 0; - bool hc_mode = false; + bool hc_mode = false, override = false; /* suspend and return if 25mA or less is requested */ if (icl_ua <= USBIN_25MA) @@ -950,6 +963,13 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) goto out; } hc_mode = true; + + /* + * Micro USB mode follows ICL register independent of override + * bit, configure override only for typeC mode. + */ + if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC) + override = true; } set_mode: @@ -960,6 +980,12 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) goto out; } + rc = smblib_icl_override(chg, override); + if (rc < 0) { + smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc); + goto out; + } + /* unsuspend after configuring current and override */ rc = smblib_set_usb_suspend(chg, false); if (rc < 0) { diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 9050c7ca34e5..6b96bad17070 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -547,6 +547,7 @@ int smblib_get_prop_pr_swap_in_progress(struct smb_charger *chg, int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg, const union power_supply_propval *val); int smblib_configure_hvdcp_apsd(struct smb_charger *chg, bool enable); +int smblib_icl_override(struct smb_charger *chg, bool override); int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); -- GitLab From 951f1eabd361c475d35fc6743dd513f2642406de Mon Sep 17 00:00:00 2001 From: Govinda Rajulu Chenna Date: Mon, 11 Jun 2018 11:50:43 -0400 Subject: [PATCH 0178/1299] drm/msm/dp: validate audio ops in cable disconnect path There is possiblity for accessing invalid audio ops when hpd unplug is processed in between dp_display_enable and dp_display_post_enable functions. This change adds the validation for audio ops before accessing them and clears audio_supported variable after processing dp_audio_off functionality to initialize the variable to correct state. CRs-Fixed: 2243808 Change-Id: I103329ec5a922e5a16ce45388b3c09165b97b757 Signed-off-by: Govinda Rajulu Chenna --- drivers/gpu/drm/msm/dp/dp_audio.c | 29 ++++++++++++++++++----------- drivers/gpu/drm/msm/dp/dp_display.c | 9 ++++++++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 48ff29351c17..0e34e2afbde7 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -669,6 +669,9 @@ static int dp_audio_notify(struct dp_audio_private *audio, u32 state) int rc = 0; struct msm_ext_disp_init_data *ext = &audio->ext_audio_data; + if (!ext->intf_ops.audio_notify) + goto end; + rc = ext->intf_ops.audio_notify(audio->ext_pdev, &ext->codec, state); if (rc) { @@ -710,12 +713,14 @@ static int dp_audio_on(struct dp_audio *dp_audio) audio->session_on = true; - rc = ext->intf_ops.audio_config(audio->ext_pdev, - &ext->codec, - EXT_DISPLAY_CABLE_CONNECT); - if (rc) { - pr_err("failed to config audio, err=%d\n", rc); - goto end; + if (ext->intf_ops.audio_config) { + rc = ext->intf_ops.audio_config(audio->ext_pdev, + &ext->codec, + EXT_DISPLAY_CABLE_CONNECT); + if (rc) { + pr_err("failed to config audio, err=%d\n", rc); + goto end; + } } rc = dp_audio_notify(audio, EXT_DISPLAY_CABLE_CONNECT); @@ -752,11 +757,13 @@ static int dp_audio_off(struct dp_audio *dp_audio) pr_debug("success\n"); end: - rc = ext->intf_ops.audio_config(audio->ext_pdev, - &ext->codec, - EXT_DISPLAY_CABLE_DISCONNECT); - if (rc) - pr_err("failed to config audio, err=%d\n", rc); + if (ext->intf_ops.audio_config) { + rc = ext->intf_ops.audio_config(audio->ext_pdev, + &ext->codec, + EXT_DISPLAY_CABLE_DISCONNECT); + if (rc) + pr_err("failed to config audio, err=%d\n", rc); + } audio->session_on = false; audio->engine_on = false; diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 89cd4cc6091a..0c7bbda8f675 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -632,8 +632,11 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp) int rc = 0, idx; struct dp_panel *dp_panel; + mutex_lock(&dp->session_lock); + if (!dp->dp_display.is_connected) { pr_debug("HPD already off\n"); + mutex_unlock(&dp->session_lock); return 0; } @@ -646,10 +649,14 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp) dp_panel = dp->active_panels[idx]; - if (dp_panel->audio_supported) + if (dp_panel->audio_supported) { dp_panel->audio->off(dp_panel->audio); + dp_panel->audio_supported = false; + } } + mutex_unlock(&dp->session_lock); + dp_display_process_mst_hpd_low(dp); rc = dp_display_send_hpd_notification(dp, false); -- GitLab From 15ea3ee1b6904a7ad0f313fe9f5a379fd9cdd21a Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Mon, 11 Jun 2018 15:52:45 -0700 Subject: [PATCH 0179/1299] msm: ipa3: fix the NOC error due to GPIO On modem SSR scenario, instead of calling GPIO API, ipa-driver should update IPA_SMP2P_SMEM_STATE_MASK directly. Change-Id: Ib9143aa69b0eb555d7389e35fd854fc68ec000a0 CRs-Fixed: 2204207 Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index d5633a179a1b..4184cb7e66c3 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -60,9 +59,6 @@ #define CREATE_TRACE_POINTS #include "ipa_trace.h" -#define IPA_GPIO_IN_QUERY_CLK_IDX 0 -#define IPA_GPIO_OUT_CLK_RSP_CMPLT_IDX 0 -#define IPA_GPIO_OUT_CLK_VOTE_IDX 1 #define IPA_SMP2P_SMEM_STATE_MASK 3 @@ -4390,7 +4386,7 @@ static void ipa3_freeze_clock_vote_and_notify_modem(void) qcom_smem_state_update_bits(ipa3_ctx->smp2p_info.smem_state, BIT(IPA_SMP2P_SMEM_STATE_MASK), - BIT(ipa3_ctx->smp2p_info.ipa_clk_on | (1<<1))); + BIT(ipa3_ctx->smp2p_info.ipa_clk_on | (1 << 1))); ipa3_ctx->smp2p_info.res_sent = true; IPADBG("IPA clocks are %s\n", @@ -4405,10 +4401,9 @@ void ipa3_reset_freeze_vote(void) if (ipa3_ctx->smp2p_info.ipa_clk_on) IPA_ACTIVE_CLIENTS_DEC_SPECIAL("FREEZE_VOTE"); - gpio_set_value(ipa3_ctx->smp2p_info.out_base_id + - IPA_GPIO_OUT_CLK_VOTE_IDX, 0); - gpio_set_value(ipa3_ctx->smp2p_info.out_base_id + - IPA_GPIO_OUT_CLK_RSP_CMPLT_IDX, 0); + qcom_smem_state_update_bits(ipa3_ctx->smp2p_info.smem_state, + BIT(IPA_SMP2P_SMEM_STATE_MASK), + BIT(ipa3_ctx->smp2p_info.ipa_clk_on | (1 << 1))); ipa3_ctx->smp2p_info.res_sent = false; ipa3_ctx->smp2p_info.ipa_clk_on = false; -- GitLab From 04dc71ab4654d65c9359e8a34b83d2125b58f52c Mon Sep 17 00:00:00 2001 From: Alex Yakavenka Date: Tue, 22 May 2018 11:34:58 -0700 Subject: [PATCH 0180/1299] ARM: dts: msm: Add calypso can controller for sm8150-auto Add calypso can controller device tree entries Change-Id: Ia71e6accc66ce96b3a2485a8565f1a387d7e9f1a Signed-off-by: Alex Yakavenka --- .../arm64/boot/dts/qcom/sm8150-auto-adp-star.dtsi | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-auto-adp-star.dtsi b/arch/arm64/boot/dts/qcom/sm8150-auto-adp-star.dtsi index 155b29fd483f..6a419fd61463 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-auto-adp-star.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-auto-adp-star.dtsi @@ -15,6 +15,21 @@ #include "sm8150-auto-pmic-overlay.dtsi" +&qupv3_se0_spi { + status = "ok"; + can-controller@0 { + compatible = "qcom,nxp,mpc5746c"; + reg = <0>; + interrupt-parent = <&tlmm>; + interrupts = <38 0>; + spi-max-frequency = <5000000>; + qcom,clk-freq-mhz = <16000000>; + qcom,max-can-channels = <4>; + qcom,bits-per-word = <8>; + qcom,support-can-fd; + }; +}; + &qupv3_se12_2uart { status = "ok"; }; -- GitLab From 2f7861a382ca8b3301e25836c1c2da378ee3b862 Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Tue, 12 Jun 2018 01:26:36 -0700 Subject: [PATCH 0181/1299] power: smb5: configure input from wireless Wireless power feeds to the DCIN input of the smb5 charger and relies on input current configurations for power draw. Provide means to configure the current limits via DC psy. Also set the initial DC ICL to 1A. Change-Id: Ic4ca30ecac2f4c0dd9080b221b4eaa2e04c4c404 Signed-off-by: Harry Yang --- drivers/power/supply/qcom/qpnp-smb5.c | 31 +++++++++++++++++++++++++++ drivers/power/supply/qcom/smb5-lib.h | 1 + drivers/power/supply/qcom/smb5-reg.h | 2 ++ 3 files changed, 34 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index e1cdf902097f..52e38333cc15 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -73,6 +73,13 @@ static struct smb_params smb5_pmi632_params = { .max_u = 1000000, .step_u = 250000, }, + .dc_icl = { + .name = "DC input current limit", + .reg = DCDC_CFG_REF_MAX_PSNS_REG, + .min_u = 0, + .max_u = 1500000, + .step_u = 50000, + }, .jeita_cc_comp_hot = { .name = "jeita fcc reduction", .reg = JEITA_CCCOMP_CFG_HOT_REG, @@ -140,6 +147,13 @@ static struct smb_params smb5_pm8150b_params = { .max_u = 3000000, .step_u = 500000, }, + .dc_icl = { + .name = "DC input current limit", + .reg = DCDC_CFG_REF_MAX_PSNS_REG, + .min_u = 0, + .max_u = 1500000, + .step_u = 50000, + }, .jeita_cc_comp_hot = { .name = "jeita fcc reduction", .reg = JEITA_CCCOMP_CFG_HOT_REG, @@ -942,6 +956,7 @@ static enum power_supply_property smb5_dc_props[] = { POWER_SUPPLY_PROP_INPUT_SUSPEND, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_REAL_TYPE, }; @@ -963,6 +978,10 @@ static int smb5_dc_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_ONLINE: rc = smblib_get_prop_dc_online(chg, val); break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + rc = smblib_get_charge_param(chg, &chg->param.dc_icl, + &val->intval); + break; case POWER_SUPPLY_PROP_REAL_TYPE: val->intval = POWER_SUPPLY_TYPE_WIPOWER; break; @@ -989,6 +1008,10 @@ static int smb5_dc_set_prop(struct power_supply *psy, rc = vote(chg->dc_suspend_votable, WBC_VOTER, (bool)val->intval, 0); break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + rc = smblib_set_charge_param(chg, &chg->param.dc_icl, + val->intval); + break; default: return -EINVAL; } @@ -1644,6 +1667,14 @@ static int smb5_init_hw(struct smb5 *chip) vote(chg->usb_icl_votable, HW_LIMIT_VOTER, chg->hw_max_icl_ua > 0, chg->hw_max_icl_ua); + /* set DC icl_max 1A */ + rc = smblib_set_charge_param(chg, &chg->param.dc_icl, 1000000); + if (rc < 0) { + dev_err(chg->dev, + "Couldn't set dc_icl rc=%d\n", rc); + return rc; + } + /* * AICL configuration: * start from min and AICL ADC disable, and enable aicl rerun diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 9050c7ca34e5..bce7f6e58309 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -235,6 +235,7 @@ struct smb_params { struct smb_chg_param icl_max_stat; struct smb_chg_param icl_stat; struct smb_chg_param otg_cl; + struct smb_chg_param dc_icl; struct smb_chg_param jeita_cc_comp_hot; struct smb_chg_param jeita_cc_comp_cold; struct smb_chg_param freq_switcher; diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h index 20a864e513e6..f607a91694bc 100644 --- a/drivers/power/supply/qcom/smb5-reg.h +++ b/drivers/power/supply/qcom/smb5-reg.h @@ -138,6 +138,8 @@ enum { #define DCDC_OTG_CFG_REG (DCDC_BASE + 0x53) #define OTG_EN_SRC_CFG_BIT BIT(1) +#define DCDC_CFG_REF_MAX_PSNS_REG (DCDC_BASE + 0x8C) + /******************************** * BATIF Peripheral Registers * ********************************/ -- GitLab From ff848c40b822498c0712db965aac1053ebdc9f7a Mon Sep 17 00:00:00 2001 From: Carter Cooper Date: Tue, 12 Jun 2018 11:04:33 -0600 Subject: [PATCH 0182/1299] msm: kgsl: Add A640v2 to the GPU list Add the handler for A640v2 settings. Add the adreno_is_a640v2() helper. Change-Id: I4f4823259cb4ea106f027ef6ed1b79ff902643bf Signed-off-by: Carter Cooper --- drivers/gpu/msm/adreno-gpulist.h | 21 +++++++++++++++++++++ drivers/gpu/msm/adreno.h | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index f461bc1649d3..d53e4501acb5 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -379,6 +379,27 @@ static const struct adreno_gpu_core adreno_gpulist[] = { .gpmu_major = 0x1, .gpmu_minor = 0x003, }, + { + .gpurev = ADRENO_REV_A640, + .core = 6, + .major = 4, + .minor = 0, + .patchid = 0, + .features = ADRENO_64BIT | ADRENO_RPMH | ADRENO_GPMU | + ADRENO_IFPC | ADRENO_CONTENT_PROTECTION, + .sqefw_name = "a630_sqe.fw", + .zap_name = "a640_zap", + .gpudev = &adreno_a6xx_gpudev, + .gmem_size = SZ_1M, //Verified 1MB + .num_protected_regs = 0x20, + .busy_mask = 0xFFFFFFFE, + .gpmufw_name = "a640_gmu.bin", + .gpmu_major = 0x2, + .gpmu_minor = 0x000, + .gpmu_tsens = 0x000C000D, + .max_power = 5448, + .va_padding = SZ_64K, + }, { .gpurev = ADRENO_REV_A640, .core = 6, diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 99ba7b01493b..82500e9b027e 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -1272,6 +1272,12 @@ static inline int adreno_is_a640v1(struct adreno_device *adreno_dev) (ADRENO_CHIPID_PATCH(adreno_dev->chipid) == 0); } +static inline int adreno_is_a640v2(struct adreno_device *adreno_dev) +{ + return (ADRENO_GPUREV(adreno_dev) == ADRENO_REV_A640) && + (ADRENO_CHIPID_PATCH(adreno_dev->chipid) == 1); +} + /* * adreno_checkreg_off() - Checks the validity of a register enum * @adreno_dev: Pointer to adreno device -- GitLab From c4f039270543c498c389ec5b5d83061837f4c3d3 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 30 Apr 2018 14:50:22 +0200 Subject: [PATCH 0183/1299] kthread, sched/wait: Fix kthread_parkme() wait-loop Gaurav reported a problem with __kthread_parkme() where a concurrent try_to_wake_up() could result in competing stores to ->state which, when the TASK_PARKED store got lost bad things would happen. The comment near set_current_state() actually mentions this competing store, but only mentions the case against TASK_RUNNING. This same store, with different timing, can happen against a subsequent !RUNNING store. This normally is not a problem, because as per that same comment, the !RUNNING state store is inside a condition based wait-loop: for (;;) { set_current_state(TASK_UNINTERRUPTIBLE); if (!need_sleep) break; schedule(); } __set_current_state(TASK_RUNNING); If we loose the (first) TASK_UNINTERRUPTIBLE store to a previous (concurrent) wakeup, the schedule() will NO-OP and we'll go around the loop once more. The problem here is that the TASK_PARKED store is not inside the KTHREAD_SHOULD_PARK condition wait-loop. There is a genuine issue with sleeps that do not have a condition; this is addressed in a subsequent patch. Change-Id: I508e74ea0fbd7e83b1712c0e2f4d069a09ab12ab Reported-by: Gaurav Kohli Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Oleg Nesterov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Ingo Molnar Git-commit: 741a76b350897604c48fb12beff1c9b77724dc96 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Gaurav Kohli Signed-off-by: Isaac J. Manjarres --- kernel/kthread.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/kthread.c b/kernel/kthread.c index 1c19edf82427..1ef8f3a5b072 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -169,12 +169,13 @@ void *kthread_probe_data(struct task_struct *task) static void __kthread_parkme(struct kthread *self) { - __set_current_state(TASK_PARKED); - while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) { + for (;;) { + set_current_state(TASK_PARKED); + if (!test_bit(KTHREAD_SHOULD_PARK, &self->flags)) + break; if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags)) complete(&self->parked); schedule(); - __set_current_state(TASK_PARKED); } clear_bit(KTHREAD_IS_PARKED, &self->flags); __set_current_state(TASK_RUNNING); -- GitLab From b0af9a45e91a4a723650a44c7bb6d8d2c01d761a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 1 May 2018 18:14:45 +0200 Subject: [PATCH 0184/1299] kthread, sched/wait: Fix kthread_parkme() completion issue Even with the wait-loop fixed, there is a further issue with kthread_parkme(). Upon hotplug, when we do takedown_cpu(), smpboot_park_threads() can return before all those threads are in fact blocked, due to the placement of the complete() in __kthread_parkme(). When that happens, sched_cpu_dying() -> migrate_tasks() can end up migrating such a still runnable task onto another CPU. Normally the task will have hit schedule() and gone to sleep by the time we do kthread_unpark(), which will then do __kthread_bind() to re-bind the task to the correct CPU. However, when we loose the initial TASK_PARKED store to the concurrent wakeup issue described previously, do the complete(), get migrated, it is possible to either: - observe kthread_unpark()'s clearing of SHOULD_PARK and terminate the park and set TASK_RUNNING, or - __kthread_bind()'s wait_task_inactive() to observe the competing TASK_RUNNING store. Either way the WARN() in __kthread_bind() will trigger and fail to correctly set the CPU affinity. Fix this by only issuing the complete() when the kthread has scheduled out. This does away with all the icky 'still running' nonsense. The alternative is to promote TASK_PARKED to a special state, this guarantees wait_task_inactive() cannot observe a 'stale' TASK_RUNNING and we'll end up doing the right thing, but this preserves the whole icky business of potentially migating the still runnable thing. Change-Id: I9706fe03ceb8df1f93a718cbb3e0ce890de12afe Reported-by: Gaurav Kohli Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Ingo Molnar Git-commit: 85f1abe0019fcb3ea10df7029056cf42702283a8 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [gkohli@codeaurora: Resolve trivial merge conflicts] Signed-off-by: Gaurav Kohli Signed-off-by: Isaac J. Manjarres --- include/linux/kthread.h | 1 + kernel/kthread.c | 43 ++++++++++++++++++----------------------- kernel/sched/core.c | 32 +++++++++++++++++++----------- 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 4e26609c77d4..3501157ede26 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -61,6 +61,7 @@ void *kthread_probe_data(struct task_struct *k); int kthread_park(struct task_struct *k); void kthread_unpark(struct task_struct *k); void kthread_parkme(void); +void kthread_park_complete(struct task_struct *k); int kthreadd(void *unused); extern struct task_struct *kthreadd_task; diff --git a/kernel/kthread.c b/kernel/kthread.c index 1ef8f3a5b072..946f8ffa7f33 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -53,7 +53,6 @@ enum KTHREAD_BITS { KTHREAD_IS_PER_CPU = 0, KTHREAD_SHOULD_STOP, KTHREAD_SHOULD_PARK, - KTHREAD_IS_PARKED, }; static inline void set_kthread_struct(void *kthread) @@ -173,11 +172,8 @@ static void __kthread_parkme(struct kthread *self) set_current_state(TASK_PARKED); if (!test_bit(KTHREAD_SHOULD_PARK, &self->flags)) break; - if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags)) - complete(&self->parked); schedule(); } - clear_bit(KTHREAD_IS_PARKED, &self->flags); __set_current_state(TASK_RUNNING); } @@ -187,6 +183,11 @@ void kthread_parkme(void) } EXPORT_SYMBOL_GPL(kthread_parkme); +void kthread_park_complete(struct task_struct *k) +{ + complete(&to_kthread(k)->parked); +} + static int kthread(void *_create) { /* Copy data: it's on kthread's stack */ @@ -444,22 +445,15 @@ void kthread_unpark(struct task_struct *k) { struct kthread *kthread = to_kthread(k); - clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); /* - * We clear the IS_PARKED bit here as we don't wait - * until the task has left the park code. So if we'd - * park before that happens we'd see the IS_PARKED bit - * which might be about to be cleared. + * Newly created kthread was parked when the CPU was offline. + * The binding was lost and we need to set it again. */ - if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) { - /* - * Newly created kthread was parked when the CPU was offline. - * The binding was lost and we need to set it again. - */ - if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags)) - __kthread_bind(k, kthread->cpu, TASK_PARKED); - wake_up_state(k, TASK_PARKED); - } + if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags)) + __kthread_bind(k, kthread->cpu, TASK_PARKED); + + clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); + wake_up_state(k, TASK_PARKED); } EXPORT_SYMBOL_GPL(kthread_unpark); @@ -482,12 +476,13 @@ int kthread_park(struct task_struct *k) if (WARN_ON(k->flags & PF_EXITING)) return -ENOSYS; - if (!test_bit(KTHREAD_IS_PARKED, &kthread->flags)) { - set_bit(KTHREAD_SHOULD_PARK, &kthread->flags); - if (k != current) { - wake_up_process(k); - wait_for_completion(&kthread->parked); - } + if (WARN_ON_ONCE(test_bit(KTHREAD_SHOULD_PARK, &kthread->flags))) + return -EBUSY; + + set_bit(KTHREAD_SHOULD_PARK, &kthread->flags); + if (k != current) { + wake_up_process(k); + wait_for_completion(&kthread->parked); } return 0; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 13ec4d8bebe6..8c992b8edc29 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -29,6 +29,8 @@ #include #include +#include + #include #include #ifdef CONFIG_PARAVIRT @@ -2786,20 +2788,28 @@ static struct rq *finish_task_switch(struct task_struct *prev) fire_sched_in_preempt_notifiers(current); if (mm) mmdrop(mm); - if (unlikely(prev_state == TASK_DEAD)) { - if (prev->sched_class->task_dead) - prev->sched_class->task_dead(prev); + if (unlikely(prev_state & (TASK_DEAD|TASK_PARKED))) { + switch (prev_state) { + case TASK_DEAD: + if (prev->sched_class->task_dead) + prev->sched_class->task_dead(prev); - /* - * Remove function-return probe instances associated with this - * task and put them back on the free list. - */ - kprobe_flush_task(prev); + /* + * Remove function-return probe instances associated with this + * task and put them back on the free list. + */ + kprobe_flush_task(prev); - /* Task is done with its stack. */ - put_task_stack(prev); + /* Task is done with its stack. */ + put_task_stack(prev); - put_task_struct(prev); + put_task_struct(prev); + break; + + case TASK_PARKED: + kthread_park_complete(prev); + break; + } } tick_nohz_task_switch(); -- GitLab From f199c2b6d4fd6b77c74552a3444a9358665a563c Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 30 Apr 2018 14:51:01 +0200 Subject: [PATCH 0185/1299] sched/core: Introduce set_special_state() Gaurav reported a perceived problem with TASK_PARKED, which turned out to be a broken wait-loop pattern in __kthread_parkme(), but the reported issue can (and does) in fact happen for states that do not do condition based sleeps. When the 'current->state = TASK_RUNNING' store of a previous (concurrent) try_to_wake_up() collides with the setting of a 'special' sleep state, we can loose the sleep state. Normal condition based wait-loops are immune to this problem, but for sleep states that are not condition based are subject to this problem. There already is a fix for TASK_DEAD. Abstract that and also apply it to TASK_STOPPED and TASK_TRACED, both of which are also without condition based wait-loop. Change-Id: I438d22302731eaaf8427c1fc7499659f96de33d2 Reported-by: Gaurav Kohli Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Oleg Nesterov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Ingo Molnar Git-commit: b5bf9a90bbebffba888c9144c5a8a10317b04064 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Gaurav Kohli Signed-off-by: Isaac J. Manjarres --- include/linux/sched.h | 50 ++++++++++++++++++++++++++++++++---- include/linux/sched/signal.h | 2 +- kernel/sched/core.c | 17 +----------- kernel/signal.c | 17 ++++++++++-- 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 2790c40436c0..96120ad99935 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -113,17 +113,36 @@ struct task_group; #ifdef CONFIG_DEBUG_ATOMIC_SLEEP +/* + * Special states are those that do not use the normal wait-loop pattern. See + * the comment with set_special_state(). + */ +#define is_special_task_state(state) \ + ((state) & (__TASK_STOPPED | __TASK_TRACED | TASK_DEAD)) + #define __set_current_state(state_value) \ do { \ + WARN_ON_ONCE(is_special_task_state(state_value));\ current->task_state_change = _THIS_IP_; \ current->state = (state_value); \ } while (0) + #define set_current_state(state_value) \ do { \ + WARN_ON_ONCE(is_special_task_state(state_value));\ current->task_state_change = _THIS_IP_; \ smp_store_mb(current->state, (state_value)); \ } while (0) +#define set_special_state(state_value) \ + do { \ + unsigned long flags; /* may shadow */ \ + WARN_ON_ONCE(!is_special_task_state(state_value)); \ + raw_spin_lock_irqsave(¤t->pi_lock, flags); \ + current->task_state_change = _THIS_IP_; \ + current->state = (state_value); \ + raw_spin_unlock_irqrestore(¤t->pi_lock, flags); \ + } while (0) #else /* * set_current_state() includes a barrier so that the write of current->state @@ -145,8 +164,8 @@ struct task_group; * * The above is typically ordered against the wakeup, which does: * - * need_sleep = false; - * wake_up_state(p, TASK_UNINTERRUPTIBLE); + * need_sleep = false; + * wake_up_state(p, TASK_UNINTERRUPTIBLE); * * Where wake_up_state() (and all other wakeup primitives) imply enough * barriers to order the store of the variable against wakeup. @@ -155,12 +174,33 @@ struct task_group; * once it observes the TASK_UNINTERRUPTIBLE store the waking CPU can issue a * TASK_RUNNING store which can collide with __set_current_state(TASK_RUNNING). * - * This is obviously fine, since they both store the exact same value. + * However, with slightly different timing the wakeup TASK_RUNNING store can + * also collide with the TASK_UNINTERRUPTIBLE store. Loosing that store is not + * a problem either because that will result in one extra go around the loop + * and our @cond test will save the day. * * Also see the comments of try_to_wake_up(). */ -#define __set_current_state(state_value) do { current->state = (state_value); } while (0) -#define set_current_state(state_value) smp_store_mb(current->state, (state_value)) +#define __set_current_state(state_value) \ + current->state = (state_value) + +#define set_current_state(state_value) \ + smp_store_mb(current->state, (state_value)) + +/* + * set_special_state() should be used for those states when the blocking task + * can not use the regular condition based wait-loop. In that case we must + * serialize against wakeups such that any possible in-flight TASK_RUNNING stores + * will not collide with our state change. + */ +#define set_special_state(state_value) \ + do { \ + unsigned long flags; /* may shadow */ \ + raw_spin_lock_irqsave(¤t->pi_lock, flags); \ + current->state = (state_value); \ + raw_spin_unlock_irqrestore(¤t->pi_lock, flags); \ + } while (0) + #endif /* Task command name length: */ diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 0aa4548fb492..fbf86ecd149d 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -280,7 +280,7 @@ static inline void kernel_signal_stop(void) { spin_lock_irq(¤t->sighand->siglock); if (current->jobctl & JOBCTL_STOP_DEQUEUED) - __set_current_state(TASK_STOPPED); + set_special_state(TASK_STOPPED); spin_unlock_irq(¤t->sighand->siglock); schedule(); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8c992b8edc29..98afe74e0d90 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3581,23 +3581,8 @@ static void __sched notrace __schedule(bool preempt) void __noreturn do_task_dead(void) { - /* - * The setting of TASK_RUNNING by try_to_wake_up() may be delayed - * when the following two conditions become true. - * - There is race condition of mmap_sem (It is acquired by - * exit_mm()), and - * - SMI occurs before setting TASK_RUNINNG. - * (or hypervisor of virtual machine switches to other guest) - * As a result, we may become TASK_RUNNING after becoming TASK_DEAD - * - * To avoid it, we have to wait for releasing tsk->pi_lock which - * is held by try_to_wake_up() - */ - raw_spin_lock_irq(¤t->pi_lock); - raw_spin_unlock_irq(¤t->pi_lock); - /* Causes final put_task_struct in finish_task_switch(): */ - __set_current_state(TASK_DEAD); + set_special_state(TASK_DEAD); /* Tell freezer to ignore us: */ current->flags |= PF_NOFREEZE; diff --git a/kernel/signal.c b/kernel/signal.c index 99db4b67269f..6994ceeb6d99 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1833,14 +1833,27 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) return; } + set_special_state(TASK_TRACED); + /* * We're committing to trapping. TRACED should be visible before * TRAPPING is cleared; otherwise, the tracer might fail do_wait(). * Also, transition to TRACED and updates to ->jobctl should be * atomic with respect to siglock and should be done after the arch * hook as siglock is released and regrabbed across it. + * + * TRACER TRACEE + * + * ptrace_attach() + * [L] wait_on_bit(JOBCTL_TRAPPING) [S] set_special_state(TRACED) + * do_wait() + * set_current_state() smp_wmb(); + * ptrace_do_wait() + * wait_task_stopped() + * task_stopped_code() + * [L] task_is_traced() [S] task_clear_jobctl_trapping(); */ - set_current_state(TASK_TRACED); + smp_wmb(); current->last_siginfo = info; current->exit_code = exit_code; @@ -2048,7 +2061,7 @@ static bool do_signal_stop(int signr) if (task_participate_group_stop(current)) notify = CLD_STOPPED; - __set_current_state(TASK_STOPPED); + set_special_state(TASK_STOPPED); spin_unlock_irq(¤t->sighand->siglock); /* -- GitLab From 0e12dd74964aa9a9f0bfa54c67970405bf385667 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 4 May 2018 11:11:42 +0200 Subject: [PATCH 0186/1299] kthread: Allow kthread_park() on a parked kthread The following commit: 85f1abe0019f ("kthread, sched/wait: Fix kthread_parkme() completion issue") added a WARN() in the case where we call kthread_park() on an already parked thread, because the old code wasn't doing the right thing there and it wasn't at all clear that would happen. It turns out, this does in fact happen, so we have to deal with it. Instead of potentially returning early, also wait for the completion. This does however mean we have to use complete_all() and re-initialize the completion on re-use. Change-Id: I35f6723ea8cab6251f66e7b127d501fa09f6a086 Reported-by: LKP Tested-by: Meelis Roos Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Peter Zijlstra Cc: kernel test robot Cc: wfg@linux.intel.com Cc: Thomas Gleixner Fixes: 85f1abe0019f ("kthread, sched/wait: Fix kthread_parkme() completion issue") Link: http://lkml.kernel.org/r/20180504091142.GI12235@hirez.programming.kicks-ass.net Signed-off-by: Ingo Molnar Git-commit: b1f5b378e126133521df668379249fb8265121f1 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Gaurav Kohli Signed-off-by: Isaac J. Manjarres --- kernel/kthread.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kernel/kthread.c b/kernel/kthread.c index 946f8ffa7f33..0dc6d5d6f89f 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -185,7 +185,7 @@ EXPORT_SYMBOL_GPL(kthread_parkme); void kthread_park_complete(struct task_struct *k) { - complete(&to_kthread(k)->parked); + complete_all(&to_kthread(k)->parked); } static int kthread(void *_create) @@ -452,6 +452,7 @@ void kthread_unpark(struct task_struct *k) if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags)) __kthread_bind(k, kthread->cpu, TASK_PARKED); + reinit_completion(&kthread->parked); clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); wake_up_state(k, TASK_PARKED); } @@ -476,9 +477,6 @@ int kthread_park(struct task_struct *k) if (WARN_ON(k->flags & PF_EXITING)) return -ENOSYS; - if (WARN_ON_ONCE(test_bit(KTHREAD_SHOULD_PARK, &kthread->flags))) - return -EBUSY; - set_bit(KTHREAD_SHOULD_PARK, &kthread->flags); if (k != current) { wake_up_process(k); -- GitLab From 251385e3f251ad9769e5397b97444e58ba0a0372 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 7 Jun 2018 14:33:11 +0200 Subject: [PATCH 0187/1299] kthread, sched: Fix kthread_parkme() (again...) Gaurav reports that commit: 85f1abe0019f ("kthread, sched/wait: Fix kthread_parkme() completion issue") isn't working for him. Because of the following race: > controller Thread CPUHP Thread > takedown_cpu > kthread_park > kthread_parkme > Set KTHREAD_SHOULD_PARK > smpboot_thread_fn > set Task interruptible > > > wake_up_process > if (!(p->state & state)) > goto out; > > Kthread_parkme > SET TASK_PARKED > schedule > raw_spin_lock(&rq->lock) > ttwu_remote > waiting for __task_rq_lock > context_switch > > finish_lock_switch > > > > Case TASK_PARKED > kthread_park_complete > > > SET Running Furthermore, Oleg noticed that the whole scheduler TASK_PARKED handling is buggered because the TASK_DEAD thing is done with preemption disabled, the current code can still complete early on preemption :/ So basically revert that earlier fix and go with a variant of the alternative mentioned in the commit. Promote TASK_PARKED to special state to avoid the store-store issue on task->state leading to the WARN in kthread_unpark() -> __kthread_bind(). But in addition, add wait_task_inactive() to kthread_park() to ensure the task really is PARKED when we return from kthread_park(). This avoids the whole kthread still gets migrated nonsense -- although it would be really good to get this done differently. Change-Id: I11d6a8c72fcf433c637f44e7b39adc979c8ddd7b Cc: Oleg Nesterov Reported-by: Gaurav Kohli Fixes: 85f1abe0019f ("kthread, sched/wait: Fix kthread_parkme() completion issue") Signed-off-by: Peter Zijlstra (Intel) Patch-mainline: linux-kernel@ 06/07/18, 05:33AM Signed-off-by: Gaurav Kohli Signed-off-by: Prasad Sodagudi --- include/linux/kthread.h | 1 - include/linux/sched.h | 2 +- kernel/kthread.c | 30 ++++++++++++++++++++++++------ kernel/sched/core.c | 9 +-------- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 3501157ede26..4e26609c77d4 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -61,7 +61,6 @@ void *kthread_probe_data(struct task_struct *k); int kthread_park(struct task_struct *k); void kthread_unpark(struct task_struct *k); void kthread_parkme(void); -void kthread_park_complete(struct task_struct *k); int kthreadd(void *unused); extern struct task_struct *kthreadd_task; diff --git a/include/linux/sched.h b/include/linux/sched.h index 96120ad99935..88da0bb5ece3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -118,7 +118,7 @@ struct task_group; * the comment with set_special_state(). */ #define is_special_task_state(state) \ - ((state) & (__TASK_STOPPED | __TASK_TRACED | TASK_DEAD)) + ((state) & (__TASK_STOPPED | __TASK_TRACED | TASK_PARKED | TASK_DEAD)) #define __set_current_state(state_value) \ do { \ diff --git a/kernel/kthread.c b/kernel/kthread.c index 0dc6d5d6f89f..df461383a2a7 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -169,9 +169,20 @@ void *kthread_probe_data(struct task_struct *task) static void __kthread_parkme(struct kthread *self) { for (;;) { - set_current_state(TASK_PARKED); + /* + * TASK_PARKED is a special state; we must serialize against + * possible pending wakeups to avoid store-store collisions on + * task->state. + * + * Such a collision might possibly result in the task state + * changin from TASK_PARKED and us failing the + * wait_task_inactive() in kthread_park(). + */ + set_special_state(TASK_PARKED); if (!test_bit(KTHREAD_SHOULD_PARK, &self->flags)) break; + + complete_all(&self->parked); schedule(); } __set_current_state(TASK_RUNNING); @@ -183,11 +194,6 @@ void kthread_parkme(void) } EXPORT_SYMBOL_GPL(kthread_parkme); -void kthread_park_complete(struct task_struct *k) -{ - complete_all(&to_kthread(k)->parked); -} - static int kthread(void *_create) { /* Copy data: it's on kthread's stack */ @@ -454,6 +460,9 @@ void kthread_unpark(struct task_struct *k) reinit_completion(&kthread->parked); clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); + /* + * __kthread_parkme() will either see !SHOULD_PARK or get the wakeup. + */ wake_up_state(k, TASK_PARKED); } EXPORT_SYMBOL_GPL(kthread_unpark); @@ -480,7 +489,16 @@ int kthread_park(struct task_struct *k) set_bit(KTHREAD_SHOULD_PARK, &kthread->flags); if (k != current) { wake_up_process(k); + /* + * Wait for __kthread_parkme() to complete(), this means we + * _will_ have TASK_PARKED and are about to call schedule(). + */ wait_for_completion(&kthread->parked); + /* + * Now wait for that schedule() to complete and the task to + * get scheduled out. + */ + WARN_ON_ONCE(!wait_task_inactive(k, TASK_PARKED)); } return 0; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 98afe74e0d90..0232fd107c74 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2788,9 +2788,7 @@ static struct rq *finish_task_switch(struct task_struct *prev) fire_sched_in_preempt_notifiers(current); if (mm) mmdrop(mm); - if (unlikely(prev_state & (TASK_DEAD|TASK_PARKED))) { - switch (prev_state) { - case TASK_DEAD: + if (unlikely(prev_state == TASK_DEAD)) { if (prev->sched_class->task_dead) prev->sched_class->task_dead(prev); @@ -2804,12 +2802,7 @@ static struct rq *finish_task_switch(struct task_struct *prev) put_task_stack(prev); put_task_struct(prev); - break; - case TASK_PARKED: - kthread_park_complete(prev); - break; - } } tick_nohz_task_switch(); -- GitLab From 500417c9e71c51063a227cd92765916eb3796e24 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Thu, 7 Jun 2018 15:48:29 -0700 Subject: [PATCH 0188/1299] msm: ipa3: fix the ipa stats query Andorid framework always set reset bit to 1 with every time's query, make the fix on ipa-driver to return the stats even when reset is set. Change-Id: I68ca1904f633df471094aa24a3407963ac153ba3 CRs-Fixed: 2252945 Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index e18d023b38ef..118ce429e827 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -3239,15 +3239,6 @@ static int rmnet_ipa3_query_tethering_stats_hw( int rc = 0; struct ipa_quota_stats_all *con_stats; - if (reset) { - IPAWANERR("only reset the pipe stats without returning stats"); - rc = ipa_get_teth_stats(); - if (rc) { - IPAWANERR("ipa_get_teth_stats failed %d,\n", rc); - return rc; - } - return 0; - } /* qet HW-stats */ rc = ipa_get_teth_stats(); if (rc) { -- GitLab From c96c434d8f16bb14a3b2ea4d9c178c1488ebf12f Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 8 May 2018 16:34:27 -0700 Subject: [PATCH 0189/1299] msm: camera: Add front camera wled flash support Front camera flash has WLED support for selfie flash. This change enables WLED support for front image sensor to request wled framework for brightness change based on request. Change-Id: I84555dab7e2609814ac98448fbb3fb06da9ec7fc Signed-off-by: Jigarkumar Zala --- .../bindings/media/video/msm-camera-flash.txt | 8 +- .../cam_flash/cam_flash_core.c | 124 ++++++++++++------ .../cam_flash/cam_flash_core.h | 1 - .../cam_flash/cam_flash_dev.h | 3 + .../cam_flash/cam_flash_soc.c | 120 +++++++++++------ 5 files changed, 170 insertions(+), 86 deletions(-) diff --git a/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt b/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt index 5e7eca0fad17..ab81329df08e 100644 --- a/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt +++ b/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt @@ -65,6 +65,11 @@ First Level Node - CAM FLASH device Value type: Definition: Max duration in ms flash can glow. +- wled-flash-support + Usage: optional + Value type: + Definition: To identity wled flash hardware support. + - gpios Usage: optional Value type: @@ -109,7 +114,8 @@ led_flash_rear: qcom,camera-flash@0 { flash-source = <&pmi8998_flash0 &pmi8998_flash1>; torch-source = <&pmi8998_torch0 &pmi8998_torch1>; switch-source = <&pmi8998_switch0>; - qcom,slave-id = <0x00 0x00 0x0011>; + wled-flash-support; + qcom,slave-id = <0x00 0x00 0x0011>; qcom,cci-master = <0>; gpios = <&msmgpio 23 0>, <&msmgpio 24 0>; diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c index 47759d56c4e0..740a94287624 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c @@ -20,38 +20,72 @@ int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl, bool regulator_enable) { int rc = 0; + struct cam_flash_private_soc *soc_private = + (struct cam_flash_private_soc *) + flash_ctrl->soc_info.soc_private; if (!(flash_ctrl->switch_trigger)) { CAM_ERR(CAM_FLASH, "Invalid argument"); return -EINVAL; } - if (regulator_enable && - (flash_ctrl->is_regulator_enabled == false)) { - rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger, - ENABLE_REGULATOR, NULL); - if (rc) { - CAM_ERR(CAM_FLASH, "regulator enable failed rc = %d", - rc); - return rc; - } - flash_ctrl->is_regulator_enabled = true; - } else if ((!regulator_enable) && - (flash_ctrl->is_regulator_enabled == true)) { - rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger, - DISABLE_REGULATOR, NULL); - if (rc) { - CAM_ERR(CAM_FLASH, "regulator disable failed rc = %d", - rc); - return rc; + if (soc_private->is_wled_flash) { + if (regulator_enable && + flash_ctrl->is_regulator_enabled == false) { + rc = wled_flash_led_prepare(flash_ctrl->switch_trigger, + ENABLE_REGULATOR, NULL); + if (rc) { + CAM_ERR(CAM_FLASH, "enable reg failed: rc: %d", + rc); + return rc; + } + + flash_ctrl->is_regulator_enabled = true; + } else if (!regulator_enable && + flash_ctrl->is_regulator_enabled == true) { + rc = wled_flash_led_prepare(flash_ctrl->switch_trigger, + DISABLE_REGULATOR, NULL); + if (rc) { + CAM_ERR(CAM_FLASH, "disalbe reg fail: rc: %d", + rc); + return rc; + } + + flash_ctrl->is_regulator_enabled = false; + } else { + CAM_ERR(CAM_FLASH, "Wrong Wled flash state: %d", + flash_ctrl->flash_state); + rc = -EINVAL; } - flash_ctrl->is_regulator_enabled = false; } else { - CAM_ERR(CAM_FLASH, "Wrong Flash State : %d", - flash_ctrl->flash_state); - rc = -EINVAL; - } + if (regulator_enable && + (flash_ctrl->is_regulator_enabled == false)) { + rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger, + ENABLE_REGULATOR, NULL); + if (rc) { + CAM_ERR(CAM_FLASH, + "Regulator enable failed rc = %d", rc); + return rc; + } + flash_ctrl->is_regulator_enabled = true; + } else if ((!regulator_enable) && + (flash_ctrl->is_regulator_enabled == true)) { + rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger, + DISABLE_REGULATOR, NULL); + if (rc) { + CAM_ERR(CAM_FLASH, + "Regulator disable failed rc = %d", rc); + return rc; + } + + flash_ctrl->is_regulator_enabled = false; + } else { + CAM_ERR(CAM_FLASH, "Wrong Flash State : %d", + flash_ctrl->flash_state); + rc = -EINVAL; + } + } return rc; } @@ -144,37 +178,31 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, for (i = 0; i < flash_ctrl->torch_num_sources; i++) { if (flash_ctrl->torch_trigger[i]) { max_current = soc_private->torch_max_current[i]; - if (flash_data->led_current_ma[i] <= max_current) curr = flash_data->led_current_ma[i]; else - curr = soc_private->torch_op_current[i]; - - CAM_DBG(CAM_FLASH, - "Led_Current[%d] = %d", i, curr); - cam_res_mgr_led_trigger_event( - flash_ctrl->torch_trigger[i], - curr); + curr = max_current; } + CAM_DBG(CAM_FLASH, "Led_Torch[%d]: Current: %d", + i, curr); + cam_res_mgr_led_trigger_event( + flash_ctrl->torch_trigger[i], curr); } } else if (op == CAMERA_SENSOR_FLASH_OP_FIREHIGH) { for (i = 0; i < flash_ctrl->flash_num_sources; i++) { if (flash_ctrl->flash_trigger[i]) { max_current = soc_private->flash_max_current[i]; - if (flash_data->led_current_ma[i] <= max_current) curr = flash_data->led_current_ma[i]; else - curr = soc_private->flash_op_current[i]; - - CAM_DBG(CAM_FLASH, "LED flash_current[%d]: %d", - i, curr); - cam_res_mgr_led_trigger_event( - flash_ctrl->flash_trigger[i], - curr); + curr = max_current; } + CAM_DBG(CAM_FLASH, "LED_Flash[%d]: Current: %d", + i, curr); + cam_res_mgr_led_trigger_event( + flash_ctrl->flash_trigger[i], curr); } } else { CAM_ERR(CAM_FLASH, "Wrong Operation: %d", op); @@ -525,11 +553,16 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) struct cam_flash_set_on_off *flash_operation_info = NULL; struct cam_flash_query_curr *flash_query_info = NULL; struct cam_flash_frame_setting *flash_data = NULL; + struct cam_flash_private_soc *soc_private = NULL; if (!fctrl || !arg) { CAM_ERR(CAM_FLASH, "fctrl/arg is NULL"); return -EINVAL; } + + soc_private = (struct cam_flash_private_soc *) + fctrl->soc_info.soc_private; + /* getting CSL Packet */ ioctl_ctrl = (struct cam_control *)arg; @@ -718,8 +751,17 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg) flash_query_info = (struct cam_flash_query_curr *)cmd_buf; - rc = qpnp_flash_led_prepare(fctrl->switch_trigger, - QUERY_MAX_AVAIL_CURRENT, &query_curr_ma); + if (soc_private->is_wled_flash) + rc = wled_flash_led_prepare( + fctrl->switch_trigger, + QUERY_MAX_AVAIL_CURRENT, + &query_curr_ma); + else + rc = qpnp_flash_led_prepare( + fctrl->switch_trigger, + QUERY_MAX_AVAIL_CURRENT, + &query_curr_ma); + CAM_DBG(CAM_FLASH, "query_curr_ma = %d", query_curr_ma); if (rc) { diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h index 0ea210696bb2..1f527b341319 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.h @@ -13,7 +13,6 @@ #ifndef _CAM_FLASH_CORE_H_ #define _CAM_FLASH_CORE_H_ -#include #include #include "cam_flash_dev.h" #include "cam_sync_api.h" diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h index 13238552416a..4fcd81d2ece0 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -123,6 +124,7 @@ struct cam_flash_frame_setting { * @torch_trigger_name : Torch trigger name array * @torch_op_current : Torch operational current * @torch_max_current : Max supported current for LED in torch mode + * @is_wled_flash : Detection between WLED/LED flash */ struct cam_flash_private_soc { @@ -134,6 +136,7 @@ struct cam_flash_private_soc { const char *torch_trigger_name[CAM_FLASH_MAX_LED_TRIGGERS]; uint32_t torch_op_current[CAM_FLASH_MAX_LED_TRIGGERS]; uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS]; + bool is_wled_flash; }; /** diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c index 22678a6cf720..d5f583a72f48 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -26,9 +26,12 @@ static int32_t cam_get_source_node_info( struct device_node *torch_src_node = NULL; struct device_node *switch_src_node = NULL; + soc_private->is_wled_flash = + of_property_read_bool(of_node, "wled-flash-support"); + switch_src_node = of_parse_phandle(of_node, "switch-source", 0); if (!switch_src_node) { - CAM_DBG(CAM_FLASH, "switch_src_node NULL"); + CAM_WARN(CAM_FLASH, "switch_src_node NULL"); } else { rc = of_property_read_string(switch_src_node, "qcom,default-led-trigger", @@ -75,46 +78,61 @@ static int32_t cam_get_source_node_info( continue; } - CAM_DBG(CAM_FLASH, "default trigger %s", + CAM_DBG(CAM_FLASH, "Flash default trigger %s", soc_private->flash_trigger_name[i]); + cam_res_mgr_led_trigger_register( + soc_private->flash_trigger_name[i], + &fctrl->flash_trigger[i]); + + if (soc_private->is_wled_flash) { + rc = wled_flash_led_prepare( + fctrl->flash_trigger[i], + QUERY_MAX_CURRENT, + &soc_private->flash_max_current[i]); + if (rc) { + CAM_ERR(CAM_FLASH, + "WLED FLASH max_current read fail: %d", + rc); + of_node_put(flash_src_node); + rc = 0; + continue; + } + } else { + rc = of_property_read_u32(flash_src_node, + "qcom,max-current", + &soc_private->flash_max_current[i]); + if (rc < 0) { + CAM_WARN(CAM_FLASH, + "LED FLASH max-current read fail: %d", + rc); + of_node_put(flash_src_node); + continue; + } + } /* Read operational-current */ rc = of_property_read_u32(flash_src_node, "qcom,current-ma", &soc_private->flash_op_current[i]); if (rc) { - CAM_WARN(CAM_FLASH, "op-current: read failed"); - of_node_put(flash_src_node); - continue; - } - - /* Read max-current */ - rc = of_property_read_u32(flash_src_node, - "qcom,max-current", - &soc_private->flash_max_current[i]); - if (rc) { - CAM_WARN(CAM_FLASH, - "max-current: read failed"); - of_node_put(flash_src_node); - continue; + CAM_INFO(CAM_FLASH, "op-current: read failed"); + rc = 0; } /* Read max-duration */ rc = of_property_read_u32(flash_src_node, "qcom,duration-ms", &soc_private->flash_max_duration[i]); - if (rc) - CAM_WARN(CAM_FLASH, - "max-duration: read failed"); - + if (rc) { + CAM_INFO(CAM_FLASH, + "max-duration prop unavailable: %d", + rc); + rc = 0; + } of_node_put(flash_src_node); - CAM_DBG(CAM_FLASH, "max_current[%d]: %d", + CAM_DBG(CAM_FLASH, "MainFlashMaxCurrent[%d]: %d", i, soc_private->flash_max_current[i]); - - cam_res_mgr_led_trigger_register( - soc_private->flash_trigger_name[i], - &fctrl->flash_trigger[i]); } } @@ -147,35 +165,51 @@ static int32_t cam_get_source_node_info( continue; } + CAM_DBG(CAM_FLASH, "Torch default trigger %s", + soc_private->torch_trigger_name[i]); + cam_res_mgr_led_trigger_register( + soc_private->torch_trigger_name[i], + &fctrl->torch_trigger[i]); + + if (soc_private->is_wled_flash) { + rc = wled_flash_led_prepare( + fctrl->torch_trigger[i], + QUERY_MAX_CURRENT, + &soc_private->torch_max_current[i]); + if (rc) { + CAM_ERR(CAM_FLASH, + "WLED TORCH max_current read fail: %d", + rc); + of_node_put(torch_src_node); + continue; + } + } else { + rc = of_property_read_u32(torch_src_node, + "qcom,max-current", + &soc_private->torch_max_current[i]); + if (rc < 0) { + CAM_WARN(CAM_FLASH, + "LED-TORCH max-current read failed: %d", + rc); + of_node_put(torch_src_node); + continue; + } + } + /* Read operational-current */ rc = of_property_read_u32(torch_src_node, "qcom,current-ma", &soc_private->torch_op_current[i]); - if (rc < 0) { - CAM_WARN(CAM_FLASH, "current: read failed"); - of_node_put(torch_src_node); - continue; - } - - /* Read max-current */ - rc = of_property_read_u32(torch_src_node, - "qcom,max-current", - &soc_private->torch_max_current[i]); if (rc < 0) { CAM_WARN(CAM_FLASH, - "max-current: read failed"); - of_node_put(torch_src_node); - continue; + "op-current prop unavailable: %d", rc); + rc = 0; } of_node_put(torch_src_node); - CAM_DBG(CAM_FLASH, "max_current[%d]: %d", + CAM_DBG(CAM_FLASH, "TorchMaxCurrent[%d]: %d", i, soc_private->torch_max_current[i]); - - cam_res_mgr_led_trigger_register( - soc_private->torch_trigger_name[i], - &fctrl->torch_trigger[i]); } } -- GitLab From 1ab6df96c1234a5aa733faebe73713e9920941f4 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Tue, 8 May 2018 16:35:49 -0700 Subject: [PATCH 0190/1299] ARM: dts: msm: Add WLED support for SM8150 platforms This change adds WLED support for front sensor torch and flash operations. Change-Id: Ie525a1def5f3f955b9287da78803d610fac5f50e Signed-off-by: Jigarkumar Zala --- .../boot/dts/qcom/sm8150-camera-sensor-cdp.dtsi | 12 ++++++++++++ .../boot/dts/qcom/sm8150-camera-sensor-mtp.dtsi | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-cdp.dtsi index 8c43df12b299..661fdb0794db 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-cdp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-cdp.dtsi @@ -32,6 +32,17 @@ status = "ok"; }; + led_flash_front: qcom,camera-flash@2 { + cell-index = <2>; + reg = <0x02 0x00>; + compatible = "qcom,camera-flash"; + wled-flash-support; + flash-source = <&wled_flash>; + torch-source = <&wled_torch>; + switch-source = <&wled_switch>; + status = "ok"; + }; + led_flash_iris: qcom,camera-flash@3 { cell-index = <3>; reg = <0x03 0x00>; @@ -313,6 +324,7 @@ sensor-position-yaw = <0>; eeprom-src = <&eeprom_front>; actuator-src = <&actuator_front>; + led-flash-src = <&led_flash_front>; cam_vio-supply = <&pm8150l_l1>; cam_vana-supply = <&pm8009_l6>; cam_vdig-supply = <&pm8009_l2>; diff --git a/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-mtp.dtsi index 8c43df12b299..661fdb0794db 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-mtp.dtsi @@ -32,6 +32,17 @@ status = "ok"; }; + led_flash_front: qcom,camera-flash@2 { + cell-index = <2>; + reg = <0x02 0x00>; + compatible = "qcom,camera-flash"; + wled-flash-support; + flash-source = <&wled_flash>; + torch-source = <&wled_torch>; + switch-source = <&wled_switch>; + status = "ok"; + }; + led_flash_iris: qcom,camera-flash@3 { cell-index = <3>; reg = <0x03 0x00>; @@ -313,6 +324,7 @@ sensor-position-yaw = <0>; eeprom-src = <&eeprom_front>; actuator-src = <&actuator_front>; + led-flash-src = <&led_flash_front>; cam_vio-supply = <&pm8150l_l1>; cam_vana-supply = <&pm8009_l6>; cam_vdig-supply = <&pm8009_l2>; -- GitLab From e6f23295a7f925e2a9b297285584c3243f278650 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Mon, 11 Jun 2018 15:38:29 -0700 Subject: [PATCH 0191/1299] msm: ipa: fix usb pm initialization Initialize PM related members in IPA_USB always, even if PM is not used. This is to avoid any race conditions between different init functions. Change-Id: I537b00030ee52f387cf92a9ec7065aa82191a979 CRs-Fixed: 2259107 Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- .../platform/msm/ipa/ipa_clients/ipa_usb.c | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c index b937964fb459..bf992ccbc9fa 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c @@ -2937,6 +2937,7 @@ static int __init ipa3_usb_init(void) int i; unsigned long flags; int res; + struct ipa3_usb_pm_context *pm_ctx; pr_debug("entry\n"); ipa3_usb_ctx = kzalloc(sizeof(struct ipa3_usb_context), GFP_KERNEL); @@ -2956,19 +2957,13 @@ static int __init ipa3_usb_init(void) ipa3_usb_ctx->dl_data_pending = false; mutex_init(&ipa3_usb_ctx->general_mutex); - if (ipa_pm_is_used()) { - struct ipa3_usb_pm_context *pm_ctx; - - pm_ctx = - &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx; - pm_ctx->hdl = ~0; - pm_ctx->remote_wakeup_work = - &ipa3_usb_notify_remote_wakeup_work; - pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx; - pm_ctx->hdl = ~0; - pm_ctx->remote_wakeup_work = - &ipa3_usb_dpl_notify_remote_wakeup_work; - } + /* init PM related members */ + pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx; + pm_ctx->hdl = ~0; + pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work; + pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx; + pm_ctx->hdl = ~0; + pm_ctx->remote_wakeup_work = &ipa3_usb_dpl_notify_remote_wakeup_work; for (i = 0; i < IPA_USB_TRANSPORT_MAX; i++) { ipa3_usb_ctx->ttype_ctx[i].rm_ctx.prod_valid = false; -- GitLab From 8601ea9279ddd06a027d2bdae82a23e8df41d515 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Tue, 5 Jun 2018 20:08:15 -0600 Subject: [PATCH 0192/1299] ipv6: Do not generate random IID only for RAWIP devices This method is incorrect as it maybe incorrectly clearing some of the bits needed for setting the IID. CRs-Fixed: 2233026 Change-Id: I231e9b6a28a0d3f61f3bb19e311432a13bbd4db8 Signed-off-by: Subash Abhinov Kasiviswanathan --- net/ipv6/addrconf.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 7985da722507..e773245b867b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2217,16 +2217,6 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) case ARPHRD_TUNNEL6: case ARPHRD_IP6GRE: return addrconf_ifid_ip6tnl(eui, dev); - case ARPHRD_RAWIP: { - struct in6_addr lladdr; - - if (ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE)) - get_random_bytes(eui, 8); - else - memcpy(eui, lladdr.s6_addr + 8, 8); - - return 0; - } } return -1; } @@ -3257,8 +3247,7 @@ static void addrconf_dev_config(struct net_device *dev) (dev->type != ARPHRD_IP6GRE) && (dev->type != ARPHRD_IPGRE) && (dev->type != ARPHRD_TUNNEL) && - (dev->type != ARPHRD_NONE) && - (dev->type != ARPHRD_RAWIP)) { + (dev->type != ARPHRD_NONE)) { /* Alas, we support only Ethernet autoconfiguration. */ return; } -- GitLab From 0b908b0fbe12499061f08dd295bf0c0636d91c80 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Fri, 25 May 2018 15:11:15 -0700 Subject: [PATCH 0193/1299] power: qcom: step-chg-jeita: Make read_range_data_from_node global Currently, read_range_data_from_node() is used to read step charging and SW JEITA thresholds from the battery profile. Since this function can be shared with other drivers which only wants to read the parameters but not use the entire step charging algorithm, make read_range_data_from_node() a global function so that it can be reused. Also, maximum entries supported for step charging thresholds should be made common. Change-Id: If318cffba864aa1fd9a48f80d38134fb2fb69326 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/step-chg-jeita.c | 17 ++++++++--------- drivers/power/supply/qcom/step-chg-jeita.h | 14 +++++++++++++- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/power/supply/qcom/step-chg-jeita.c b/drivers/power/supply/qcom/step-chg-jeita.c index a75cbbbce56f..b0e62d32f188 100644 --- a/drivers/power/supply/qcom/step-chg-jeita.c +++ b/drivers/power/supply/qcom/step-chg-jeita.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -20,7 +20,6 @@ #include #include "step-chg-jeita.h" -#define MAX_STEP_CHG_ENTRIES 8 #define STEP_CHG_VOTER "STEP_CHG_VOTER" #define JEITA_VOTER "JEITA_VOTER" @@ -30,12 +29,6 @@ || ((left) <= (right) && (left) <= (value) \ && (value) <= (right))) -struct range_data { - u32 low_threshold; - u32 high_threshold; - u32 value; -}; - struct step_chg_cfg { u32 psy_prop; char *prop_name; @@ -118,12 +111,17 @@ static bool is_bms_available(struct step_chg_info *chip) return true; } -static int read_range_data_from_node(struct device_node *node, +int read_range_data_from_node(struct device_node *node, const char *prop_str, struct range_data *ranges, u32 max_threshold, u32 max_value) { int rc = 0, i, length, per_tuple_length, tuples; + if (!node || !prop_str || !ranges) { + pr_err("Invalid parameters passed\n"); + return -EINVAL; + } + rc = of_property_count_elems_of_size(node, prop_str, sizeof(u32)); if (rc < 0) { pr_err("Count %s failed, rc=%d\n", prop_str, rc); @@ -184,6 +182,7 @@ static int read_range_data_from_node(struct device_node *node, memset(ranges, 0, tuples * sizeof(struct range_data)); return rc; } +EXPORT_SYMBOL(read_range_data_from_node); static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip) { diff --git a/drivers/power/supply/qcom/step-chg-jeita.h b/drivers/power/supply/qcom/step-chg-jeita.h index 2404b866b94e..6760d66143f1 100644 --- a/drivers/power/supply/qcom/step-chg-jeita.h +++ b/drivers/power/supply/qcom/step-chg-jeita.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -12,7 +12,19 @@ #ifndef __STEP_CHG_H__ #define __STEP_CHG_H__ + +#define MAX_STEP_CHG_ENTRIES 8 + +struct range_data { + u32 low_threshold; + u32 high_threshold; + u32 value; +}; + int qcom_step_chg_init(struct device *dev, bool step_chg_enable, bool sw_jeita_enable); void qcom_step_chg_deinit(void); +int read_range_data_from_node(struct device_node *node, + const char *prop_str, struct range_data *ranges, + u32 max_threshold, u32 max_value); #endif /* __STEP_CHG_H__ */ -- GitLab From 557a3b4d19fc7546b25bf212d98c887d167e7e9b Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Mon, 4 Jun 2018 19:26:07 -0600 Subject: [PATCH 0194/1299] net: ipv6: Generate random IID for addresses on RAWIP devices RAWIP devices such as rmnet do not have a hardware address and instead require the kernel to generate a random IID for the IPv6 addresses. CRs-Fixed: 2233026 Change-Id: Ic46b85f43e4e87cc463d214f8085ffc5584e31f0 Signed-off-by: Sean Tranchetti Signed-off-by: David S. Miller Git-commit: 9deb441c113ae9e761e42f78d90736d762ff49a3 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 4 ++++ net/ipv6/addrconf.c | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c index d644ce998cdd..72fa095e756f 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c @@ -227,6 +227,10 @@ void rmnet_vnd_setup(struct net_device *rmnet_dev) rmnet_dev->needs_free_netdev = true; rmnet_dev->ethtool_ops = &rmnet_ethtool_ops; + + /* This perm addr will be used as interface identifier by IPv6 */ + rmnet_dev->addr_assign_type = NET_ADDR_RANDOM; + eth_random_addr(rmnet_dev->perm_addr); } /* Exposed API */ diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e773245b867b..7bbae058a277 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2216,6 +2216,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) return addrconf_ifid_ieee1394(eui, dev); case ARPHRD_TUNNEL6: case ARPHRD_IP6GRE: + case ARPHRD_RAWIP: return addrconf_ifid_ip6tnl(eui, dev); } return -1; @@ -3247,7 +3248,8 @@ static void addrconf_dev_config(struct net_device *dev) (dev->type != ARPHRD_IP6GRE) && (dev->type != ARPHRD_IPGRE) && (dev->type != ARPHRD_TUNNEL) && - (dev->type != ARPHRD_NONE)) { + (dev->type != ARPHRD_NONE) && + (dev->type != ARPHRD_RAWIP)) { /* Alas, we support only Ethernet autoconfiguration. */ return; } -- GitLab From 47c88a85d5580b5cc1501768a73ba0230c74f9df Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Fri, 8 Jun 2018 19:50:21 -0700 Subject: [PATCH 0195/1299] fg-alg: Add TTF support for step charging Step charging configuration comes from the battery profile which defines the variable charging current configurations based on Vbatt or State of charge (SOC). When voltage based step charging is enabled, Time to full (TTF) calculations needs a change as the charging rate changes. As per the hardware recommendation, add the calculation needed to go through each of the charging window and compute the time. Change-Id: I9b264b8af25f93aba20a8609f4786427081764a0 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-alg.c | 97 +++++++++++++++++++++++++++++- drivers/power/supply/qcom/fg-alg.h | 17 ++++++ 2 files changed, 112 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c index b230f7295441..9500b6648011 100644 --- a/drivers/power/supply/qcom/fg-alg.c +++ b/drivers/power/supply/qcom/fg-alg.c @@ -798,12 +798,16 @@ static int ttf_lerp(const struct ttf_pt *pts, size_t tablesize, static int get_time_to_full_locked(struct ttf *ttf, int *val) { + struct step_chg_data *step_chg_data = ttf->step_chg_data; + struct range_data *step_chg_cfg = ttf->step_chg_cfg; int rc, ibatt_avg, vbatt_avg, rbatt = 0, msoc = 0, act_cap_mah = 0, i_cc2cv = 0, soc_cc2cv, tau, divisor, iterm = 0, ttf_mode = 0, i, soc_per_step, msoc_this_step, msoc_next_step, ibatt_this_step, t_predicted_this_step, ttf_slope, - t_predicted_cv, t_predicted = 0, charge_type = 0, + t_predicted_cv, t_predicted = 0, charge_type = 0, i_step, float_volt_uv = 0; + int vbatt_now, multiplier, curr_window = 0, pbatt_avg; + bool power_approx = false; s64 delta_ms; rc = ttf->get_ttf_param(ttf->data, TTF_MSOC, &msoc); @@ -873,7 +877,7 @@ static int get_time_to_full_locked(struct ttf *ttf, int *val) return rc; } - pr_debug(" TTF: ibatt_avg=%d vbatt_avg=%d rbatt=%d act_cap_mah=%d\n", + pr_debug("TTF: ibatt_avg=%d vbatt_avg=%d rbatt=%d act_cap_mah=%d\n", ibatt_avg, vbatt_avg, rbatt, act_cap_mah); rc = ttf->get_ttf_param(ttf->data, TTF_VFLOAT, &float_volt_uv); @@ -887,9 +891,13 @@ static int get_time_to_full_locked(struct ttf *ttf, int *val) pr_err("failed to get charge_type rc=%d\n", rc); return rc; } + + pr_debug("TTF: mode: %d\n", ttf->mode); + /* estimated battery current at the CC to CV transition */ switch (ttf->mode) { case TTF_MODE_NORMAL: + case TTF_MODE_V_STEP_CHG: i_cc2cv = ibatt_avg * vbatt_avg / max(MILLI_UNIT, float_volt_uv / MILLI_UNIT); break; @@ -945,6 +953,91 @@ static int get_time_to_full_locked(struct ttf *ttf, int *val) msoc_this_step, msoc_next_step, ibatt_this_step, t_predicted_this_step); } + break; + case TTF_MODE_V_STEP_CHG: + if (!step_chg_data || !step_chg_cfg) + break; + + pbatt_avg = vbatt_avg * ibatt_avg; + + rc = ttf->get_ttf_param(ttf->data, TTF_VBAT, &vbatt_now); + if (rc < 0) { + pr_err("failed to get battery voltage, rc=%d\n", rc); + return rc; + } + + curr_window = ttf->step_chg_num_params - 1; + for (i = 0; i < ttf->step_chg_num_params; i++) { + if (is_between(step_chg_cfg[i].low_threshold, + step_chg_cfg[i].high_threshold, + vbatt_now)) + curr_window = i; + } + + pr_debug("TTF: curr_window: %d pbatt_avg: %d\n", curr_window, + pbatt_avg); + + t_predicted_this_step = 0; + for (i = 0; i < ttf->step_chg_num_params; i++) { + /* + * If Ibatt_avg differs by step charging threshold by + * more than 100 mA, then use power approximation to + * get charging current step. + */ + + if (step_chg_cfg[i].value - ibatt_avg > 100) + power_approx = true; + + /* Calculate OCV for each window */ + if (power_approx) { + i_step = pbatt_avg / max((u32)MILLI_UNIT, + (step_chg_cfg[i].high_threshold / + MILLI_UNIT)); + } else { + if (i == curr_window) + i_step = ((step_chg_cfg[i].value / + MILLI_UNIT) + + ibatt_avg) / 2; + else + i_step = (step_chg_cfg[i].value / + MILLI_UNIT); + } + + step_chg_data[i].ocv = step_chg_cfg[i].high_threshold - + (rbatt * i_step); + + /* Calculate SOC for each window */ + step_chg_data[i].soc = (float_volt_uv - + step_chg_data[i].ocv) / OCV_SLOPE_UV; + step_chg_data[i].soc = 100 - step_chg_data[i].soc; + + /* Calculate CC time for each window */ + multiplier = act_cap_mah * HOURS_TO_SECONDS; + if (curr_window > 0 && i < curr_window) + t_predicted_this_step = 0; + else if (i == curr_window) + t_predicted_this_step = + div_s64((s64)multiplier * + (step_chg_data[i].soc - msoc), + i_step); + else if (i > 0) + t_predicted_this_step = + div_s64((s64)multiplier * + (step_chg_data[i].soc - + step_chg_data[i - 1].soc), + i_step); + + if (t_predicted_this_step < 0) + t_predicted_this_step = 0; + + t_predicted_this_step = + DIV_ROUND_CLOSEST(t_predicted_this_step, 100); + pr_debug("TTF: step: %d i_step: %d OCV: %d SOC: %d t_pred: %d\n", + i, i_step, step_chg_data[i].ocv, + step_chg_data[i].soc, t_predicted_this_step); + t_predicted += t_predicted_this_step; + } + break; default: pr_err("TTF mode %d is not supported\n", ttf->mode); diff --git a/drivers/power/supply/qcom/fg-alg.h b/drivers/power/supply/qcom/fg-alg.h index 7c75bac8843b..89670d50cfaa 100644 --- a/drivers/power/supply/qcom/fg-alg.h +++ b/drivers/power/supply/qcom/fg-alg.h @@ -13,11 +13,18 @@ #ifndef __FG_ALG_H__ #define __FG_ALG_H__ +#include "step-chg-jeita.h" + #define BUCKET_COUNT 8 #define BUCKET_SOC_PCT (256 / BUCKET_COUNT) #define MAX_CC_STEPS 20 #define MAX_TTF_SAMPLES 10 +#define is_between(left, right, value) \ + (((left) >= (right) && (left) >= (value) \ + && (value) >= (right)) \ + || ((left) <= (right) && (left) <= (value) \ + && (value) <= (right))) struct cycle_counter { void *data; char str_buf[BUCKET_COUNT * 8]; @@ -63,6 +70,7 @@ struct cap_learning { enum ttf_mode { TTF_MODE_NORMAL = 0, TTF_MODE_QNOVO, + TTF_MODE_V_STEP_CHG, }; enum ttf_param { @@ -94,12 +102,21 @@ struct ttf_pt { s32 y; }; +struct step_chg_data { + int ocv; + int soc; +}; + struct ttf { void *data; struct ttf_circ_buf ibatt; struct ttf_circ_buf vbatt; struct ttf_cc_step_data cc_step; struct mutex lock; + struct step_chg_data *step_chg_data; + struct range_data *step_chg_cfg; + bool step_chg_cfg_valid; + int step_chg_num_params; int mode; int last_ttf; int input_present; -- GitLab From 158cb6d72969ca67853e91138b472b3e515ff826 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Fri, 8 Jun 2018 19:51:50 -0700 Subject: [PATCH 0196/1299] power: qpnp-fg-gen4: Add TTF support for step charging Add TTF support for step charging by reading the parameters from the battery profile and notifying the parameters when TTF algorithm queries for the mode. Change-Id: Ibe8a6ec41444735a7d4fc8392ed6a0f9caaf1dc3 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/qpnp-fg-gen4.c | 72 +++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index afd0c9ed7d8f..915611b87c86 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -591,6 +591,8 @@ static int fg_gen4_get_ttf_param(void *data, enum ttf_param param, int *val) case TTF_MODE: if (is_qnovo_en(fg)) *val = TTF_MODE_QNOVO; + else if (chip->ttf->step_chg_cfg_valid) + *val = TTF_MODE_V_STEP_CHG; else *val = TTF_MODE_NORMAL; break; @@ -801,7 +803,7 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) struct device_node *node = fg->dev->of_node; struct device_node *batt_node, *profile_node; const char *data; - int rc, len; + int rc, len, i, tuple_len; batt_node = of_find_node_by_name(node, "qcom,battery-data"); if (!batt_node) { @@ -876,6 +878,64 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) } } + /* + * Currently step charging thresholds should be read only for Vbatt + * based and not for SOC based. + */ + if (!of_property_read_bool(profile_node, "qcom,soc-based-step-chg") && + of_find_property(profile_node, "qcom,step-chg-ranges", &len) && + fg->bp.float_volt_uv > 0 && fg->bp.fastchg_curr_ma > 0) { + len /= sizeof(u32); + tuple_len = len / (sizeof(struct range_data) / sizeof(u32)); + if (tuple_len <= 0 || tuple_len > MAX_STEP_CHG_ENTRIES) + return -EINVAL; + + mutex_lock(&chip->ttf->lock); + chip->ttf->step_chg_cfg = + kcalloc(len, sizeof(*chip->ttf->step_chg_cfg), + GFP_KERNEL); + if (!chip->ttf->step_chg_cfg) { + mutex_unlock(&chip->ttf->lock); + return -ENOMEM; + } + + chip->ttf->step_chg_data = + kcalloc(tuple_len, sizeof(*chip->ttf->step_chg_data), + GFP_KERNEL); + if (!chip->ttf->step_chg_data) { + kfree(chip->ttf->step_chg_cfg); + mutex_unlock(&chip->ttf->lock); + return -ENOMEM; + } + + rc = read_range_data_from_node(profile_node, + "qcom,step-chg-ranges", + chip->ttf->step_chg_cfg, + fg->bp.float_volt_uv, + fg->bp.fastchg_curr_ma * 1000); + if (rc < 0) { + pr_err("Error in reading qcom,step-chg-ranges from battery profile, rc=%d\n", + rc); + kfree(chip->ttf->step_chg_data); + kfree(chip->ttf->step_chg_cfg); + chip->ttf->step_chg_cfg = NULL; + mutex_unlock(&chip->ttf->lock); + return rc; + } + + chip->ttf->step_chg_num_params = tuple_len; + chip->ttf->step_chg_cfg_valid = true; + mutex_unlock(&chip->ttf->lock); + + if (chip->ttf->step_chg_cfg_valid) { + for (i = 0; i < tuple_len; i++) + pr_debug("Vbatt_low: %d Vbatt_high: %d FCC: %d\n", + chip->ttf->step_chg_cfg[i].low_threshold, + chip->ttf->step_chg_cfg[i].high_threshold, + chip->ttf->step_chg_cfg[i].value); + } + } + data = of_get_property(profile_node, "qcom,fg-profile-data", &len); if (!data) { pr_err("No profile data available\n"); @@ -1493,6 +1553,7 @@ static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data) static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data) { struct fg_dev *fg = data; + struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); u8 status; int rc; @@ -1511,6 +1572,15 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data) fg->profile_load_status = PROFILE_NOT_LOADED; fg->soc_reporting_ready = false; fg->batt_id_ohms = -EINVAL; + + mutex_lock(&chip->ttf->lock); + chip->ttf->step_chg_cfg_valid = false; + chip->ttf->step_chg_num_params = 0; + kfree(chip->ttf->step_chg_cfg); + chip->ttf->step_chg_cfg = NULL; + kfree(chip->ttf->step_chg_data); + chip->ttf->step_chg_data = NULL; + mutex_unlock(&chip->ttf->lock); return IRQ_HANDLED; } -- GitLab From 2a3d83c1a1523aad7d3fd8e536cb858a88063c60 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Mon, 4 Jun 2018 19:43:38 -0600 Subject: [PATCH 0197/1299] net: qualcomm: rmnet: Fix use after free while sending command ack When sending an ack to a command packet, the skb is still referenced after it is sent to the real device. Since the real device could free the skb, the device pointer would be invalid. Also, remove an unnecessary variable. CRs-Fixed: 2233026 Change-Id: I79baf20b52a51041d2d1a4da73a70fb4b320544e Fixes: ceed73a2cf4a ("drivers: net: ethernet: qualcomm: rmnet: Initial implementation") Signed-off-by: David S. Miller Git-commit: 3602207ca6582dd359308b7bd2ce08348cc0854e Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c index 56a93df962e6..3ee8ae9b6838 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c @@ -67,7 +67,7 @@ static void rmnet_map_send_ack(struct sk_buff *skb, struct rmnet_port *port) { struct rmnet_map_control_command *cmd; - int xmit_status; + struct net_device *dev = skb->dev; if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) skb_trim(skb, @@ -78,9 +78,9 @@ static void rmnet_map_send_ack(struct sk_buff *skb, cmd = RMNET_MAP_GET_CMD_START(skb); cmd->cmd_type = type & 0x03; - netif_tx_lock(skb->dev); - xmit_status = skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev); - netif_tx_unlock(skb->dev); + netif_tx_lock(dev); + dev->netdev_ops->ndo_start_xmit(skb, dev); + netif_tx_unlock(dev); } /* Process MAP command frame and send N/ACK message as appropriate. Message cmd -- GitLab From 5d97fdb75a0dbdb71cc366b3da744868470f8e70 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Mon, 4 Jun 2018 23:37:53 +0530 Subject: [PATCH 0198/1299] ARM: dts: msm: add remote debugger support for sm8150 Add remote debugger device configuration. The Remote Debugger driver allows a debugger running on a host PC to communicate with a remote stub running on peripheral subsystems. Change-Id: I6a6c251ac7642af85dbd7374374c4a1adfb75b48 Acked-by: Chenna Kesava Raju Signed-off-by: Tharun Kumar Merugu --- arch/arm64/boot/dts/qcom/msm-rdbg.dtsi | 35 ++++++++++++++++++++++ arch/arm64/boot/dts/qcom/sm8150-smp2p.dtsi | 22 ++++++++++++++ arch/arm64/boot/dts/qcom/sm8150.dtsi | 1 + 3 files changed, 58 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/msm-rdbg.dtsi diff --git a/arch/arm64/boot/dts/qcom/msm-rdbg.dtsi b/arch/arm64/boot/dts/qcom/msm-rdbg.dtsi new file mode 100644 index 000000000000..426e105b0b87 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm-rdbg.dtsi @@ -0,0 +1,35 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + /* smp2p information */ + qcom,smp2p_interrupt_rdbg_2_out { + compatible = "qcom,smp2p-interrupt-rdbg-2-out"; + qcom,smem-states = <&smp2p_rdbg2_out 0>; + qcom,smem-state-names = "rdbg-smp2p-out"; + }; + qcom,smp2p_interrupt_rdbg_2_in { + compatible = "qcom,smp2p-interrupt-rdbg-2-in"; + interrupts-extended = <&smp2p_rdbg2_in 0 0>; + interrupt-names = "rdbg-smp2p-in"; + }; + qcom,smp2p_interrupt_rdbg_5_out { + compatible = "qcom,smp2p-interrupt-rdbg-5-out"; + qcom,smem-states = <&smp2p_rdbg5_out 0>; + qcom,smem-state-names = "rdbg-smp2p-out"; + }; + qcom,smp2p_interrupt_rdbg_5_in { + compatible = "qcom,smp2p-interrupt-rdbg-5-in"; + interrupts-extended = <&smp2p_rdbg5_in 0 0>; + interrupt-names = "rdbg-smp2p-in"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-smp2p.dtsi b/arch/arm64/boot/dts/qcom/sm8150-smp2p.dtsi index 212304295be9..64d4be3cf4c0 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-smp2p.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-smp2p.dtsi @@ -64,6 +64,17 @@ interrupt-controller; #interrupt-cells = <2>; }; + + smp2p_rdbg2_out: qcom,smp2p-rdbg2-out { + qcom,entry-name = "rdbg"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_rdbg2_in: qcom,smp2p-rdbg2-in { + qcom,entry-name = "rdbg"; + interrupt-controller; + #interrupt-cells = <2>; + }; }; qcom,smp2p-dsps@1799000c { @@ -109,6 +120,17 @@ interrupt-controller; #interrupt-cells = <2>; }; + + smp2p_rdbg5_out: qcom,smp2p-rdbg5-out { + qcom,entry-name = "rdbg"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_rdbg5_in: qcom,smp2p-rdbg5-in { + qcom,entry-name = "rdbg"; + interrupt-controller; + #interrupt-cells = <2>; + }; }; /* wlan - inbound entry from mss/WLAN PD */ diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index 9ebd06d7773a..5b0065081fbd 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -770,6 +770,7 @@ #include "sm8150-sde-pll.dtsi" #include "sm8150-sde.dtsi" +#include "msm-rdbg.dtsi" #include "sm8150-camera.dtsi" -- GitLab From 25b4778d6f4e0696eb77fecdcba0291b64aef231 Mon Sep 17 00:00:00 2001 From: Jayant Shekhar Date: Wed, 13 Jun 2018 11:25:18 +0530 Subject: [PATCH 0199/1299] defconfig: qcs405: Enable LED class config Enable LED class config which are used by display framebuffer driver. Change-Id: Ibbb914f3d0845e057c802e526b7f8212e50e9841 Signed-off-by: Jayant Shekhar --- arch/arm/configs/qcs405_defconfig | 3 +++ arch/arm64/configs/qcs405_defconfig | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/arm/configs/qcs405_defconfig b/arch/arm/configs/qcs405_defconfig index 3196dbd9f27e..3d153143d105 100644 --- a/arch/arm/configs/qcs405_defconfig +++ b/arch/arm/configs/qcs405_defconfig @@ -360,6 +360,9 @@ CONFIG_MMC_CLKGATE=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_MSM=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_QPNP=y CONFIG_DMADEVICES=y diff --git a/arch/arm64/configs/qcs405_defconfig b/arch/arm64/configs/qcs405_defconfig index 097c0b790c1e..d91e809a1ca2 100644 --- a/arch/arm64/configs/qcs405_defconfig +++ b/arch/arm64/configs/qcs405_defconfig @@ -361,6 +361,9 @@ CONFIG_MMC_CLKGATE=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_MSM=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_QPNP=y CONFIG_DMADEVICES=y -- GitLab From da12fc7c1b5995b75da3d5417134e822d1856b32 Mon Sep 17 00:00:00 2001 From: Jayant Shekhar Date: Wed, 13 Jun 2018 11:26:34 +0530 Subject: [PATCH 0200/1299] fbdev: msm: Enable led class apis in framebuffer driver Enable apis which are is used for backlight by display framebuffer driver. Change-Id: I63f970e25089ad1da4504b8b46910b42e9f91bfa Signed-off-by: Jayant Shekhar --- drivers/video/fbdev/msm/mdss_fb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 52159abf64b3..b5a858d3fdf4 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -1329,7 +1329,10 @@ static int mdss_fb_probe(struct platform_device *pdev) if (!lcd_backlight_registered) { backlight_led.brightness = mfd->panel_info->brightness_max; backlight_led.max_brightness = mfd->panel_info->brightness_max; - lcd_backlight_registered = 1; + if (led_classdev_register(&pdev->dev, &backlight_led)) + pr_err("led_classdev_register failed\n"); + else + lcd_backlight_registered = 1; } mdss_fb_init_panel_modes(mfd, pdata); @@ -1426,6 +1429,7 @@ static int mdss_fb_remove(struct platform_device *pdev) if (lcd_backlight_registered) { lcd_backlight_registered = 0; + led_classdev_unregister(&backlight_led); } return 0; -- GitLab From bfe939efc9a27288b274cd331ecc00556c0d06f5 Mon Sep 17 00:00:00 2001 From: Saranya Chidura Date: Wed, 13 Jun 2018 12:16:15 +0530 Subject: [PATCH 0201/1299] ARM: dts: msm: add TMC buffer reset support for qcs405 Add cti0 for TMC-ETR/ETF node to support the CTI trigger on buffer full for qcs405. Change-Id: I8a45402b2594d88fa494b4e51d05ddb94529cafa Signed-off-by: Saranya Chidura --- arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi b/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi index c4dc6cb25d89..9cb4826f6eb1 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi @@ -72,7 +72,7 @@ arm,buffer-size = <0x400000>; coresight-name = "coresight-tmc-etr"; - coresight-ctis = <&cti0>; + coresight-ctis = <&cti0 &cti0>; coresight-csr = <&csr>; clocks = <&clock_rpmcc RPM_QDSS_CLK>, @@ -98,7 +98,7 @@ reg-names = "tmc-base"; coresight-name = "coresight-tmc-etf"; - coresight-ctis = <&cti0>; + coresight-ctis = <&cti0 &cti0>; arm,default-sink; coresight-csr = <&csr>; -- GitLab From 279a71e92efd6388d46c2985096ee616d16a8eae Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Mon, 4 Jun 2018 15:53:33 +0530 Subject: [PATCH 0202/1299] f_gsi: Bail out if suspend event is pending before enabling data path When cable is connected, following sequence is expected to happen: set_alt() ->ipa_connect_channels()->ipa_data_path(). As part of ipa_data_path(), endpoints will be enabled and start ringing Doorbell to GSI. If suspend interrupt is received after this, it stops ringing Doorbell to GSI and suspends path to GSI by calling xdci_suspend(). If suspend is received before enablement of data path as part of connect handling, driver does enable GSI endpoints and starts ringing Doorbell to GSI. This is not expected and resulting in USB controller accessing invalid memory and causing SMMU fault. Fix it by bailing out data path enablement if suspend event is pending. Change-Id: I1603e4c675f85abff284c385c96230f1fb54231e Signed-off-by: Vijayavardhan Vennapusa --- drivers/usb/gadget/function/f_gsi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index e8b96378a50d..177b7b85326c 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -676,6 +676,11 @@ static void ipa_work_handler(struct work_struct *w) log_event_dbg("%s: ST_CON_IN_PROG_EVT_HOST_READY", __func__); } else if (event == EVT_CONNECTED) { + if (peek_event(d_port) == EVT_SUSPEND) { + log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUSPEND", + __func__); + break; + } ipa_data_path_enable(d_port); d_port->sm_state = STATE_CONNECTED; log_event_dbg("%s: ST_CON_IN_PROG_EVT_CON %d", -- GitLab From 96b0ea907a1cd3b2abd41105defaea032fcdf295 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Wed, 13 Jun 2018 11:45:15 +0300 Subject: [PATCH 0203/1299] msm: gsi: add support for h/w smart prefetch Adding H/W smart prefetch mode support to GSI 2.5. CRs-Fixed: 2258741 Change-Id: I35144b75b806223798bb06f37a05736f65f58ef2 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/gsi/gsi.c | 67 ++++++++++++++++++++++++------ drivers/platform/msm/gsi/gsi_dbg.c | 9 +++- drivers/platform/msm/gsi/gsi_reg.h | 14 +++++++ include/linux/msm_gsi.h | 19 ++++++++- 4 files changed, 93 insertions(+), 16 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index b0415234659c..44e6f56c1ab8 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -1623,6 +1623,56 @@ int gsi_set_evt_ring_cfg(unsigned long evt_ring_hdl, } EXPORT_SYMBOL(gsi_set_evt_ring_cfg); +static void gsi_program_chan_ctx_qos(struct gsi_chan_props *props, + unsigned int ee) +{ + uint32_t val; + + val = + (((props->low_weight << + GSI_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_SHFT) & + GSI_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_BMSK) | + ((props->max_prefetch << + GSI_EE_n_GSI_CH_k_QOS_MAX_PREFETCH_SHFT) & + GSI_EE_n_GSI_CH_k_QOS_MAX_PREFETCH_BMSK) | + ((props->use_db_eng << + GSI_EE_n_GSI_CH_k_QOS_USE_DB_ENG_SHFT) & + GSI_EE_n_GSI_CH_k_QOS_USE_DB_ENG_BMSK)); + if (gsi_ctx->per.ver >= GSI_VER_2_0) + val |= ((props->prefetch_mode << + GSI_EE_n_GSI_CH_k_QOS_USE_ESCAPE_BUF_ONLY_SHFT) + & GSI_EE_n_GSI_CH_k_QOS_USE_ESCAPE_BUF_ONLY_BMSK); + + gsi_writel(val, gsi_ctx->base + + GSI_EE_n_GSI_CH_k_QOS_OFFS(props->ch_id, ee)); +} + +static void gsi_program_chan_ctx_qos_v2_5(struct gsi_chan_props *props, + unsigned int ee) +{ + uint32_t val; + + val = + (((props->low_weight << + GSI_V2_5_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_SHFT) & + GSI_V2_5_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_BMSK) | + ((props->max_prefetch << + GSI_V2_5_EE_n_GSI_CH_k_QOS_MAX_PREFETCH_SHFT) & + GSI_V2_5_EE_n_GSI_CH_k_QOS_MAX_PREFETCH_BMSK) | + ((props->use_db_eng << + GSI_V2_5_EE_n_GSI_CH_k_QOS_USE_DB_ENG_SHFT) & + GSI_V2_5_EE_n_GSI_CH_k_QOS_USE_DB_ENG_BMSK) | + ((props->prefetch_mode << + GSI_V2_5_EE_n_GSI_CH_k_QOS_PREFETCH_MODE_SHFT) & + GSI_V2_5_EE_n_GSI_CH_k_QOS_PREFETCH_MODE_BMSK) | + ((props->empty_lvl_threshold << + GSI_V2_5_EE_n_GSI_CH_k_QOS_EMPTY_LVL_THRSHOLD_SHFT) & + GSI_V2_5_EE_n_GSI_CH_k_QOS_EMPTY_LVL_THRSHOLD_BMSK)); + + gsi_writel(val, gsi_ctx->base + + GSI_V2_5_EE_n_GSI_CH_k_QOS_OFFS(props->ch_id, ee)); +} + static void gsi_program_chan_ctx(struct gsi_chan_props *props, unsigned int ee, uint8_t erindex) { @@ -1656,19 +1706,10 @@ static void gsi_program_chan_ctx(struct gsi_chan_props *props, unsigned int ee, gsi_writel(val, gsi_ctx->base + GSI_EE_n_GSI_CH_k_CNTXT_3_OFFS(props->ch_id, ee)); - val = (((props->low_weight << GSI_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_SHFT) & - GSI_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_BMSK) | - ((props->max_prefetch << - GSI_EE_n_GSI_CH_k_QOS_MAX_PREFETCH_SHFT) & - GSI_EE_n_GSI_CH_k_QOS_MAX_PREFETCH_BMSK) | - ((props->use_db_eng << GSI_EE_n_GSI_CH_k_QOS_USE_DB_ENG_SHFT) & - GSI_EE_n_GSI_CH_k_QOS_USE_DB_ENG_BMSK)); - if (gsi_ctx->per.ver >= GSI_VER_2_0) - val |= ((props->prefetch_mode << - GSI_EE_n_GSI_CH_k_QOS_USE_ESCAPE_BUF_ONLY_SHFT) - & GSI_EE_n_GSI_CH_k_QOS_USE_ESCAPE_BUF_ONLY_BMSK); - gsi_writel(val, gsi_ctx->base + - GSI_EE_n_GSI_CH_k_QOS_OFFS(props->ch_id, ee)); + if (gsi_ctx->per.ver >= GSI_VER_2_5) + gsi_program_chan_ctx_qos_v2_5(props, ee); + else + gsi_program_chan_ctx_qos(props, ee); } static void gsi_init_chan_ring(struct gsi_chan_props *props, diff --git a/drivers/platform/msm/gsi/gsi_dbg.c b/drivers/platform/msm/gsi/gsi_dbg.c index bd288b9ce949..dab8dc29e20b 100644 --- a/drivers/platform/msm/gsi/gsi_dbg.c +++ b/drivers/platform/msm/gsi/gsi_dbg.c @@ -220,8 +220,13 @@ static ssize_t gsi_dump_ch(struct file *file, GSI_EE_n_GSI_CH_k_RE_FETCH_WRITE_PTR_OFFS(arg1, gsi_ctx->per.ee)); TERR("CH%2d REFWP 0x%x\n", arg1, val); - val = gsi_readl(gsi_ctx->base + - GSI_EE_n_GSI_CH_k_QOS_OFFS(arg1, gsi_ctx->per.ee)); + if (gsi_ctx->per.ver >= GSI_VER_2_5) { + val = gsi_readl(gsi_ctx->base + + GSI_V2_5_EE_n_GSI_CH_k_QOS_OFFS(arg1, gsi_ctx->per.ee)); + } else { + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_QOS_OFFS(arg1, gsi_ctx->per.ee)); + } TERR("CH%2d QOS 0x%x\n", arg1, val); val = gsi_readl(gsi_ctx->base + GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(arg1, gsi_ctx->per.ee)); diff --git a/drivers/platform/msm/gsi/gsi_reg.h b/drivers/platform/msm/gsi/gsi_reg.h index e332bf274ec2..a9adbb1cde78 100644 --- a/drivers/platform/msm/gsi/gsi_reg.h +++ b/drivers/platform/msm/gsi/gsi_reg.h @@ -1144,6 +1144,20 @@ #define GSI_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_BMSK 0xf #define GSI_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_SHFT 0x0 +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_OFFS(k, n) \ + (GSI_GSI_REG_BASE_OFFS + 0x0000f05c + 0x4000 * (n) + 0x80 * (k)) +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_EMPTY_LVL_THRSHOLD_BMSK 0xff0000 +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_EMPTY_LVL_THRSHOLD_SHFT 0x10 +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_PREFETCH_MODE_BMSK 0x3c00 +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_PREFETCH_MODE_SHFT 0xa +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_USE_DB_ENG_BMSK 0x200 +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_USE_DB_ENG_SHFT 0x9 +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_MAX_PREFETCH_BMSK 0x100 +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_MAX_PREFETCH_SHFT 0x8 +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_BMSK 0xf +#define GSI_V2_5_EE_n_GSI_CH_k_QOS_WRR_WEIGHT_SHFT 0x0 + + #define GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c060 + 0x4000 * (n) + 0x80 * (k)) #define GSI_EE_n_GSI_CH_k_SCRATCH_0_RMSK 0xffffffff diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h index fe8a7138e5fe..f0994b3c3acb 100644 --- a/include/linux/msm_gsi.h +++ b/include/linux/msm_gsi.h @@ -221,9 +221,19 @@ enum gsi_max_prefetch { GSI_TWO_PREFETCH_SEG = 0x1 }; +/** + * @GSI_USE_PREFETCH_BUFS: Channel will use normal prefetch buffers if possible + * @GSI_ESCAPE_BUF_ONLY: Channel will always use escape buffers only + * @GSI_SMART_PRE_FETCH: Channel will work in smart prefetch mode. + * relevant starting GSI 2.5 + * @GSI_FREE_PRE_FETCH: Channel will work in free prefetch mode. + * relevant starting GSI 2.5 + */ enum gsi_prefetch_mode { GSI_USE_PREFETCH_BUFS = 0x0, - GSI_ESCAPE_BUF_ONLY = 0x1 + GSI_ESCAPE_BUF_ONLY = 0x1, + GSI_SMART_PRE_FETCH = 0x2, + GSI_FREE_PRE_FETCH = 0x3, }; enum gsi_chan_evt { @@ -315,6 +325,12 @@ enum gsi_chan_use_db_eng { * @max_prefetch: limit number of pre-fetch segments for channel * @low_weight: low channel weight (priority of channel for RE engine * round robin algorithm); must be >= 1 + * @empty_lvl_threshold: + * The thershold number of free entries available in the + * receiving fifos of GSI-peripheral. If Smart PF mode + * is used, REE will fetch/send new TRE to peripheral only + * if peripheral's empty_level_count is higher than + * EMPTY_LVL_THRSHOLD defined for this channel * @xfer_cb: transfer notification callback, this callback happens * on event boundaries * @@ -365,6 +381,7 @@ struct gsi_chan_props { enum gsi_max_prefetch max_prefetch; uint8_t low_weight; enum gsi_prefetch_mode prefetch_mode; + uint8_t empty_lvl_threshold; void (*xfer_cb)(struct gsi_chan_xfer_notify *notify); void (*err_cb)(struct gsi_chan_err_notify *notify); void *chan_user_data; -- GitLab From 6dee0129d19d1df75f5d6982f59af049088a2711 Mon Sep 17 00:00:00 2001 From: Jayant Shekhar Date: Wed, 13 Jun 2018 11:51:59 +0530 Subject: [PATCH 0204/1299] fbdev: msm: Fix 32 bit compilation on qcs405 Fix compilation issue in display framebuffer driver for qcs405 target. Change-Id: Ib764860294462badff15c2ebe4d5c266b7f6319e Signed-off-by: Jayant Shekhar --- drivers/video/fbdev/msm/mdss_mdp_overlay.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 64b420e44455..44c63aa8f173 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -59,6 +59,7 @@ #define DFPS_DATA_MAX_FPS 0x7fffffff #define DFPS_DATA_MAX_CLK_RATE 250000 +struct mdp_overlay tmp; static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd); static int mdss_mdp_overlay_fb_parse_dt(struct msm_fb_data_type *mfd); static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd); @@ -5354,7 +5355,9 @@ static int __mdss_overlay_map(struct mdp_overlay *ovs, static inline void __overlay_swap_func(void *a, void *b, int size) { - swap(*(struct mdp_overlay *)a, *(struct mdp_overlay *)b); + tmp = *(struct mdp_overlay *)a; + *(struct mdp_overlay *)a = *(struct mdp_overlay *)b; + *(struct mdp_overlay *)b = tmp; } static inline int __zorder_dstx_cmp_func(const void *a, const void *b) -- GitLab From bda41cddabb529418c8e4dabf4bed0781d65ddfb Mon Sep 17 00:00:00 2001 From: Mulu He Date: Fri, 8 Jun 2018 11:21:10 +0800 Subject: [PATCH 0205/1299] coresight: stm: Out of bound access from STM The memory size allocated for stm_master is less than it's defined. Change-Id: Ia913ac899c069383cff498b03815d985dacacdf4 Signed-off-by: Mulu He --- drivers/hwtracing/stm/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c index fedbaa9733cb..24be5a8454ac 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -175,8 +175,9 @@ static int stp_master_alloc(struct stm_device *stm, unsigned int idx) { struct stp_master *master; size_t size; + unsigned long align = sizeof(unsigned long); - size = ALIGN(stm->data->sw_nchannels, 8) / 8; + size = ALIGN(stm->data->sw_nchannels, align) / align; size += sizeof(struct stp_master); master = kzalloc(size, GFP_ATOMIC); if (!master) -- GitLab From c53c792612734696645eec03e7cc5e8f4955cc3d Mon Sep 17 00:00:00 2001 From: sssanjee Date: Wed, 13 Jun 2018 15:06:39 +0530 Subject: [PATCH 0206/1299] msm: fastcvpd: removing spin_lock around hyp_assign Removing spin_lock around hyp_assign since hyp_assign will call kmalloc and block spin_lock for longer duration. Change-Id: I98a4aecc577102c0e8a422eee1f72cec1f949391 Acked-by: Abhikrant Sharma Signed-off-by: Suman Voora --- drivers/char/fastcvpd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/char/fastcvpd.c b/drivers/char/fastcvpd.c index 279fc71b53a7..202d4404a550 100644 --- a/drivers/char/fastcvpd.c +++ b/drivers/char/fastcvpd.c @@ -184,7 +184,7 @@ EXPORT_SYMBOL(fastcvpd_video_resume); int fastcvpd_video_shutdown(uint32_t session_flag) { struct fastcvpd_apps *me = &gfa_cv; - int err; + int err, local_cmd_msg_rsp; struct fastcvpd_cmd_msg local_cmd_msg; int srcVM[DEST_VM_NUM] = {VMID_HLOS, VMID_CDSP_Q6}; int destVM[SRC_VM_NUM] = {VMID_HLOS}; @@ -202,21 +202,21 @@ int fastcvpd_video_shutdown(uint32_t session_flag) spin_lock(&me->hlock); local_cmd_msg.msg_ptr = cmd_msg.msg_ptr; local_cmd_msg.msg_ptr_len = cmd_msg.msg_ptr_len; - if (cmd_msg_rsp.ret_val == 0) { + local_cmd_msg_rsp = cmd_msg_rsp.ret_val; + spin_unlock(&me->hlock); + if (local_cmd_msg_rsp == 0) { err = hyp_assign_phys((uint64_t)local_cmd_msg.msg_ptr, local_cmd_msg.msg_ptr_len, srcVM, DEST_VM_NUM, destVM, destVMperm, SRC_VM_NUM); if (err) { pr_err("%s: Failed to hyp_assign. err=%d\n", __func__, err); - spin_unlock(&me->hlock); return err; } } else { pr_err("%s: Skipping hyp_assign as CDSP sent invalid response=%d\n", __func__, cmd_msg_rsp.ret_val); } - spin_unlock(&me->hlock); return err; } -- GitLab From a2f12fa986888caeece8712ec3dac2fb9c0bf6a8 Mon Sep 17 00:00:00 2001 From: Lingutla Chandrasekhar Date: Mon, 11 Jun 2018 16:56:00 +0530 Subject: [PATCH 0207/1299] defconfig: msm: Enable energy aware scheduler for qcs405 target Enable EAS scheduler for qcs405 target and also enable schedutil governor for cpu frequency scaling for both 64-bit and 32-bit. Change-Id: I0a393123253257200ec0e9c0f97dd190c884a8b1 Signed-off-by: Lingutla Chandrasekhar --- arch/arm/configs/qcs405_defconfig | 2 ++ arch/arm64/configs/qcs405_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/configs/qcs405_defconfig b/arch/arm/configs/qcs405_defconfig index b6ee98ca78ef..195ec259b907 100644 --- a/arch/arm/configs/qcs405_defconfig +++ b/arch/arm/configs/qcs405_defconfig @@ -16,6 +16,7 @@ CONFIG_CGROUP_DEBUG=y CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set +CONFIG_DEFAULT_USE_ENERGY_AWARE=y CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS_ALL=y @@ -41,6 +42,7 @@ CONFIG_CMA_DEBUGFS=y CONFIG_ZSMALLOC=y CONFIG_SECCOMP=y CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y CONFIG_CPU_IDLE=y CONFIG_VFP=y CONFIG_NEON=y diff --git a/arch/arm64/configs/qcs405_defconfig b/arch/arm64/configs/qcs405_defconfig index 903254566905..57dca2656eb7 100644 --- a/arch/arm64/configs/qcs405_defconfig +++ b/arch/arm64/configs/qcs405_defconfig @@ -16,6 +16,7 @@ CONFIG_CGROUP_DEBUG=y CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set +CONFIG_DEFAULT_USE_ENERGY_AWARE=y CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS_ALL=y @@ -49,6 +50,7 @@ CONFIG_PM_DEBUG=y CONFIG_CPU_IDLE=y CONFIG_ARM_CPUIDLE=y CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y -- GitLab From a849d364ebf96e1896b69ff5d76ed264874ee004 Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Mon, 11 Jun 2018 15:06:59 -0400 Subject: [PATCH 0208/1299] ARM: dts: Update NPU clocks for sm8150 Update NPU clocks to enable ati/apb/atp clocks. Change-Id: Ic578c1f64a8efa8c8a2d98dbcc802dda424f67f0 Signed-off-by: Jilai Wang --- arch/arm64/boot/dts/qcom/sm8150-npu.dtsi | 288 +++++++++++------------ 1 file changed, 144 insertions(+), 144 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi b/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi index fd99bfeb4482..d006daa38f95 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi @@ -24,43 +24,43 @@ cache-slice-names = "npu"; cache-slices = <&llcc 23>; clocks = <&clock_npucc NPU_CC_CAL_DP_CLK>, - <&clock_npucc NPU_CC_CAL_DP_CLK_SRC>, - <&clock_npucc NPU_CC_XO_CLK>, - <&clock_npucc NPU_CC_ARMWIC_CORE_CLK>, - <&clock_npucc NPU_CC_BTO_CORE_CLK>, - <&clock_npucc NPU_CC_BWMON_CLK>, - <&clock_npucc NPU_CC_CAL_DP_CDC_CLK>, - <&clock_npucc NPU_CC_COMP_NOC_AXI_CLK>, - <&clock_npucc NPU_CC_CONF_NOC_AHB_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_APB_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_ATB_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_CLK_SRC>, - <&clock_npucc NPU_CC_NPU_CORE_CTI_CLK>, - <&clock_npucc NPU_CC_NPU_CPC_CLK>, - <&clock_npucc NPU_CC_NPU_CPC_TIMER_CLK>, - <&clock_npucc NPU_CC_PERF_CNT_CLK>, - <&clock_npucc NPU_CC_QTIMER_CORE_CLK>, - <&clock_npucc NPU_CC_SLEEP_CLK>; + <&clock_npucc NPU_CC_XO_CLK>, + <&clock_npucc NPU_CC_ARMWIC_CORE_CLK>, + <&clock_npucc NPU_CC_BTO_CORE_CLK>, + <&clock_npucc NPU_CC_BWMON_CLK>, + <&clock_npucc NPU_CC_CAL_DP_CDC_CLK>, + <&clock_npucc NPU_CC_COMP_NOC_AXI_CLK>, + <&clock_npucc NPU_CC_CONF_NOC_AHB_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_APB_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_ATB_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_CTI_CLK>, + <&clock_npucc NPU_CC_NPU_CPC_CLK>, + <&clock_npucc NPU_CC_NPU_CPC_TIMER_CLK>, + <&clock_npucc NPU_CC_PERF_CNT_CLK>, + <&clock_npucc NPU_CC_QTIMER_CORE_CLK>, + <&clock_npucc NPU_CC_SLEEP_CLK>, + <&clock_gcc GCC_NPU_AT_CLK>, + <&clock_gcc GCC_NPU_TRIG_CLK>; clock-names = "cal_dp_clk", - "cal_dp_clk_src", - "xo_clk", - "armwic_core_clk", - "bto_core_clk", - "bwmon_clk", - "cal_dp_cdc_clk", - "comp_noc_axi_clk", - "conf_noc_ahb_clk", - "npu_core_apb_clk", - "npu_core_atb_clk", - "npu_core_clk", - "npu_core_clk_src", - "npu_core_cti_clk", - "npu_cpc_clk", - "npu_cpc_timer_clk", - "perf_cnt_clk", - "qtimer_core_clk", - "sleep_clk"; + "xo_clk", + "armwic_core_clk", + "bto_core_clk", + "bwmon_clk", + "cal_dp_cdc_clk", + "comp_noc_axi_clk", + "conf_noc_ahb_clk", + "npu_core_apb_clk", + "npu_core_atb_clk", + "npu_core_clk", + "npu_core_cti_clk", + "npu_cpc_clk", + "npu_cpc_timer_clk", + "perf_cnt_clk", + "qtimer_core_clk", + "sleep_clk", + "at_clk", + "trig_clk"; vdd-supply = <&npu_core_gdsc>; vdd_cx-supply = <&VDD_CX_LEVEL>; qcom,proxy-reg-names ="vdd", "vdd_cx"; @@ -77,134 +77,134 @@ qcom,npu-pwrlevel@0 { reg = <0>; clk-freq = <9600000 - 9600000 - 19200000 - 19200000 - 19200000 - 19200000 - 9600000 - 60000000 - 19200000 - 19200000 - 30000000 - 19200000 - 19200000 - 19200000 - 19200000 - 19200000 - 9600000 - 19200000 - 0>; + 19200000 + 19200000 + 19200000 + 19200000 + 9600000 + 60000000 + 19200000 + 19200000 + 30000000 + 19200000 + 19200000 + 19200000 + 19200000 + 9600000 + 19200000 + 0 + 0 + 0>; }; qcom,npu-pwrlevel@1 { reg = <1>; clk-freq = <300000000 - 300000000 - 19200000 - 100000000 - 19200000 - 19200000 - 300000000 - 150000000 - 19200000 - 19200000 - 60000000 - 100000000 - 100000000 - 37500000 - 100000000 - 19200000 - 300000000 - 19200000 - 0>; + 19200000 + 100000000 + 19200000 + 19200000 + 300000000 + 150000000 + 19200000 + 19200000 + 60000000 + 100000000 + 37500000 + 100000000 + 19200000 + 300000000 + 19200000 + 0 + 0 + 0>; }; qcom,npu-pwrlevel@2 { reg = <2>; clk-freq = <350000000 - 350000000 - 19200000 - 150000000 - 19200000 - 19200000 - 350000000 - 200000000 - 37500000 - 19200000 - 120000000 - 150000000 - 150000000 - 75000000 - 150000000 - 19200000 - 350000000 - 19200000 - 0>; + 19200000 + 150000000 + 19200000 + 19200000 + 350000000 + 200000000 + 37500000 + 19200000 + 120000000 + 150000000 + 75000000 + 150000000 + 19200000 + 350000000 + 19200000 + 0 + 0 + 0>; }; qcom,npu-pwrlevel@3 { reg = <3>; clk-freq = <400000000 - 400000000 - 19200000 - 200000000 - 19200000 - 19200000 - 400000000 - 300000000 - 37500000 - 19200000 - 120000000 - 200000000 - 200000000 - 75000000 - 200000000 - 19200000 - 400000000 - 19200000 - 0>; + 19200000 + 200000000 + 19200000 + 19200000 + 400000000 + 300000000 + 37500000 + 19200000 + 120000000 + 200000000 + 75000000 + 200000000 + 19200000 + 400000000 + 19200000 + 0 + 0 + 0>; }; qcom,npu-pwrlevel@4 { reg = <4>; clk-freq = <600000000 - 600000000 - 19200000 - 300000000 - 19200000 - 19200000 - 600000000 - 403000000 - 75000000 - 19200000 - 240000000 - 300000000 - 300000000 - 150000000 - 300000000 - 19200000 - 600000000 - 19200000 - 0>; + 19200000 + 300000000 + 19200000 + 19200000 + 600000000 + 403000000 + 75000000 + 19200000 + 240000000 + 300000000 + 150000000 + 300000000 + 19200000 + 600000000 + 19200000 + 0 + 0 + 0>; }; qcom,npu-pwrlevel@5 { reg = <5>; clk-freq = <715000000 - 715000000 - 19200000 - 350000000 - 19200000 - 19200000 - 715000000 - 533000000 - 75000000 - 19200000 - 240000000 - 350000000 - 350000000 - 150000000 - 350000000 - 19200000 - 715000000 - 19200000 - 0>; + 19200000 + 350000000 + 19200000 + 19200000 + 715000000 + 533000000 + 75000000 + 19200000 + 240000000 + 350000000 + 150000000 + 350000000 + 19200000 + 715000000 + 19200000 + 0 + 0 + 0>; }; }; }; -- GitLab From 04ff63a396d99ab676186c2718581bb27771d7d3 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 29 May 2018 13:11:05 +0100 Subject: [PATCH 0209/1299] arm/arm64: smccc: Add SMCCC-specific return codes We've so far used the PSCI return codes for SMCCC because they were extremely similar. But with the new ARM DEN 0070A specification, "NOT_REQUIRED" (-2) is clashing with PSCI's "PSCI_RET_INVALID_PARAMS". Let's bite the bullet and add SMCCC specific return codes. Users can be repainted as and when required. Change-Id: Ia19dc183a646858569df488d8299d94f6429848a Acked-by: Will Deacon Reviewed-by: Mark Rutland Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: eff0e9e1078ea7dc1d794dc50e31baef984c46d7 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Isaac J. Manjarres --- include/linux/arm-smccc.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 43690f501712..00a88b9f5ce1 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -293,5 +293,10 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, */ #define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__) +/* Return codes defined in ARM DEN 0070A */ +#define SMCCC_RET_SUCCESS 0 +#define SMCCC_RET_NOT_SUPPORTED -1 +#define SMCCC_RET_NOT_REQUIRED -2 + #endif /*__ASSEMBLY__*/ #endif /*__LINUX_ARM_SMCCC_H*/ -- GitLab From f045269b5a597be78d39e9950ff6d1f063bd4681 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 29 May 2018 13:11:06 +0100 Subject: [PATCH 0210/1299] arm64: Call ARCH_WORKAROUND_2 on transitions between EL0 and EL1 In order for the kernel to protect itself, let's call the SSBD mitigation implemented by the higher exception level (either hypervisor or firmware) on each transition between userspace and kernel. We must take the PSCI conduit into account in order to target the right exception level, hence the introduction of a runtime patching callback. Change-Id: Ic4cc012d804dd0c68b557ba58e34e1b8031f1ae2 Reviewed-by: Mark Rutland Reviewed-by: Julien Grall Acked-by: Will Deacon Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: 8e2906245f1e3b0d027169d9f2e55ce0548cb96e Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [isaacm@codeaurora.org: remove code for alternative_cb, as that is not present. Instead, since the psci conduit is smc, replace the alternative_cb reference with the smc call it would be anyway.] Signed-off-by: Isaac J. Manjarres --- arch/arm64/kernel/entry.S | 20 ++++++++++++++++++++ include/linux/arm-smccc.h | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 93958d1341bb..20e95a24b24b 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +#include #include #include @@ -137,6 +138,16 @@ alternative_else_nop_endif add \dst, \dst, #(\sym - .entry.tramp.text) .endm + // This macro corrupts x0-x3. It is the caller's duty + // to save/restore them if required. + .macro apply_ssbd, state +#ifdef CONFIG_ARM64_SSBD + mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 + mov w1, #\state + smc #0 +#endif + .endm + .macro kernel_entry, el, regsize = 64 .if \regsize == 32 mov w0, w0 // zero upper 32 bits of x0 @@ -163,6 +174,13 @@ alternative_else_nop_endif ldr x19, [tsk, #TSK_TI_FLAGS] // since we can unmask debug disable_step_tsk x19, x20 // exceptions when scheduling. + apply_ssbd 1 + +#ifdef CONFIG_ARM64_SSBD + ldp x0, x1, [sp, #16 * 0] + ldp x2, x3, [sp, #16 * 1] +#endif + mov x29, xzr // fp pointed to user-space .else add x21, sp, #S_FRAME_SIZE @@ -301,6 +319,8 @@ alternative_if ARM64_WORKAROUND_845719 alternative_else_nop_endif #endif 3: + apply_ssbd 0 + .endif msr elr_el1, x21 // set up the return data diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 00a88b9f5ce1..43072b1fde0c 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -80,6 +80,11 @@ ARM_SMCCC_SMC_32, \ 0, 0x8000) +#define ARM_SMCCC_ARCH_WORKAROUND_2 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 0x7fff) + #ifndef __ASSEMBLY__ #include -- GitLab From 5bd92949770b258cd3157d519a0d35b16e1a737c Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 29 May 2018 13:11:07 +0100 Subject: [PATCH 0211/1299] arm64: Add per-cpu infrastructure to call ARCH_WORKAROUND_2 In a heterogeneous system, we can end up with both affected and unaffected CPUs. Let's check their status before calling into the firmware. Change-Id: Ie938e9c0ec0ae85e070c3a80d9b6043208471edb Reviewed-by: Julien Grall Reviewed-by: Mark Rutland Acked-by: Will Deacon Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: 5cf9ce6e5ea50f805c6188c04ed0daaec7b6887d Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [isaacm@codeaurora.org: define per cpu var only when ssbd config option is set.] Signed-off-by: Isaac J. Manjarres --- arch/arm64/kernel/cpu_errata.c | 4 ++++ arch/arm64/kernel/entry.S | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index b5a28336c077..1bb6452f194c 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -228,6 +228,10 @@ static int qcom_enable_link_stack_sanitization(void *data) } #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ +#ifdef CONFIG_ARM64_SSBD +DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required); +#endif /* CONFIG_ARM64_SSBD */ + #define MIDR_RANGE(model, min, max) \ .def_scope = SCOPE_LOCAL_CPU, \ .matches = is_affected_midr_range, \ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 20e95a24b24b..d093d47e3d03 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -140,8 +140,10 @@ alternative_else_nop_endif // This macro corrupts x0-x3. It is the caller's duty // to save/restore them if required. - .macro apply_ssbd, state + .macro apply_ssbd, state, targ, tmp1, tmp2 #ifdef CONFIG_ARM64_SSBD + ldr_this_cpu \tmp2, arm64_ssbd_callback_required, \tmp1 + cbz \tmp2, \targ mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 mov w1, #\state smc #0 @@ -174,12 +176,13 @@ alternative_else_nop_endif ldr x19, [tsk, #TSK_TI_FLAGS] // since we can unmask debug disable_step_tsk x19, x20 // exceptions when scheduling. - apply_ssbd 1 + apply_ssbd 1, 1f, x22, x23 #ifdef CONFIG_ARM64_SSBD ldp x0, x1, [sp, #16 * 0] ldp x2, x3, [sp, #16 * 1] #endif +1: mov x29, xzr // fp pointed to user-space .else @@ -319,8 +322,8 @@ alternative_if ARM64_WORKAROUND_845719 alternative_else_nop_endif #endif 3: - apply_ssbd 0 - + apply_ssbd 0, 5f, x0, x1 +5: .endif msr elr_el1, x21 // set up the return data -- GitLab From cf4ca60c16c106be2a10ce74b62bcab6bcfba2f4 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 29 May 2018 13:11:08 +0100 Subject: [PATCH 0212/1299] arm64: Add ARCH_WORKAROUND_2 probing As for Spectre variant-2, we rely on SMCCC 1.1 to provide the discovery mechanism for detecting the SSBD mitigation. A new capability is also allocated for that purpose, and a config option. Change-Id: Ibf7a217bb6ecf796e50f79c2681de094f1caaa8e Reviewed-by: Julien Grall Reviewed-by: Mark Rutland Acked-by: Will Deacon Reviewed-by: Suzuki K Poulose Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: a725e3dda1813ed306734823ac4c65ca04e38500 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [isaacm@codeaurora.org: Move inclusion of psci header and arm-smccc header to beginning of source to not break compilation, and use correct capability numbers and structure fields. Also, disable SSBD mitigation for the time being.] Signed-off-by: Isaac J. Manjarres --- arch/arm64/Kconfig | 8 ++++ arch/arm64/include/asm/cpucaps.h | 3 +- arch/arm64/kernel/cpu_errata.c | 73 +++++++++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index c05aa8ad7bdf..c05f6decafbd 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -942,6 +942,14 @@ config PRINT_VMEMLAYOUT If unsure, say N. +config ARM64_SSBD + bool "Speculative Store Bypass Disable" if EXPERT + help + This enables mitigation of the bypassing of previous stores + by speculative loads. + + If unsure, say Y. + menuconfig ARMV8_DEPRECATED bool "Emulate deprecated/obsolete ARMv8 instructions" depends on COMPAT diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index a5f476752f4e..ac16e2efb348 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -44,7 +44,8 @@ #define ARM64_HARDEN_BRANCH_PREDICTOR 24 #define ARM64_HARDEN_BP_POST_GUEST_EXIT 25 #define ARM64_HW_DBM 26 +#define ARM64_SSBD 27 -#define ARM64_NCAPS 27 +#define ARM64_NCAPS 28 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 1bb6452f194c..57c98912aa91 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -16,7 +16,9 @@ * along with this program. If not, see . */ +#include #include +#include #include #include #include @@ -148,8 +150,6 @@ static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry, } #include -#include -#include static void call_smc_arch_workaround_1(void) { @@ -230,6 +230,67 @@ static int qcom_enable_link_stack_sanitization(void *data) #ifdef CONFIG_ARM64_SSBD DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required); + +static void arm64_set_ssbd_mitigation(bool state) +{ + switch (psci_ops.conduit) { + case PSCI_CONDUIT_HVC: + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); + break; + + case PSCI_CONDUIT_SMC: + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); + break; + + default: + WARN_ON_ONCE(1); + break; + } +} + +static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry, + int scope) +{ + struct arm_smccc_res res; + bool supported = true; + + WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); + + if (psci_ops.smccc_version == SMCCC_VERSION_1_0) + return false; + + /* + * The probe function return value is either negative + * (unsupported or mitigated), positive (unaffected), or zero + * (requires mitigation). We only need to do anything in the + * last case. + */ + switch (psci_ops.conduit) { + case PSCI_CONDUIT_HVC: + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_2, &res); + if ((int)res.a0 != 0) + supported = false; + break; + + case PSCI_CONDUIT_SMC: + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_2, &res); + if ((int)res.a0 != 0) + supported = false; + break; + + default: + supported = false; + } + + if (supported) { + __this_cpu_write(arm64_ssbd_callback_required, 1); + arm64_set_ssbd_mitigation(true); + } + + return supported; +} #endif /* CONFIG_ARM64_SSBD */ #define MIDR_RANGE(model, min, max) \ @@ -429,6 +490,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), .enable = enable_smccc_arch_workaround_1, }, +#endif +#ifdef CONFIG_ARM64_SSBD + { + .desc = "Speculative Store Bypass Disable", + .def_scope = SCOPE_LOCAL_CPU, + .capability = ARM64_SSBD, + .matches = has_ssbd_mitigation, + }, #endif { } -- GitLab From 986178285549f499028e5ecc454cd8a1b6a86b70 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 29 May 2018 13:11:09 +0100 Subject: [PATCH 0213/1299] arm64: Add 'ssbd' command-line option On a system where the firmware implements ARCH_WORKAROUND_2, it may be useful to either permanently enable or disable the workaround for cases where the user decides that they'd rather not get a trap overhead, and keep the mitigation permanently on or off instead of switching it on exception entry/exit. In any case, default to the mitigation being enabled. Change-Id: I66f7b80ad2c0d6acf8ce18d7035bbb56a3146af6 Reviewed-by: Julien Grall Reviewed-by: Mark Rutland Acked-by: Will Deacon Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: a43ae4dfe56a01f5b98ba0cb2f784b6a43bafcc6 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [isaacm@codeaurora.org: remove code that is not needed to apply workaround for ssbd. Also, move ssbd constant definitions, to expose these constants to assembly, so compilation does not break later.] Signed-off-by: Isaac J. Manjarres --- .../admin-guide/kernel-parameters.txt | 17 +++ arch/arm64/include/asm/cpufeature.h | 6 + arch/arm64/kernel/cpu_errata.c | 103 +++++++++++++++--- 3 files changed, 110 insertions(+), 16 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 51ec539c8ddb..0613573ed177 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4006,6 +4006,23 @@ expediting. Set to zero to disable automatic expediting. + ssbd= [ARM64,HW] + Speculative Store Bypass Disable control + + On CPUs that are vulnerable to the Speculative + Store Bypass vulnerability and offer a + firmware based mitigation, this parameter + indicates how the mitigation should be used: + + force-on: Unconditionally enable mitigation for + for both kernel and userspace + force-off: Unconditionally disable mitigation for + for both kernel and userspace + kernel: Always enable mitigation in the + kernel, and offer a prctl interface + to allow userspace to register its + interest in being mitigated too. + stack_guard_gap= [MM] override the default stack gap protection. The value is in page units and it defines how many pages prior diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 428ee1f2468c..a8053d0c5591 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -23,6 +23,12 @@ #define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap)) #define cpu_feature(x) ilog2(HWCAP_ ## x) +#define ARM64_SSBD_UNKNOWN -1 +#define ARM64_SSBD_FORCE_DISABLE 0 +#define ARM64_SSBD_KERNEL 1 +#define ARM64_SSBD_FORCE_ENABLE 2 +#define ARM64_SSBD_MITIGATED 3 + #ifndef __ASSEMBLY__ #include diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 57c98912aa91..1dd3504ac656 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -231,6 +231,38 @@ static int qcom_enable_link_stack_sanitization(void *data) #ifdef CONFIG_ARM64_SSBD DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required); +int ssbd_state __read_mostly = ARM64_SSBD_KERNEL; + +static const struct ssbd_options { + const char *str; + int state; +} ssbd_options[] = { + { "force-on", ARM64_SSBD_FORCE_ENABLE, }, + { "force-off", ARM64_SSBD_FORCE_DISABLE, }, + { "kernel", ARM64_SSBD_KERNEL, }, +}; + +static int __init ssbd_cfg(char *buf) +{ + int i; + + if (!buf || !buf[0]) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(ssbd_options); i++) { + int len = strlen(ssbd_options[i].str); + + if (strncmp(buf, ssbd_options[i].str, len)) + continue; + + ssbd_state = ssbd_options[i].state; + return 0; + } + + return -EINVAL; +} +early_param("ssbd", ssbd_cfg); + static void arm64_set_ssbd_mitigation(bool state) { switch (psci_ops.conduit) { @@ -252,44 +284,83 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry, int scope) { struct arm_smccc_res res; - bool supported = true; + bool required = true; + s32 val; WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); - if (psci_ops.smccc_version == SMCCC_VERSION_1_0) + if (psci_ops.smccc_version == SMCCC_VERSION_1_0) { + ssbd_state = ARM64_SSBD_UNKNOWN; return false; + } - /* - * The probe function return value is either negative - * (unsupported or mitigated), positive (unaffected), or zero - * (requires mitigation). We only need to do anything in the - * last case. - */ switch (psci_ops.conduit) { case PSCI_CONDUIT_HVC: arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ARM_SMCCC_ARCH_WORKAROUND_2, &res); - if ((int)res.a0 != 0) - supported = false; break; case PSCI_CONDUIT_SMC: arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ARM_SMCCC_ARCH_WORKAROUND_2, &res); - if ((int)res.a0 != 0) - supported = false; break; default: - supported = false; + ssbd_state = ARM64_SSBD_UNKNOWN; + return false; + } + + val = (s32)res.a0; + + switch (val) { + case SMCCC_RET_NOT_SUPPORTED: + ssbd_state = ARM64_SSBD_UNKNOWN; + return false; + + case SMCCC_RET_NOT_REQUIRED: + pr_info_once("%s mitigation not required\n", entry->desc); + ssbd_state = ARM64_SSBD_MITIGATED; + return false; + + case SMCCC_RET_SUCCESS: + required = true; + break; + + case 1: /* Mitigation not required on this CPU */ + required = false; + break; + + default: + WARN_ON(1); + return false; } - if (supported) { - __this_cpu_write(arm64_ssbd_callback_required, 1); + switch (ssbd_state) { + case ARM64_SSBD_FORCE_DISABLE: + pr_info_once("%s disabled from command-line\n", entry->desc); + arm64_set_ssbd_mitigation(false); + required = false; + break; + + case ARM64_SSBD_KERNEL: + if (required) { + __this_cpu_write(arm64_ssbd_callback_required, 1); + arm64_set_ssbd_mitigation(true); + } + break; + + case ARM64_SSBD_FORCE_ENABLE: + pr_info_once("%s forced from command-line\n", entry->desc); arm64_set_ssbd_mitigation(true); + required = true; + break; + + default: + WARN_ON(1); + break; } - return supported; + return required; } #endif /* CONFIG_ARM64_SSBD */ -- GitLab From c085b8379d21573f61a33c7e547cccc97bf8c578 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 29 May 2018 13:11:10 +0100 Subject: [PATCH 0214/1299] arm64: ssbd: Add global mitigation state accessor We're about to need the mitigation state in various parts of the kernel in order to do the right thing for userspace and guests. Let's expose an accessor that will let other subsystems know about the state. Change-Id: I8c96e8980817ea336935eda2729b023ec56a818e Reviewed-by: Julien Grall Reviewed-by: Mark Rutland Acked-by: Will Deacon Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: c32e1736ca03904c03de0e4459a673be194f56fd Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Isaac J. Manjarres --- arch/arm64/include/asm/cpufeature.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index a8053d0c5591..c75e695998de 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -268,6 +268,16 @@ static inline bool system_uses_ttbr0_pan(void) !cpus_have_const_cap(ARM64_HAS_PAN); } +static inline int arm64_get_ssbd_state(void) +{ +#ifdef CONFIG_ARM64_SSBD + extern int ssbd_state; + return ssbd_state; +#else + return ARM64_SSBD_UNKNOWN; +#endif +} + #endif /* __ASSEMBLY__ */ #endif -- GitLab From 947ffaa83d20356d29ebbe14bcf782332e4152b6 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 29 May 2018 13:11:11 +0100 Subject: [PATCH 0215/1299] arm64: ssbd: Skip apply_ssbd if not using dynamic mitigation In order to avoid checking arm64_ssbd_callback_required on each kernel entry/exit even if no mitigation is required, let's add yet another alternative that by default jumps over the mitigation, and that gets nop'ed out if we're doing dynamic mitigation. Think of it as a poor man's static key... Change-Id: Idc527c176f171542d22fc43088bd8b84a6a8a790 Reviewed-by: Julien Grall Reviewed-by: Mark Rutland Acked-by: Will Deacon Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: 986372c4367f46b34a3c0f6918d7fb95cbdf39d6 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [isaacm@codeaurora.org: Add assembly logic to compare ssbd_state value and branch to target label, since the alternative_cb macro is not implemented.] Signed-off-by: Isaac J. Manjarres --- arch/arm64/kernel/entry.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index d093d47e3d03..8ec336bedcb6 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -142,6 +142,10 @@ alternative_else_nop_endif // to save/restore them if required. .macro apply_ssbd, state, targ, tmp1, tmp2 #ifdef CONFIG_ARM64_SSBD + ldr \tmp1, =ssbd_state + ldr \tmp1, [\tmp1] + cmp \tmp1, #ARM64_SSBD_KERNEL + b.ne \targ ldr_this_cpu \tmp2, arm64_ssbd_callback_required, \tmp1 cbz \tmp2, \targ mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 -- GitLab From 9be5bc93e48d2221fc5edacfc31351c1cea0a1ba Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 29 May 2018 13:11:12 +0100 Subject: [PATCH 0216/1299] arm64: ssbd: Restore mitigation status on CPU resume On a system where firmware can dynamically change the state of the mitigation, the CPU will always come up with the mitigation enabled, including when coming back from suspend. If the user has requested "no mitigation" via a command line option, let's enforce it by calling into the firmware again to disable it. Similarily, for a resume from hibernate, the mitigation could have been disabled by the boot kernel. Let's ensure that it is set back on in that case. Change-Id: I02111bcf8f44e0234f50927f078eae454d31e0b6 Acked-by: Will Deacon Reviewed-by: Mark Rutland Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: 647d0519b53f440a55df163de21c52a8205431cc Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [isaacm@codeaurora.org: resolve trivial merge conflicts] Signed-off-by: Isaac J. Manjarres --- arch/arm64/include/asm/cpufeature.h | 6 ++++++ arch/arm64/kernel/cpu_errata.c | 2 +- arch/arm64/kernel/hibernate.c | 11 +++++++++++ arch/arm64/kernel/suspend.c | 8 ++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index c75e695998de..3128d4dc4a02 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -278,6 +278,12 @@ static inline int arm64_get_ssbd_state(void) #endif } +#ifdef CONFIG_ARM64_SSBD +void arm64_set_ssbd_mitigation(bool state); +#else +static inline void arm64_set_ssbd_mitigation(bool state) {} +#endif + #endif /* __ASSEMBLY__ */ #endif diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 1dd3504ac656..e28b8bed6417 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -263,7 +263,7 @@ static int __init ssbd_cfg(char *buf) } early_param("ssbd", ssbd_cfg); -static void arm64_set_ssbd_mitigation(bool state) +void arm64_set_ssbd_mitigation(bool state) { switch (psci_ops.conduit) { case PSCI_CONDUIT_HVC: diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 095d3c170f5d..a028cc95afe1 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -313,6 +313,17 @@ int swsusp_arch_suspend(void) sleep_cpu = -EINVAL; __cpu_suspend_exit(); + + /* + * Just in case the boot kernel did turn the SSBD + * mitigation off behind our back, let's set the state + * to what we expect it to be. + */ + switch (arm64_get_ssbd_state()) { + case ARM64_SSBD_FORCE_ENABLE: + case ARM64_SSBD_KERNEL: + arm64_set_ssbd_mitigation(true); + } } local_dbg_restore(flags); diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c index 77cd655e6eb7..7a655e60cf4b 100644 --- a/arch/arm64/kernel/suspend.c +++ b/arch/arm64/kernel/suspend.c @@ -62,6 +62,14 @@ void notrace __cpu_suspend_exit(void) */ if (hw_breakpoint_restore) hw_breakpoint_restore(cpu); + + /* + * On resume, firmware implementing dynamic mitigation will + * have turned the mitigation on. If the user has forcefully + * disabled it, make sure their wishes are obeyed. + */ + if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) + arm64_set_ssbd_mitigation(false); } /* -- GitLab From d60d65aec95a5aba3725c44caca9633e5c5c82a2 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 29 May 2018 13:11:13 +0100 Subject: [PATCH 0217/1299] arm64: ssbd: Introduce thread flag to control userspace mitigation In order to allow userspace to be mitigated on demand, let's introduce a new thread flag that prevents the mitigation from being turned off when exiting to userspace, and doesn't turn it on on entry into the kernel (with the assumption that the mitigation is always enabled in the kernel itself). This will be used by a prctl interface introduced in a later patch. Change-Id: I9583873ac796489eba615e857cb9f21adcef2179 Reviewed-by: Mark Rutland Acked-by: Will Deacon Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: 9dd9614f5476687abbff8d4b12cd08ae70d7c2ad Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Isaac J. Manjarres --- arch/arm64/include/asm/thread_info.h | 1 + arch/arm64/kernel/entry.S | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index ae0ef18f68b9..e873dc6f40a4 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -93,6 +93,7 @@ void arch_setup_new_exec(void); #define TIF_SINGLESTEP 21 #define TIF_32BIT 22 /* 32bit process */ #define TIF_MM_RELEASED 24 +#define TIF_SSBD 25 /* Wants SSB mitigation */ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 8ec336bedcb6..3a61a8a3de39 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -148,6 +148,8 @@ alternative_else_nop_endif b.ne \targ ldr_this_cpu \tmp2, arm64_ssbd_callback_required, \tmp1 cbz \tmp2, \targ + ldr \tmp2, [tsk, #TSK_TI_FLAGS] + tbnz \tmp2, #TIF_SSBD, \targ mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 mov w1, #\state smc #0 -- GitLab From f022c0ba212220a237cc276d4b158337ebc817ef Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 29 May 2018 13:11:14 +0100 Subject: [PATCH 0218/1299] arm64: ssbd: Add prctl interface for per-thread mitigation If running on a system that performs dynamic SSBD mitigation, allow userspace to request the mitigation for itself. This is implemented as a prctl call, allowing the mitigation to be enabled or disabled at will for this particular thread. Change-Id: I94a21f74b17bc0f35ca141efa21356c9d16bd3eb Acked-by: Will Deacon Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas Git-commit: 9cdc0108baa8ef87c76ed834619886a46bd70cbe Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [isaacm@codeaurora.org: resolve trivial merge conflicts] Signed-off-by: Isaac J. Manjarres --- arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/ssbd.c | 110 +++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 arch/arm64/kernel/ssbd.c diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 255c8c36f487..a15a07e94182 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -59,6 +59,7 @@ arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o ifeq ($(CONFIG_KVM),y) arm64-obj-$(CONFIG_HARDEN_BRANCH_PREDICTOR) += bpi.o endif +arm64-obj-$(CONFIG_ARM64_SSBD) += ssbd.o obj-y += $(arm64-obj-y) vdso/ probes/ obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/ssbd.c b/arch/arm64/kernel/ssbd.c new file mode 100644 index 000000000000..3432e5ef9f41 --- /dev/null +++ b/arch/arm64/kernel/ssbd.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 ARM Ltd, All Rights Reserved. + */ + +#include +#include +#include + +#include + +/* + * prctl interface for SSBD + * FIXME: Drop the below ifdefery once merged in 4.18. + */ +#ifdef PR_SPEC_STORE_BYPASS +static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl) +{ + int state = arm64_get_ssbd_state(); + + /* Unsupported */ + if (state == ARM64_SSBD_UNKNOWN) + return -EINVAL; + + /* Treat the unaffected/mitigated state separately */ + if (state == ARM64_SSBD_MITIGATED) { + switch (ctrl) { + case PR_SPEC_ENABLE: + return -EPERM; + case PR_SPEC_DISABLE: + case PR_SPEC_FORCE_DISABLE: + return 0; + } + } + + /* + * Things are a bit backward here: the arm64 internal API + * *enables the mitigation* when the userspace API *disables + * speculation*. So much fun. + */ + switch (ctrl) { + case PR_SPEC_ENABLE: + /* If speculation is force disabled, enable is not allowed */ + if (state == ARM64_SSBD_FORCE_ENABLE || + task_spec_ssb_force_disable(task)) + return -EPERM; + task_clear_spec_ssb_disable(task); + clear_tsk_thread_flag(task, TIF_SSBD); + break; + case PR_SPEC_DISABLE: + if (state == ARM64_SSBD_FORCE_DISABLE) + return -EPERM; + task_set_spec_ssb_disable(task); + set_tsk_thread_flag(task, TIF_SSBD); + break; + case PR_SPEC_FORCE_DISABLE: + if (state == ARM64_SSBD_FORCE_DISABLE) + return -EPERM; + task_set_spec_ssb_disable(task); + task_set_spec_ssb_force_disable(task); + set_tsk_thread_flag(task, TIF_SSBD); + break; + default: + return -ERANGE; + } + + return 0; +} + +int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, + unsigned long ctrl) +{ + switch (which) { + case PR_SPEC_STORE_BYPASS: + return ssbd_prctl_set(task, ctrl); + default: + return -ENODEV; + } +} + +static int ssbd_prctl_get(struct task_struct *task) +{ + switch (arm64_get_ssbd_state()) { + case ARM64_SSBD_UNKNOWN: + return -EINVAL; + case ARM64_SSBD_FORCE_ENABLE: + return PR_SPEC_DISABLE; + case ARM64_SSBD_KERNEL: + if (task_spec_ssb_force_disable(task)) + return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; + if (task_spec_ssb_disable(task)) + return PR_SPEC_PRCTL | PR_SPEC_DISABLE; + return PR_SPEC_PRCTL | PR_SPEC_ENABLE; + case ARM64_SSBD_FORCE_DISABLE: + return PR_SPEC_ENABLE; + default: + return PR_SPEC_NOT_AFFECTED; + } +} + +int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) +{ + switch (which) { + case PR_SPEC_STORE_BYPASS: + return ssbd_prctl_get(task); + default: + return -ENODEV; + } +} +#endif /* PR_SPEC_STORE_BYPASS */ -- GitLab From 92129e79f23c9abd13c6c9706e7505a6b143c3e5 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Fri, 20 Apr 2018 17:54:00 +0530 Subject: [PATCH 0219/1299] usb: gadget: qdss: Add support for qdss fs descriptor handling Currently f_qdss driver does not support full-speed mode. This results in Chapter 9 USB2 CV Other Speed Configuration Test failures with qdss composition. Hence add full speed descriptors support in qdss driver. Change-Id: I1ca4b2f1aba1479661f89497cfd5c5f25369fa8e Signed-off-by: Chandana Kishori Chiluveru Signed-off-by: Mayank Rana --- drivers/usb/gadget/function/f_qdss.c | 61 ++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/function/f_qdss.c b/drivers/usb/gadget/function/f_qdss.c index fbc8cc49ae20..f3ed5ed6f8ad 100644 --- a/drivers/usb/gadget/function/f_qdss.c +++ b/drivers/usb/gadget/function/f_qdss.c @@ -117,6 +117,40 @@ static struct usb_ss_ep_comp_descriptor qdss_ctrl_out_ep_comp_desc = { .wBytesPerInterval = 0, }; +/* Full speed support */ +static struct usb_endpoint_descriptor qdss_fs_data_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(64), +}; + +static struct usb_endpoint_descriptor qdss_fs_ctrl_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(64), +}; + +static struct usb_endpoint_descriptor qdss_fs_ctrl_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(64), +}; + +static struct usb_descriptor_header *qdss_fs_desc[] = { + (struct usb_descriptor_header *) &qdss_data_intf_desc, + (struct usb_descriptor_header *) &qdss_fs_data_desc, + (struct usb_descriptor_header *) &qdss_ctrl_intf_desc, + (struct usb_descriptor_header *) &qdss_fs_ctrl_in_desc, + (struct usb_descriptor_header *) &qdss_fs_ctrl_out_desc, + NULL, +}; + static struct usb_descriptor_header *qdss_hs_desc[] = { (struct usb_descriptor_header *) &qdss_data_intf_desc, (struct usb_descriptor_header *) &qdss_hs_data_desc, @@ -138,6 +172,12 @@ static struct usb_descriptor_header *qdss_ss_desc[] = { NULL, }; +static struct usb_descriptor_header *qdss_fs_data_only_desc[] = { + (struct usb_descriptor_header *) &qdss_data_intf_desc, + (struct usb_descriptor_header *) &qdss_fs_data_desc, + NULL, +}; + static struct usb_descriptor_header *qdss_hs_data_only_desc[] = { (struct usb_descriptor_header *) &qdss_data_intf_desc, (struct usb_descriptor_header *) &qdss_hs_data_desc, @@ -374,11 +414,6 @@ static int qdss_bind(struct usb_configuration *c, struct usb_function *f) pr_debug("%s\n", __func__); - if (!gadget_is_dualspeed(gadget) && !gadget_is_superspeed(gadget)) { - pr_err("%s: full-speed is not supported\n", __func__); - return -ENOTSUPP; - } - /* Allocate data I/F */ iface = usb_interface_id(c, f); if (iface < 0) { @@ -443,6 +478,16 @@ static int qdss_bind(struct usb_configuration *c, struct usb_function *f) ep->driver_data = qdss; } + /*update fs descriptors*/ + qdss_fs_data_desc.bEndpointAddress = + qdss_ss_data_desc.bEndpointAddress; + if (qdss->debug_inface_enabled) { + qdss_fs_ctrl_in_desc.bEndpointAddress = + qdss_ss_ctrl_in_desc.bEndpointAddress; + qdss_fs_ctrl_out_desc.bEndpointAddress = + qdss_ss_ctrl_out_desc.bEndpointAddress; + } + /*update descriptors*/ qdss_hs_data_desc.bEndpointAddress = qdss_ss_data_desc.bEndpointAddress; @@ -454,10 +499,10 @@ static int qdss_bind(struct usb_configuration *c, struct usb_function *f) } if (qdss->debug_inface_enabled) - ret = usb_assign_descriptors(f, qdss_hs_desc, qdss_hs_desc, + ret = usb_assign_descriptors(f, qdss_fs_desc, qdss_hs_desc, qdss_ss_desc, qdss_ss_desc); else - ret = usb_assign_descriptors(f, qdss_hs_data_only_desc, + ret = usb_assign_descriptors(f, qdss_fs_data_only_desc, qdss_hs_data_only_desc, qdss_ss_data_only_desc, qdss_ss_data_only_desc); @@ -1138,7 +1183,7 @@ static struct usb_function *qdss_alloc(struct usb_function_instance *fi) struct f_qdss *usb_qdss = opts->usb_qdss; usb_qdss->port.function.name = "usb_qdss"; - usb_qdss->port.function.fs_descriptors = qdss_hs_desc; + usb_qdss->port.function.fs_descriptors = qdss_fs_desc; usb_qdss->port.function.hs_descriptors = qdss_hs_desc; usb_qdss->port.function.strings = qdss_strings; usb_qdss->port.function.bind = qdss_bind; -- GitLab From d7d858af5e937baa89e4f64fa803bf2c220684bd Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Tue, 24 Apr 2018 10:30:32 +0530 Subject: [PATCH 0220/1299] usb: gadget: qdss: Fix runtime PM usage count for multiple set_alt In some scenarios such as USBCV tests, multiple set_alt could be issued with same interface setting. In that case, driver get the usage count in set_alt but do not put it. This causes a mismatch of usage count and DWC3 LPM does not work anymore. Fix this by adding check in qdss_set_alt to ignore multiple set_alts. Change-Id: I232456c3f99b0cfaa61eb1c044bdd86013c930fa Signed-off-by: Chandana Kishori Chiluveru --- drivers/usb/gadget/function/f_qdss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_qdss.c b/drivers/usb/gadget/function/f_qdss.c index f3ed5ed6f8ad..4313fa8790b2 100644 --- a/drivers/usb/gadget/function/f_qdss.c +++ b/drivers/usb/gadget/function/f_qdss.c @@ -681,7 +681,7 @@ static int qdss_set_alt(struct usb_function *f, unsigned int intf, goto fail1; } - if (intf == qdss->data_iface_id) { + if (intf == qdss->data_iface_id && !qdss->data_enabled) { /* Increment usage count on connect */ usb_gadget_autopm_get_async(qdss->gadget); -- GitLab From 5dd14bdd2079f594a17083c3e30d6e1f5dafe275 Mon Sep 17 00:00:00 2001 From: Michael Adisumarta Date: Wed, 13 Jun 2018 10:49:36 -0700 Subject: [PATCH 0221/1299] msm: ipa4: fix client register and deregister for usb Register all USB protocols instead of the first one. Use pm Deregister if pm is configured. Start as 1 for a valid pm handle for clients since 0 is commonly used for debug purposes. Change-Id: I7bcc487b40873d00cfecb378bb25d4eba3081acf Signed-off-by: Michael Adisumarta --- drivers/platform/msm/ipa/ipa_v3/ipa_pm.c | 9 +++++---- drivers/platform/msm/ipa/ipa_v3/ipa_pm.h | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c index bffadfb7147e..34065cf8c2ed 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c @@ -242,7 +242,7 @@ static int calculate_throughput(void) struct ipa_pm_client *client; /* Create a basic array to hold throughputs*/ - for (i = 0, n = 0; i < IPA_PM_MAX_CLIENTS; i++) { + for (i = 1, n = 0; i < IPA_PM_MAX_CLIENTS; i++) { client = ipa_pm_ctx->clients[i]; if (client != NULL && IPA_PM_STATE_ACTIVE(client->state)) { /* default case */ @@ -498,7 +498,8 @@ static int find_next_open_array_element(const char *name) n = -ENOBUFS; - for (i = IPA_PM_MAX_CLIENTS - 1; i >= 0; i--) { + /* 0 is not a valid handle */ + for (i = IPA_PM_MAX_CLIENTS - 1; i >= 1; i--) { if (ipa_pm_ctx->clients[i] == NULL) { n = i; continue; @@ -1063,7 +1064,7 @@ int ipa_pm_deactivate_all_deferred(void) return -EINVAL; } - for (i = 0; i < IPA_PM_MAX_CLIENTS; i++) { + for (i = 1; i < IPA_PM_MAX_CLIENTS; i++) { client = ipa_pm_ctx->clients[i]; if (client == NULL) @@ -1304,7 +1305,7 @@ int ipa_pm_stat(char *buf, int size) cnt += result; - for (i = 0; i < IPA_PM_MAX_CLIENTS; i++) { + for (i = 1; i < IPA_PM_MAX_CLIENTS; i++) { client = ipa_pm_ctx->clients[i]; if (client == NULL) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h index 38e082f35e6f..47a03f938243 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,7 +16,7 @@ #include /* internal to ipa */ -#define IPA_PM_MAX_CLIENTS 12 /* actual max is value -1 since we start from 1*/ +#define IPA_PM_MAX_CLIENTS 32 /* actual max is value -1 since we start from 1*/ #define IPA_PM_MAX_EX_CL 64 #define IPA_PM_THRESHOLD_MAX 5 #define IPA_PM_EXCEPTION_MAX 2 -- GitLab From 9898e43e5440f45d6a4d036e65c5853bc95bace6 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Wed, 30 May 2018 12:36:33 +0530 Subject: [PATCH 0222/1299] usb: phy: Clean up phy-msm-ssusb to enable LDOs on init Clean up phy-msm-ssusb driver to enable LDOs on init rather than on probe. VDD is set to LPM to support VDDMIN on when the PHY is suspended. Add ref clock which is routed to this PHY wrapper and needs to be enabled for proper functioning. Change-Id: Ic27404627501f14566bdfee0cb89a43e8d93dc50 Signed-off-by: Sriharsha Allenki --- drivers/usb/phy/phy-msm-ssusb.c | 143 +++++++++++++++----------------- 1 file changed, 67 insertions(+), 76 deletions(-) diff --git a/drivers/usb/phy/phy-msm-ssusb.c b/drivers/usb/phy/phy-msm-ssusb.c index 91217e4092f7..d54cef45d879 100644 --- a/drivers/usb/phy/phy-msm-ssusb.c +++ b/drivers/usb/phy/phy-msm-ssusb.c @@ -59,15 +59,16 @@ MODULE_PARM_DESC(ss_phy_override_deemphasis, "Override SSPHY demphasis value"); struct msm_ssphy { struct usb_phy phy; void __iomem *base; - struct clk *core_clk; /* USB3 master clock */ + struct clk *ref_clk; struct reset_control *phy_com_reset; struct reset_control *phy_reset; struct regulator *vdd; struct regulator *vdda18; - atomic_t active_count; /* num of active instances */ bool suspended; int vdd_levels[3]; /* none, low, high */ int deemphasis_val; + + int power_enabled; }; static int msm_ssusb_config_vdd(struct msm_ssphy *phy, int high) @@ -93,47 +94,80 @@ static int msm_ssusb_ldo_enable(struct msm_ssphy *phy, int on) dev_dbg(phy->phy.dev, "reg (%s)\n", on ? "HPM" : "LPM"); + if (phy->power_enabled == on) { + dev_dbg(phy->phy.dev, "LDOs are already %s\n", + on ? "ON" : "OFF"); + return 0; + } + if (!on) goto disable_regulators; + rc = msm_ssusb_config_vdd(phy, 1); + if (rc) { + dev_err(phy->phy.dev, "Unable to config vdd: %d\n", rc); + return rc; + } + + rc = regulator_enable(phy->vdd); + if (rc) { + dev_err(phy->phy.dev, "Unable to enable vdd: %d\n", rc); + goto unset_vdd; + } rc = regulator_set_load(phy->vdda18, USB_SSPHY_1P8_HPM_LOAD); if (rc < 0) { - dev_err(phy->phy.dev, "Unable to set HPM of vdda18\n"); - return rc; + dev_err(phy->phy.dev, "Unable to set HPM of vdda18: %d\n", rc); + goto disable_vdd; } rc = regulator_set_voltage(phy->vdda18, USB_SSPHY_1P8_VOL_MIN, USB_SSPHY_1P8_VOL_MAX); if (rc) { - dev_err(phy->phy.dev, "unable to set voltage for vdda18\n"); + dev_err(phy->phy.dev, "unable to set voltage for vdda18: %d\n", + rc); goto put_vdda18_lpm; } rc = regulator_enable(phy->vdda18); if (rc) { - dev_err(phy->phy.dev, "Unable to enable vdda18\n"); + dev_err(phy->phy.dev, "Unable to enable vdda18: %d\n", rc); goto unset_vdda18; } + phy->power_enabled = 1; + return 0; disable_regulators: rc = regulator_disable(phy->vdda18); if (rc) - dev_err(phy->phy.dev, "Unable to disable vdda18\n"); + dev_err(phy->phy.dev, "Unable to disable vdda18: %d\n", rc); unset_vdda18: rc = regulator_set_voltage(phy->vdda18, 0, USB_SSPHY_1P8_VOL_MAX); if (rc) - dev_err(phy->phy.dev, "unable to set voltage for vdda18\n"); + dev_err(phy->phy.dev, "unable to set min voltage for vdda18: %d\n", + rc); put_vdda18_lpm: rc = regulator_set_load(phy->vdda18, 0); if (rc < 0) - dev_err(phy->phy.dev, "Unable to set LPM of vdda18\n"); + dev_err(phy->phy.dev, "Unable to set LPM of vdda18: %d\n", rc); + +disable_vdd: + rc = regulator_disable(phy->vdd); + if (rc) + dev_err(phy->phy.dev, "Unable to disable vdd: %d\n", rc); +unset_vdd: + rc = msm_ssusb_config_vdd(phy, 0); + if (rc) + dev_err(phy->phy.dev, "unable to set min voltage for vdd: %d\n", + rc); + + phy->power_enabled = 0; - return rc < 0 ? rc : 0; + return rc; } static void msm_usb_write_readback(void *base, u32 offset, @@ -285,8 +319,9 @@ static int msm_ssphy_init(struct usb_phy *uphy) struct msm_ssphy *phy = container_of(uphy, struct msm_ssphy, phy); u32 val; - /* Ensure clock is on before accessing QSCRATCH registers */ - clk_prepare_enable(phy->core_clk); + msm_ssusb_ldo_enable(phy, 1); + + clk_prepare_enable(phy->ref_clk); /* read initial value */ val = readl_relaxed(phy->base + SS_PHY_CTRL_REG); @@ -320,8 +355,6 @@ static int msm_ssphy_init(struct usb_phy *uphy) */ msm_ssphy_set_params(uphy); - clk_disable_unprepare(phy->core_clk); - return 0; } @@ -329,24 +362,17 @@ static int msm_ssphy_set_suspend(struct usb_phy *uphy, int suspend) { struct msm_ssphy *phy = container_of(uphy, struct msm_ssphy, phy); void __iomem *base = phy->base; - int count; - /* Ensure clock is on before accessing QSCRATCH registers */ - clk_prepare_enable(phy->core_clk); + dev_dbg(uphy->dev, "%s: phy->suspended:%d suspend:%d", __func__, + phy->suspended, suspend); - if (suspend) { - count = atomic_dec_return(&phy->active_count); - if (count > 0 || phy->suspended) { - dev_dbg(uphy->dev, "Skipping suspend, active_count=%d phy->suspended=%d\n", - count, phy->suspended); - goto done; - } + if (phy->suspended == suspend) { + dev_dbg(uphy->dev, "PHY is already %s\n", + suspend ? "suspended" : "resumed"); + return 0; + } - if (count < 0) { - dev_WARN(uphy->dev, "Suspended too many times! active_count=%d\n", - count); - atomic_set(&phy->active_count, 0); - } + if (suspend) { /* Clear REF_SS_PHY_EN */ msm_usb_write_readback(base, SS_PHY_CTRL_REG, REF_SS_PHY_EN, 0); @@ -362,24 +388,17 @@ static int msm_ssphy_set_suspend(struct usb_phy *uphy, int suspend) reset_control_assert(phy->phy_reset); } + clk_disable_unprepare(phy->ref_clk); msm_ssusb_ldo_enable(phy, 0); - msm_ssusb_config_vdd(phy, 0); phy->suspended = true; } else { - count = atomic_inc_return(&phy->active_count); - if (count > 1 || !phy->suspended) { - dev_dbg(uphy->dev, "Skipping resume, active_count=%d phy->suspended=%d\n", - count, phy->suspended); - goto done; - } - phy->suspended = false; - msm_ssusb_config_vdd(phy, 1); msm_ssusb_ldo_enable(phy, 1); + clk_prepare_enable(phy->ref_clk); if (phy->phy.flags & ENABLE_SECONDARY_PHY) { dev_err(uphy->dev, "secondary PHY, skipping reset\n"); - goto done; + return 0; } if (phy->phy_com_reset) { @@ -405,10 +424,10 @@ static int msm_ssphy_set_suspend(struct usb_phy *uphy, int suspend) msm_usb_write_readback(base, SS_PHY_CTRL_REG, SS_PHY_RESET, 0); } + + phy->suspended = false; } -done: - clk_disable_unprepare(phy->core_clk); return 0; } @@ -467,10 +486,10 @@ static int msm_ssphy_probe(struct platform_device *pdev) return -ENODEV; } - phy->core_clk = devm_clk_get(dev, "core_clk"); - if (IS_ERR(phy->core_clk)) { - dev_err(dev, "unable to get core_clk\n"); - return PTR_ERR(phy->core_clk); + phy->ref_clk = devm_clk_get(dev, "ref_clk"); + if (IS_ERR(phy->ref_clk)) { + dev_err(dev, "unable to get ref_clk\n"); + return PTR_ERR(phy->ref_clk); } phy->phy_com_reset = devm_reset_control_get(dev, "phy_com_reset"); @@ -513,24 +532,6 @@ static int msm_ssphy_probe(struct platform_device *pdev) return PTR_ERR(phy->vdda18); } - ret = msm_ssusb_config_vdd(phy, 1); - if (ret) { - dev_err(dev, "ssusb vdd_dig configuration failed\n"); - return ret; - } - - ret = regulator_enable(phy->vdd); - if (ret) { - dev_err(dev, "unable to enable the ssusb vdd_dig\n"); - goto unconfig_ss_vdd; - } - - ret = msm_ssusb_ldo_enable(phy, 1); - if (ret) { - dev_err(dev, "ssusb vreg enable failed\n"); - goto disable_ss_vdd; - } - platform_set_drvdata(pdev, phy); if (of_property_read_bool(dev->of_node, "qcom,vbus-valid-override")) @@ -548,18 +549,9 @@ static int msm_ssphy_probe(struct platform_device *pdev) ret = usb_add_phy_dev(&phy->phy); if (ret) - goto disable_ss_ldo; + return ret; return 0; - -disable_ss_ldo: - msm_ssusb_ldo_enable(phy, 0); -disable_ss_vdd: - regulator_disable(phy->vdd); -unconfig_ss_vdd: - msm_ssusb_config_vdd(phy, 0); - - return ret; } static int msm_ssphy_remove(struct platform_device *pdev) @@ -569,10 +561,9 @@ static int msm_ssphy_remove(struct platform_device *pdev) if (!phy) return 0; + msm_ssphy_set_suspend(&phy->phy, 0); usb_remove_phy(&phy->phy); - msm_ssusb_ldo_enable(phy, 0); - regulator_disable(phy->vdd); - msm_ssusb_config_vdd(phy, 0); + msm_ssphy_set_suspend(&phy->phy, 1); kfree(phy); return 0; -- GitLab From 1d88ce2c5cf54b26ce21f7a5b629a6d05fa35de9 Mon Sep 17 00:00:00 2001 From: Prasad Sodagudi Date: Wed, 6 Jun 2018 17:14:43 -0700 Subject: [PATCH 0223/1299] pinctrl: qcom: Add EGPIO feature support to pinctrl driver Island IO can be assigned to Apps TLMM dynamically if that island is not using the pin for any connectivity. Add support for enabling EGPIO feature if the pin can support it. EGPIO_PRESENT bit shows if EGPIO feature is present or not for particular pin. Once EGPIO_ENABLE bit is set the pin is now controlled by Apps TLMM. When pinctrl properties are getting initialized by device driver framework, pin functions select would call to msm_pinmux_set_mux function to select pin function and enable EGPIO. Change-Id: I64514904096286f2a5df351880cd56d753f0658f Signed-off-by: Prasad Sodagudi --- drivers/pinctrl/qcom/pinctrl-msm.c | 4 ++++ drivers/pinctrl/qcom/pinctrl-msm.h | 2 ++ drivers/pinctrl/qcom/pinctrl-sm8150.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 7dc276b59dfa..9bea154ffff1 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -161,6 +161,10 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev, val = readl(pctrl->regs + g->ctl_reg); val &= ~mask; val |= i << g->mux_bit; + /* Check if egpio present and enable that feature */ + if (val & BIT(g->egpio_present)) + val |= BIT(g->egpio_enable); + writel(val, pctrl->regs + g->ctl_reg); raw_spin_unlock_irqrestore(&pctrl->lock, flags); diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h index 6ae59dc7a62f..7eb857d81036 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.h +++ b/drivers/pinctrl/qcom/pinctrl-msm.h @@ -84,6 +84,8 @@ struct msm_pingroup { unsigned pull_bit:5; unsigned drv_bit:5; + unsigned egpio_enable:5; + unsigned egpio_present:5; unsigned oe_bit:5; unsigned in_bit:5; unsigned out_bit:5; diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c index 33c16f295d31..f3565102a780 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c @@ -59,6 +59,8 @@ .mux_bit = 2, \ .pull_bit = 0, \ .drv_bit = 6, \ + .egpio_enable = 12, \ + .egpio_present = 11, \ .oe_bit = 9, \ .in_bit = 0, \ .out_bit = 1, \ -- GitLab From 8ee1e2bcf7ae92e82b288a86fc3a06cec5c61f1d Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Wed, 6 Jun 2018 15:27:44 -0700 Subject: [PATCH 0224/1299] ion: carveout: Use device for cache maintenance Use device when calling ion_pages_sync_for_device to make sure cache maintenance is properly applied. Change-Id: I7f8499148cfd560122de430e343830d5e870b505 Signed-off-by: Liam Mark --- drivers/staging/android/ion/ion_carveout_heap.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 03427f31c38d..88dc7995fb3f 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -96,12 +96,13 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer) struct sg_table *table = buffer->sg_table; struct page *page = sg_page(table->sgl); phys_addr_t paddr = page_to_phys(page); + struct device *dev = (struct device *)heap->priv; ion_heap_buffer_zero(buffer); if (ion_buffer_cached(buffer)) - dma_sync_sg_for_device(NULL, table->sgl, table->nents, - DMA_BIDIRECTIONAL); + ion_pages_sync_for_device(dev, page, buffer->size, + DMA_BIDIRECTIONAL); ion_carveout_free(heap, paddr, buffer->size); sg_free_table(table); @@ -123,11 +124,12 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) struct page *page; size_t size; + struct device *dev = (struct device *)heap_data->priv; page = pfn_to_page(PFN_DOWN(heap_data->base)); size = heap_data->size; - ion_pages_sync_for_device(NULL, page, size, DMA_BIDIRECTIONAL); + ion_pages_sync_for_device(dev, page, size, DMA_BIDIRECTIONAL); ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL)); if (ret) -- GitLab From da3e875e182112853b87a122adea49a3018358fc Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Mon, 11 Jun 2018 22:47:53 -0700 Subject: [PATCH 0225/1299] mhi: core: remove firmware info from devicetree It's not recommended to put firmware information inside devicetree, get firmware information from mhi control driver instead of devicetree. CRs-Fixed: 2258358 Change-Id: Icdb32d674ce5a962733398149e420d5ffed1607c Signed-off-by: Sujeev Dias --- Documentation/devicetree/bindings/bus/mhi.txt | 26 ------------------- arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi | 1 - drivers/bus/mhi/core/mhi_init.c | 9 ------- 3 files changed, 36 deletions(-) diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt index 0d640144173b..efb9510595e5 100644 --- a/Documentation/devicetree/bindings/bus/mhi.txt +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -19,31 +19,6 @@ Main node properties: Value type: Definition: Maximum timeout in ms wait for state and cmd completion -- mhi,fw-name - Usage: optional - Value type: - Definition: Firmware image name to upload - -- mhi,edl-name - Usage: optional - Value type: - Definition: Firmware image name for emergency download - -- mhi,fbc-download - Usage: optional - Value type: - Definition: If set true, image specified by fw-name is for full image - -- mhi,sbl-size - Usage: optional - Value type: - Definition: Size of SBL image in bytes - -- mhi,seg-len - Usage: optional - Value type: - Definition: Size of each segment to allocate for BHIe vector table - - mhi,time-sync Usage: optional Value type: @@ -281,7 +256,6 @@ mhi_controller { mhi,bstmode = <2>; }; - mhi,fw-name = "sbl1.mbn"; mhi,timeout = <500>; children_node { diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi index e715a75c3add..140ae927b8e3 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi @@ -47,7 +47,6 @@ esoc-0 = <&mdm3>; qcom,smmu-cfg = <0x1d>; qcom,addr-win = <0x0 0x20000000 0x0 0x3fffffff>; - mhi,fw-name = "sdx50m/sbl1.mbn"; }; &tlmm { diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index cd455571b599..949f3084bef6 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -992,15 +992,6 @@ static int of_parse_dt(struct mhi_controller *mhi_cntrl, int ret; struct mhi_timesync *mhi_tsync; - /* parse firmware image info (optional parameters) */ - of_property_read_string(of_node, "mhi,fw-name", &mhi_cntrl->fw_image); - of_property_read_string(of_node, "mhi,edl-name", &mhi_cntrl->fw_image); - mhi_cntrl->fbc_download = of_property_read_bool(of_node, "mhi,dl-fbc"); - of_property_read_u32(of_node, "mhi,sbl-size", - (u32 *)&mhi_cntrl->sbl_size); - of_property_read_u32(of_node, "mhi,seg-len", - (u32 *)&mhi_cntrl->seg_len); - /* parse MHI channel configuration */ ret = of_parse_ch_cfg(mhi_cntrl, of_node); if (ret) -- GitLab From 385dbf30403d1b8f13bb994e02190b28096ff9d5 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Wed, 13 Jun 2018 11:57:49 -0700 Subject: [PATCH 0226/1299] usb: pd: Update some sysfs entries to return hex values Update several of the PD 3.0 related sysfs entries to return a hexadecimal string of the byte data returned instead of decimal. For the messages that correspond to non-extended messages, these data objects should be printed as '0x1234ABCD' to ease human translation to binary. For extended messages the payloads contain fields of single or multi-byte values, so it's easiest to return a string of hex bytes. Change-Id: I436e90d9b5b472362ae39050dd775363db46207c Signed-off-by: Jack Pham --- drivers/usb/pd/policy_engine.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 497cad2d7819..feca4ded2b30 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -3686,8 +3686,12 @@ static ssize_t get_src_cap_ext_show(struct device *dev, return ret; for (i = 0; i < PD_SRC_CAP_EXT_DB_LEN; i++) - len += snprintf(buf + len, PAGE_SIZE - len, "%d\n", - pd->src_cap_ext_db[i]); + len += snprintf(buf + len, PAGE_SIZE - len, "%s0x%02x", + i ? " " : "", pd->src_cap_ext_db[i]); + + buf[len++] = '\n'; + buf[len] = '\0'; + return len; } static DEVICE_ATTR_RO(get_src_cap_ext); @@ -3705,7 +3709,7 @@ static ssize_t get_pps_status_show(struct device *dev, if (ret) return ret; - return snprintf(buf, PAGE_SIZE, "%d\n", pd->pps_status_db); + return snprintf(buf, PAGE_SIZE, "0x%08x\n", pd->pps_status_db); } static DEVICE_ATTR_RO(get_pps_status); @@ -3747,8 +3751,12 @@ static ssize_t get_battery_cap_show(struct device *dev, return -EINVAL; for (i = 0; i < PD_BATTERY_CAP_DB_LEN; i++) - len += snprintf(buf + len, PAGE_SIZE - len, "%d\n", - pd->battery_cap_db[i]); + len += snprintf(buf + len, PAGE_SIZE - len, "%s0x%02x", + i ? " " : "", pd->battery_cap_db[i]); + + buf[len++] = '\n'; + buf[len] = '\0'; + return len; } static DEVICE_ATTR_RW(get_battery_cap); @@ -3779,7 +3787,7 @@ static ssize_t get_battery_status_show(struct device *dev, if (pd->get_battery_status_db == -EINVAL) return -EINVAL; - return snprintf(buf, PAGE_SIZE, "%d\n", pd->battery_sts_dobj); + return snprintf(buf, PAGE_SIZE, "0x%08x\n", pd->battery_sts_dobj); } static DEVICE_ATTR_RW(get_battery_status); -- GitLab From 081c1c9550121d8806e611f002bced1f840536d8 Mon Sep 17 00:00:00 2001 From: Runmin Wang Date: Thu, 23 Jun 2016 11:13:24 -0700 Subject: [PATCH 0227/1299] drivers: GICv3: Enable logging of interrupts that triggered wakeup This change enables logging of irq number and name which triggered wake up of the system from deep sleep. This helps in debugging the spurious wakeups due to interrupts from various subsystems. Change-Id: I6246871e638e761031c1d2f2b4bb1964b34bd2e5 CRs-Fixed: 1033023 Signed-off-by: Runmin Wang Signed-off-by: Maria Yu --- drivers/irqchip/irq-gic-common.h | 6 +++ drivers/irqchip/irq-gic-v3.c | 65 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h index 83b72f4f85e4..623e57239821 100644 --- a/drivers/irqchip/irq-gic-common.h +++ b/drivers/irqchip/irq-gic-common.h @@ -30,6 +30,12 @@ struct gic_quirk { extern bool from_suspend; extern struct irq_chip gic_arch_extn; +#ifdef CONFIG_QCOM_SHOW_RESUME_IRQ +extern int msm_show_resume_irq_mask; +#else +#define msm_show_resume_irq_mask 0 +#endif + int gic_configure_irq(unsigned int irq, unsigned int type, void __iomem *base, void (*sync_access)(void)); void gic_dist_config(void __iomem *base, int gic_irqs, diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 65cb116ac0aa..dae3bddaa7fd 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -40,6 +40,8 @@ #include #include +#include + #include "irq-gic-common.h" struct redist_region { @@ -331,6 +333,69 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu) return 0; } +#ifdef CONFIG_PM + +static int gic_suspend(void) +{ + return 0; +} + +static void gic_show_resume_irq(struct gic_chip_data *gic) +{ + unsigned int i; + u32 enabled; + u32 pending[32]; + void __iomem *base = gic_data.dist_base; + + if (!msm_show_resume_irq_mask) + return; + + for (i = 0; i * 32 < gic->irq_nr; i++) { + enabled = readl_relaxed(base + GICD_ICENABLER + i * 4); + pending[i] = readl_relaxed(base + GICD_ISPENDR + i * 4); + pending[i] &= enabled; + } + + for (i = find_first_bit((unsigned long *)pending, gic->irq_nr); + i < gic->irq_nr; + i = find_next_bit((unsigned long *)pending, gic->irq_nr, i+1)) { + unsigned int irq = irq_find_mapping(gic->domain, i); + struct irq_desc *desc = irq_to_desc(irq); + const char *name = "null"; + + if (desc == NULL) + name = "stray irq"; + else if (desc->action && desc->action->name) + name = desc->action->name; + + pr_warn("%s: %d triggered %s\n", __func__, irq, name); + } +} + +static void gic_resume_one(struct gic_chip_data *gic) +{ + gic_show_resume_irq(gic); +} + +static void gic_resume(void) +{ + gic_resume_one(&gic_data); +} + +static struct syscore_ops gic_syscore_ops = { + .suspend = gic_suspend, + .resume = gic_resume, +}; + +static int __init gic_init_sys(void) +{ + register_syscore_ops(&gic_syscore_ops); + return 0; +} +arch_initcall(gic_init_sys); + +#endif + static u64 gic_mpidr_to_affinity(unsigned long mpidr) { u64 aff; -- GitLab From abb006356de4e0151072be0672f7549286d1630b Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Fri, 8 Jun 2018 09:58:13 -0700 Subject: [PATCH 0228/1299] msm: vidc: Set operating rate to video firmware Video firmware needs operating rate setting from driver to decide frame skip logic. Set operating to firmware from driver. Change-Id: I09c8f5b484ec4894a0b454cfc5b7580f02ae84a0 Signed-off-by: Maheshwar Ajja --- drivers/media/platform/msm/vidc/hfi_packetization.c | 12 ++++++++++++ drivers/media/platform/msm/vidc/msm_venc.c | 5 +++++ drivers/media/platform/msm/vidc/vidc_hfi_api.h | 5 +++++ drivers/media/platform/msm/vidc/vidc_hfi_helper.h | 6 ++++++ 4 files changed, 28 insertions(+) diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c index f1ba2f85a415..8c495204da45 100644 --- a/drivers/media/platform/msm/vidc/hfi_packetization.c +++ b/drivers/media/platform/msm/vidc/hfi_packetization.c @@ -1001,6 +1001,18 @@ int create_pkt_cmd_session_set_property( pkt->size += sizeof(struct hfi_frame_rate); break; } + case HAL_CONFIG_OPERATING_RATE: + { + struct hfi_operating_rate *hfi; + struct hal_operating_rate *prop = + (struct hal_operating_rate *) pdata; + + pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_OPERATING_RATE; + hfi = (struct hfi_operating_rate *) &pkt->rg_property_data[1]; + hfi->operating_rate = prop->operating_rate; + pkt->size += sizeof(struct hfi_operating_rate); + break; + } case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT: { u32 buffer_type; diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 405575f8f904..a6f5a91c0c56 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -1224,6 +1224,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) int rc = 0; struct hal_request_iframe request_iframe; struct hal_bitrate bitrate; + struct hal_operating_rate operating_rate; struct hal_profile_level profile_level; enum hal_h264_entropy h264_entropy; struct hal_intra_period intra_period; @@ -1909,6 +1910,10 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) ctrl->val >> 16); inst->clk_data.operating_rate = ctrl->val; inst->clk_data.turbo_mode = false; + property_id = HAL_CONFIG_OPERATING_RATE; + operating_rate.operating_rate = + inst->clk_data.operating_rate; + pdata = &operating_rate; } break; case V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_TYPE: diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h index 65e1545927db..fdcc9664c6dd 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h @@ -118,6 +118,7 @@ enum hal_extradata_id { enum hal_property { HAL_CONFIG_FRAME_RATE = 0x04000001, + HAL_CONFIG_OPERATING_RATE, HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT, HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO, HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO, @@ -408,6 +409,10 @@ struct hal_frame_rate { u32 frame_rate; }; +struct hal_operating_rate { + u32 operating_rate; +}; + enum hal_uncompressed_format { HAL_COLOR_FORMAT_MONOCHROME = 0x00000001, HAL_COLOR_FORMAT_NV12 = 0x00000002, diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h index c16a407a4833..42210f980da1 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h @@ -247,6 +247,8 @@ struct hfi_buffer_info { (HFI_PROPERTY_CONFIG_COMMON_START + 0x001) #define HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE \ (HFI_PROPERTY_CONFIG_COMMON_START + 0x002) +#define HFI_PROPERTY_CONFIG_OPERATING_RATE \ + (HFI_PROPERTY_CONFIG_COMMON_START + 0x003) #define HFI_PROPERTY_PARAM_VDEC_COMMON_START \ (HFI_DOMAIN_BASE_VDEC + HFI_ARCH_COMMON_OFFSET + 0x3000) @@ -479,6 +481,10 @@ struct hfi_frame_rate { u32 frame_rate; }; +struct hfi_operating_rate { + u32 operating_rate; +}; + #define HFI_INTRA_REFRESH_NONE (HFI_COMMON_BASE + 0x1) #define HFI_INTRA_REFRESH_CYCLIC (HFI_COMMON_BASE + 0x2) #define HFI_INTRA_REFRESH_RANDOM (HFI_COMMON_BASE + 0x5) -- GitLab From cac2f3375d76139bf3583f18acf663ab46e17d6b Mon Sep 17 00:00:00 2001 From: Swathi Sridhar Date: Wed, 13 Jun 2018 17:22:54 -0700 Subject: [PATCH 0229/1299] ARM: dts: msm: Include reserved-memory DT changes for sdxprairie Describe the reserved-memory regions for sdxprairie. Change-Id: Ic18661f3f7136e5a84dc3e8bc48158e8a9cc2200 Signed-off-by: Swathi Sridhar --- arch/arm64/boot/dts/qcom/sdxprairie.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi index b5659a5fe02b..c2fe6075a075 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi @@ -31,6 +31,19 @@ reg = <0x8fd00000 0x300000>; label = "peripheral2_mem"; }; + + hyp_mem: hyp_region@8fc00000 { + no-map; + reg = <0x8fc00000 0x80000>; + label = "hyp_mem"; + }; + + mpss_adsp_mem: mpss_adsp_region@84000000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x84000000 0xb700000>; + label = "mpss_adsp_mem"; + }; }; cpus { -- GitLab From aa46b37854604493163f1e1ac9b3d69d6ca3f885 Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Wed, 13 Jun 2018 17:28:11 -0700 Subject: [PATCH 0230/1299] msm: vidc: Do not set defer flag again Initially MSM_VIDC_FLAG_DEFERRED flag will be set to all the buffers that are queued by client and the flag will be removed before submitting the buffer to video firmware. In batch mode driver will hold (or defer submission to firmware) the buffers until full batch size buffers are queued by client. While deferring driver is setting the flag again to the buffer (which is wrong). There is release buffer reference (RBR) event from firmware which will submit the buffer if it is found to be queued by the client already and this buffer submission will clear the flag. There is a race condition due to RBR event as below, Client queued the buffer and driver set the flag initially. Firmware raised RBR event which will submit the buffer and clears the flag. Now driver will check the batch condition and decides to defer the buffer by setting the flag again. After full batch size count of buffers queued by the client, driver will try to submit all the buffers at once which will submit the buffer (which was already submitted as part of RBR event processing) again to firmware and resulting video failure. Resolve the issue by not setting the flag again while deciding to defer a buffer. Change-Id: I19f7aa0ef2527b5948174476d0897cb46c6f134e Signed-off-by: Maheshwar Ajja --- drivers/media/platform/msm/vidc/msm_vidc_common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 16d504c55501..454b5721734a 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -4183,7 +4183,6 @@ int msm_comm_qbuf_decode_batch(struct msm_vidc_inst *inst, count = num_pending_qbufs(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); if (count < inst->batch.size) { - mbuf->flags |= MSM_VIDC_FLAG_DEFERRED; print_vidc_buffer(VIDC_DBG, "batch-qbuf deferred", inst, mbuf); return 0; -- GitLab From 699bed22947365fec6dfa449e5e6b6b8354776a0 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Tue, 27 Mar 2018 15:27:27 -0700 Subject: [PATCH 0231/1299] PM / hibernate: Add CONFIG_HIBERNATION_IMAGE_REUSE By default this hibernation image is erased after either a successful or unsuccessful hibernation restore sequeunce. Since filesystem contents on disk are not part of the hibernation image, failure to create a new hibernation image every boot can lead to filesystem corruption. Conversely, if the usecase can guarantee that the filesystem is not ever modified, the same hibernation image can be reused. This prevents creating additional hibernation images unncesarily. For more details, refer to the description of CONFIG_HIBERNATION for booting without resuming. Change-Id: I4a8d5aba170bbf00f837804c2df26d8d8d682af2 Signed-off-by: Patrick Daly --- kernel/power/Kconfig | 17 +++++++++++++++++ kernel/power/swap.c | 2 ++ 2 files changed, 19 insertions(+) diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index f4330a2842a3..a29eaee3789d 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -77,6 +77,23 @@ config HIBERNATION For more information take a look at . +config HIBERNATION_IMAGE_REUSE + bool "Reuse hibernation image" + depends on HIBERNATION + ---help--- + By default this hibernation image is erased after either a + successful or unsuccessful hibernation restore sequeunce. Since + filesystem contents on disk are not part of the hibernation + image, failure to create a new hibernation image every boot can + lead to filesystem corruption. + + Conversely, if the usecase can guarantee that the filesystem is + not ever modified, the same hibernation image can be reused. This + prevents creating additional hibernation images unncesarily. + + For more details, refer to the description of CONFIG_HIBERNATION + for booting without resuming. + config ARCH_SAVE_PAGE_KEYS bool diff --git a/kernel/power/swap.c b/kernel/power/swap.c index d7cdc426ee38..a7a7849d8ac6 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -1540,10 +1540,12 @@ int swsusp_check(void) if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) { memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); +#ifndef CONFIG_HIBERNATION_IMAGE_REUSE /* Reset swap signature now */ error = hib_submit_io(REQ_OP_WRITE, REQ_SYNC, swsusp_resume_block, swsusp_header, NULL); +#endif } else { error = -EINVAL; } -- GitLab From edcfa65abe5e2231ff663f68c65352ccf986339d Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Mon, 7 May 2018 13:07:50 -0700 Subject: [PATCH 0232/1299] PM/Hibernate: Add Config option to skip crc check Some filesystem devices may have hw support for integrity checks. Repeating the check in software is unnecessary. Change-Id: I3a487e1714aecd57124f9b032751ee71d6d6dc37 Signed-off-by: Patrick Daly --- kernel/power/Kconfig | 10 ++++++++++ kernel/power/swap.c | 10 ++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index a29eaee3789d..bf60b37f1df1 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -94,6 +94,16 @@ config HIBERNATION_IMAGE_REUSE For more details, refer to the description of CONFIG_HIBERNATION for booting without resuming. +config HIBERNATION_SKIP_CRC + bool "Skip LZO image CRC check" + default n + depends on HIBERNATION + ---help--- + Some filesystem devices may have hw based integrity checks. In this + scenario, repeating the integrity check in software is unnecessary + and wasteful. This config option has no effect if uncompressed + hibernation images are used. + config ARCH_SAVE_PAGE_KEYS bool diff --git a/kernel/power/swap.c b/kernel/power/swap.c index a7a7849d8ac6..52623f04f18f 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -605,9 +605,10 @@ static int crc32_threadfn(void *data) } atomic_set(&d->ready, 0); - for (i = 0; i < d->run_threads; i++) - *d->crc32 = crc32_le(*d->crc32, - d->unc[i], *d->unc_len[i]); + if (!IS_ENABLED(CONFIG_HIBERNATION_SKIP_CRC)) + for (i = 0; i < d->run_threads; i++) + *d->crc32 = crc32_le(*d->crc32, + d->unc[i], *d->unc_len[i]); atomic_set(&d->stop, 1); wake_up(&d->done); } @@ -1453,7 +1454,8 @@ static int load_image_lzo(struct swap_map_handle *handle, if (!snapshot_image_loaded(snapshot)) ret = -ENODATA; if (!ret) { - if (swsusp_header->flags & SF_CRC32_MODE) { + if ((swsusp_header->flags & SF_CRC32_MODE) && + (!IS_ENABLED(CONFIG_HIBERNATION_SKIP_CRC))) { if(handle->crc32 != swsusp_header->crc32) { printk(KERN_ERR "PM: Invalid image CRC32!\n"); -- GitLab From cdc02dd066000961b20ade9817af809042d06d02 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Mon, 16 Apr 2018 18:19:17 -0700 Subject: [PATCH 0233/1299] ARM: Add option to build Image/dtb combo Add a target Image-dtb which will build an uncompressed kernel with an appended dtb image. Change-Id: I2ede8fd935327d75d7378c2868d39c416d704724 Signed-off-by: Patrick Daly --- arch/arm/Makefile | 4 ++++ arch/arm/boot/.gitignore | 2 ++ arch/arm/boot/Makefile | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 45baf1b38f29..561a4d2ed19f 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -361,6 +361,10 @@ endif zImage-dtb: vmlinux scripts dtbs $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) DTSSUBDIR=$(DTSSUBDIR) $(boot)/$@ +Image-dtb: vmlinux scripts dtbs + $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) DTSSUBDIR=$(DTSSUBDIR) $(boot)/$@ + + # We use MRPROPER_FILES and CLEAN_FILES now archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore index ce1c5ff746e7..c8ed363b6a44 100644 --- a/arch/arm/boot/.gitignore +++ b/arch/arm/boot/.gitignore @@ -3,3 +3,5 @@ zImage xipImage bootpImage uImage +Image-dtb-hdr +Image-dtb diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 4175dfe43225..2fa123e315cc 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -59,6 +59,14 @@ $(obj)/xipImage: FORCE $(obj)/Image: vmlinux FORCE $(call if_changed,objcopy) +$(obj)/Image-dtb-hdr: $(obj)/Image FORCE + echo -n 'UNCOMPRESSED_IMG' > $@ && \ + $(call size_append, $(filter-out FORCE,$^)) >> $@ + +$(obj)/Image-dtb: $(obj)/Image-dtb-hdr $(obj)/Image $(DTB_OBJS) FORCE + $(call if_changed,cat) + @echo ' Kernel: $@ is ready' + $(obj)/compressed/vmlinux: $(obj)/Image FORCE $(Q)$(MAKE) $(build)=$(obj)/compressed $@ -- GitLab From 8a4ab68ac94aafbf13ee9a09a5a26deb04887273 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 28 Mar 2017 13:30:18 -0700 Subject: [PATCH 0234/1299] ANDROID: ARM: Allow to choose appended kernel image By default appended kernel image is Image.gz-dtb. New config option BUILD_ARM_APPENDED_KERNEL_IMAGE_NAME allows to choose between zImage-dtb and Image-dtb. Change-Id: I1c71b85136f1beeb61782e4646820718c1ccd7e4 Signed-off-by: Dmitry Shmidt Git-Repo: https://android.googlesource.com/kernel/common Git-Commit: 4bdcc9366ab74f0880ba72f7a1a98391359f127f [pdaly] Ported to ARM32 Signed-off-by: Patrick Daly --- arch/arm/Kconfig | 20 ++++++++++++++++++++ arch/arm/Makefile | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a4a62a217ed3..9756f8ab7867 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1902,6 +1902,26 @@ config BUILD_ARM_APPENDED_DTB_IMAGE Enabling this option will cause a concatenated zImage and list of DTBs to be built by default (instead of a standalone zImage.) The image will built in arch/arm/boot/zImage-dtb +choice + prompt "Appended DTB Kernel Image name" + depends on BUILD_ARM_APPENDED_DTB_IMAGE + default ZIMG_DTB + help + Enabling this option will cause a specific kernel image Image or + Image.gz to be used for final image creation. + The image will built in arch/arm/boot/IMAGE-NAME-dtb + + config ZIMG_DTB + bool "zImage-dtb" + config IMG_DTB + bool "Image-dtb" +endchoice + +config BUILD_ARM_APPENDED_KERNEL_IMAGE_NAME + string + depends on BUILD_ARM_APPENDED_DTB_IMAGE + default "zImage-dtb" if ZIMG_DTB + default "Image-dtb" if IMG_DTB config BUILD_ARM_APPENDED_DTB_IMAGE_NAMES string "Default dtb names" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 561a4d2ed19f..3d806f902610 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -307,7 +307,7 @@ boot := arch/arm/boot ifeq ($(CONFIG_XIP_KERNEL),y) KBUILD_IMAGE := $(boot)/xipImage else ifeq ($(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE),y) -KBUILD_IMAGE := $(boot)/zImage-dtb +KBUILD_IMAGE := $(boot)/$(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_KERNEL_IMAGE_NAME)) else KBUILD_IMAGE := $(boot)/zImage endif -- GitLab From 5203ee82eb7457a4b998f81e2693b0b5b87b0345 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Thu, 17 May 2018 19:48:57 -0700 Subject: [PATCH 0235/1299] usb: dwc3: Fix probe deferral issue regulator_get will return -EPROBE_DEFER if named supply is present in devicetree, but the regulator driver has not probed. Change-Id: Ieef7c133e92a35d881fd6fcebd88df38a1b60357 Signed-off-by: Patrick Daly --- drivers/usb/dwc3/dwc3-msm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 1ad0bc4f47dc..55381d82b193 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -2713,8 +2713,11 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc) int ret; mdwc->dwc3_gdsc = devm_regulator_get(mdwc->dev, "USB3_GDSC"); - if (IS_ERR(mdwc->dwc3_gdsc)) + if (IS_ERR(mdwc->dwc3_gdsc)) { + if (PTR_ERR(mdwc->dwc3_gdsc) == -EPROBE_DEFER) + return PTR_ERR(mdwc->dwc3_gdsc); mdwc->dwc3_gdsc = NULL; + } mdwc->xo_clk = devm_clk_get(mdwc->dev, "xo"); if (IS_ERR(mdwc->xo_clk)) { -- GitLab From bd1f050cdf6f76d8eaa305adf7d5c92f96fb68e3 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Fri, 11 May 2018 18:47:45 -0700 Subject: [PATCH 0236/1299] spmi: pmic-arb: Use asynchronous probe A spmi controller may have many child devices, which together may take a signifigant amount of time to register and probe. Reduce this effect by probing asynchronously. After: [ 0.277217] calling__software_resume+0x0/0x24c_@_1 Before: [ 0.319295] calling__software_resume+0x0/0x24c_@_1 Change-Id: I95704a2ae7aae98e23dc9f29c7d023867d60388d Signed-off-by: Patrick Daly --- drivers/spmi/spmi-pmic-arb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index db43169a95fb..6985e6cc434e 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -1369,6 +1369,7 @@ static struct platform_driver spmi_pmic_arb_driver = { .driver = { .name = "spmi_pmic_arb", .of_match_table = spmi_pmic_arb_match_table, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; -- GitLab From 8c3c05020a10aff04bf755d6370b1f672ffdb20e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 4 Oct 2017 19:30:53 -0500 Subject: [PATCH 0237/1299] of: move kobj_to_device_node() into dynamic.c The only user of kobj_to_device_node() is in dynamic.c, so move it there. This avoids having to make it conditional once kobject is configurable. Change-Id: I5bab9af9d6ebda3aff5359e5aba3ca2eccca493e Tested-by: Nicolas Pitre Reviewed-by: Frank Rowand Acked-by: Grant Likely Signed-off-by: Rob Herring Git-Commit: 4c2bb57400394e4ec631a42dcf637e925db6202e Git-Repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Patrick Daly --- drivers/of/dynamic.c | 5 +++++ drivers/of/of_private.h | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index 301b6db2b48d..9d6ba18c529f 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -16,6 +16,11 @@ #include "of_private.h" +static struct device_node *kobj_to_device_node(struct kobject *kobj) +{ + return container_of(kobj, struct device_node, kobj); +} + /** * of_node_get() - Increment refcount of a node * @node: Node to inc refcount, NULL is supported to simplify writing of diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index f2111674e45c..4b317318a3f3 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -35,12 +35,6 @@ extern struct mutex of_mutex; extern struct list_head aliases_lookup; extern struct kset *of_kset; - -static inline struct device_node *kobj_to_device_node(struct kobject *kobj) -{ - return container_of(kobj, struct device_node, kobj); -} - #if defined(CONFIG_OF_DYNAMIC) extern int of_property_notify(int action, struct device_node *np, struct property *prop, struct property *old_prop); -- GitLab From c83742d4885b05df1800aa0b9a193f9008c898f5 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 4 Oct 2017 14:04:01 -0500 Subject: [PATCH 0238/1299] of: wrap accesses to device_node kobject In preparation to make kobject element in struct device_node optional, provide and use a macro to return the kobject pointer. The only user outside the DT core is the driver core. Change-Id: I47023bc3b123af975adf99d9bbb8e41bdffdaeb2 Acked-by: Greg Kroah-Hartman Tested-by: Nicolas Pitre Reviewed-by: Frank Rowand Acked-by: Grant Likely Signed-off-by: Rob Herring Git-Commit: 0c3c234b95fa7f1dfa19e1456a47ebafc300dd6b Git-Repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Patrick Daly --- drivers/base/core.c | 2 +- include/linux/of.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 425a460f9211..4fbf07a77fab 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1579,7 +1579,7 @@ static int device_add_class_symlinks(struct device *dev) int error; if (of_node) { - error = sysfs_create_link(&dev->kobj, &of_node->kobj,"of_node"); + error = sysfs_create_link(&dev->kobj, of_node_kobj(of_node), "of_node"); if (error) dev_warn(dev, "Error %d creating of_node link\n",error); /* An error here doesn't warrant bringing down the device */ diff --git a/include/linux/of.h b/include/linux/of.h index 13eb8bc92c10..08182177168a 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -107,6 +107,8 @@ static inline void of_node_init(struct device_node *node) node->fwnode.ops = &of_fwnode_ops; } +#define of_node_kobj(n) (&(n)->kobj) + /* true when node is initialized */ static inline int of_node_is_initialized(struct device_node *node) { -- GitLab From 0cade139bd54854e1770561524d336126433e740 Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Wed, 13 Jun 2018 17:04:38 -0700 Subject: [PATCH 0239/1299] ARM: dts: msm: configure secondary chargers on MTP and QRD Configure both SMB1390 and SMB1355 as secondary chargers on SM8150 MTP. Disable SMB1355 on QRD as it is not present and keep SMB1390 as the only secondary charger. Change-Id: I7fce8cb4d8e01f3f04ae29531f26e5f6a5721d1c Signed-off-by: Harry Yang --- arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi | 2 +- arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi index ade27786b84c..1d2bd5450e73 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi @@ -558,7 +558,7 @@ }; &pm8150b_charger { - qcom,sec-charger-config = <1>; + qcom,sec-charger-config = <3>; qcom,auto-recharge-soc = <98>; io-channels = <&pm8150b_vadc ADC_USB_IN_V_16>, <&pm8150b_vadc ADC_USB_IN_I>, diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi index caa51c71c686..d346884fa069 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi @@ -512,13 +512,3 @@ <0x49 0x70 0x28 0x74>; }; - -&smb1355 { - status = "ok"; -}; - -&smb1355_charger { - io-channels = <&pm8150b_vadc ADC_AMUX_THM2>; - io-channel-names = "charger_temp"; - status = "ok"; -}; -- GitLab From 561531a51600c0860619d39096a2d65085f0bac8 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 4 Oct 2017 14:09:40 -0500 Subject: [PATCH 0240/1299] of: make kobject and bin_attribute support configurable Having device_nodes be kobjects is only needed if sysfs or OF_DYNAMIC is enabled. Otherwise, having a kobject in struct device_node is unnecessary bloat in minimal kernel configurations. Likewise, bin_attribute is only needed in struct property when sysfs is enabled, so we can make it configurable too. Change-Id: I0a70d2b4b0d362493987fca2eb91e77ae3171d1e Tested-by: Nicolas Pitre Reviewed-by: Frank Rowand Acked-by: Grant Likely Signed-off-by: Rob Herring Git-Commit: b56b5528f5b3c3d47e7c0ca67318c45e980d93f0 Git-Repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [pdaly: added NULL check in safe_name()] Signed-off-by: Patrick Daly --- drivers/of/Kconfig | 4 + drivers/of/Makefile | 1 + drivers/of/base.c | 133 -------------------------------- drivers/of/dynamic.c | 22 ------ drivers/of/kobj.c | 164 ++++++++++++++++++++++++++++++++++++++++ drivers/of/of_private.h | 23 ++++++ include/linux/of.h | 22 +++--- 7 files changed, 202 insertions(+), 167 deletions(-) create mode 100644 drivers/of/kobj.c diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 52a297d5560a..e4304e70a6d3 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -46,10 +46,14 @@ config OF_EARLY_FLATTREE config OF_PROMTREE bool +config OF_KOBJ + def_bool SYSFS + # Hardly any platforms need this. It is safe to select, but only do so if you # need it. config OF_DYNAMIC bool "Support for dynamic device trees" if OF_UNITTEST + select OF_KOBJ help On some platforms, the device tree can be manipulated at runtime. While this option is selected automatically on such platforms, you diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 97ad18c5f360..700d878b7c6c 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-y = base.o device.o platform.o property.o +obj-$(CONFIG_OF_KOBJ) += kobj.o obj-$(CONFIG_OF_DYNAMIC) += dynamic.o obj-$(CONFIG_OF_FLATTREE) += fdt.o obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o diff --git a/drivers/of/base.c b/drivers/of/base.c index 9e8dca88f071..48ec9878b79c 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -95,108 +95,6 @@ int __weak of_node_to_nid(struct device_node *np) } #endif -#ifndef CONFIG_OF_DYNAMIC -static void of_node_release(struct kobject *kobj) -{ - /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ -} -#endif /* CONFIG_OF_DYNAMIC */ - -struct kobj_type of_node_ktype = { - .release = of_node_release, -}; - -static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buf, - loff_t offset, size_t count) -{ - struct property *pp = container_of(bin_attr, struct property, attr); - return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length); -} - -/* always return newly allocated name, caller must free after use */ -static const char *safe_name(struct kobject *kobj, const char *orig_name) -{ - const char *name = orig_name; - struct kernfs_node *kn; - int i = 0; - - /* don't be a hero. After 16 tries give up */ - while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) { - sysfs_put(kn); - if (name != orig_name) - kfree(name); - name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i); - } - - if (name == orig_name) { - name = kstrdup(orig_name, GFP_KERNEL); - } else { - pr_warn("Duplicate name in %s, renamed to \"%s\"\n", - kobject_name(kobj), name); - } - return name; -} - -int __of_add_property_sysfs(struct device_node *np, struct property *pp) -{ - int rc; - - /* Important: Don't leak passwords */ - bool secure = strncmp(pp->name, "security-", 9) == 0; - - if (!IS_ENABLED(CONFIG_SYSFS)) - return 0; - - if (!of_kset || !of_node_is_attached(np)) - return 0; - - sysfs_bin_attr_init(&pp->attr); - pp->attr.attr.name = safe_name(&np->kobj, pp->name); - pp->attr.attr.mode = secure ? 0400 : 0444; - pp->attr.size = secure ? 0 : pp->length; - pp->attr.read = of_node_property_read; - - rc = sysfs_create_bin_file(&np->kobj, &pp->attr); - WARN(rc, "error adding attribute %s to node %pOF\n", pp->name, np); - return rc; -} - -int __of_attach_node_sysfs(struct device_node *np) -{ - const char *name; - struct kobject *parent; - struct property *pp; - int rc; - - if (!IS_ENABLED(CONFIG_SYSFS)) - return 0; - - if (!of_kset) - return 0; - - np->kobj.kset = of_kset; - if (!np->parent) { - /* Nodes without parents are new top level trees */ - name = safe_name(&of_kset->kobj, "base"); - parent = NULL; - } else { - name = safe_name(&np->parent->kobj, kbasename(np->full_name)); - parent = &np->parent->kobj; - } - if (!name) - return -ENOMEM; - rc = kobject_add(&np->kobj, parent, "%s", name); - kfree(name); - if (rc) - return rc; - - for_each_property_of_node(np, pp) - __of_add_property_sysfs(np, pp); - - return 0; -} - static struct device_node **phandle_cache; static u32 phandle_cache_mask; @@ -1608,22 +1506,6 @@ int __of_remove_property(struct device_node *np, struct property *prop) return 0; } -void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop) -{ - sysfs_remove_bin_file(&np->kobj, &prop->attr); - kfree(prop->attr.attr.name); -} - -void __of_remove_property_sysfs(struct device_node *np, struct property *prop) -{ - if (!IS_ENABLED(CONFIG_SYSFS)) - return; - - /* at early boot, bail here and defer setup to of_init() */ - if (of_kset && of_node_is_attached(np)) - __of_sysfs_remove_bin_file(np, prop); -} - /** * of_remove_property - Remove a property from a node. * @@ -1683,21 +1565,6 @@ int __of_update_property(struct device_node *np, struct property *newprop, return 0; } -void __of_update_property_sysfs(struct device_node *np, struct property *newprop, - struct property *oldprop) -{ - if (!IS_ENABLED(CONFIG_SYSFS)) - return; - - /* At early boot, bail out and defer setup to of_init() */ - if (!of_kset) - return; - - if (oldprop) - __of_sysfs_remove_bin_file(np, oldprop); - __of_add_property_sysfs(np, newprop); -} - /* * of_update_property - Update a property in a node, if the property does * not exist, add it. diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index 9d6ba18c529f..39e8cf731764 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -48,28 +48,6 @@ void of_node_put(struct device_node *node) } EXPORT_SYMBOL(of_node_put); -void __of_detach_node_sysfs(struct device_node *np) -{ - struct property *pp; - - if (!IS_ENABLED(CONFIG_SYSFS)) - return; - - BUG_ON(!of_node_is_initialized(np)); - if (!of_kset) - return; - - /* only remove properties if on sysfs */ - if (of_node_is_attached(np)) { - for_each_property_of_node(np, pp) - __of_sysfs_remove_bin_file(np, pp); - kobject_del(&np->kobj); - } - - /* finally remove the kobj_init ref */ - of_node_put(np); -} - static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain); int of_reconfig_notifier_register(struct notifier_block *nb) diff --git a/drivers/of/kobj.c b/drivers/of/kobj.c new file mode 100644 index 000000000000..23d8f2e1ffea --- /dev/null +++ b/drivers/of/kobj.c @@ -0,0 +1,164 @@ +#include +#include + +#include "of_private.h" + +/* true when node is initialized */ +static int of_node_is_initialized(struct device_node *node) +{ + return node && node->kobj.state_initialized; +} + +/* true when node is attached (i.e. present on sysfs) */ +int of_node_is_attached(struct device_node *node) +{ + return node && node->kobj.state_in_sysfs; +} + + +#ifndef CONFIG_OF_DYNAMIC +static void of_node_release(struct kobject *kobj) +{ + /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ +} +#endif /* CONFIG_OF_DYNAMIC */ + +struct kobj_type of_node_ktype = { + .release = of_node_release, +}; + +static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t offset, size_t count) +{ + struct property *pp = container_of(bin_attr, struct property, attr); + return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length); +} + +/* always return newly allocated name, caller must free after use */ +static const char *safe_name(struct kobject *kobj, const char *orig_name) +{ + const char *name = orig_name; + struct kernfs_node *kn; + int i = 0; + + /* don't be a hero. After 16 tries give up */ + while (i < 16 && name && (kn = sysfs_get_dirent(kobj->sd, name))) { + sysfs_put(kn); + if (name != orig_name) + kfree(name); + name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i); + } + + if (name == orig_name) { + name = kstrdup(orig_name, GFP_KERNEL); + } else { + pr_warn("Duplicate name in %s, renamed to \"%s\"\n", + kobject_name(kobj), name); + } + return name; +} + +int __of_add_property_sysfs(struct device_node *np, struct property *pp) +{ + int rc; + + /* Important: Don't leak passwords */ + bool secure = strncmp(pp->name, "security-", 9) == 0; + + if (!IS_ENABLED(CONFIG_SYSFS)) + return 0; + + if (!of_kset || !of_node_is_attached(np)) + return 0; + + sysfs_bin_attr_init(&pp->attr); + pp->attr.attr.name = safe_name(&np->kobj, pp->name); + pp->attr.attr.mode = secure ? 0400 : 0444; + pp->attr.size = secure ? 0 : pp->length; + pp->attr.read = of_node_property_read; + + rc = sysfs_create_bin_file(&np->kobj, &pp->attr); + WARN(rc, "error adding attribute %s to node %pOF\n", pp->name, np); + return rc; +} + +void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop) +{ + if (!IS_ENABLED(CONFIG_SYSFS)) + return; + + sysfs_remove_bin_file(&np->kobj, &prop->attr); + kfree(prop->attr.attr.name); +} + +void __of_remove_property_sysfs(struct device_node *np, struct property *prop) +{ + /* at early boot, bail here and defer setup to of_init() */ + if (of_kset && of_node_is_attached(np)) + __of_sysfs_remove_bin_file(np, prop); +} + +void __of_update_property_sysfs(struct device_node *np, struct property *newprop, + struct property *oldprop) +{ + /* At early boot, bail out and defer setup to of_init() */ + if (!of_kset) + return; + + if (oldprop) + __of_sysfs_remove_bin_file(np, oldprop); + __of_add_property_sysfs(np, newprop); +} + +int __of_attach_node_sysfs(struct device_node *np) +{ + const char *name; + struct kobject *parent; + struct property *pp; + int rc; + + if (!of_kset) + return 0; + + np->kobj.kset = of_kset; + if (!np->parent) { + /* Nodes without parents are new top level trees */ + name = safe_name(&of_kset->kobj, "base"); + parent = NULL; + } else { + name = safe_name(&np->parent->kobj, kbasename(np->full_name)); + parent = &np->parent->kobj; + } + if (!name) + return -ENOMEM; + rc = kobject_add(&np->kobj, parent, "%s", name); + kfree(name); + if (rc) + return rc; + + for_each_property_of_node(np, pp) + __of_add_property_sysfs(np, pp); + + return 0; +} + +void __of_detach_node_sysfs(struct device_node *np) +{ + struct property *pp; + + BUG_ON(!of_node_is_initialized(np)); + if (!of_kset) + return; + + /* only remove properties if on sysfs */ + if (of_node_is_attached(np)) { + for_each_property_of_node(np, pp) + __of_sysfs_remove_bin_file(np, pp); + kobject_del(&np->kobj); + } + + /* finally remove the kobj_init ref */ + of_node_put(np); +} + diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 4b317318a3f3..3b0b3a5c7c6e 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -49,6 +49,29 @@ static inline int of_property_notify(int action, struct device_node *np, } #endif /* CONFIG_OF_DYNAMIC */ +#if defined(CONFIG_OF_KOBJ) +int of_node_is_attached(struct device_node *node); +int __of_add_property_sysfs(struct device_node *np, struct property *pp); +void __of_remove_property_sysfs(struct device_node *np, struct property *prop); +void __of_update_property_sysfs(struct device_node *np, struct property *newprop, + struct property *oldprop); +int __of_attach_node_sysfs(struct device_node *np); +void __of_detach_node_sysfs(struct device_node *np); +#else +static inline int __of_add_property_sysfs(struct device_node *np, struct property *pp) +{ + return 0; +} +static inline void __of_remove_property_sysfs(struct device_node *np, struct property *prop) {} +static inline void __of_update_property_sysfs(struct device_node *np, + struct property *newprop, struct property *oldprop) {} +static inline int __of_attach_node_sysfs(struct device_node *np) +{ + return 0; +} +static inline void __of_detach_node_sysfs(struct device_node *np) {} +#endif + #if defined(CONFIG_OF_UNITTEST) && defined(CONFIG_OF_OVERLAY) extern void __init unittest_unflatten_overlay_base(void); #else diff --git a/include/linux/of.h b/include/linux/of.h index 08182177168a..5081debc56df 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -39,7 +39,9 @@ struct property { struct property *next; unsigned long _flags; unsigned int unique_id; +#if defined(CONFIG_OF_KOBJ) struct bin_attribute attr; +#endif }; #if defined(CONFIG_SPARC) @@ -58,7 +60,9 @@ struct device_node { struct device_node *parent; struct device_node *child; struct device_node *sibling; +#if defined(CONFIG_OF_KOBJ) struct kobject kobj; +#endif unsigned long _flags; void *data; #if defined(CONFIG_SPARC) @@ -103,23 +107,17 @@ extern struct kobj_type of_node_ktype; extern const struct fwnode_operations of_fwnode_ops; static inline void of_node_init(struct device_node *node) { +#if defined(CONFIG_OF_KOBJ) kobject_init(&node->kobj, &of_node_ktype); +#endif node->fwnode.ops = &of_fwnode_ops; } +#if defined(CONFIG_OF_KOBJ) #define of_node_kobj(n) (&(n)->kobj) - -/* true when node is initialized */ -static inline int of_node_is_initialized(struct device_node *node) -{ - return node && node->kobj.state_initialized; -} - -/* true when node is attached (i.e. present on sysfs) */ -static inline int of_node_is_attached(struct device_node *node) -{ - return node && node->kobj.state_in_sysfs; -} +#else +#define of_node_kobj(n) NULL +#endif #ifdef CONFIG_OF_DYNAMIC extern struct device_node *of_node_get(struct device_node *node); -- GitLab From 7683695831ce6800dcabf20458968fb56e38e643 Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Wed, 13 Jun 2018 18:15:01 -0700 Subject: [PATCH 0241/1299] sched/fair: fix possible usage of uninitialized variables It is possible that uninitialized variables would be used when sched_task_util trace point is enabled in some cases. Fix it by using local variables. Change-Id: Ib8edf0b40fa735ff98907ed2f29b9f1b4ec871cd Signed-off-by: Satya Durga Srinivasu Prabhala --- kernel/sched/fair.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 3ace54a93c45..929b5fa2adbf 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7644,8 +7644,10 @@ static int find_energy_efficient_cpu(struct sched_domain *sd, struct cpumask *rtg_target = find_rtg_target(p); struct find_best_target_env fbt_env; bool need_idle = wake_to_idle(p); + bool placement_boost = task_placement_boost_enabled(p); u64 start_t = 0; int fastpath = 0; + int next_cpu = -1, backup_cpu = -1; if (trace_sched_task_util_enabled()) start_t = sched_clock(); @@ -7714,13 +7716,15 @@ static int find_energy_efficient_cpu(struct sched_domain *sd, eenv->max_cpu_count = EAS_CPU_BKP + 1; fbt_env.rtg_target = rtg_target; - fbt_env.placement_boost = task_placement_boost_enabled(p); + fbt_env.placement_boost = placement_boost; fbt_env.need_idle = need_idle; /* Find a cpu with sufficient capacity */ eenv->cpu[EAS_CPU_NXT].cpu_id = find_best_target(p, &eenv->cpu[EAS_CPU_BKP].cpu_id, boosted, prefer_idle, &fbt_env); + next_cpu = eenv->cpu[EAS_CPU_NXT].cpu_id; + backup_cpu = eenv->cpu[EAS_CPU_BKP].cpu_id; /* take note if no backup was found */ if (eenv->cpu[EAS_CPU_BKP].cpu_id < 0) @@ -7758,11 +7762,9 @@ static int find_energy_efficient_cpu(struct sched_domain *sd, eenv->cpu[eenv->next_idx].cpu_id; out: - trace_sched_task_util(p, eenv->cpu[EAS_CPU_NXT].cpu_id, - eenv->cpu[EAS_CPU_BKP].cpu_id, energy_cpu, sync, - fbt_env.need_idle, fastpath, fbt_env.placement_boost, - rtg_target ? cpumask_first(rtg_target) : -1, - start_t); + trace_sched_task_util(p, next_cpu, backup_cpu, energy_cpu, sync, + need_idle, fastpath, placement_boost, + rtg_target ? cpumask_first(rtg_target) : -1, start_t); return energy_cpu; } -- GitLab From 3a533744f51c6fb84d30e9a3903b7f6f7f9d34b5 Mon Sep 17 00:00:00 2001 From: Swathi Sridhar Date: Wed, 13 Jun 2018 17:24:57 -0700 Subject: [PATCH 0242/1299] ARM: dts: msm: Include ION DT changes for sdxprairie Describe the ION device tree nodes for sdxprairie. Change-Id: I08bec24e9a64677a53719c57015b49242bb0da4d Signed-off-by: Swathi Sridhar --- arch/arm64/boot/dts/qcom/sdxprairie-ion.dtsi | 23 ++++++++++++++++++++ arch/arm64/boot/dts/qcom/sdxprairie.dtsi | 1 + 2 files changed, 24 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sdxprairie-ion.dtsi diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-ion.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-ion.dtsi new file mode 100644 index 000000000000..f1fcf928746e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdxprairie-ion.dtsi @@ -0,0 +1,23 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +&soc { + qcom,ion { + compatible = "qcom,msm-ion"; + #address-cells = <1>; + #size-cells = <0>; + + system_heap: qcom,ion-heap@25 { + reg = <25>; + qcom,ion-heap-type = "SYSTEM"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi index b5659a5fe02b..32f890529865 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi @@ -138,3 +138,4 @@ }; #include "sdxprairie-pinctrl.dtsi" +#include "sdxprairie-ion.dtsi" -- GitLab From 932c964d47f5b7fd5ed038ebb29b9a9f3b65346d Mon Sep 17 00:00:00 2001 From: Tingwei Zhang Date: Wed, 13 Jun 2018 14:33:50 +0800 Subject: [PATCH 0243/1299] ARM: dts: msm: Add header file in camera dtsi on SM8150 Device tree file should include the header file it uses. Add header file to camera device tree file. Change-Id: I77c741e972ab8bdfe3ba14b99e9897bd0d9ac6eb Signed-off-by: Tingwei Zhang --- arch/arm64/boot/dts/qcom/sm8150-camera-sensor-qrd.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-qrd.dtsi index 1a13e57b20c8..003a25edde70 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-qrd.dtsi @@ -11,6 +11,8 @@ * GNU General Public License for more details. */ +#include + &soc { led_flash_rear: qcom,camera-flash@0 { cell-index = <0>; -- GitLab From a4541dfbb64be178338d6dcdf07b0fd53acb1d04 Mon Sep 17 00:00:00 2001 From: Tingwei Zhang Date: Mon, 11 Jun 2018 15:46:47 +0800 Subject: [PATCH 0244/1299] ARM: dts: msm: Add SM8150 QRD DVT support Add device tree support for SM8150 QRD DVT device. Change-Id: If73d74beeda8ce2212e9f2851a19593029d82d06 Signed-off-by: Tingwei Zhang --- arch/arm64/boot/dts/qcom/Makefile | 3 +++ .../boot/dts/qcom/sm8150-qrd-dvt-overlay.dts | 27 +++++++++++++++++++ arch/arm64/boot/dts/qcom/sm8150-qrd-dvt.dtsi | 13 +++++++++ .../arm64/boot/dts/qcom/sm8150-v2-qrd-dvt.dts | 22 +++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sm8150-qrd-dvt-overlay.dts create mode 100644 arch/arm64/boot/dts/qcom/sm8150-qrd-dvt.dtsi create mode 100644 arch/arm64/boot/dts/qcom/sm8150-v2-qrd-dvt.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index b27f1d9ab513..1a73d9623ba3 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -16,6 +16,7 @@ ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y) sm8150-mtp-overlay.dtbo \ sm8150-rumi-overlay.dtbo \ sm8150-qrd-overlay.dtbo \ + sm8150-qrd-dvt-overlay.dtbo \ sm8150-auto-adp-star-overlay.dtbo \ sm8150p-cdp-overlay.dtbo \ sm8150p-mtp-overlay.dtbo \ @@ -29,6 +30,7 @@ sm8150-cdp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-mtp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-rumi-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-qrd-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb +sm8150-qrd-dvt-overlay.dtbo-base := sm8150-v2.dtb sm8150-auto-adp-star-overlay.dtbo-base := sm8150-auto.dtb sm8150-sdx50m-cdp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-sdx50m-mtp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb @@ -46,6 +48,7 @@ dtb-$(CONFIG_ARCH_SM8150) += sm8150-rumi.dtb \ sm8150-v2-mtp.dtb \ sm8150-v2-cdp.dtb \ sm8150-v2-qrd.dtb \ + sm8150-v2-qrd-dvt.dtb \ sm8150p-mtp.dtb \ sm8150p-cdp.dtb \ sm8150p-qrd.dtb \ diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd-dvt-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-qrd-dvt-overlay.dts new file mode 100644 index 000000000000..6dff873d9755 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd-dvt-overlay.dts @@ -0,0 +1,27 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include + +#include "sm8150-qrd-dvt.dtsi" + +/ { + model = "QRD DVT"; + compatible = "qcom,sm8150-qrd", "qcom,sm8150", "qcom,qrd"; + qcom,board-id = <0x01000B 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd-dvt.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd-dvt.dtsi new file mode 100644 index 000000000000..2aeddc2e51e7 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd-dvt.dtsi @@ -0,0 +1,13 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sm8150-qrd.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sm8150-v2-qrd-dvt.dts b/arch/arm64/boot/dts/qcom/sm8150-v2-qrd-dvt.dts new file mode 100644 index 000000000000..297bc1c14358 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8150-v2-qrd-dvt.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "sm8150-v2.dtsi" +#include "sm8150-qrd-dvt.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SM8150 V2 QRD DVT"; + compatible = "qcom,sm8150-qrd", "qcom,sm8150", "qcom,qrd"; + qcom,board-id = <0x01000B 0>; +}; -- GitLab From 009108f4e114dd4eac9a65984c3cb044c9d64f87 Mon Sep 17 00:00:00 2001 From: Vaibhav Deshu Venkatesh Date: Fri, 1 Jun 2018 13:04:48 -0700 Subject: [PATCH 0245/1299] msm: vidc: Amend min buffer count maintenance logic Initialize the min buffer count in driver based on the codec format and ignore the min buffer count from firmware except in case of sufficient/insufficient event. So the min buffer count will never be updated in driver until sufficient/insufficient event is received from firmware. CRs-Fixed: 2257450 Change-Id: Ie3e02dcd59c62be2da8189e3d4c49eeec1b79c8e Signed-off-by: Vaibhav Deshu Venkatesh Signed-off-by: Maheshwar Ajja --- drivers/media/platform/msm/vidc/msm_vdec.c | 72 ++++- drivers/media/platform/msm/vidc/msm_venc.c | 22 ++ drivers/media/platform/msm/vidc/msm_vidc.c | 151 +-------- drivers/media/platform/msm/vidc/msm_vidc.h | 3 +- .../media/platform/msm/vidc/msm_vidc_clocks.c | 32 +- .../media/platform/msm/vidc/msm_vidc_clocks.h | 2 +- .../media/platform/msm/vidc/msm_vidc_common.c | 289 +++++++++--------- .../media/platform/msm/vidc/msm_vidc_common.h | 3 +- .../platform/msm/vidc/msm_vidc_internal.h | 4 +- .../platform/msm/vidc/msm_vidc_platform.c | 16 + .../platform/msm/vidc/msm_vidc_res_parse.c | 2 + .../platform/msm/vidc/msm_vidc_resources.h | 1 + 12 files changed, 285 insertions(+), 312 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c index 5044fbf7c2ce..0fc5415a3348 100644 --- a/drivers/media/platform/msm/vidc/msm_vdec.c +++ b/drivers/media/platform/msm/vidc/msm_vdec.c @@ -476,6 +476,8 @@ struct msm_vidc_format vdec_formats[] = { .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, .defer_outputs = false, + .input_min_count = 4, + .output_min_count = 6, }, { .name = "H264", @@ -484,6 +486,8 @@ struct msm_vidc_format vdec_formats[] = { .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, .defer_outputs = false, + .input_min_count = 4, + .output_min_count = 8, }, { .name = "HEVC", @@ -492,6 +496,8 @@ struct msm_vidc_format vdec_formats[] = { .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, .defer_outputs = false, + .input_min_count = 4, + .output_min_count = 8, }, { .name = "VP8", @@ -500,6 +506,8 @@ struct msm_vidc_format vdec_formats[] = { .get_frame_size = get_frame_size_compressed_full_yuv, .type = OUTPUT_PORT, .defer_outputs = false, + .input_min_count = 4, + .output_min_count = 6, }, { .name = "VP9", @@ -508,6 +516,8 @@ struct msm_vidc_format vdec_formats[] = { .get_frame_size = get_frame_size_compressed_full_yuv, .type = OUTPUT_PORT, .defer_outputs = true, + .input_min_count = 4, + .output_min_count = 11, }, }; @@ -769,6 +779,16 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) inst->buff_req.buffer[3].buffer_count_min_host = inst->buff_req.buffer[3].buffer_count_actual = MIN_NUM_DEC_CAPTURE_BUFFERS; + inst->buff_req.buffer[4].buffer_type = HAL_BUFFER_EXTRADATA_INPUT; + inst->buff_req.buffer[5].buffer_type = HAL_BUFFER_EXTRADATA_OUTPUT; + inst->buff_req.buffer[6].buffer_type = HAL_BUFFER_EXTRADATA_OUTPUT2; + inst->buff_req.buffer[7].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH; + inst->buff_req.buffer[8].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH_1; + inst->buff_req.buffer[9].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH_2; + inst->buff_req.buffer[10].buffer_type = HAL_BUFFER_INTERNAL_PERSIST; + inst->buff_req.buffer[11].buffer_type = HAL_BUFFER_INTERNAL_PERSIST_1; + inst->buff_req.buffer[12].buffer_type = HAL_BUFFER_INTERNAL_CMD_QUEUE; + inst->buff_req.buffer[13].buffer_type = HAL_BUFFER_INTERNAL_RECON; /* By default, initialize OUTPUT port to H264 decoder */ fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats, @@ -811,6 +831,7 @@ int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) struct hal_profile_level profile_level; struct hal_frame_size frame_sz; struct hal_buffer_requirements *bufreq; + struct hal_buffer_requirements *bufreq_out2; if (!inst || !inst->core || !inst->core->device) { dprintk(VIDC_ERR, "%s invalid parameters\n", __func__); @@ -1013,6 +1034,16 @@ int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) dprintk(VIDC_ERR, "Failed:Disabling OUTPUT2 port : %d\n", rc); + + bufreq_out2 = get_buff_req_buffer(inst, + HAL_BUFFER_OUTPUT2); + if (!bufreq_out2) + break; + + bufreq_out2->buffer_count_min = + bufreq_out2->buffer_count_min_host = + bufreq_out2->buffer_count_actual = 0; + break; case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY: switch (inst->bit_depth) { @@ -1079,21 +1110,43 @@ int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) dprintk(VIDC_ERR, "Failed setting OUTPUT2 size : %d\n", rc); + /* Populate output2 bufreqs with output bufreqs */ + bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); + if (!bufreq) + break; - rc = msm_comm_try_get_bufreqs(inst); - if (rc) { - dprintk(VIDC_ERR, - "%s Failed to get buffer reqs : %d\n", - __func__, rc); + bufreq_out2 = get_buff_req_buffer(inst, + HAL_BUFFER_OUTPUT2); + if (!bufreq_out2) break; - } - rc = msm_vidc_update_host_buff_counts(inst); + memcpy(bufreq_out2, bufreq, + sizeof(struct hal_buffer_requirements)); + bufreq_out2->buffer_type = HAL_BUFFER_OUTPUT2; + rc = msm_comm_set_buffer_count(inst, + bufreq_out2->buffer_count_min_host, + bufreq_out2->buffer_count_actual, + HAL_BUFFER_OUTPUT2); if (rc) { dprintk(VIDC_ERR, - "%s Failed: update buff counts : %d\n", - __func__, rc); + "%s: Failed to set opb buffer count to FW\n"); + return -EINVAL; } + /* Do the same for extradata but no set is required */ + bufreq = get_buff_req_buffer(inst, + HAL_BUFFER_EXTRADATA_OUTPUT); + if (!bufreq) + break; + + bufreq_out2 = get_buff_req_buffer(inst, + HAL_BUFFER_EXTRADATA_OUTPUT2); + if (!bufreq_out2) + break; + + memcpy(bufreq_out2, bufreq, + sizeof(struct hal_buffer_requirements)); + bufreq_out2->buffer_type = + HAL_BUFFER_EXTRADATA_OUTPUT2; break; default: dprintk(VIDC_ERR, @@ -1228,7 +1281,6 @@ int msm_vdec_s_ext_ctrl(struct msm_vidc_inst *inst, dprintk(VIDC_ERR, "%s Failed setting stream output mode : %d\n", __func__, rc); - rc = msm_vidc_update_host_buff_counts(inst); break; case V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT: conceal_color.conceal_color_8bit = ext_control[i].value; diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 405575f8f904..0c9a6cc066ba 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -1160,6 +1160,8 @@ static struct msm_vidc_format venc_formats[] = { .fourcc = V4L2_PIX_FMT_H264, .get_frame_size = get_frame_size_compressed, .type = CAPTURE_PORT, + .input_min_count = 4, + .output_min_count = 4, }, { .name = "VP8", @@ -1167,6 +1169,8 @@ static struct msm_vidc_format venc_formats[] = { .fourcc = V4L2_PIX_FMT_VP8, .get_frame_size = get_frame_size_compressed, .type = CAPTURE_PORT, + .input_min_count = 4, + .output_min_count = 4, }, { .name = "HEVC", @@ -1174,6 +1178,8 @@ static struct msm_vidc_format venc_formats[] = { .fourcc = V4L2_PIX_FMT_HEVC, .get_frame_size = get_frame_size_compressed, .type = CAPTURE_PORT, + .input_min_count = 4, + .output_min_count = 4, }, { .name = "YCrCb Semiplanar 4:2:0", @@ -1195,6 +1201,8 @@ static struct msm_vidc_format venc_formats[] = { .fourcc = V4L2_PIX_FMT_TME, .get_frame_size = get_frame_size_compressed, .type = CAPTURE_PORT, + .input_min_count = 4, + .output_min_count = 4, }, { .name = "YCbCr Semiplanar 4:2:0 10bit", @@ -2414,6 +2422,20 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) inst->buff_req.buffer[2].buffer_count_min_host = inst->buff_req.buffer[2].buffer_count_actual = MIN_NUM_ENC_CAPTURE_BUFFERS; + inst->buff_req.buffer[3].buffer_type = HAL_BUFFER_OUTPUT2; + inst->buff_req.buffer[3].buffer_count_min_host = + inst->buff_req.buffer[3].buffer_count_actual = + MIN_NUM_ENC_CAPTURE_BUFFERS; + inst->buff_req.buffer[4].buffer_type = HAL_BUFFER_EXTRADATA_INPUT; + inst->buff_req.buffer[5].buffer_type = HAL_BUFFER_EXTRADATA_OUTPUT; + inst->buff_req.buffer[6].buffer_type = HAL_BUFFER_EXTRADATA_OUTPUT2; + inst->buff_req.buffer[7].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH; + inst->buff_req.buffer[8].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH_1; + inst->buff_req.buffer[9].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH_2; + inst->buff_req.buffer[10].buffer_type = HAL_BUFFER_INTERNAL_PERSIST; + inst->buff_req.buffer[11].buffer_type = HAL_BUFFER_INTERNAL_PERSIST_1; + inst->buff_req.buffer[12].buffer_type = HAL_BUFFER_INTERNAL_CMD_QUEUE; + inst->buff_req.buffer[13].buffer_type = HAL_BUFFER_INTERNAL_RECON; /* By default, initialize OUTPUT port to UBWC YUV format */ fmt = msm_comm_get_pixel_fmt_fourcc(venc_formats, diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index 3b8e85fe7001..82c277f7e321 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -30,8 +30,6 @@ static int try_get_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl); -static int msm_vidc_get_count(struct msm_vidc_inst *inst, - struct v4l2_ctrl *ctrl); static int get_poll_flags(void *instance) { @@ -376,7 +374,6 @@ int msm_vidc_g_ext_ctrl(void *instance, struct v4l2_ext_controls *control) { struct msm_vidc_inst *inst = instance; struct v4l2_ext_control *ext_control; - struct v4l2_ctrl ctrl; int i = 0, rc = 0; if (!inst || !control) @@ -386,19 +383,10 @@ int msm_vidc_g_ext_ctrl(void *instance, struct v4l2_ext_controls *control) for (i = 0; i < control->count; i++) { switch (ext_control[i].id) { - case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: - case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: - ctrl.id = ext_control[i].id; - ctrl.val = ext_control[i].value; - - msm_vidc_get_count(inst, &ctrl); - ext_control->value = ctrl.val; - break; default: dprintk(VIDC_ERR, "This control %x is not supported yet\n", ext_control[i].id); - rc = -EINVAL; break; } } @@ -742,29 +730,6 @@ static void msm_vidc_cleanup_buffer(struct vb2_buffer *vb) __func__, rc); } -static int set_buffer_count(struct msm_vidc_inst *inst, - int host_count, int act_count, enum hal_buffer type) -{ - int rc = 0; - struct hfi_device *hdev; - struct hal_buffer_count_actual buf_count; - - hdev = inst->core->device; - - buf_count.buffer_type = type; - buf_count.buffer_count_actual = act_count; - buf_count.buffer_count_min_host = host_count; - dprintk(VIDC_DBG, "%s : Act count = %d Host count = %d\n", - __func__, act_count, host_count); - rc = call_hfi_op(hdev, session_set_property, - inst->session, HAL_PARAM_BUFFER_COUNT_ACTUAL, &buf_count); - if (rc) - dprintk(VIDC_ERR, - "Failed to set actual buffer count %d for buffer type %d\n", - act_count, type); - return rc; -} - static int msm_vidc_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, unsigned int sizes[], struct device *alloc_devs[]) @@ -811,7 +776,8 @@ static int msm_vidc_queue_setup(struct vb2_queue *q, sizes[i] = inst->bufq[OUTPUT_PORT].plane_sizes[i]; bufreq->buffer_count_actual = *num_buffers; - rc = set_buffer_count(inst, bufreq->buffer_count_min_host, + rc = msm_comm_set_buffer_count(inst, + bufreq->buffer_count_min_host, bufreq->buffer_count_actual, HAL_BUFFER_INPUT); } break; @@ -844,7 +810,8 @@ static int msm_vidc_queue_setup(struct vb2_queue *q, sizes[i] = inst->bufq[CAPTURE_PORT].plane_sizes[i]; bufreq->buffer_count_actual = *num_buffers; - rc = set_buffer_count(inst, bufreq->buffer_count_min_host, + rc = msm_comm_set_buffer_count(inst, + bufreq->buffer_count_min_host, bufreq->buffer_count_actual, buffer_type); } break; @@ -1555,114 +1522,6 @@ static int msm_vidc_op_s_ctrl(struct v4l2_ctrl *ctrl) inst, v4l2_ctrl_get_name(ctrl->id)); return rc; } - -static int msm_vidc_get_count(struct msm_vidc_inst *inst, - struct v4l2_ctrl *ctrl) -{ - int rc = 0; - struct hal_buffer_requirements *bufreq; - enum hal_buffer buffer_type; - - if (ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_OUTPUT) { - bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT); - if (!bufreq) { - dprintk(VIDC_ERR, - "Failed to find bufreqs for buffer type = %d\n", - HAL_BUFFER_INPUT); - return 0; - } - if (inst->bufq[OUTPUT_PORT].vb2_bufq.streaming) { - ctrl->val = bufreq->buffer_count_min_host; - return 0; - } - if (ctrl->val > bufreq->buffer_count_min_host && - ctrl->val <= MAX_NUM_OUTPUT_BUFFERS) { - dprintk(VIDC_DBG, - "Buffer count Host changed from %d to %d\n", - bufreq->buffer_count_min_host, - ctrl->val); - bufreq->buffer_count_actual = - bufreq->buffer_count_min = - bufreq->buffer_count_min_host = - ctrl->val; - } else { - ctrl->val = bufreq->buffer_count_min_host; - } - rc = set_buffer_count(inst, - bufreq->buffer_count_min_host, - bufreq->buffer_count_actual, - HAL_BUFFER_INPUT); - - msm_vidc_update_host_buff_counts(inst); - ctrl->val = bufreq->buffer_count_min_host; - dprintk(VIDC_DBG, - "g_count: %x : OUTPUT: min %d min_host %d actual %d\n", - hash32_ptr(inst->session), - bufreq->buffer_count_min, - bufreq->buffer_count_min_host, - bufreq->buffer_count_actual); - return rc; - - } else if (ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE) { - - buffer_type = msm_comm_get_hal_output_buffer(inst); - bufreq = get_buff_req_buffer(inst, - buffer_type); - if (!bufreq) { - dprintk(VIDC_ERR, - "Failed to find bufreqs for buffer type = %d\n", - buffer_type); - return 0; - } - if (inst->bufq[CAPTURE_PORT].vb2_bufq.streaming) { - if (ctrl->val != bufreq->buffer_count_min_host) - return -EINVAL; - else - return 0; - } - - if (inst->session_type == MSM_VIDC_DECODER && - !inst->in_reconfig && - inst->state < MSM_VIDC_LOAD_RESOURCES_DONE) { - dprintk(VIDC_DBG, - "Clients updates Buffer count from %d to %d\n", - bufreq->buffer_count_min_host, ctrl->val); - bufreq->buffer_count_actual = - bufreq->buffer_count_min = - bufreq->buffer_count_min_host = - ctrl->val; - } - if (ctrl->val > bufreq->buffer_count_min_host && - ctrl->val <= MAX_NUM_CAPTURE_BUFFERS) { - dprintk(VIDC_DBG, - "Buffer count Host changed from %d to %d\n", - bufreq->buffer_count_min_host, - ctrl->val); - bufreq->buffer_count_actual = - bufreq->buffer_count_min = - bufreq->buffer_count_min_host = - ctrl->val; - } else { - ctrl->val = bufreq->buffer_count_min_host; - } - rc = set_buffer_count(inst, - bufreq->buffer_count_min_host, - bufreq->buffer_count_actual, - HAL_BUFFER_OUTPUT); - - msm_vidc_update_host_buff_counts(inst); - ctrl->val = bufreq->buffer_count_min_host; - dprintk(VIDC_DBG, - "g_count: %x : CAPTURE: min %d min_host %d actual %d\n", - hash32_ptr(inst->session), - bufreq->buffer_count_min, - bufreq->buffer_count_min_host, - bufreq->buffer_count_actual); - return rc; - } - return -EINVAL; -} - static int try_get_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) { int rc = 0; @@ -1703,8 +1562,6 @@ static int try_get_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) break; case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: - if (inst->in_reconfig) - msm_vidc_update_host_buff_counts(inst); buffer_type = msm_comm_get_hal_output_buffer(inst); bufreq = get_buff_req_buffer(inst, buffer_type); diff --git a/drivers/media/platform/msm/vidc/msm_vidc.h b/drivers/media/platform/msm/vidc/msm_vidc.h index 776c74357cd2..c22970833f83 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.h +++ b/drivers/media/platform/msm/vidc/msm_vidc.h @@ -21,7 +21,7 @@ #include #include -#define HAL_BUFFER_MAX 0xd +#define HAL_BUFFER_MAX 0xe enum smem_type { SMEM_DMA = 1, @@ -133,5 +133,4 @@ int msm_vidc_g_crop(void *instance, struct v4l2_crop *a); int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize); int msm_vidc_private(void *vidc_inst, unsigned int cmd, struct msm_vidc_arg *arg); - #endif diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c index 1a258c452820..1a9698b49c8f 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c @@ -971,18 +971,12 @@ int msm_dcvs_try_enable(struct msm_vidc_inst *inst) inst->clk_data.low_latency_mode || inst->batch.enable) { dprintk(VIDC_PROF, "DCVS disabled: %pK\n", inst); - inst->clk_data.extra_capture_buffer_count = 0; - inst->clk_data.extra_output_buffer_count = 0; inst->clk_data.dcvs_mode = false; return false; } inst->clk_data.dcvs_mode = true; dprintk(VIDC_PROF, "DCVS enabled: %pK\n", inst); - inst->clk_data.extra_capture_buffer_count = - DCVS_DEC_EXTRA_OUTPUT_BUFFERS; - inst->clk_data.extra_output_buffer_count = - DCVS_DEC_EXTRA_OUTPUT_BUFFERS; return true; } @@ -1090,6 +1084,17 @@ void msm_clock_data_reset(struct msm_vidc_inst *inst) __func__); } +static bool is_output_buffer(struct msm_vidc_inst *inst, + enum hal_buffer buffer_type) +{ + if (msm_comm_get_stream_output_mode(inst) == + HAL_VIDEO_DECODER_SECONDARY) { + return buffer_type == HAL_BUFFER_OUTPUT2; + } else { + return buffer_type == HAL_BUFFER_OUTPUT; + } +} + int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, enum hal_buffer buffer_type) { @@ -1106,15 +1111,22 @@ int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, if (is_thumbnail_session(inst)) return 0; - count = buffer_type == HAL_BUFFER_INPUT ? - inst->clk_data.extra_output_buffer_count : - inst->clk_data.extra_capture_buffer_count; + /* Add DCVS extra buffer count */ + if (inst->core->resources.dcvs) { + if (is_decode_session(inst) && + is_output_buffer(inst, buffer_type)) { + count += DCVS_DEC_EXTRA_OUTPUT_BUFFERS; + } else if ((is_encode_session(inst) && + buffer_type == HAL_BUFFER_INPUT)) { + count += DCVS_ENC_EXTRA_INPUT_BUFFERS; + } + } /* * if platform supports decode batching ensure minimum * batch size count of extra buffers added on output port */ - if (buffer_type == HAL_BUFFER_OUTPUT) { + if (is_output_buffer(inst, buffer_type)) { if (inst->core->resources.decode_batching && is_decode_session(inst) && count < inst->batch.size) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h index 73dcc1670f6d..c25bf8103765 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h @@ -16,7 +16,7 @@ #include "msm_vidc_internal.h" /* extra o/p buffers in case of encoder dcvs */ -#define DCVS_ENC_EXTRA_OUTPUT_BUFFERS 2 +#define DCVS_ENC_EXTRA_INPUT_BUFFERS 4 /* extra o/p buffers in case of decoder dcvs */ #define DCVS_DEC_EXTRA_OUTPUT_BUFFERS 4 diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 16d504c55501..15dbfe3aaec9 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -1567,6 +1567,7 @@ static void handle_event_change(enum hal_command_response cmd, void *data) struct hfi_device *hdev; u32 *ptr = NULL; struct hal_buffer_requirements *bufreq; + int extra_buff_count = 0; if (!event_notify) { dprintk(VIDC_WARN, "Got an empty event from hfi\n"); @@ -1669,17 +1670,17 @@ static void handle_event_change(enum hal_command_response cmd, void *data) event_notify->level); dprintk(VIDC_DBG, - "Event payload: height = %d width = %d profile = %d level = %d\n", + "Event payload: height = %u width = %u profile = %u level = %u\n", event_notify->height, event_notify->width, ptr[9], ptr[10]); dprintk(VIDC_DBG, - "Event payload: bit_depth = %d pic_struct = %d colour_space = %d\n", + "Event payload: bit_depth = %u pic_struct = %u colour_space = %u\n", event_notify->bit_depth, event_notify->pic_struct, event_notify->colour_space); dprintk(VIDC_DBG, - "Event payload: CROP top = %d left = %d Height = %d Width = %d\n", + "Event payload: CROP top = %u left = %u Height = %u Width = %u\n", event_notify->crop_data.top, event_notify->crop_data.left, event_notify->crop_data.height, @@ -1693,39 +1694,37 @@ static void handle_event_change(enum hal_command_response cmd, void *data) if (msm_comm_get_stream_output_mode(inst) == HAL_VIDEO_DECODER_SECONDARY) { - bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); - if (!bufreq) { - dprintk(VIDC_ERR, - "Failed : No buffer requirements : %x\n", - HAL_BUFFER_OUTPUT); + if (!bufreq) return; - } + /* No need to add extra buffers to DPBs */ bufreq->buffer_count_min = event_notify->capture_buf_count; + bufreq->buffer_count_min_host = bufreq->buffer_count_min; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT2); - if (!bufreq) { - dprintk(VIDC_ERR, - "Failed : No buffer requirements : %x\n", - HAL_BUFFER_OUTPUT2); + if (!bufreq) return; - } + extra_buff_count = msm_vidc_get_extra_buff_count(inst, + HAL_BUFFER_OUTPUT2); bufreq->buffer_count_min = event_notify->capture_buf_count; + bufreq->buffer_count_min_host = bufreq->buffer_count_min + + extra_buff_count; } else { bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); - if (!bufreq) { - dprintk(VIDC_ERR, - "Failed : No buffer requirements : %x\n", - HAL_BUFFER_OUTPUT); + if (!bufreq) return; - } + + extra_buff_count = msm_vidc_get_extra_buff_count(inst, + HAL_BUFFER_OUTPUT); bufreq->buffer_count_min = event_notify->capture_buf_count; + bufreq->buffer_count_min_host = bufreq->buffer_count_min + + extra_buff_count; } mutex_unlock(&inst->lock); @@ -3038,6 +3037,81 @@ static int msm_comm_session_init_done(int flipped_state, return rc; } +static int msm_comm_init_buffer_count(struct msm_vidc_inst *inst) +{ + int extra_buff_count = 0; + struct hal_buffer_requirements *bufreq; + int rc = 0; + int port; + + if (!is_decode_session(inst) && !is_encode_session(inst)) + return 0; + + if (is_decode_session(inst)) + port = OUTPUT_PORT; + else + port = CAPTURE_PORT; + + /* Update input buff counts */ + bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT); + if (!bufreq) + return -EINVAL; + + extra_buff_count = msm_vidc_get_extra_buff_count(inst, + HAL_BUFFER_INPUT); + bufreq->buffer_count_min = inst->fmts[port].input_min_count; + bufreq->buffer_count_min_host = bufreq->buffer_count_actual = + bufreq->buffer_count_min + extra_buff_count; + + rc = msm_comm_set_buffer_count(inst, + bufreq->buffer_count_min_host, + bufreq->buffer_count_actual, HAL_BUFFER_INPUT); + if (rc) { + dprintk(VIDC_ERR, + "%s: Failed to set in buffer count to FW\n", + __func__); + return -EINVAL; + } + + bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT); + if (!bufreq) + return -EINVAL; + + bufreq->buffer_count_min = inst->fmts[port].input_min_count; + bufreq->buffer_count_min_host = bufreq->buffer_count_actual = + bufreq->buffer_count_min + extra_buff_count; + + /* Update output buff count */ + bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); + if (!bufreq) + return -EINVAL; + + extra_buff_count = msm_vidc_get_extra_buff_count(inst, + HAL_BUFFER_OUTPUT); + bufreq->buffer_count_min = inst->fmts[port].output_min_count; + bufreq->buffer_count_min_host = bufreq->buffer_count_actual = + bufreq->buffer_count_min + extra_buff_count; + + rc = msm_comm_set_buffer_count(inst, + bufreq->buffer_count_min_host, + bufreq->buffer_count_actual, HAL_BUFFER_OUTPUT); + if (rc) { + dprintk(VIDC_ERR, + "%s: Failed to set out buffer count to FW\n"); + return -EINVAL; + } + + bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT); + if (!bufreq) + return -EINVAL; + + bufreq->buffer_count_min = inst->fmts[port].output_min_count; + bufreq->buffer_count_min_host = bufreq->buffer_count_actual = + bufreq->buffer_count_min + extra_buff_count; + + return 0; +} + static int msm_comm_session_init(int flipped_state, struct msm_vidc_inst *inst) { @@ -3083,7 +3157,14 @@ static int msm_comm_session_init(int flipped_state, rc = -EINVAL; goto exit; } + + rc = msm_comm_init_buffer_count(inst); + if (rc) { + dprintk(VIDC_ERR, "Failed to initialize buff counts\n"); + goto exit; + } change_inst_state(inst, MSM_VIDC_OPEN); + exit: return rc; } @@ -3368,6 +3449,7 @@ struct hal_buffer_requirements *get_buff_req_buffer( if (inst->buff_req.buffer[i].buffer_type == buffer_type) return &inst->buff_req.buffer[i]; } + dprintk(VIDC_ERR, "Failed to get buff req for : %x", buffer_type); return NULL; } @@ -4224,122 +4306,6 @@ int msm_comm_qbuf_decode_batch(struct msm_vidc_inst *inst, return rc; } -int msm_vidc_update_host_buff_counts(struct msm_vidc_inst *inst) -{ - int extra_buffers; - struct hal_buffer_requirements *bufreq; - struct hal_buffer_requirements *bufreq_extra; - - bufreq = get_buff_req_buffer(inst, - HAL_BUFFER_INPUT); - if (!bufreq) { - dprintk(VIDC_ERR, - "Failed : No buffer requirements : %x\n", - HAL_BUFFER_INPUT); - return -EINVAL; - } - extra_buffers = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT); - bufreq->buffer_count_min_host = bufreq->buffer_count_min + - extra_buffers; - - /* decode batching needs minimum batch size count of input buffers */ - if (is_decode_session(inst) && !is_thumbnail_session(inst) && - inst->core->resources.decode_batching && - bufreq->buffer_count_min_host < inst->batch.size) - bufreq->buffer_count_min_host = inst->batch.size; - - /* adjust min_host count for VP9 decoder */ - if (is_decode_session(inst) && !is_thumbnail_session(inst) && - inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9 && - bufreq->buffer_count_min_host < MIN_NUM_OUTPUT_BUFFERS_VP9) - bufreq->buffer_count_min_host = MIN_NUM_OUTPUT_BUFFERS_VP9; - - bufreq_extra = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT); - if (bufreq_extra) { - if (bufreq_extra->buffer_count_min) - bufreq_extra->buffer_count_min_host = - bufreq->buffer_count_min_host; - } - - if (msm_comm_get_stream_output_mode(inst) == - HAL_VIDEO_DECODER_SECONDARY) { - - bufreq = get_buff_req_buffer(inst, - HAL_BUFFER_OUTPUT); - if (!bufreq) { - dprintk(VIDC_ERR, - "Failed : No buffer requirements : %x\n", - HAL_BUFFER_OUTPUT); - return -EINVAL; - } - - /* For DPB buffers, no need to add Extra buffers */ - bufreq->buffer_count_min_host = bufreq->buffer_count_actual = - bufreq->buffer_count_min; - - bufreq = get_buff_req_buffer(inst, - HAL_BUFFER_OUTPUT2); - if (!bufreq) { - dprintk(VIDC_ERR, - "Failed : No buffer requirements : %x\n", - HAL_BUFFER_OUTPUT2); - return -EINVAL; - } - - extra_buffers = msm_vidc_get_extra_buff_count(inst, - HAL_BUFFER_OUTPUT); - - bufreq->buffer_count_min_host = bufreq->buffer_count_actual = - bufreq->buffer_count_min + extra_buffers; - - bufreq = get_buff_req_buffer(inst, - HAL_BUFFER_EXTRADATA_OUTPUT2); - if (!bufreq) { - dprintk(VIDC_DBG, - "No buffer requirements : %x\n", - HAL_BUFFER_EXTRADATA_OUTPUT2); - } else { - if (bufreq->buffer_count_min) { - bufreq->buffer_count_min_host = - bufreq->buffer_count_actual = - bufreq->buffer_count_min + extra_buffers; - } - } - } else { - - bufreq = get_buff_req_buffer(inst, - HAL_BUFFER_OUTPUT); - if (!bufreq) { - dprintk(VIDC_ERR, - "Failed : No buffer requirements : %x\n", - HAL_BUFFER_OUTPUT); - return -EINVAL; - } - - extra_buffers = msm_vidc_get_extra_buff_count(inst, - HAL_BUFFER_OUTPUT); - - bufreq->buffer_count_min_host = bufreq->buffer_count_actual = - bufreq->buffer_count_min + extra_buffers; - - bufreq = get_buff_req_buffer(inst, - HAL_BUFFER_EXTRADATA_OUTPUT); - if (!bufreq) { - dprintk(VIDC_DBG, - "No buffer requirements : %x\n", - HAL_BUFFER_EXTRADATA_OUTPUT); - } else { - if (bufreq->buffer_count_min) { - bufreq->buffer_count_min_host = - bufreq->buffer_count_actual = - bufreq->buffer_count_min + extra_buffers; - } - } - } - - return 0; -} - int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst) { int rc = 0, i = 0; @@ -4359,8 +4325,32 @@ int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst) "buffer type", "count", "mincount_host", "mincount_fw", "size"); for (i = 0; i < HAL_BUFFER_MAX; i++) { struct hal_buffer_requirements req = hprop.buf_req.buffer[i]; + struct hal_buffer_requirements *curr_req; + + /* + * For decoder we can ignore the buffer counts that firmware + * sends for inp/out buffers. + * FW buffer counts for these are used only in reconfig + */ + curr_req = get_buff_req_buffer(inst, req.buffer_type); + if (!curr_req) + return -EINVAL; + + if (req.buffer_type == HAL_BUFFER_INPUT || + req.buffer_type == HAL_BUFFER_OUTPUT || + req.buffer_type == HAL_BUFFER_OUTPUT2 || + req.buffer_type == HAL_BUFFER_EXTRADATA_INPUT || + req.buffer_type == HAL_BUFFER_EXTRADATA_OUTPUT || + req.buffer_type == HAL_BUFFER_EXTRADATA_OUTPUT2) { + curr_req->buffer_size = req.buffer_size; + curr_req->buffer_region_size = req.buffer_region_size; + curr_req->contiguous = req.contiguous; + curr_req->buffer_alignment = req.buffer_alignment; + } else { + memcpy(curr_req, &req, + sizeof(struct hal_buffer_requirements)); + } - inst->buff_req.buffer[i] = req; if (req.buffer_type != HAL_BUFFER_NONE) { dprintk(VIDC_DBG, "%15s %8d %8d %8d %8d\n", get_buffer_name(req.buffer_type), @@ -4369,10 +4359,8 @@ int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst) req.buffer_count_min, req.buffer_size); } } - if (inst->session_type == MSM_VIDC_ENCODER) - rc = msm_vidc_update_host_buff_counts(inst); - dprintk(VIDC_DBG, "Buffer requirements host adjusted:\n"); + dprintk(VIDC_DBG, "Buffer requirements driver adjusted:\n"); dprintk(VIDC_DBG, "%15s %8s %8s %8s %8s\n", "buffer type", "count", "mincount_host", "mincount_fw", "size"); for (i = 0; i < HAL_BUFFER_MAX; i++) { @@ -4792,6 +4780,29 @@ int msm_comm_try_set_prop(struct msm_vidc_inst *inst, return rc; } +int msm_comm_set_buffer_count(struct msm_vidc_inst *inst, + int host_count, int act_count, enum hal_buffer type) +{ + int rc = 0; + struct hfi_device *hdev; + struct hal_buffer_count_actual buf_count; + + hdev = inst->core->device; + + buf_count.buffer_type = type; + buf_count.buffer_count_actual = act_count; + buf_count.buffer_count_min_host = host_count; + dprintk(VIDC_DBG, "%s : Act count = %d Host count = %d\n", + __func__, act_count, host_count); + rc = call_hfi_op(hdev, session_set_property, + inst->session, HAL_PARAM_BUFFER_COUNT_ACTUAL, &buf_count); + if (rc) + dprintk(VIDC_ERR, + "Failed to set actual buffer count %d for buffer type %d\n", + act_count, type); + return rc; +} + int msm_comm_set_output_buffers(struct msm_vidc_inst *inst) { int rc = 0; diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h index d73da96f89b6..b30adad9f10c 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h @@ -103,6 +103,8 @@ int msm_comm_try_get_prop(struct msm_vidc_inst *inst, int msm_comm_set_recon_buffers(struct msm_vidc_inst *inst); int msm_comm_set_scratch_buffers(struct msm_vidc_inst *inst); int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst); +int msm_comm_set_buffer_count(struct msm_vidc_inst *inst, + int host_count, int act_count, enum hal_buffer type); int msm_comm_set_output_buffers(struct msm_vidc_inst *inst); int msm_comm_queue_output_buffers(struct msm_vidc_inst *inst); int msm_comm_qbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf); @@ -119,7 +121,6 @@ int msm_comm_release_output_buffers(struct msm_vidc_inst *inst, void msm_comm_validate_output_buffers(struct msm_vidc_inst *inst); int msm_comm_force_cleanup(struct msm_vidc_inst *inst); int msm_comm_suspend(int core_id); -int msm_vidc_update_host_buff_counts(struct msm_vidc_inst *inst); enum hal_extradata_id msm_comm_get_hal_extradata_index( enum v4l2_mpeg_vidc_extradata index); struct hal_buffer_requirements *get_buff_req_buffer( diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index 3b3882026bd4..2996fe0555a2 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -253,6 +253,8 @@ struct msm_vidc_format { int type; u32 (*get_frame_size)(int plane, u32 height, u32 width); bool defer_outputs; + u32 input_min_count; + u32 output_min_count; }; struct msm_vidc_drv { @@ -320,8 +322,6 @@ struct clock_data { int load_high; int min_threshold; int max_threshold; - unsigned int extra_capture_buffer_count; - unsigned int extra_output_buffer_count; enum hal_buffer buffer_type; bool dcvs_mode; unsigned long bitrate; diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c index 8281ea7fec3d..0ceb12d3dec3 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c @@ -234,6 +234,10 @@ static struct msm_vidc_common_data sm8150_common_data[] = { .key = "qcom,decode-batching", .value = 1, }, + { + .key = "qcom,dcvs", + .value = 1, + }, }; static struct msm_vidc_common_data sdm845_common_data[] = { @@ -289,6 +293,10 @@ static struct msm_vidc_common_data sdm845_common_data[] = { .key = "qcom,debug-timeout", .value = 0, }, + { + .key = "qcom,dcvs", + .value = 1, + }, }; static struct msm_vidc_common_data sdm670_common_data_v0[] = { @@ -336,6 +344,10 @@ static struct msm_vidc_common_data sdm670_common_data_v0[] = { .key = "qcom,hw-resp-timeout", .value = 250, }, + { + .key = "qcom,dcvs", + .value = 1, + }, }; static struct msm_vidc_common_data sdm670_common_data_v1[] = { @@ -383,6 +395,10 @@ static struct msm_vidc_common_data sdm670_common_data_v1[] = { .key = "qcom,hw-resp-timeout", .value = 250, }, + { + .key = "qcom,dcvs", + .value = 1, + }, }; static struct msm_vidc_efuse_data sdm670_efuse_data[] = { diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c index 8ff33e8a0257..f78a50a4a418 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c @@ -789,6 +789,8 @@ int read_platform_resources_from_drv_data( "qcom,domain-attr-cache-pagetables"); res->decode_batching = find_key_value(platform_data, "qcom,decode-batching"); + res->dcvs = find_key_value(platform_data, + "qcom,dcvs"); res->csc_coeff_data = &platform_data->csc_data; diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h index 981aafaa8fe6..ab7271ff512d 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h @@ -193,6 +193,7 @@ struct msm_vidc_platform_resources { bool non_fatal_pagefaults; bool cache_pagetables; bool decode_batching; + bool dcvs; struct msm_vidc_codec_data *codec_data; int codec_data_count; struct msm_vidc_csc_coeff *csc_coeff_data; -- GitLab From 3f7521d9af4cd365097f93a6825b01f545d9f960 Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Tue, 12 Jun 2018 15:01:54 +0530 Subject: [PATCH 0246/1299] clk: qcom: gcc: Remove support of 650Mhz frequency for gfx3d_clk_src Max vdd for gfx3d_clk_src is 598Mhz. So remove the support of 650Mhz which is greater than max vdd. Change-Id: I25abfe72688a97aa348ee812b49838ca484d7f03 Signed-off-by: Shefali Jain --- drivers/clk/qcom/gcc-qcs405.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/qcom/gcc-qcs405.c b/drivers/clk/qcom/gcc-qcs405.c index b8d9501ca58a..9ffc684ac62b 100644 --- a/drivers/clk/qcom/gcc-qcs405.c +++ b/drivers/clk/qcom/gcc-qcs405.c @@ -917,7 +917,6 @@ static const struct freq_tbl ftbl_gfx3d_clk_src[] = { F_SLEW(523200000, P_GPLL3_OUT_MAIN, 1, 0, 0, 1046400000), F_SLEW(550000000, P_GPLL3_OUT_MAIN, 1, 0, 0, 1100000000), F_SLEW(598000000, P_GPLL3_OUT_MAIN, 1, 0, 0, 1196000000), - F_SLEW(650000000, P_GPLL3_OUT_MAIN, 1, 0, 0, 1300000000), { } }; -- GitLab From 434220fd0ed1df17853f5f796e6d29b4d025e840 Mon Sep 17 00:00:00 2001 From: Swathi Sridhar Date: Wed, 13 Jun 2018 22:01:32 -0700 Subject: [PATCH 0247/1299] ARM: dts: msm: Include SMMU DT changes for sdxprairie Include DT changes for APPS SMMU for sdxprairie. Change-Id: I511e9284c6126648a0186251859d50ca1f0003cf Signed-off-by: Swathi Sridhar --- .../dts/qcom/msm-arm-smmu-sdxprairie.dtsi | 101 ++++++++++++++++++ arch/arm64/boot/dts/qcom/sdxprairie.dtsi | 1 + 2 files changed, 102 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/msm-arm-smmu-sdxprairie.dtsi diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdxprairie.dtsi new file mode 100644 index 000000000000..65fee9dff61a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdxprairie.dtsi @@ -0,0 +1,101 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +&soc { + apps_smmu: apps-smmu@0x15000000 { + compatible = "qcom,qsmmu-v500"; + reg = <0x15000000 0x20000>, + <0x15022000 0x20>; + reg-names = "base", "tcu-base"; + #iommu-cells = <2>; + qcom,use-3-lvl-tables; + #global-interrupts = <1>; + #size-cells = <1>; + #address-cells = <1>; + ranges; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + + periph_tbu: periph_tbu@0x15025000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15025000 0x1000>, + <0x15022200 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x0 0x400>; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + ipa_tbu: ipa_tbu@0x15029000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15029000 0x1000>, + <0x15022208 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x400 0x400>; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + }; + + apps_iommu_test_device { + compatible = "iommu-debug-test"; + iommus = <&apps_smmu 0x100 0x0>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi index 32f890529865..bf6ac43845e8 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi @@ -139,3 +139,4 @@ #include "sdxprairie-pinctrl.dtsi" #include "sdxprairie-ion.dtsi" +#include "msm-arm-smmu-sdxprairie.dtsi" -- GitLab From 761fb8562bd3a640ebf39ff7eb4df7a119822c15 Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Thu, 14 Jun 2018 13:59:27 +0800 Subject: [PATCH 0248/1299] ARM: dts: msm: Enable DFPS support for SM8150 2K panel Add the required properties to enable DFPS feature for the 2K display panel used by SM8150. CRs-Fixed: 2256126 Change-Id: I3a3feb1b7767c30223e5fd2176437401266f0205 Signed-off-by: Ray Zhang --- arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi index be2723b07647..477d3e280af1 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi @@ -400,6 +400,10 @@ /* PHY TIMINGS REVISION P */ &dsi_dual_nt35597_truly_video { + qcom,mdss-dsi-min-refresh-rate = <53>; + qcom,mdss-dsi-max-refresh-rate = <60>; + qcom,mdss-dsi-pan-enable-dynamic-fps; + qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp"; qcom,mdss-dsi-display-timings { timing@0{ qcom,mdss-dsi-panel-phy-timings = [00 1c 08 07 23 22 07 -- GitLab From 55831c064f40ff70eba2d727b48ab96a2d7fa7c8 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Tue, 21 Feb 2017 20:44:46 +0530 Subject: [PATCH 0249/1299] genirq: Use irq_set_affinity_locked to change irq affinity Currently PM QoS is not getting notifications if irq affinity is changed by core isolation with irq_do_set_affinity. Use irq_set_affinity_locked instead to get notifications when updating affinity. Change-Id: Iab745a23637d9353f730ca77ac7e92cf61b1bf67 Signed-off-by: Maulik Shah Signed-off-by: Lingutla Chandrasekhar --- kernel/irq/cpuhotplug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c index 1c87ea49e5df..dc6dd95cad00 100644 --- a/kernel/irq/cpuhotplug.c +++ b/kernel/irq/cpuhotplug.c @@ -131,12 +131,12 @@ static bool migrate_one_irq(struct irq_desc *desc) brokeaff = true; } /* - * Do not set the force argument of irq_do_set_affinity() as this + * Do not set the force argument of irq_set_affinity_locked() as this * disables the masking of offline CPUs from the supplied affinity * mask and therefore might keep/reassign the irq to the outgoing * CPU. */ - err = irq_do_set_affinity(d, affinity, false); + err = irq_set_affinity_locked(d, affinity, false); if (err) { pr_warn_ratelimited("IRQ%u: set affinity failed(%d).\n", d->irq, err); -- GitLab From 68752c0290c901fa6e1e75f170f6efc35f858d0f Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Thu, 22 Jun 2017 13:33:08 +0530 Subject: [PATCH 0250/1299] genriq: pick only one CPU while overriding the affinity during migration With commit bfc60d474137 ("genirq: Use irq_set_affinity_locked to change irq affinity"), affinity listeners receive the notification when the irq affinity is changed during migration. If there is no online and un-isolated CPU available from the user specified affinity, the affinity is overridden with all online and un-isolated CPUs. The same cpumask is notified to PM QOS affinity listener which applies PM_QOS_CPU_DMA_LATENCY vote to all those CPUs. As the low level irqchip driver sets affinity to only one CPU, do the same while overriding the affinity during migration. Change-Id: I0bcb75dd356658da100fbeeefd33ef8b121f4d6d Signed-off-by: Pavankumar Kondeti --- kernel/irq/cpuhotplug.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c index dc6dd95cad00..4fdb113f1286 100644 --- a/kernel/irq/cpuhotplug.c +++ b/kernel/irq/cpuhotplug.c @@ -128,6 +128,17 @@ static bool migrate_one_irq(struct irq_desc *desc) cpu_isolated_mask); if (cpumask_empty(affinity)) affinity = cpu_online_mask; + /* + * We are overriding the affinity with all online and + * un-isolated cpus. irq_set_affinity_locked() call + * below notify this mask to PM QOS affinity listener. + * That results in applying the CPU_DMA_LATENCY QOS + * to all the CPUs specified in the mask. But the low + * level irqchip driver sets the affinity of an irq + * to only one CPU. So pick only one CPU from the + * prepared mask while overriding the user affinity. + */ + affinity = cpumask_of(cpumask_any(affinity)); brokeaff = true; } /* -- GitLab From 1279e9f722d3ce6c8f2f7610a3fd6c988e9598d6 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Fri, 16 Jun 2017 09:36:25 +0530 Subject: [PATCH 0251/1299] genirq: honour default IRQ affinity setting during migration Userspace can set the default IRQ affinity setting by writing into /proc/irq/default_smp_affinity file. When an IRQ affinity is broken during isolation/hotplug, override the affinity to online and un-isolated CPUs from the default affinity CPUs. If no such CPU is available, then only override with cpu_online_mask. Change-Id: I7578728ed0d7c17c5890d9916cfd6451d1968568 Signed-off-by: Pavankumar Kondeti Signed-off-by: Lingutla Chandrasekhar --- kernel/irq/cpuhotplug.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c index 4fdb113f1286..ea4cba8ab058 100644 --- a/kernel/irq/cpuhotplug.c +++ b/kernel/irq/cpuhotplug.c @@ -124,10 +124,21 @@ static bool migrate_one_irq(struct irq_desc *desc) irq_shutdown(desc); return false; } + /* + * The order of preference for selecting a fallback CPU is + * + * (1) online and un-isolated CPU from default affinity + * (2) online and un-isolated CPU + * (3) online CPU + */ cpumask_andnot(&available_cpus, cpu_online_mask, cpu_isolated_mask); - if (cpumask_empty(affinity)) + if (cpumask_intersects(&available_cpus, irq_default_affinity)) + cpumask_and(&available_cpus, &available_cpus, + irq_default_affinity); + else if (cpumask_empty(&available_cpus)) affinity = cpu_online_mask; + /* * We are overriding the affinity with all online and * un-isolated cpus. irq_set_affinity_locked() call -- GitLab From 5e2c5c412956a534f20e66c77b203c3666523289 Mon Sep 17 00:00:00 2001 From: Shaoqing Liu Date: Mon, 21 May 2018 18:25:50 +0800 Subject: [PATCH 0252/1299] ARM: dts: msm: Add cti0 for tmc-etr/etf node for sm8150 TMC(Trace Memory Controller) is designed as a successor to the coresight embedded trace buffer that enables you to capture trace using device node: coresight-tmc-etr(ddr mode) or coresight-tmc-etf(etb mode). Add cti0 for tmc-etr/etf node for supporting reset and flush operation in TMC driver. CRs-Fixed: 2256917 Change-Id: I0530ea4bbe78c4b87c80d68e2179e6452ad8f018 Signed-off-by: Shaoqing Liu --- arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi b/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi index 5da67a724097..deac2e6b7602 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi @@ -325,7 +325,7 @@ arm,buffer-size = <0x400000>; coresight-name = "coresight-tmc-etr"; - coresight-ctis = <&cti0>; + coresight-ctis = <&cti0 &cti0>; coresight-csr = <&csr>; clocks = <&clock_aop QDSS_CLK>; @@ -350,7 +350,7 @@ reg-names = "tmc-base"; coresight-name = "coresight-tmc-etf"; - coresight-ctis = <&cti0>; + coresight-ctis = <&cti0 &cti0>; coresight-csr = <&csr>; arm,default-sink; -- GitLab From 4b7ebca9fb18f4b46a3b6dbb18621c96c5404386 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Wed, 30 May 2018 15:38:59 +0530 Subject: [PATCH 0253/1299] mmc: core: Update cmdq for making use of per-request data Update cmdq initialization path for making use of per-request data. Also, update cmdq request processing paths per this new change. Since we are making use of per-request data, no need to maintain the statically allocated array of mmc_queue_req data structure. Change-Id: I65fa9fbb45c97835115405d558db764e6189d5f3 Signed-off-by: Veerabhadrarao Badiganti --- drivers/mmc/core/block.c | 23 +++++++--------- drivers/mmc/core/queue.c | 57 +++++++++++----------------------------- drivers/mmc/core/queue.h | 2 -- 3 files changed, 26 insertions(+), 56 deletions(-) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index b157b530e037..b5eae724ff51 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -2225,7 +2225,7 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq, } mqrq->areq.mrq = &brq->mrq; - mqrq->areq.mrq->req = mqrq->req; + mqrq->areq.mrq->req = req; mqrq->areq.err_check = mmc_blk_err_check; } @@ -2388,14 +2388,14 @@ static int mmc_blk_cmdq_switch(struct mmc_card *card, static struct mmc_cmdq_req *mmc_cmdq_prep_dcmd( struct mmc_queue_req *mqrq, struct mmc_queue *mq) { - struct request *req = mqrq->req; + struct request *req = mmc_queue_req_to_req(mqrq); struct mmc_cmdq_req *cmdq_req = &mqrq->cmdq_req; memset(&mqrq->cmdq_req, 0, sizeof(struct mmc_cmdq_req)); cmdq_req->mrq.data = NULL; cmdq_req->cmd_flags = req->cmd_flags; - cmdq_req->mrq.req = mqrq->req; + cmdq_req->mrq.req = req; req->special = mqrq; cmdq_req->cmdq_req_flags |= DCMD; cmdq_req->mrq.cmdq_req = cmdq_req; @@ -2418,8 +2418,7 @@ static struct mmc_cmdq_req *mmc_blk_cmdq_prep_discard_req(struct mmc_queue *mq, set_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); - active_mqrq = &mq->mqrq_cmdq[req->tag]; - active_mqrq->req = req; + active_mqrq = req_to_mmc_queue_req(req); cmdq_req = mmc_cmdq_prep_dcmd(active_mqrq, mq); cmdq_req->cmdq_req_flags |= QBR; @@ -2553,7 +2552,7 @@ static struct mmc_cmdq_req *mmc_blk_cmdq_rw_prep( struct mmc_queue_req *mqrq, struct mmc_queue *mq) { struct mmc_card *card = mq->card; - struct request *req = mqrq->req; + struct request *req = mmc_queue_req_to_req(mqrq); struct mmc_blk_data *md = mq->blkdata; bool do_rel_wr = mmc_req_rel_wr(req) && (md->flags & MMC_BLK_REL_WR); bool do_data_tag; @@ -2615,14 +2614,14 @@ static struct mmc_cmdq_req *mmc_blk_cmdq_rw_prep( } mqrq->cmdq_req.cmd_flags = req->cmd_flags; - mqrq->cmdq_req.mrq.req = mqrq->req; + mqrq->cmdq_req.mrq.req = req; mqrq->cmdq_req.mrq.cmdq_req = &mqrq->cmdq_req; mqrq->cmdq_req.mrq.data = &mqrq->cmdq_req.data; - mqrq->req->special = mqrq; + req->special = mqrq; pr_debug("%s: %s: mrq: 0x%p req: 0x%p mqrq: 0x%p bytes to xf: %d\n", mmc_hostname(card->host), __func__, &mqrq->cmdq_req.mrq, - mqrq->req, mqrq, (cmdq_rq->data.blocks * cmdq_rq->data.blksz)); + req, mqrq, (cmdq_rq->data.blocks * cmdq_rq->data.blksz)); pr_debug("%s: %s: mmc_cmdq_req: 0x%p card-addr: 0x%08x dir(r-1/w-0): %d\n", mmc_hostname(card->host), __func__, cmdq_rq, cmdq_rq->blk_addr, @@ -2658,8 +2657,7 @@ static int mmc_blk_cmdq_issue_rw_rq(struct mmc_queue *mq, struct request *req) BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.data_active_reqs)); BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs)); - active_mqrq = &mq->mqrq_cmdq[req->tag]; - active_mqrq->req = req; + active_mqrq = req_to_mmc_queue_req(req); mc_rq = mmc_blk_cmdq_rw_prep(active_mqrq, mq); @@ -2722,8 +2720,7 @@ int mmc_blk_cmdq_issue_flush_rq(struct mmc_queue *mq, struct request *req) set_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); - active_mqrq = &mq->mqrq_cmdq[req->tag]; - active_mqrq->req = req; + active_mqrq = req_to_mmc_queue_req(req); cmdq_req = mmc_cmdq_prep_dcmd(active_mqrq, mq); cmdq_req->cmdq_req_flags |= QBR; diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 1b91e693ef46..67fa942ec544 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -220,43 +220,23 @@ static struct scatterlist *mmc_alloc_sg(int sg_len, gfp_t gfp) int mmc_cmdq_init(struct mmc_queue *mq, struct mmc_card *card) { - int i, ret = 0; + int ret = 0; /* one slot is reserved for dcmd requests */ int q_depth = card->ext_csd.cmdq_depth - 1; card->cmdq_init = false; if (!(card->host->caps2 & MMC_CAP2_CMD_QUEUE)) { - ret = -ENOTSUPP; - goto out; + return -ENOTSUPP; } init_waitqueue_head(&card->host->cmdq_ctx.queue_empty_wq); init_waitqueue_head(&card->host->cmdq_ctx.wait); - mq->mqrq_cmdq = kcalloc(q_depth, - sizeof(struct mmc_queue_req), GFP_KERNEL); - if (!mq->mqrq_cmdq) { - ret = -ENOMEM; - goto out; - } - - /* sg is allocated for data request slots only */ - for (i = 0; i < q_depth; i++) { - mq->mqrq_cmdq[i].sg = - mmc_alloc_sg(card->host->max_segs, GFP_KERNEL); - if (ret) { - pr_warn("%s: unable to allocate cmdq sg of size %d\n", - mmc_card_name(card), - card->host->max_segs); - goto free_mqrq_sg; - } - } - ret = blk_queue_init_tags(mq->queue, q_depth, NULL, BLK_TAG_ALLOC_FIFO); if (ret) { pr_warn("%s: unable to allocate cmdq tags %d\n", mmc_card_name(card), q_depth); - goto free_mqrq_sg; + return ret; } blk_queue_softirq_done(mq->queue, mmc_cmdq_softirq_done); @@ -268,30 +248,14 @@ int mmc_cmdq_init(struct mmc_queue *mq, struct mmc_card *card) blk_queue_rq_timeout(mq->queue, 120 * HZ); card->cmdq_init = true; - goto out; - -free_mqrq_sg: - for (i = 0; i < q_depth; i++) - kfree(mq->mqrq_cmdq[i].sg); - kfree(mq->mqrq_cmdq); - mq->mqrq_cmdq = NULL; -out: return ret; } void mmc_cmdq_clean(struct mmc_queue *mq, struct mmc_card *card) { - int i; - int q_depth = card->ext_csd.cmdq_depth - 1; - blk_free_tags(mq->queue->queue_tags); mq->queue->queue_tags = NULL; blk_queue_free_tags(mq->queue); - - for (i = 0; i < q_depth; i++) - kfree(mq->mqrq_cmdq[i].sg); - kfree(mq->mqrq_cmdq); - mq->mqrq_cmdq = NULL; } static int mmc_queue_thread(void *d) @@ -430,9 +394,21 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, mq->card = card; if (card->ext_csd.cmdq_support && (area_type == MMC_BLK_DATA_AREA_MAIN)) { - mq->queue = blk_init_queue(mmc_cmdq_dispatch_req, lock); + mq->queue = blk_alloc_queue(GFP_KERNEL); if (!mq->queue) return -ENOMEM; + mq->queue->queue_lock = lock; + mq->queue->request_fn = mmc_cmdq_dispatch_req; + mq->queue->init_rq_fn = mmc_init_request; + mq->queue->exit_rq_fn = mmc_exit_request; + mq->queue->cmd_size = sizeof(struct mmc_queue_req); + mq->queue->queuedata = mq; + ret = blk_init_allocated_queue(mq->queue); + if (ret) { + blk_cleanup_queue(mq->queue); + return ret; + } + mmc_cmdq_setup_queue(mq, card); ret = mmc_cmdq_init(mq, card); if (ret) { @@ -444,7 +420,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, /* hook for pm qos cmdq init */ if (card->host->cmdq_ops->init) card->host->cmdq_ops->init(card->host); - mq->queue->queuedata = mq; mq->thread = kthread_run(mmc_cmdq_thread, mq, "mmc-cmdqd/%d%s", host->index, diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h index a8dccc53c2ed..b03aea8f2b76 100644 --- a/drivers/mmc/core/queue.h +++ b/drivers/mmc/core/queue.h @@ -48,7 +48,6 @@ enum mmc_drv_op { }; struct mmc_queue_req { - struct request *req; struct mmc_blk_request brq; struct scatterlist *sg; struct mmc_async_req areq; @@ -78,7 +77,6 @@ struct mmc_queue { struct mmc_queue_req mqrq[2]; struct mmc_queue_req *mqrq_cur; struct mmc_queue_req *mqrq_prev; - struct mmc_queue_req *mqrq_cmdq; struct work_struct cmdq_err_work; struct completion cmdq_pending_req_done; -- GitLab From 12ed159fa4af3fb1d6efff375e2211e5da898fa3 Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Mon, 14 May 2018 22:50:30 +0530 Subject: [PATCH 0254/1299] clk: qcom: Add video clock driver for SM6150 Add support for the video clock controller found on SM6150 based devices. This would allow video device drivers to probe and control their clocks. Change-Id: I25ad0aff644b99b6579aab7d49828ed015a731d1 Signed-off-by: Odelu Kukatla --- .../bindings/clock/qcom,videocc.txt | 3 +- drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/videocc-sm6150.c | 433 ++++++++++++++++++ .../dt-bindings/clock/qcom,videocc-sm6150.h | 35 +- 5 files changed, 461 insertions(+), 20 deletions(-) create mode 100644 drivers/clk/qcom/videocc-sm6150.c diff --git a/Documentation/devicetree/bindings/clock/qcom,videocc.txt b/Documentation/devicetree/bindings/clock/qcom,videocc.txt index b758de540298..1c7dfcd90270 100644 --- a/Documentation/devicetree/bindings/clock/qcom,videocc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,videocc.txt @@ -1,7 +1,8 @@ Qualcomm Technologies, Inc. Video Clock & Reset Controller Bindings Required properties: -- compatible: shall contain "qcom,videocc-sm8150" or "qcom,videocc-sm8150-v2". +- compatible: shall contain "qcom,videocc-sm8150" or "qcom,videocc-sm8150-v2" or + "qcom,videocc-sm6150". - reg: shall contain base register location and length. - reg-names: names of registers listed in the same order as in the reg property. - vdd_mm-supply: the logic rail supply. diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index bc4778ffd09e..768a462dfb3d 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -358,3 +358,12 @@ config MSM_GPUCC_SM6150 Support for the graphics clock controller on Qualcomm Technologies, Inc. SM6150 devices. Say Y if you want to support graphics clocks. + +config MSM_VIDEOCC_SM6150 + tristate "SM6150 Video Clock Controller" + depends on COMMON_CLK_QCOM + help + Support for the video clock controller on Qualcomm Technologies, Inc. + SM6150 devices. + Say Y if you want to support video devices and functionality such as + video encode/decode. diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 24d49dbf84ad..6c6d5904964b 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o obj-$(CONFIG_MSM_NPUCC_SM8150) += npucc-sm8150.o +obj-$(CONFIG_MSM_VIDEOCC_SM6150) += videocc-sm6150.o obj-$(CONFIG_MSM_VIDEOCC_SM8150) += videocc-sm8150.o obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o diff --git a/drivers/clk/qcom/videocc-sm6150.c b/drivers/clk/qcom/videocc-sm6150.c new file mode 100644 index 000000000000..0e3d9825f50e --- /dev/null +++ b/drivers/clk/qcom/videocc-sm6150.c @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "clk: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "common.h" +#include "vdd-level-sm6150.h" + +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } + +static DEFINE_VDD_REGULATORS(vdd_cx, VDD_NUM, 1, vdd_corner); + +enum { + P_BI_TCXO, + P_CHIP_SLEEP_CLK, + P_CORE_BI_PLL_TEST_SE, + P_VIDEO_PLL0_OUT_AUX, + P_VIDEO_PLL0_OUT_AUX2, + P_VIDEO_PLL0_OUT_MAIN, +}; + +static const struct parent_map video_cc_parent_map_0[] = { + { P_CHIP_SLEEP_CLK, 0 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const video_cc_parent_names_0[] = { + "chip_sleep_clk", + "core_bi_pll_test_se", +}; + +static const struct parent_map video_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_PLL0_OUT_MAIN, 1 }, + { P_VIDEO_PLL0_OUT_AUX, 2 }, + { P_VIDEO_PLL0_OUT_AUX2, 3 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const video_cc_parent_names_1[] = { + "bi_tcxo", + "video_pll0_out_main", + "video_pll0_out_aux", + "video_pll0_out_aux2", + "core_bi_pll_test_se", +}; + +static const struct parent_map video_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const video_cc_parent_names_2[] = { + "bi_tcxo", + "core_bi_pll_test_se", +}; + +static struct pll_vco video_cc_pll_vco[] = { + { 500000000, 1000000000, 2 }, +}; + +/* 600MHz configuration */ +static const struct alpha_pll_config video_pll0_config = { + .l = 0x1F, + .alpha_u = 0x40, + .alpha = 0x00, + .alpha_en_mask = BIT(24), + .vco_val = 0x2 << 20, + .vco_mask = 0x3 << 20, + .main_output_mask = BIT(0), + .config_ctl_val = 0x4001055b, + .user_ctl_val = 0x00000001, + .user_ctl_hi_val = 0x00000004, +}; + +static struct clk_alpha_pll video_pll0_out_main = { + .offset = 0x42c, + .vco_table = video_cc_pll_vco, + .num_vco = ARRAY_SIZE(video_cc_pll_vco), + .flags = SUPPORTS_DYNAMIC_UPDATE, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "video_pll0_out_main", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 1000000000, + [VDD_NOMINAL] = 2000000000}, + }, + }, +}; + +/* chip_sleep_clk is external clocks running at 32000Hz */ +static struct clk_fixed_rate chip_sleep_clk = { + .fixed_rate = 32000, + .hw.init = &(struct clk_init_data){ + .name = "chip_sleep_clk", + .ops = &clk_fixed_rate_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = { + F(32000, P_CHIP_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_sleep_clk_src = { + .cmd_rcgr = 0xaf8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_sleep_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "video_cc_sleep_clk_src", + .parent_names = video_cc_parent_names_0, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 32000}, + }, +}; + +static const struct freq_tbl ftbl_video_cc_venus_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(133333333, P_VIDEO_PLL0_OUT_MAIN, 4.5, 0, 0), + F(240000000, P_VIDEO_PLL0_OUT_MAIN, 2.5, 0, 0), + F(300000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), + F(380000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), + F(410000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), + F(460000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_venus_clk_src = { + .cmd_rcgr = 0x7f0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_1, + .freq_tbl = ftbl_video_cc_venus_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "video_cc_venus_clk_src", + .parent_names = video_cc_parent_names_1, + .num_parents = 5, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 133333333, + [VDD_LOW] = 240000000, + [VDD_LOW_L1] = 300000000, + [VDD_NOMINAL] = 380000000, + [VDD_NOMINAL_L1] = 410000000, + [VDD_HIGH] = 460000000}, + }, +}; + +static const struct freq_tbl ftbl_video_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_xo_clk_src = { + .cmd_rcgr = 0xa98, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_2, + .freq_tbl = ftbl_video_cc_xo_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "video_cc_xo_clk_src", + .parent_names = video_cc_parent_names_2, + .num_parents = 2, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000}, + }, +}; + +static struct clk_branch video_cc_apb_clk = { + .halt_reg = 0x990, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x990, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_apb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_sleep_clk = { + .halt_reg = 0xb18, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb18, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_sleep_clk", + .parent_names = (const char *[]){ + "video_cc_sleep_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_vcodec0_axi_clk = { + .halt_reg = 0x8f0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8f0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_vcodec0_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_vcodec0_core_clk = { + .halt_reg = 0x890, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x890, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_vcodec0_core_clk", + .parent_names = (const char *[]){ + "video_cc_venus_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_venus_ahb_clk = { + .halt_reg = 0x9b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9b0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_venus_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_venus_ctl_axi_clk = { + .halt_reg = 0x8d0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8d0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_venus_ctl_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_venus_ctl_core_clk = { + .halt_reg = 0x850, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x850, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_venus_ctl_core_clk", + .parent_names = (const char *[]){ + "video_cc_venus_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_xo_clk = { + .halt_reg = 0xab8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xab8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_xo_clk", + .parent_names = (const char *[]){ + "video_cc_xo_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +struct clk_hw *video_cc_sm6150_hws[] = { + [CHIP_SLEEP_CLK] = &chip_sleep_clk.hw, +}; + +static struct clk_regmap *video_cc_sm6150_clocks[] = { + [VIDEO_CC_APB_CLK] = &video_cc_apb_clk.clkr, + [VIDEO_CC_SLEEP_CLK] = &video_cc_sleep_clk.clkr, + [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr, + [VIDEO_CC_VCODEC0_AXI_CLK] = &video_cc_vcodec0_axi_clk.clkr, + [VIDEO_CC_VCODEC0_CORE_CLK] = &video_cc_vcodec0_core_clk.clkr, + [VIDEO_CC_VENUS_AHB_CLK] = &video_cc_venus_ahb_clk.clkr, + [VIDEO_CC_VENUS_CLK_SRC] = &video_cc_venus_clk_src.clkr, + [VIDEO_CC_VENUS_CTL_AXI_CLK] = &video_cc_venus_ctl_axi_clk.clkr, + [VIDEO_CC_VENUS_CTL_CORE_CLK] = &video_cc_venus_ctl_core_clk.clkr, + [VIDEO_CC_XO_CLK] = &video_cc_xo_clk.clkr, + [VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr, + [VIDEO_PLL0_OUT_MAIN] = &video_pll0_out_main.clkr, +}; + +static const struct regmap_config video_cc_sm6150_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xb94, + .fast_io = true, +}; + +static const struct qcom_cc_desc video_cc_sm6150_desc = { + .config = &video_cc_sm6150_regmap_config, + .clks = video_cc_sm6150_clocks, + .num_clks = ARRAY_SIZE(video_cc_sm6150_clocks), + .hwclks = video_cc_sm6150_hws, + .num_hwclks = ARRAY_SIZE(video_cc_sm6150_hws), +}; + +static const struct of_device_id video_cc_sm6150_match_table[] = { + { .compatible = "qcom,videocc-sm6150" }, + { } +}; +MODULE_DEVICE_TABLE(of, video_cc_sm6150_match_table); + +static int video_cc_sm6150_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret = 0; + + vdd_cx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_cx"); + if (IS_ERR(vdd_cx.regulator[0])) { + if (!(PTR_ERR(vdd_cx.regulator[0]) == -EPROBE_DEFER)) + dev_err(&pdev->dev, + "Unable to get vdd_cx regulator\n"); + return PTR_ERR(vdd_cx.regulator[0]); + } + + regmap = qcom_cc_map(pdev, &video_cc_sm6150_desc); + if (IS_ERR(regmap)) { + pr_err("Failed to map the video_cc registers\n"); + return PTR_ERR(regmap); + } + + clk_alpha_pll_configure(&video_pll0_out_main, regmap, + &video_pll0_config); + + ret = qcom_cc_really_probe(pdev, &video_cc_sm6150_desc, regmap); + if (ret) { + dev_err(&pdev->dev, "Failed to register Video CC clocks\n"); + return ret; + } + + dev_info(&pdev->dev, "Registered Video CC clocks\n"); + + return ret; +} + +static struct platform_driver video_cc_sm6150_driver = { + .probe = video_cc_sm6150_probe, + .driver = { + .name = "video_cc-sm6150", + .of_match_table = video_cc_sm6150_match_table, + }, +}; + +static int __init video_cc_sm6150_init(void) +{ + return platform_driver_register(&video_cc_sm6150_driver); +} +subsys_initcall(video_cc_sm6150_init); + +static void __exit video_cc_sm6150_exit(void) +{ + platform_driver_unregister(&video_cc_sm6150_driver); +} +module_exit(video_cc_sm6150_exit); + +MODULE_DESCRIPTION("QTI VIDEO_CC sm6150 Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:video_cc-sm6150"); diff --git a/include/dt-bindings/clock/qcom,videocc-sm6150.h b/include/dt-bindings/clock/qcom,videocc-sm6150.h index be71dfb72427..0d911e44f2f8 100644 --- a/include/dt-bindings/clock/qcom,videocc-sm6150.h +++ b/include/dt-bindings/clock/qcom,videocc-sm6150.h @@ -14,25 +14,22 @@ #ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM6150_H #define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM6150_H -#define VIDEO_CC_APB_CLK 0 -#define VIDEO_CC_AT_CLK 1 -#define VIDEO_CC_QDSS_TRIG_CLK 2 -#define VIDEO_CC_QDSS_TSCTR_DIV8_CLK 3 -#define VIDEO_CC_SLEEP_CLK 4 -#define VIDEO_CC_SLEEP_CLK_SRC 5 -#define VIDEO_CC_VCODEC0_AXI_CLK 6 -#define VIDEO_CC_VCODEC0_CORE_CLK 7 -#define VIDEO_CC_VENUS_AHB_CLK 8 -#define VIDEO_CC_VENUS_CLK_SRC 9 -#define VIDEO_CC_VENUS_CTL_AXI_CLK 10 -#define VIDEO_CC_VENUS_CTL_CORE_CLK 11 -#define VIDEO_CC_XO_CLK 12 -#define VIDEO_CC_XO_CLK_SRC 13 -#define VIDEO_PLL0 14 -#define VIDEO_PLL0_OUT_MAIN 15 +/* Hardware clocks*/ +#define CHIP_SLEEP_CLK 0 -#define VIDEO_CC_INTERFACE_BCR 0 -#define VIDEO_CC_VCODEC0_BCR 1 -#define VIDEO_CC_VENUS_BCR 2 +/* VIDEOCC clock registers */ +#define VIDEO_CC_APB_CLK 1 +#define VIDEO_CC_SLEEP_CLK 2 +#define VIDEO_CC_SLEEP_CLK_SRC 3 +#define VIDEO_CC_VCODEC0_AXI_CLK 4 +#define VIDEO_CC_VCODEC0_CORE_CLK 5 +#define VIDEO_CC_VENUS_AHB_CLK 6 +#define VIDEO_CC_VENUS_CLK_SRC 7 +#define VIDEO_CC_VENUS_CTL_AXI_CLK 8 +#define VIDEO_CC_VENUS_CTL_CORE_CLK 9 +#define VIDEO_CC_XO_CLK 10 +#define VIDEO_CC_XO_CLK_SRC 11 +#define VIDEO_PLL0 12 +#define VIDEO_PLL0_OUT_MAIN 13 #endif -- GitLab From ea9d04f12b4441db8a0e9688fe7e3754f0c22a2f Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Wed, 16 May 2018 15:07:24 +0530 Subject: [PATCH 0255/1299] ARM: dts: msm: Update the clock_videocc node on SM6150 Update the VIDEOCC clock controller device node to register to actual VIDEOCC driver. Also update the video GDSCs by replacing the dummy nodes with actual GDSC device nodes. Change-Id: I08da8ddcb0e0b2855276947ec1dd6799abfb477b Signed-off-by: Odelu Kukatla --- arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi | 4 ++-- arch/arm64/boot/dts/qcom/sm6150.dtsi | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi b/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi index a566a4facd78..0c9ffdc43afe 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-gdsc.dtsi @@ -196,7 +196,7 @@ /* GDSCs in Video CC */ vcodec0_gdsc: qcom,gdsc@ab00874 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "vcodec0_gdsc"; reg = <0xab00874 0x4>; qcom,poll-cfg-gdscr; @@ -204,7 +204,7 @@ }; venus_gdsc: qcom,gdsc@ab00814 { - compatible = "regulator-fixed"; + compatible = "qcom,gdsc"; regulator-name = "venus_gdsc"; reg = <0xab00814 0x4>; qcom,poll-cfg-gdscr; diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index a0f2eece261f..7724c78c7db9 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -620,8 +620,10 @@ }; clock_videocc: qcom,videocc { - compatible = "qcom,dummycc"; - clock-output-names = "videocc_clocks"; + compatible = "qcom,videocc-sm6150", "syscon"; + reg = <0xab00000 0x10000>; + reg-names = "cc_base"; + vdd_cx-supply = <&pm6150_s1_level>; #clock-cells = <1>; #reset-cells = <1>; }; -- GitLab From e5bb75523d95c445819c1529dedebc12d1fea20f Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Mon, 7 May 2018 21:42:23 +0530 Subject: [PATCH 0256/1299] ARM: dts: msm: Introduce bus topology for SM6150 Bus topology is the representation of bus connections in SOC and is required for the bus driver to serve the bandwidth requests from clients. Change-Id: Ic44244ec597a45d0426aea00a3fa4c5e2b1f1492 Signed-off-by: Odelu Kukatla --- arch/arm64/boot/dts/qcom/sm6150-bus.dtsi | 1612 ++++++++++++++++++++++ arch/arm64/boot/dts/qcom/sm6150.dtsi | 1 + include/dt-bindings/msm/msm-bus-ids.h | 4 + 3 files changed, 1617 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sm6150-bus.dtsi diff --git a/arch/arm64/boot/dts/qcom/sm6150-bus.dtsi b/arch/arm64/boot/dts/qcom/sm6150-bus.dtsi new file mode 100644 index 000000000000..565c4ead011c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm6150-bus.dtsi @@ -0,0 +1,1612 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +&soc { + ad_hoc_bus: ad-hoc-bus { + compatible = "qcom,msm-bus-device"; + reg = <0x1700000 0x40000>, + <0x1500000 0x40000>, + <0x9160000 0x40000>, + <0x9680000 0x60000>, + <0x1380000 0x40000>, + <0x1740000 0x40000>, + <0x1620000 0x40000>, + <0x1620000 0x40000>, + <0x1620000 0x40000>; + + reg-names = "aggre1_noc-base", "config_noc-base", + "dc_noc-base", "gem_noc-base", + "mc_virt-base", "mmss_noc-base", + "system_noc-base", "ipa_virt-base", + "camnoc_virt-base"; + + mbox-names = "apps_rsc", "disp_rsc"; + mboxes = <&apps_rsc 0 &disp_rsc 0>; + + /*RSCs*/ + rsc_apps: rsc-apps { + cell-id = ; + label = "apps_rsc"; + qcom,rsc-dev; + qcom,req_state = <2>; + }; + + rsc_disp: rsc-disp { + cell-id = ; + label = "disp_rsc"; + qcom,rsc-dev; + qcom,req_state = <3>; + }; + + /*BCMs*/ + bcm_acv: bcm-acv { + cell-id = ; + label = "ACV"; + qcom,bcm-name = "ACV"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_alc: bcm-alc { + cell-id = ; + label = "ALC"; + qcom,bcm-name = "ALC"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_mc0: bcm-mc0 { + cell-id = ; + label = "MC0"; + qcom,bcm-name = "MC0"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sh0: bcm-sh0 { + cell-id = ; + label = "SH0"; + qcom,bcm-name = "SH0"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_mm0: bcm-mm0 { + cell-id = ; + label = "MM0"; + qcom,bcm-name = "MM0"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_mm1: bcm-mm1 { + cell-id = ; + label = "MM1"; + qcom,bcm-name = "MM1"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sh2: bcm-sh2 { + cell-id = ; + label = "SH2"; + qcom,bcm-name = "SH2"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_mm2: bcm-mm2 { + cell-id = ; + label = "MM2"; + qcom,bcm-name = "MM2"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sh3: bcm-sh3 { + cell-id = ; + label = "SH3"; + qcom,bcm-name = "SH3"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_mm3: bcm-mm3 { + cell-id = ; + label = "MM3"; + qcom,bcm-name = "MM3"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn0: bcm-sn0 { + cell-id = ; + label = "SN0"; + qcom,bcm-name = "SN0"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_ce0: bcm-ce0 { + cell-id = ; + label = "CE0"; + qcom,bcm-name = "CE0"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_ip0: bcm-ip0 { + cell-id = ; + label = "IP0"; + qcom,bcm-name = "IP0"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_cn0: bcm-cn0 { + cell-id = ; + label = "CN0"; + qcom,bcm-name = "CN0"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_qup0: bcm-qup0 { + cell-id = ; + label = "QUP0"; + qcom,bcm-name = "QUP0"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn1: bcm-sn1 { + cell-id = ; + label = "SN1"; + qcom,bcm-name = "SN1"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn2: bcm-sn2 { + cell-id = ; + label = "SN2"; + qcom,bcm-name = "SN2"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn3: bcm-sn3 { + cell-id = ; + label = "SN3"; + qcom,bcm-name = "SN3"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn4: bcm-sn4 { + cell-id = ; + label = "SN4"; + qcom,bcm-name = "SN4"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn5: bcm-sn5 { + cell-id = ; + label = "SN5"; + qcom,bcm-name = "SN5"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn8: bcm-sn8 { + cell-id = ; + label = "SN8"; + qcom,bcm-name = "SN8"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn9: bcm-sn9 { + cell-id = ; + label = "SN9"; + qcom,bcm-name = "SN9"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn12: bcm-sn12 { + cell-id = ; + label = "SN12"; + qcom,bcm-name = "SN12"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn13: bcm-sn13 { + cell-id = ; + label = "SN13"; + qcom,bcm-name = "SN13"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn14: bcm-sn14 { + cell-id = ; + label = "SN14"; + qcom,bcm-name = "SN14"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_sn15: bcm-sn15 { + cell-id = ; + label = "SN15"; + qcom,bcm-name = "SN15"; + qcom,rscs = <&rsc_apps>; + qcom,bcm-dev; + }; + + bcm_mc0_display: bcm-mc0_display { + cell-id = ; + label = "MC0_DISPLAY"; + qcom,bcm-name = "MC0"; + qcom,rscs = <&rsc_disp>; + qcom,bcm-dev; + }; + + bcm_sh0_display: bcm-sh0_display { + cell-id = ; + label = "SH0_DISPLAY"; + qcom,bcm-name = "SH0"; + qcom,rscs = <&rsc_disp>; + qcom,bcm-dev; + }; + + bcm_mm0_display: bcm-mm0_display { + cell-id = ; + label = "MM0_DISPLAY"; + qcom,bcm-name = "MM0"; + qcom,rscs = <&rsc_disp>; + qcom,bcm-dev; + }; + + bcm_mm1_display: bcm-mm1_display { + cell-id = ; + label = "MM1_DISPLAY"; + qcom,bcm-name = "MM1"; + qcom,rscs = <&rsc_disp>; + qcom,bcm-dev; + }; + + bcm_mm2_display: bcm-mm2_display { + cell-id = ; + label = "MM2_DISPLAY"; + qcom,bcm-name = "MM2"; + qcom,rscs = <&rsc_disp>; + qcom,bcm-dev; + }; + + bcm_mm3_display: bcm-mm3_display { + cell-id = ; + label = "MM3_DISPLAY"; + qcom,bcm-name = "MM3"; + qcom,rscs = <&rsc_disp>; + qcom,bcm-dev; + }; + + /*Buses*/ + fab_aggre1_noc: fab-aggre1_noc { + cell-id = ; + label = "fab-aggre1_noc"; + qcom,fab-dev; + qcom,base-name = "aggre1_noc-base"; + qcom,qos-off = <4096>; + qcom,base-offset = <16384>; + qcom,sbm-offset = <0>; + qcom,bypass-qos-prg; + qcom,bus-type = <1>; + clocks = <>; + }; + + fab_camnoc_virt: fab-camnoc_virt { + cell-id = ; + label = "fab-camnoc_virt"; + qcom,fab-dev; + qcom,base-name = "camnoc_virt-base"; + qcom,bypass-qos-prg; + clocks = <>; + }; + + fab_config_noc: fab-config_noc { + cell-id = ; + label = "fab-config_noc"; + qcom,fab-dev; + qcom,base-name = "config_noc-base"; + qcom,bypass-qos-prg; + qcom,bus-type = <1>; + clocks = <>; + }; + + fab_dc_noc: fab-dc_noc { + cell-id = ; + label = "fab-dc_noc"; + qcom,fab-dev; + qcom,base-name = "dc_noc-base"; + qcom,bypass-qos-prg; + qcom,bus-type = <1>; + clocks = <>; + }; + + fab_gem_noc: fab-gem_noc { + cell-id = ; + label = "fab-gem_noc"; + qcom,fab-dev; + qcom,base-name = "gem_noc-base"; + qcom,bypass-qos-prg; + qcom,bus-type = <1>; + clocks = <>; + }; + + fab_ipa_virt: fab-ipa_virt { + cell-id = ; + label = "fab-ipa_virt"; + qcom,fab-dev; + qcom,base-name = "ipa_virt-base"; + qcom,bypass-qos-prg; + clocks = <>; + }; + + fab_mc_virt: fab-mc_virt { + cell-id = ; + label = "fab-mc_virt"; + qcom,fab-dev; + qcom,base-name = "mc_virt-base"; + qcom,bypass-qos-prg; + clocks = <>; + }; + + fab_mmss_noc: fab-mmss_noc { + cell-id = ; + label = "fab-mmss_noc"; + qcom,fab-dev; + qcom,base-name = "mmss_noc-base"; + qcom,qos-off = <4096>; + qcom,base-offset = <36864>; + qcom,sbm-offset = <0>; + qcom,bypass-qos-prg; + qcom,bus-type = <1>; + clocks = <>; + }; + + fab_system_noc: fab-system_noc { + cell-id = ; + label = "fab-system_noc"; + qcom,fab-dev; + qcom,base-name = "system_noc-base"; + qcom,qos-off = <4096>; + qcom,base-offset = <45056>; + qcom,sbm-offset = <0>; + qcom,bypass-qos-prg; + qcom,bus-type = <1>; + clocks = <>; + }; + + fab_gem_noc_display: fab-gem_noc_display { + cell-id = ; + label = "fab-gem_noc_display"; + qcom,fab-dev; + qcom,base-name = "gem_noc-base"; + qcom,qos-off = <128>; + qcom,base-offset = <176128>; + qcom,sbm-offset = <0>; + qcom,bypass-qos-prg; + qcom,bus-type = <1>; + clocks = <>; + }; + + fab_mc_virt_display: fab-mc_virt_display { + cell-id = ; + label = "fab-mc_virt_display"; + qcom,fab-dev; + qcom,base-name = "mc_virt-base"; + qcom,bypass-qos-prg; + clocks = <>; + }; + + fab_mmss_noc_display: fab-mmss_noc_display { + cell-id = ; + label = "fab-mmss_noc_display"; + qcom,fab-dev; + qcom,base-name = "mmss_noc-base"; + qcom,bypass-qos-prg; + qcom,bus-type = <1>; + clocks = <>; + }; + + /*Masters*/ + + mas_qhm_a1noc_cfg: mas-qhm-a1noc-cfg { + cell-id = ; + label = "mas-qhm-a1noc-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_srvc_aggre1_noc>; + qcom,bus-dev = <&fab_aggre1_noc>; + }; + + mas_qhm_qdss_bam: mas-qhm-qdss-bam { + cell-id = ; + label = "mas-qhm-qdss-bam"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,qport = <8>; + qcom,connections = <&slv_qns_a1noc_snoc>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,ap-owned; + qcom,prio = <2>; + }; + + mas_qhm_qspi: mas-qhm-qspi { + cell-id = ; + label = "mas-qhm-qspi"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,qport = <19>; + qcom,connections = <&slv_qns_a1noc_snoc>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,ap-owned; + qcom,prio = <2>; + }; + + mas_qhm_qup1: mas-qhm-qup1 { + cell-id = ; + label = "mas-qhm-qup1"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,qport = <14>; + qcom,connections = <&slv_qns_a1noc_snoc>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,bcms = <&bcm_qup0>; + qcom,ap-owned; + qcom,prio = <2>; + }; + + mas_qnm_cnoc: mas-qnm-cnoc { + cell-id = ; + label = "mas-qnm-cnoc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <0>; + qcom,connections = <&slv_qns_a1noc_snoc>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,ap-owned; + qcom,prio = <2>; + qcom,forwarding; + }; + + mas_qxm_crypto: mas-qxm-crypto { + cell-id = ; + label = "mas-qxm-crypto"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <1>; + qcom,connections = <&slv_qns_a1noc_snoc>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,bcms = <&bcm_ce0>; + qcom,ap-owned; + qcom,prio = <2>; + qcom,forwarding; + }; + + mas_qxm_ipa: mas-qxm-ipa { + cell-id = ; + label = "mas-qxm-ipa"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <2>; + qcom,connections = <&slv_qns_lpass_snoc>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,ap-owned; + qcom,prio = <2>; + qcom,forwarding; + }; + + mas_xm_pcie: mas-xm-pcie { + cell-id = ; + label = "mas-xm-pcie"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <15>; + qcom,connections = <&slv_qns_pcie_snoc>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,ap-owned; + qcom,prio = <2>; + }; + + mas_xm_qdss_etr: mas-xm-qdss-etr { + cell-id = ; + label = "mas-xm-qdss-etr"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <7>; + qcom,connections = <&slv_qns_a1noc_snoc>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,ap-owned; + qcom,prio = <2>; + }; + + mas_xm_sdc2: mas-xm-sdc2 { + cell-id = ; + label = "mas-xm-sdc2"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <18>; + qcom,connections = <&slv_qns_a1noc_snoc>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,ap-owned; + qcom,prio = <2>; + }; + + mas_qxm_camnoc_hf0_uncomp: mas-qxm-camnoc-hf0-uncomp { + cell-id = ; + label = "mas-qxm-camnoc-hf0-uncomp"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qns_camnoc_uncomp>; + qcom,bus-dev = <&fab_camnoc_virt>; + qcom,bcms = <&bcm_mm1>; + }; + + mas_qxm_camnoc_hf1_uncomp: mas-qxm-camnoc-hf1-uncomp { + cell-id = ; + label = "mas-qxm-camnoc-hf1-uncomp"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qns_camnoc_uncomp>; + qcom,bus-dev = <&fab_camnoc_virt>; + qcom,bcms = <&bcm_mm1>; + }; + + mas_qxm_camnoc_sf_uncomp: mas-qxm-camnoc-sf-uncomp { + cell-id = ; + label = "mas-qxm-camnoc-sf-uncomp"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qns_camnoc_uncomp>; + qcom,bus-dev = <&fab_camnoc_virt>; + qcom,bcms = <&bcm_mm1>; + }; + + mas_qhm_spdm: mas-qhm-spdm { + cell-id = ; + label = "mas-qhm-spdm"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qns_cnoc_a2noc>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + mas_qnm_snoc: mas-qnm-snoc { + cell-id = ; + label = "mas-qnm-snoc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qhs_tlmm_south + &slv_qhs_camera_cfg &slv_qhs_snoc_cfg + &slv_qhs_mnoc_cfg &slv_qhs_ufs_mem_cfg + &slv_qhs_glm &slv_qhs_qdss_cfg + &slv_qhs_display_cfg &slv_qhs_tcsr + &slv_qhs_ddrss_cfg &slv_qhs_sdc2 + &slv_qhs_gpuss_cfg &slv_qhs_venus_cfg + &slv_qhs_ipa &slv_qhs_clk_ctl + &slv_qhs_aop &slv_srvc_cnoc + &slv_qhs_ahb2phy_west &slv_qhs_cpr_cx + &slv_qhs_a1_noc_cfg &slv_qhs_aoss + &slv_qhs_prng &slv_qhs_vsense_ctrl_cfg + &slv_qhs_spdm &slv_qhs_crypto0_cfg + &slv_qhs_pimem_cfg &slv_qhs_cpr_mx + &slv_qhs_imem_cfg>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + mas_xm_qdss_dap: mas-xm-qdss-dap { + cell-id = ; + label = "mas-xm-qdss-dap"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qhs_tlmm_south + &slv_qhs_camera_cfg &slv_qhs_snoc_cfg + &slv_qhs_mnoc_cfg &slv_qhs_ufs_mem_cfg + &slv_qhs_glm &slv_qhs_qdss_cfg + &slv_qhs_display_cfg &slv_qhs_tcsr + &slv_qhs_ddrss_cfg &slv_qns_cnoc_a2noc + &slv_qhs_sdc2 &slv_qhs_gpuss_cfg + &slv_qhs_venus_cfg &slv_qhs_ipa + &slv_qhs_clk_ctl &slv_qhs_aop + &slv_srvc_cnoc &slv_qhs_ahb2phy_west + &slv_qhs_cpr_cx &slv_qhs_a1_noc_cfg + &slv_qhs_aoss &slv_qhs_prng + &slv_qhs_vsense_ctrl_cfg &slv_qhs_spdm + &slv_qhs_crypto0_cfg &slv_qhs_pimem_cfg + &slv_qhs_cpr_mx &slv_qhs_imem_cfg>; + qcom,bus-dev = <&fab_config_noc>; + }; + + mas_qhm_cnoc: mas-qhm-cnoc { + cell-id = ; + label = "mas-qhm-cnoc"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qhs_llcc + &slv_qhs_dc_noc_gemnoc>; + qcom,bus-dev = <&fab_dc_noc>; + }; + + mas_acm_apps: mas-acm-apps { + cell-id = ; + label = "mas-acm-apps"; + qcom,buswidth = <16>; + qcom,agg-ports = <1>; + qcom,qport = <96 98>; + qcom,connections = <&slv_qns_llcc &slv_qns_gem_noc_snoc + &slv_qns_sys_pcie>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,bcms = <&bcm_sh2>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_acm_gpu_tcu: mas-acm-gpu-tcu { + cell-id = ; + label = "mas-acm-gpu-tcu"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <352>; + qcom,connections = <&slv_qns_llcc + &slv_qns_gem_noc_snoc>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,ap-owned; + qcom,prio = <6>; + }; + + mas_acm_sys_tcu: mas-acm-sys-tcu { + cell-id = ; + label = "mas-acm-sys-tcu"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <384>; + qcom,connections = <&slv_qns_llcc + &slv_qns_gem_noc_snoc>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,ap-owned; + qcom,prio = <6>; + }; + + mas_qhm_gemnoc_cfg: mas-qhm-gemnoc-cfg { + cell-id = ; + label = "mas-qhm-gemnoc-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_srvc_gemnoc + &slv_qhs_mdsp_ms_mpu_cfg>; + qcom,bus-dev = <&fab_gem_noc>; + }; + + mas_qnm_gpu: mas-qnm-gpu { + cell-id = ; + label = "mas-qnm-gpu"; + qcom,buswidth = <32>; + qcom,agg-ports = <2>; + qcom,qport = <288 289>; + qcom,connections = <&slv_qns_llcc + &slv_qns_gem_noc_snoc>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qnm_mnoc_hf: mas-qnm-mnoc-hf { + cell-id = ; + label = "mas-qnm-mnoc-hf"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <128>; + qcom,connections = <&slv_qns_llcc>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qnm_mnoc_sf: mas-qnm-mnoc-sf { + cell-id = ; + label = "mas-qnm-mnoc-sf"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <320>; + qcom,connections = <&slv_qns_llcc + &slv_qns_gem_noc_snoc>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qnm_snoc_gc: mas-qnm-snoc-gc { + cell-id = ; + label = "mas-qnm-snoc-gc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <192>; + qcom,connections = <&slv_qns_llcc>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qnm_snoc_sf: mas-qnm-snoc-sf { + cell-id = ; + label = "mas-qnm-snoc-sf"; + qcom,buswidth = <16>; + qcom,agg-ports = <1>; + qcom,qport = <160>; + qcom,connections = <&slv_qns_llcc>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_ipa_core_master: mas-ipa-core-master { + cell-id = ; + label = "mas-ipa-core-master"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_ipa_core_slave>; + qcom,bus-dev = <&fab_ipa_virt>; + }; + + mas_llcc_mc: mas-llcc-mc { + cell-id = ; + label = "mas-llcc-mc"; + qcom,buswidth = <4>; + qcom,agg-ports = <4>; + qcom,connections = <&slv_ebi>; + qcom,bus-dev = <&fab_mc_virt>; + }; + + mas_qhm_mnoc_cfg: mas-qhm-mnoc-cfg { + cell-id = ; + label = "mas-qhm-mnoc-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_srvc_mnoc>; + qcom,bus-dev = <&fab_mmss_noc>; + }; + + mas_qxm_camnoc_hf0: mas-qxm-camnoc-hf0 { + cell-id = ; + label = "mas-qxm-camnoc-hf0"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <1>; + qcom,connections = <&slv_qns_mem_noc_hf>; + qcom,bus-dev = <&fab_mmss_noc>; + qcom,bcms = <&bcm_mm1>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qxm_camnoc_hf1: mas-qxm-camnoc-hf1 { + cell-id = ; + label = "mas-qxm-camnoc-hf1"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <2>; + qcom,connections = <&slv_qns_mem_noc_hf>; + qcom,bus-dev = <&fab_mmss_noc>; + qcom,bcms = <&bcm_mm1>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qxm_camnoc_sf: mas-qxm-camnoc-sf { + cell-id = ; + label = "mas-qxm-camnoc-sf"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <0>; + qcom,connections = <&slv_qns2_mem_noc>; + qcom,bus-dev = <&fab_mmss_noc>; + qcom,bcms = <&bcm_mm2>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qxm_mdp0: mas-qxm-mdp0 { + cell-id = ; + label = "mas-qxm-mdp0"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <3>; + qcom,connections = <&slv_qns_mem_noc_hf>; + qcom,bus-dev = <&fab_mmss_noc>; + qcom,bcms = <&bcm_mm1>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qxm_rot: mas-qxm-rot { + cell-id = ; + label = "mas-qxm-rot"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <5>; + qcom,connections = <&slv_qns2_mem_noc>; + qcom,bus-dev = <&fab_mmss_noc>; + qcom,bcms = <&bcm_mm3>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qxm_venus0: mas-qxm-venus0 { + cell-id = ; + label = "mas-qxm-venus0"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <6>; + qcom,connections = <&slv_qns2_mem_noc>; + qcom,bus-dev = <&fab_mmss_noc>; + qcom,bcms = <&bcm_mm3>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qxm_venus_arm9: mas-qxm-venus-arm9 { + cell-id = ; + label = "mas-qxm-venus-arm9"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <8>; + qcom,connections = <&slv_qns2_mem_noc>; + qcom,bus-dev = <&fab_mmss_noc>; + qcom,bcms = <&bcm_mm3>; + qcom,ap-owned; + qcom,prio = <0>; + qcom,forwarding; + }; + + mas_qhm_snoc_cfg: mas-qhm-snoc-cfg { + cell-id = ; + label = "mas-qhm-snoc-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_srvc_snoc>; + qcom,bus-dev = <&fab_system_noc>; + }; + + mas_qnm_aggre1_noc: mas-qnm-aggre1-noc { + cell-id = ; + label = "mas-qnm-aggre1-noc"; + qcom,buswidth = <16>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qns_gemnoc_sf &slv_qxs_pimem + &slv_xs_pcie &slv_qxs_imem + &slv_qhs_apss &slv_qns_cnoc + &slv_xs_sys_tcu_cfg &slv_xs_qdss_stm>; + qcom,bus-dev = <&fab_system_noc>; + qcom,bcms = <&bcm_sn9>; + }; + + mas_qnm_gemnoc: mas-qnm-gemnoc { + cell-id = ; + label = "mas-qnm-gemnoc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qxs_pimem &slv_qxs_imem + &slv_qhs_apss &slv_qns_cnoc + &slv_xs_sys_tcu_cfg &slv_xs_qdss_stm>; + qcom,bus-dev = <&fab_system_noc>; + qcom,bcms = <&bcm_sn15>; + }; + + mas_qnm_gemnoc_pcie: mas-qnm-gemnoc-pcie { + cell-id = ; + label = "mas-qnm-gemnoc-pcie"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_xs_pcie>; + qcom,bus-dev = <&fab_system_noc>; + qcom,bcms = <&bcm_sn8>; + }; + + mas_qnm_lpass_anoc: mas-qnm-lpass-anoc { + cell-id = ; + label = "mas-qnm-lpass-anoc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qns_gemnoc_sf + &slv_qxs_pimem &slv_xs_pcie + &slv_qxs_imem &slv_qhs_apss + &slv_qns_cnoc &slv_xs_qdss_stm>; + qcom,bus-dev = <&fab_system_noc>; + qcom,bcms = <&bcm_sn13>; + }; + + mas_qnm_pcie_anoc: mas-qnm-pcie-anoc { + cell-id = ; + label = "mas-qnm-pcie-anoc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_qns_gemnoc_sf &slv_qxs_imem + &slv_qhs_apss &slv_qns_cnoc + &slv_xs_qdss_stm>; + qcom,bus-dev = <&fab_system_noc>; + }; + + mas_qxm_pimem: mas-qxm-pimem { + cell-id = ; + label = "mas-qxm-pimem"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <1>; + qcom,connections = <&slv_qxs_imem &slv_qns_memnoc_gc>; + qcom,bus-dev = <&fab_system_noc>; + qcom,bcms = <&bcm_sn12>; + qcom,ap-owned; + qcom,prio = <2>; + qcom,forwarding; + }; + + mas_xm_gic: mas-xm-gic { + cell-id = ; + label = "mas-xm-gic"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,qport = <2>; + qcom,connections = <&slv_qxs_imem &slv_qns_memnoc_gc>; + qcom,bus-dev = <&fab_system_noc>; + qcom,bcms = <&bcm_sn12>; + qcom,ap-owned; + qcom,prio = <2>; + qcom,forwarding; + }; + + mas_alc: mas-alc { + cell-id = ; + label = "mas-alc"; + qcom,buswidth = <1>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_mc_virt>; + qcom,bcms = <&bcm_alc>; + }; + + mas_qnm_mnoc_hf_display: mas-qnm-mnoc-hf_display { + cell-id = ; + label = "mas-qnm-mnoc-hf_display"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <128>; + qcom,connections = <&slv_qns_llcc_display>; + qcom,bus-dev = <&fab_gem_noc_display>; + }; + + mas_qnm_mnoc_sf_display: mas-qnm-mnoc-sf_display { + cell-id = ; + label = "mas-qnm-mnoc-sf_display"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <320>; + qcom,connections = <&slv_qns_llcc_display>; + qcom,bus-dev = <&fab_gem_noc_display>; + }; + + mas_llcc_mc_display: mas-llcc-mc_display { + cell-id = ; + label = "mas-llcc-mc_display"; + qcom,buswidth = <4>; + qcom,agg-ports = <4>; + qcom,connections = <&slv_ebi_display>; + qcom,bus-dev = <&fab_mc_virt_display>; + }; + + mas_qxm_mdp0_display: mas-qxm-mdp0_display { + cell-id = ; + label = "mas-qxm-mdp0_display"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <3>; + qcom,connections = <&slv_qns_mem_noc_hf_display>; + qcom,bus-dev = <&fab_mmss_noc_display>; + qcom,bcms = <&bcm_mm1_display>; + }; + + mas_qxm_rot_display: mas-qxm-rot_display { + cell-id = ; + label = "mas-qxm-rot_display"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,qport = <5>; + qcom,connections = <&slv_qns2_mem_noc_display>; + qcom,bus-dev = <&fab_mmss_noc_display>; + qcom,bcms = <&bcm_mm3_display>; + }; + + /*Internal nodes*/ + + /*Slaves*/ + + slv_qns_a1noc_snoc:slv-qns-a1noc-snoc { + cell-id = ; + label = "slv-qns-a1noc-snoc"; + qcom,buswidth = <16>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,connections = <&mas_qnm_aggre1_noc>; + }; + + slv_srvc_aggre1_noc:slv-srvc-aggre1-noc { + cell-id = ; + label = "slv-srvc-aggre1-noc"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,bcms = <&bcm_sn8>; + }; + + slv_qns_lpass_snoc:slv-qns-lpass-snoc { + cell-id = ; + label = "slv-qns-lpass-snoc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,connections = <&mas_qnm_lpass_anoc>; + }; + + slv_qns_pcie_snoc:slv-qns-pcie-snoc { + cell-id = ; + label = "slv-qns-pcie-snoc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_aggre1_noc>; + qcom,connections = <&mas_qnm_pcie_anoc>; + qcom,bcms = <&bcm_sn14>; + }; + + slv_qns_camnoc_uncomp:slv-qns-camnoc-uncomp { + cell-id = ; + label = "slv-qns-camnoc-uncomp"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_camnoc_virt>; + }; + + slv_qhs_a1_noc_cfg:slv-qhs-a1-noc-cfg { + cell-id = ; + label = "slv-qhs-a1-noc-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,connections = <&mas_qhm_a1noc_cfg>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_ahb2phy_west:slv-qhs-ahb2phy-west { + cell-id = ; + label = "slv-qhs-ahb2phy-west"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_aop:slv-qhs-aop { + cell-id = ; + label = "slv-qhs-aop"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_aoss:slv-qhs-aoss { + cell-id = ; + label = "slv-qhs-aoss"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_camera_cfg:slv-qhs-camera-cfg { + cell-id = ; + label = "slv-qhs-camera-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_clk_ctl:slv-qhs-clk-ctl { + cell-id = ; + label = "slv-qhs-clk-ctl"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_cpr_cx:slv-qhs-cpr-cx { + cell-id = ; + label = "slv-qhs-cpr-cx"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_cpr_mx:slv-qhs-cpr-mx { + cell-id = ; + label = "slv-qhs-cpr-mx"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_crypto0_cfg:slv-qhs-crypto0-cfg { + cell-id = ; + label = "slv-qhs-crypto0-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_ddrss_cfg:slv-qhs-ddrss-cfg { + cell-id = ; + label = "slv-qhs-ddrss-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,connections = <&mas_qhm_cnoc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_display_cfg:slv-qhs-display-cfg { + cell-id = ; + label = "slv-qhs-display-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_glm:slv-qhs-glm { + cell-id = ; + label = "slv-qhs-glm"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_gpuss_cfg:slv-qhs-gpuss-cfg { + cell-id = ; + label = "slv-qhs-gpuss-cfg"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_imem_cfg:slv-qhs-imem-cfg { + cell-id = ; + label = "slv-qhs-imem-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_ipa:slv-qhs-ipa { + cell-id = ; + label = "slv-qhs-ipa"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_mnoc_cfg:slv-qhs-mnoc-cfg { + cell-id = ; + label = "slv-qhs-mnoc-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,connections = <&mas_qhm_mnoc_cfg>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_pimem_cfg:slv-qhs-pimem-cfg { + cell-id = ; + label = "slv-qhs-pimem-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_prng:slv-qhs-prng { + cell-id = ; + label = "slv-qhs-prng"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_qdss_cfg:slv-qhs-qdss-cfg { + cell-id = ; + label = "slv-qhs-qdss-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_sdc2:slv-qhs-sdc2 { + cell-id = ; + label = "slv-qhs-sdc2"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_snoc_cfg:slv-qhs-snoc-cfg { + cell-id = ; + label = "slv-qhs-snoc-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,connections = <&mas_qhm_snoc_cfg>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_spdm:slv-qhs-spdm { + cell-id = ; + label = "slv-qhs-spdm"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_tcsr:slv-qhs-tcsr { + cell-id = ; + label = "slv-qhs-tcsr"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_tlmm_south:slv-qhs-tlmm-south { + cell-id = ; + label = "slv-qhs-tlmm-south"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_ufs_mem_cfg:slv-qhs-ufs-mem-cfg { + cell-id = ; + label = "slv-qhs-ufs-mem-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_venus_cfg:slv-qhs-venus-cfg { + cell-id = ; + label = "slv-qhs-venus-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_vsense_ctrl_cfg:slv-qhs-vsense-ctrl-cfg { + cell-id = ; + label = "slv-qhs-vsense-ctrl-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qns_cnoc_a2noc:slv-qns-cnoc-a2noc { + cell-id = ; + label = "slv-qns-cnoc-a2noc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,connections = <&mas_qnm_cnoc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_srvc_cnoc:slv-srvc-cnoc { + cell-id = ; + label = "slv-srvc-cnoc"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_config_noc>; + qcom,bcms = <&bcm_cn0>; + }; + + slv_qhs_dc_noc_gemnoc:slv-qhs-dc-noc-gemnoc { + cell-id = ; + label = "slv-qhs-dc-noc-gemnoc"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_dc_noc>; + qcom,connections = <&mas_qhm_gemnoc_cfg>; + }; + + slv_qhs_llcc:slv-qhs-llcc { + cell-id = ; + label = "slv-qhs-llcc"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_dc_noc>; + }; + + slv_qhs_mdsp_ms_mpu_cfg:slv-qhs-mdsp-ms-mpu-cfg { + cell-id = ; + label = "slv-qhs-mdsp-ms-mpu-cfg"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_gem_noc>; + }; + + slv_qns_gem_noc_snoc:slv-qns-gem-noc-snoc { + cell-id = ; + label = "slv-qns-gem-noc-snoc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,connections = <&mas_qnm_gemnoc>; + qcom,bcms = <&bcm_sh3>; + }; + + slv_qns_llcc:slv-qns-llcc { + cell-id = ; + label = "slv-qns-llcc"; + qcom,buswidth = <16>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,connections = <&mas_llcc_mc>; + qcom,bcms = <&bcm_sh0>; + }; + + slv_qns_sys_pcie:slv-qns-sys-pcie { + cell-id = ; + label = "slv-qns-sys-pcie"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_gem_noc>; + qcom,connections = <&mas_qnm_gemnoc_pcie>; + }; + + slv_srvc_gemnoc:slv-srvc-gemnoc { + cell-id = ; + label = "slv-srvc-gemnoc"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_gem_noc>; + }; + + slv_ipa_core_slave:slv-ipa-core-slave { + cell-id = ; + label = "slv-ipa-core-slave"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_ipa_virt>; + qcom,bcms = <&bcm_ip0>; + }; + + slv_ebi:slv-ebi { + cell-id = ; + label = "slv-ebi"; + qcom,buswidth = <4>; + qcom,agg-ports = <4>; + qcom,bus-dev = <&fab_mc_virt>; + qcom,bcms = <&bcm_mc0>, <&bcm_acv>; + }; + + slv_qns2_mem_noc:slv-qns2-mem-noc { + cell-id = ; + label = "slv-qns2-mem-noc"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_mmss_noc>; + qcom,connections = <&mas_qnm_mnoc_sf>; + qcom,bcms = <&bcm_mm2>; + }; + + slv_qns_mem_noc_hf:slv-qns-mem-noc-hf { + cell-id = ; + label = "slv-qns-mem-noc-hf"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_mmss_noc>; + qcom,connections = <&mas_qnm_mnoc_hf>; + qcom,bcms = <&bcm_mm0>; + }; + + slv_srvc_mnoc:slv-srvc-mnoc { + cell-id = ; + label = "slv-srvc-mnoc"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_mmss_noc>; + }; + + slv_qhs_apss:slv-qhs-apss { + cell-id = ; + label = "slv-qhs-apss"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_system_noc>; + }; + + slv_qns_cnoc:slv-qns-cnoc { + cell-id = ; + label = "slv-qns-cnoc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_system_noc>; + qcom,connections = <&mas_qnm_snoc>; + qcom,bcms = <&bcm_sn3>; + }; + + slv_qns_gemnoc_sf:slv-qns-gemnoc-sf { + cell-id = ; + label = "slv-qns-gemnoc-sf"; + qcom,buswidth = <16>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_system_noc>; + qcom,connections = <&mas_qnm_snoc_sf>; + qcom,bcms = <&bcm_sn0>; + }; + + slv_qns_memnoc_gc:slv-qns-memnoc-gc { + cell-id = ; + label = "slv-qns-memnoc-gc"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_system_noc>; + qcom,connections = <&mas_qnm_snoc_gc>; + qcom,bcms = <&bcm_sn2>; + }; + + slv_qxs_imem:slv-qxs-imem { + cell-id = ; + label = "slv-qxs-imem"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_system_noc>; + qcom,bcms = <&bcm_sn1>; + }; + + slv_qxs_pimem:slv-qxs-pimem { + cell-id = ; + label = "slv-qxs-pimem"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_system_noc>; + qcom,bcms = <&bcm_sn4>; + }; + + slv_srvc_snoc:slv-srvc-snoc { + cell-id = ; + label = "slv-srvc-snoc"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_system_noc>; + }; + + slv_xs_pcie:slv-xs-pcie { + cell-id = ; + label = "slv-xs-pcie"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_system_noc>; + qcom,bcms = <&bcm_sn8>; + }; + + slv_xs_qdss_stm:slv-xs-qdss-stm { + cell-id = ; + label = "slv-xs-qdss-stm"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_system_noc>; + qcom,bcms = <&bcm_sn5>; + }; + + slv_xs_sys_tcu_cfg:slv-xs-sys-tcu-cfg { + cell-id = ; + label = "slv-xs-sys-tcu-cfg"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_system_noc>; + }; + + slv_qns_llcc_display:slv-qns-llcc_display { + cell-id = ; + label = "slv-qns-llcc_display"; + qcom,buswidth = <16>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_gem_noc_display>; + qcom,connections = <&mas_llcc_mc_display>; + qcom,bcms = <&bcm_sh0_display>; + }; + + slv_ebi_display:slv-ebi_display { + cell-id = ; + label = "slv-ebi_display"; + qcom,buswidth = <4>; + qcom,agg-ports = <4>; + qcom,bus-dev = <&fab_mc_virt_display>; + qcom,bcms = <&bcm_mc0_display>; + }; + + slv_qns2_mem_noc_display:slv-qns2-mem-noc_display { + cell-id = ; + label = "slv-qns2-mem-noc_display"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_mmss_noc_display>; + qcom,connections = <&mas_qnm_mnoc_sf_display>; + qcom,bcms = <&bcm_mm2_display>; + }; + + slv_qns_mem_noc_hf_display:slv-qns-mem-noc-hf_display { + cell-id = ; + label = "slv-qns-mem-noc-hf_display"; + qcom,buswidth = <32>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_mmss_noc_display>; + qcom,connections = <&mas_qnm_mnoc_hf_display>; + qcom,bcms = <&bcm_mm0_display>; + }; + }; +}; + diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index a0f2eece261f..0d3bf8e00fb7 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -1678,3 +1678,4 @@ #include "sm6150-ion.dtsi" #include "msm-arm-smmu-sm6150.dtsi" #include "sm6150-coresight.dtsi" +#include "sm6150-bus.dtsi" diff --git a/include/dt-bindings/msm/msm-bus-ids.h b/include/dt-bindings/msm/msm-bus-ids.h index 0d35fdadefb2..c53b2551ac54 100644 --- a/include/dt-bindings/msm/msm-bus-ids.h +++ b/include/dt-bindings/msm/msm-bus-ids.h @@ -276,6 +276,7 @@ #define MSM_BUS_MASTER_QSPI_0 165 #define MSM_BUS_MASTER_QSPI_1 166 #define MSM_BUS_MASTER_PCIE_3 167 +#define MSM_BUS_MASTER_LPASS_ANOC 168 #define MSM_BUS_MASTER_LLCC_DISPLAY 20000 #define MSM_BUS_MASTER_MNOC_HF_MEM_NOC_DISPLAY 20001 @@ -644,6 +645,9 @@ #define MSM_BUS_SLAVE_USB3_2 799 #define MSM_BUS_SLAVE_SERVICE_GEM_NOC_1 800 #define MSM_BUS_SLAVE_PCIE_3 801 +#define MSM_BUS_SLAVE_LPASS_SNOC 802 +#define MSM_BUS_SLAVE_DC_NOC_GEMNOC 803 +#define MSM_BUS_SLAVE_MEM_NOC_PCIE_SNOC 804 #define MSM_BUS_SLAVE_EBI_CH0_DISPLAY 20512 #define MSM_BUS_SLAVE_LLCC_DISPLAY 20513 -- GitLab From 1939413c0f60db80e31f003e73155850ebdd45af Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Thu, 9 Feb 2017 20:44:29 +0530 Subject: [PATCH 0257/1299] arm: dma-mapping: add dma mapper for io-pgtable-fast for 32 bit io-pgtable-fast was implemented to achieve better performance for IOMMU map/un-map. Add DMA API support that goes through io-pgtable-fast for 32 bit targets. Change-Id:I3d0560a4331f6b7b87c70d0885df11d12cb1d6ec Signed-off-by: Charan Teja Reddy --- arch/arm/include/asm/cacheflush.h | 18 +++++++++++++++++- arch/arm/include/asm/dma-iommu.h | 4 ++++ arch/arm/include/asm/glue-cache.h | 5 +++++ arch/arm/mm/dma-mapping.c | 19 +++++++++++++++++-- arch/arm/mm/dma.h | 3 --- 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index f7ba4389f0fa..072773152928 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -178,10 +178,26 @@ extern void __cpuc_flush_dcache_area(void *, size_t); * is visible to DMA, or data written by DMA to system memory is * visible to the CPU. */ +extern void __dma_map_area(const void *addr, size_t size, int dir); +extern void __dma_unmap_area(const void *addr, size_t size, int dir); extern void dmac_inv_range(const void *start, const void *end); extern void dmac_clean_range(const void *start, const void *end); -extern void dmac_flush_range(const void *, const void *); +extern void dmac_flush_range(const void *start, const void *end); +static inline void __dma_inv_area(const void *start, size_t len) +{ + dmac_inv_range(start, start + len); +} + +static inline void __dma_clean_area(const void *start, size_t len) +{ + dmac_clean_range(start, start + len); +} + +static inline void __dma_flush_area(const void *start, size_t len) +{ + dmac_flush_range(start, start + len); +} #endif /* diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h index 6821f1249300..ad3d57afe1a3 100644 --- a/arch/arm/include/asm/dma-iommu.h +++ b/arch/arm/include/asm/dma-iommu.h @@ -8,12 +8,14 @@ #include #include #include +#include #define ARM_MAPPING_ERROR (~(dma_addr_t)0x0) struct dma_iommu_mapping { /* iommu specific data */ struct iommu_domain *domain; + const struct dma_map_ops *ops; unsigned long **bitmaps; /* array of bitmaps */ unsigned int nr_bitmaps; /* nr of elements in array */ @@ -24,6 +26,8 @@ struct dma_iommu_mapping { spinlock_t lock; struct kref kref; + + struct dma_fast_smmu_mapping *fast; }; struct dma_iommu_mapping * diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h index d14f31047a5c..f7c75dcae829 100644 --- a/arch/arm/include/asm/glue-cache.h +++ b/arch/arm/include/asm/glue-cache.h @@ -157,6 +157,11 @@ static inline void nop_dma_unmap_area(const void *s, size_t l, int f) { } #define dmac_flush_range __glue(_CACHE,_dma_flush_range) #define dmac_inv_range __glue(_CACHE, _dma_inv_range) #define dmac_clean_range __glue(_CACHE, _dma_clean_range) +#define dmac_map_area __glue(_CACHE, _dma_map_area) +#define dmac_unmap_area __glue(_CACHE, _dma_unmap_area) + +#define __dma_map_area dmac_map_area +#define __dma_unmap_area dmac_unmap_area #endif #endif diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 600e4ac82485..7976f0f4d79e 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -2336,6 +2337,7 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, u64 size) goto err4; kref_init(&mapping->kref); + mapping->ops = &iommu_ops; return mapping; err4: kfree(mapping->bitmaps[0]); @@ -2351,9 +2353,15 @@ EXPORT_SYMBOL_GPL(arm_iommu_create_mapping); static void release_iommu_mapping(struct kref *kref) { int i; + int is_fast = 0; + struct dma_iommu_mapping *mapping = container_of(kref, struct dma_iommu_mapping, kref); + iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast); + if (is_fast) + fast_smmu_release_mapping(kref); + iommu_domain_free(mapping->domain); for (i = 0; i < mapping->nr_bitmaps; i++) kfree(mapping->bitmaps[i]); @@ -2419,7 +2427,14 @@ int arm_iommu_attach_device(struct device *dev, struct dma_iommu_mapping *mapping) { int err; - int s1_bypass = 0; + int s1_bypass = 0, is_fast = 0; + + iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast); + if (is_fast) { + err = fast_smmu_init_mapping(dev, mapping); + if (err) + return err; + } err = __arm_iommu_attach_device(dev, mapping); if (err) @@ -2428,7 +2443,7 @@ int arm_iommu_attach_device(struct device *dev, iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS, &s1_bypass); if (!s1_bypass) - set_dma_ops(dev, &iommu_ops); + set_dma_ops(dev, mapping->ops); return 0; } EXPORT_SYMBOL_GPL(arm_iommu_attach_device); diff --git a/arch/arm/mm/dma.h b/arch/arm/mm/dma.h index aaef64b7f177..ca148192d5e6 100644 --- a/arch/arm/mm/dma.h +++ b/arch/arm/mm/dma.h @@ -5,9 +5,6 @@ #include #ifndef MULTI_CACHE -#define dmac_map_area __glue(_CACHE,_dma_map_area) -#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area) - /* * These are private to the dma-mapping API. Do not use directly. * Their sole purpose is to ensure that data held in the cache -- GitLab From 8fe4de562348b25ee8359a6254ad781df1a673ff Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Tue, 12 Jun 2018 19:17:10 +0530 Subject: [PATCH 0258/1299] usb: phy: Add support for init sequence for femto phy Add support for power up init sequence to bring up the Synopsys HS Femto phy in required configuration. Also provide module param to be able to override the init sequence passed from DT files. Also, correct the MIN voltage for 1P8 regulator which needs min and max to be the same as this is a fixed regulator. Change-Id: I50ae4cb382a3694922e1db097e689f2821ffd7ee Signed-off-by: Sriharsha Allenki --- drivers/usb/phy/phy-qcom-snps-28nm-hs.c | 51 ++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/usb/phy/phy-qcom-snps-28nm-hs.c b/drivers/usb/phy/phy-qcom-snps-28nm-hs.c index 3aeca1f72679..be1cc29da670 100644 --- a/drivers/usb/phy/phy-qcom-snps-28nm-hs.c +++ b/drivers/usb/phy/phy-qcom-snps-28nm-hs.c @@ -33,7 +33,7 @@ #define USB_HSPHY_3P3_VOL_MAX 3300000 /* uV */ #define USB_HSPHY_3P3_HPM_LOAD 16000 /* uA */ -#define USB_HSPHY_1P8_VOL_MIN 1704000 /* uV */ +#define USB_HSPHY_1P8_VOL_MIN 1800000 /* uV */ #define USB_HSPHY_1P8_VOL_MAX 1800000 /* uV */ #define USB_HSPHY_1P8_HPM_LOAD 19000 /* uA */ @@ -71,6 +71,17 @@ struct msm_snps_hsphy { struct mutex phy_lock; }; +static char *override_phy_init; +module_param(override_phy_init, charp, 0644); +MODULE_PARM_DESC(override_phy_init, + "Override SNPS HS PHY Init Settings"); + +struct hsphy_reg_val { + u32 offset; + u32 val; + u32 delay; +}; + static void msm_snps_hsphy_disable_clocks(struct msm_snps_hsphy *phy) { dev_dbg(phy->phy.dev, "%s: clocks_enabled:%d\n", @@ -250,6 +261,42 @@ static int msm_snps_phy_block_reset(struct msm_snps_hsphy *phy) return 0; } +static void msm_snps_hsphy_por(struct msm_snps_hsphy *phy) +{ + struct hsphy_reg_val *reg = NULL; + u32 aseq[20]; + u32 *seq, tmp; + + if (override_phy_init) { + dev_dbg(phy->phy.dev, "Override HS PHY Init:%s\n", + override_phy_init); + get_options(override_phy_init, ARRAY_SIZE(aseq), aseq); + seq = &aseq[1]; + } else { + seq = phy->phy_init_seq; + } + + reg = (struct hsphy_reg_val *)seq; + if (!reg) + return; + + while (reg->offset != -1) { + writeb_relaxed(reg->val, + phy->phy_csr_regs + reg->offset); + + tmp = readb_relaxed(phy->phy_csr_regs + reg->offset); + if (tmp != reg->val) + dev_err(phy->phy.dev, "write:%x to: %x failed\n", + reg->val, reg->offset); + if (reg->delay) + usleep_range(reg->delay, reg->delay + 10); + reg++; + } + + /* Ensure that the above parameter overrides is successful. */ + mb(); +} + static int msm_snps_hsphy_reset(struct msm_snps_hsphy *phy) { int ret; @@ -308,6 +355,8 @@ static int msm_snps_hsphy_init(struct usb_phy *uphy) if (ret) return ret; + msm_snps_hsphy_por(phy); + ret = msm_snps_hsphy_reset(phy); return ret; -- GitLab From 69499579186532be1555cb8a40ec482829c58971 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Wed, 13 Jun 2018 21:06:26 +0300 Subject: [PATCH 0259/1299] msm: gsi: Update Channel Scratch structures for GSI 2.5 GSI 2.5 introduced changes to the GSI channel scratches including the SWI fields. E.g. due to removal of smart prefetch from MCS. This change adapt the code for the new scratch structures for MHI, xDCI and GPI protocols. CRs-Fixed: 2260038 Change-Id: Ib79e3dc3356e65c8767d1f8e9005db34dd0061e4 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/gsi/gsi.c | 94 +++++++++++++++++-- .../platform/msm/ipa/ipa_clients/ipa_usb.c | 16 +++- drivers/platform/msm/ipa/ipa_v3/ipa_client.c | 14 ++- drivers/platform/msm/ipa/ipa_v3/ipa_dp.c | 23 +++-- drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c | 28 ++++-- include/linux/msm_gsi.h | 50 ++++++++-- 6 files changed, 185 insertions(+), 40 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 44e6f56c1ab8..5c6ef29b4b1f 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -1909,8 +1909,6 @@ EXPORT_SYMBOL(gsi_alloc_channel); static void __gsi_write_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch val) { - uint32_t reg; - gsi_writel(val.data.word1, gsi_ctx->base + GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(chan_hdl, gsi_ctx->per.ee)); @@ -1920,17 +1918,69 @@ static void __gsi_write_channel_scratch(unsigned long chan_hdl, gsi_writel(val.data.word3, gsi_ctx->base + GSI_EE_n_GSI_CH_k_SCRATCH_2_OFFS(chan_hdl, gsi_ctx->per.ee)); + + gsi_writel(val.data.word4, gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl, + gsi_ctx->per.ee)); +} + +static union __packed gsi_channel_scratch __gsi_update_mhi_channel_scratch( + unsigned long chan_hdl, struct __packed gsi_mhi_channel_scratch mscr) +{ + union __packed gsi_channel_scratch scr; + /* below sequence is not atomic. assumption is sequencer specific fields * will remain unchanged across this sequence */ - reg = gsi_readl(gsi_ctx->base + + + /* READ */ + scr.data.word1 = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(chan_hdl, + gsi_ctx->per.ee)); + + scr.data.word2 = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_1_OFFS(chan_hdl, + gsi_ctx->per.ee)); + + scr.data.word3 = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_2_OFFS(chan_hdl, + gsi_ctx->per.ee)); + + scr.data.word4 = gsi_readl(gsi_ctx->base + GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl, gsi_ctx->per.ee)); - reg &= 0xFFFF; - reg |= (val.data.word4 & 0xFFFF0000); - gsi_writel(reg, gsi_ctx->base + + + /* UPDATE */ + scr.mhi.mhi_host_wp_addr = mscr.mhi_host_wp_addr; + scr.mhi.assert_bit40 = mscr.assert_bit40; + scr.mhi.polling_configuration = mscr.polling_configuration; + scr.mhi.burst_mode_enabled = mscr.burst_mode_enabled; + scr.mhi.polling_mode = mscr.polling_mode; + scr.mhi.oob_mod_threshold = mscr.oob_mod_threshold; + + if (gsi_ctx->per.ver < GSI_VER_2_5) { + scr.mhi.max_outstanding_tre = mscr.max_outstanding_tre; + scr.mhi.outstanding_threshold = mscr.outstanding_threshold; + } + + /* WRITE */ + gsi_writel(scr.data.word1, gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(chan_hdl, + gsi_ctx->per.ee)); + + gsi_writel(scr.data.word2, gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_1_OFFS(chan_hdl, + gsi_ctx->per.ee)); + + gsi_writel(scr.data.word3, gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_2_OFFS(chan_hdl, + gsi_ctx->per.ee)); + + gsi_writel(scr.data.word4, gsi_ctx->base + GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl, gsi_ctx->per.ee)); + + return scr; } int gsi_write_channel_scratch(unsigned long chan_hdl, @@ -1966,6 +2016,38 @@ int gsi_write_channel_scratch(unsigned long chan_hdl, } EXPORT_SYMBOL(gsi_write_channel_scratch); +int gsi_update_mhi_channel_scratch(unsigned long chan_hdl, + struct __packed gsi_mhi_channel_scratch mscr) +{ + struct gsi_chan_ctx *ctx; + + if (!gsi_ctx) { + pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); + return -GSI_STATUS_NODEV; + } + + if (chan_hdl >= gsi_ctx->max_ch) { + GSIERR("bad params chan_hdl=%lu\n", chan_hdl); + return -GSI_STATUS_INVALID_PARAMS; + } + + if (gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_ALLOCATED && + gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_STOPPED) { + GSIERR("bad state %d\n", + gsi_ctx->chan[chan_hdl].state); + return -GSI_STATUS_UNSUPPORTED_OP; + } + + ctx = &gsi_ctx->chan[chan_hdl]; + + mutex_lock(&ctx->mlock); + ctx->scratch = __gsi_update_mhi_channel_scratch(chan_hdl, mscr); + mutex_unlock(&ctx->mlock); + + return GSI_STATUS_SUCCESS; +} +EXPORT_SYMBOL(gsi_update_mhi_channel_scratch); + int gsi_query_channel_db_addr(unsigned long chan_hdl, uint32_t *db_addr_wp_lsb, uint32_t *db_addr_wp_msb) { diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c index bf992ccbc9fa..be0032ccb21c 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c @@ -1351,14 +1351,20 @@ static int ipa3_usb_request_xdci_channel( params->xfer_scratch.depcmd_low_addr; chan_params.chan_scratch.xdci.depcmd_hi_addr = params->xfer_scratch.depcmd_hi_addr; - chan_params.chan_scratch.xdci.outstanding_threshold = + + /* + * Update scratch for MCS smart prefetch: + * Starting IPA4.5, smart prefetch implemented by H/W. + * At IPA 4.0/4.1/4.2, we do not use MCS smart prefetch + * so keep the fields zero. + */ + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { + chan_params.chan_scratch.xdci.outstanding_threshold = ((params->teth_prot == IPA_USB_MBIM) ? 1 : 2) * chan_params.chan_params.re_size; - - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) - chan_params.chan_scratch.xdci.outstanding_threshold = 0; - + } /* max_outstanding_tre is set in ipa3_request_gsi_channel() */ + result = ipa3_request_gsi_channel(&chan_params, out_params); if (result) { IPA_USB_ERR("failed to allocate GSI channel\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 637d0f8b4c48..309378712be5 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -823,11 +823,17 @@ int ipa3_request_gsi_channel(struct ipa_request_gsi_channel_params *params, memcpy(&ep->chan_scratch, ¶ms->chan_scratch, sizeof(union __packed gsi_channel_scratch)); - ep->chan_scratch.xdci.max_outstanding_tre = - params->chan_params.re_size * gsi_ep_cfg_ptr->ipa_if_tlv; - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) - ep->chan_scratch.xdci.max_outstanding_tre = 0; + /* + * Update scratch for MCS smart prefetch: + * Starting IPA4.5, smart prefetch implemented by H/W. + * At IPA 4.0/4.1/4.2, we do not use MCS smart prefetch + * so keep the fields zero. + */ + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { + ep->chan_scratch.xdci.max_outstanding_tre = + params->chan_params.re_size * gsi_ep_cfg_ptr->ipa_if_tlv; + } gsi_res = gsi_write_channel_scratch(ep->gsi_chan_hdl, params->chan_scratch); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 6649017f0848..b8703ff4dfb0 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -3792,15 +3792,20 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in, goto fail_alloc_channel; memset(&ch_scratch, 0, sizeof(ch_scratch)); - ch_scratch.gpi.max_outstanding_tre = gsi_ep_info->ipa_if_tlv * - GSI_CHAN_RE_SIZE_16B; - ch_scratch.gpi.outstanding_threshold = 2 * GSI_CHAN_RE_SIZE_16B; - - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) { - ch_scratch.gpi.max_outstanding_tre = 0; - ch_scratch.gpi.outstanding_threshold = 0; - } - + /* + * Update scratch for MCS smart prefetch: + * Starting IPA4.5, smart prefetch implemented by H/W. + * At IPA 4.0/4.1/4.2, we do not use MCS smart prefetch + * so keep the fields zero. + */ + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { + ch_scratch.gpi.max_outstanding_tre = + gsi_ep_info->ipa_if_tlv * GSI_CHAN_RE_SIZE_16B; + ch_scratch.gpi.outstanding_threshold = + 2 * GSI_CHAN_RE_SIZE_16B; + } + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) + ch_scratch.gpi.dl_nlo_channel = 0; result = gsi_write_channel_scratch(ep->gsi_chan_hdl, ch_scratch); if (result != GSI_STATUS_SUCCESS) { IPAERR("failed to write scratch %d\n", result); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c index 82cd81878903..4eb44b40862d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c @@ -298,13 +298,18 @@ static int ipa_mhi_start_gsi_channel(enum ipa_client_type client, params->channel_context_addr + offsetof(struct ipa_mhi_ch_ctx, wp)); ch_scratch.mhi.assert_bit40 = params->assert_bit40; - ch_scratch.mhi.max_outstanding_tre = - ep_cfg->ipa_if_tlv * ch_props.re_size; - ch_scratch.mhi.outstanding_threshold = - min(ep_cfg->ipa_if_tlv / 2, 8) * ch_props.re_size; - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) { - ch_scratch.mhi.max_outstanding_tre = 0; - ch_scratch.mhi.outstanding_threshold = 0; + + /* + * Update scratch for MCS smart prefetch: + * Starting IPA4.5, smart prefetch implemented by H/W. + * At IPA 4.0/4.1/4.2, we do not use MCS smart prefetch + * so keep the fields zero. + */ + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { + ch_scratch.mhi.max_outstanding_tre = + ep_cfg->ipa_if_tlv * ch_props.re_size; + ch_scratch.mhi.outstanding_threshold = + min(ep_cfg->ipa_if_tlv / 2, 8) * ch_props.re_size; } ch_scratch.mhi.oob_mod_threshold = 4; if (params->ch_ctx_host->brstmode == IPA_MHI_BURST_MODE_DEFAULT || @@ -564,8 +569,13 @@ int ipa3_mhi_resume_channels_internal(enum ipa_client_type client, * set polling mode bit to DB mode before * resuming the channel */ - res = gsi_write_channel_scratch( - ep->gsi_chan_hdl, ch_scratch); + ch_scratch.mhi.polling_mode = IPA_MHI_POLLING_MODE_DB_MODE; + + /* Use GSI update API to not affect non-SWI fields + * inside the scratch while in suspend-resume operation + */ + res = gsi_update_mhi_channel_scratch( + ep->gsi_chan_hdl, ch_scratch.mhi); if (res) { IPA_MHI_ERR("write ch scratch fail %d\n" , res); diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h index f0994b3c3acb..30629b221c8d 100644 --- a/include/linux/msm_gsi.h +++ b/include/linux/msm_gsi.h @@ -457,6 +457,8 @@ struct gsi_xfer_elem { * gsi_gpi_channel_scratch - GPI protocol SW config area of * channel scratch * + * @dl_nlo_channel: Whether this is DL NLO Channel or not? Relevant for + * GSI 2.5 and above where DL NLO introduced. * @max_outstanding_tre: Used for the prefetch management sequence by the * sequencer. Defines the maximum number of allowed * outstanding TREs in IPA/GSI (in Bytes). RE engine @@ -466,18 +468,23 @@ struct gsi_xfer_elem { * the feature in doorbell mode (DB Mode=1). Maximum * outstanding TREs should be set to 64KB * (or any value larger or equal to ring length . RLEN) + * The field is irrelevant starting GSI 2.5 where smart + * prefetch implemented by the H/W. * @outstanding_threshold: Used for the prefetch management sequence by the * sequencer. Defines the threshold (in Bytes) as to when * to update the channel doorbell. Should be smaller than * Maximum outstanding TREs. value. It is suggested to * configure this value to 2 * element size. + * The field is irrelevant starting GSI 2.5 where smart + * prefetch implemented by the H/W. */ struct __packed gsi_gpi_channel_scratch { - uint64_t resvd1; + uint64_t dl_nlo_channel:1; /* Relevant starting GSI 2.5 */ + uint64_t resvd1:63; uint32_t resvd2:16; - uint32_t max_outstanding_tre:16; + uint32_t max_outstanding_tre:16; /* Not relevant starting GSI 2.5 */ uint32_t resvd3:16; - uint32_t outstanding_threshold:16; + uint32_t outstanding_threshold:16; /* Not relevant starting GSI 2.5 */ }; /** @@ -517,12 +524,16 @@ struct __packed gsi_gpi_channel_scratch { * To disable the feature in doorbell mode (DB Mode=1). * Maximum outstanding TREs should be set to 64KB * (or any value larger or equal to ring length . RLEN) + * The field is irrelevant starting GSI 2.5 where smart + * prefetch implemented by the H/W. * @outstanding_threshold: Used for the prefetch management sequence by the * sequencer. Defines the threshold (in Bytes) as to when * to update the channel doorbell. Should be smaller than * Maximum outstanding TREs. value. It is suggested to * configure this value to min(TLV_FIFO_SIZE/2,8) * * element size. + * The field is irrelevant starting GSI 2.5 where smart + * prefetch implemented by the H/W. */ struct __packed gsi_mhi_channel_scratch { uint64_t mhi_host_wp_addr; @@ -533,9 +544,9 @@ struct __packed gsi_mhi_channel_scratch { uint32_t polling_mode:1; uint32_t oob_mod_threshold:5; uint32_t resvd2:2; - uint32_t max_outstanding_tre:16; + uint32_t max_outstanding_tre:16; /* Not relevant starting GSI 2.5 */ uint32_t resvd3:16; - uint32_t outstanding_threshold:16; + uint32_t outstanding_threshold:16; /* Not relevant starting GSI 2.5 */ }; /** @@ -560,6 +571,8 @@ struct __packed gsi_mhi_channel_scratch { * To disable the feature in doorbell mode (DB Mode=1) * Maximum outstanding TREs should be set to 64KB * (or any value larger or equal to ring length . RLEN) + * The field is irrelevant starting GSI 2.5 where smart + * prefetch implemented by the H/W. * @depcmd_hi_addr: Used to generate "Update Transfer" command * @outstanding_threshold: Used for the prefetch management sequence by the * sequencer. Defines the threshold (in Bytes) as to when @@ -567,6 +580,8 @@ struct __packed gsi_mhi_channel_scratch { * Maximum outstanding TREs. value. It is suggested to * configure this value to 2 * element size. for MBIM the * suggested configuration is the element size. + * The field is irrelevant starting GSI 2.5 where smart + * prefetch implemented by the H/W. */ struct __packed gsi_xdci_channel_scratch { uint32_t last_trb_addr:16; @@ -576,9 +591,9 @@ struct __packed gsi_xdci_channel_scratch { uint32_t depcmd_low_addr; uint32_t depcmd_hi_addr:8; uint32_t resvd2:8; - uint32_t max_outstanding_tre:16; + uint32_t max_outstanding_tre:16; /* Not relevant starting GSI 2.5 */ uint32_t resvd3:16; - uint32_t outstanding_threshold:16; + uint32_t outstanding_threshold:16; /* Not relevant starting GSI 2.5 */ }; /** @@ -865,6 +880,21 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, int gsi_write_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch val); +/** + * gsi_update_mhi_channel_scratch - MHI Peripheral should call this + * function to update the scratch area of the channel context. Updating + * will be by read-modify-write method, so non SWI fields will not be + * affected + * + * @chan_hdl: Client handle previously obtained from + * gsi_alloc_channel + * @mscr: MHI Channel Scratch value + * + * @Return gsi_status + */ +int gsi_update_mhi_channel_scratch(unsigned long chan_hdl, + struct __packed gsi_mhi_channel_scratch mscr); + /** * gsi_start_channel - Peripheral should call this function to * start a channel i.e put into running state @@ -1228,6 +1258,12 @@ static inline int gsi_write_channel_scratch(unsigned long chan_hdl, return -GSI_STATUS_UNSUPPORTED_OP; } +static inline int gsi_update_mhi_channel_scratch(unsigned long chan_hdl, + struct __packed gsi_mhi_channel_scratch mscr) +{ + return -GSI_STATUS_UNSUPPORTED_OP; +} + static inline int gsi_start_channel(unsigned long chan_hdl) { return -GSI_STATUS_UNSUPPORTED_OP; -- GitLab From ae23e65213a0251be30b871060690f92bec64bba Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Mon, 6 Nov 2017 17:29:30 -0800 Subject: [PATCH 0260/1299] arm: dma-mapping: Fix broken iommu attach and detach 'Commit 1748f086a39c ("arm64: dma-mapping: Support attach after detach case")' modified the attach detach API framework for arm64 alone, leaving 32-bit arm into compilation menace. Hence, fix this. Change-Id: I7cdeecca599aec4c70cf0aa9d34f5db2d5844f39 Signed-off-by: Sudarshan Rajagopalan Signed-off-by: Charan Teja Reddy --- arch/arm/include/asm/dma-iommu.h | 2 +- arch/arm/mm/dma-mapping.c | 186 +++++++++++++++++++++++-------- 2 files changed, 141 insertions(+), 47 deletions(-) diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h index ad3d57afe1a3..f567f3da27fd 100644 --- a/arch/arm/include/asm/dma-iommu.h +++ b/arch/arm/include/asm/dma-iommu.h @@ -15,8 +15,8 @@ struct dma_iommu_mapping { /* iommu specific data */ struct iommu_domain *domain; + bool init; const struct dma_map_ops *ops; - unsigned long **bitmaps; /* array of bitmaps */ unsigned int nr_bitmaps; /* nr of elements in array */ unsigned int extensions; diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 7976f0f4d79e..7d5cfe48b1cb 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -2284,24 +2285,48 @@ const struct dma_map_ops iommu_coherent_ops = { * IO address ranges, which is required to perform memory allocation and * mapping with IOMMU aware functions. * - * The client device need to be attached to the mapping with - * arm_iommu_attach_device function. + * Clients may use iommu_domain_set_attr() to set additional flags prior + * to calling arm_iommu_attach_device() to complete initialization. */ struct dma_iommu_mapping * arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, u64 size) { unsigned int bits = size >> PAGE_SHIFT; - unsigned int bitmap_size = BITS_TO_LONGS(bits) * sizeof(long); struct dma_iommu_mapping *mapping; + + if (!bits) + return ERR_PTR(-EINVAL); + + mapping = kzalloc(sizeof(struct dma_iommu_mapping), GFP_KERNEL); + if (!mapping) + return ERR_PTR(-ENOMEM); + + mapping->base = base; + mapping->bits = bits; + + mapping->domain = iommu_domain_alloc(bus); + if (!mapping->domain) + goto err_domain_alloc; + + mapping->init = false; + return mapping; + +err_domain_alloc: + kfree(mapping); + return ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL(arm_iommu_create_mapping); + +static int +iommu_init_mapping(struct device *dev, struct dma_iommu_mapping *mapping) +{ + unsigned int bitmap_size = BITS_TO_LONGS(mapping->bits) * sizeof(long); + u64 size = mapping->bits << PAGE_SHIFT; int extensions = 1; int err = -ENOMEM; - /* currently only 32-bit DMA address space is supported */ - if (size > DMA_BIT_MASK(32) + 1) - return ERR_PTR(-ERANGE); - if (!bitmap_size) - return ERR_PTR(-EINVAL); + return -EINVAL; WARN(!IS_ALIGNED(size, SZ_128M), "size is not aligned to 128M, alignment enforced"); @@ -2311,46 +2336,29 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, u64 size) bitmap_size = PAGE_SIZE; } - mapping = kzalloc(sizeof(struct dma_iommu_mapping), GFP_KERNEL); - if (!mapping) - goto err; - mapping->bitmap_size = bitmap_size; mapping->bitmaps = kzalloc(extensions * sizeof(unsigned long *), - GFP_KERNEL); + GFP_KERNEL); + if (!mapping->bitmaps) - goto err2; + return -ENOMEM; mapping->bitmaps[0] = kzalloc(bitmap_size, GFP_KERNEL); if (!mapping->bitmaps[0]) - goto err3; + goto err; mapping->nr_bitmaps = 1; mapping->extensions = extensions; - mapping->base = base; - mapping->bits = BITS_PER_BYTE * bitmap_size; spin_lock_init(&mapping->lock); - - mapping->domain = iommu_domain_alloc(bus); - if (!mapping->domain) - goto err4; - - kref_init(&mapping->kref); mapping->ops = &iommu_ops; - return mapping; -err4: - kfree(mapping->bitmaps[0]); -err3: - kfree(mapping->bitmaps); -err2: - kfree(mapping); + return 0; err: - return ERR_PTR(err); + kfree(mapping->bitmaps); + return err; } -EXPORT_SYMBOL_GPL(arm_iommu_create_mapping); -static void release_iommu_mapping(struct kref *kref) +static void iommu_release_mapping(struct kref *kref) { int i; int is_fast = 0; @@ -2387,13 +2395,70 @@ static int extend_iommu_mapping(struct dma_iommu_mapping *mapping) return 0; } +/* + * arm_iommu_release_mapping + * @mapping: allocted via arm_iommu_create_mapping() + * + * Frees all resources associated with the iommu mapping. + * The device associated with this mapping must be in the 'detached' state + */ void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping) { - if (mapping) - kref_put(&mapping->kref, release_iommu_mapping); + int is_fast = 0; + void (*release)(struct kref *kref); + + if (!mapping) + return; + + if (!mapping->init) { + iommu_domain_free(mapping->domain); + kfree(mapping); + return; + } + + iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast); + + if (is_fast) + release = fast_smmu_release_mapping; + else + release = iommu_release_mapping; + + kref_put(&mapping->kref, release); } EXPORT_SYMBOL_GPL(arm_iommu_release_mapping); +static int arm_iommu_init_mapping(struct device *dev, + struct dma_iommu_mapping *mapping) +{ + int err = -EINVAL; + u64 size = mapping->bits << PAGE_SHIFT; + int is_fast = 0; + + if (mapping->init) { + kref_get(&mapping->kref); + return 0; + } + + /* currently only 32-bit DMA address space is supported */ + if (size > DMA_BIT_MASK(32) + 1) { + dev_err(dev, "dma mask %llx too small\n", dma_get_mask(dev)); + return -ERANGE; + } + + iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast); + + if (is_fast) + err = fast_smmu_init_mapping(dev, mapping); + else + err = iommu_init_mapping(dev, mapping); + if (!err) { + kref_init(&mapping->kref); + mapping->init = true; + } + return err; +} + + static int __arm_iommu_attach_device(struct device *dev, struct dma_iommu_mapping *mapping) { @@ -2403,13 +2468,31 @@ static int __arm_iommu_attach_device(struct device *dev, if (err) return err; - kref_get(&mapping->kref); to_dma_iommu_mapping(dev) = mapping; pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev)); return 0; } +static void __arm_iommu_detach_device(struct device *dev) +{ + struct dma_iommu_mapping *mapping; + + mapping = to_dma_iommu_mapping(dev); + if (!mapping) { + dev_warn(dev, "Not attached\n"); + return; + } + + if (msm_dma_unmap_all_for_dev(dev)) + dev_warn(dev, "IOMMU detach with outstanding mappings\n"); + + iommu_detach_device(mapping->domain, dev); + to_dma_iommu_mapping(dev) = NULL; + + pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev)); +} + /** * arm_iommu_attach_device * @dev: valid struct device pointer @@ -2427,21 +2510,31 @@ int arm_iommu_attach_device(struct device *dev, struct dma_iommu_mapping *mapping) { int err; - int s1_bypass = 0, is_fast = 0; + int s1_bypass = 0; + struct iommu_group *group = dev->iommu_group; - iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast); - if (is_fast) { - err = fast_smmu_init_mapping(dev, mapping); - if (err) - return err; + if (!group) { + dev_err(dev, "No iommu associated with device\n"); + return -EINVAL; + } + + if (iommu_get_domain_for_dev(dev)) { + dev_err(dev, "Device already attached to other iommu_domain\n"); + return -EINVAL; } err = __arm_iommu_attach_device(dev, mapping); if (err) return err; + err = arm_iommu_init_mapping(dev, mapping); + if (err) { + __arm_iommu_detach_device(dev); + return err; + } + iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS, - &s1_bypass); + &s1_bypass); if (!s1_bypass) set_dma_ops(dev, mapping->ops); return 0; @@ -2466,9 +2559,10 @@ void arm_iommu_detach_device(struct device *dev) return; } - iommu_detach_device(mapping->domain, dev); - kref_put(&mapping->kref, release_iommu_mapping); - to_dma_iommu_mapping(dev) = NULL; + __arm_iommu_detach_device(dev); + + iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS, + &s1_bypass); if (!s1_bypass) set_dma_ops(dev, NULL); -- GitLab From 6306e7f7630a63cb13fb3ca61efd012b75257c77 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Wed, 30 May 2018 15:57:21 +0530 Subject: [PATCH 0261/1299] mmc: core: Remove obsolete members from mmc_queue Few items in mmc_queue structure are obsolte on latest kernel. So removing them. Change-Id: I6ba25076c692afe0d5537f19eb0721bc07a083ba Signed-off-by: Veerabhadrarao Badiganti --- drivers/mmc/core/queue.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h index b03aea8f2b76..7171761123fe 100644 --- a/drivers/mmc/core/queue.h +++ b/drivers/mmc/core/queue.h @@ -74,16 +74,11 @@ struct mmc_queue { bool asleep; struct mmc_blk_data *blkdata; struct request_queue *queue; - struct mmc_queue_req mqrq[2]; - struct mmc_queue_req *mqrq_cur; - struct mmc_queue_req *mqrq_prev; struct work_struct cmdq_err_work; struct completion cmdq_pending_req_done; struct completion cmdq_shutdown_complete; struct request *cmdq_req_peeked; - enum mmc_blk_status (*err_check_fn)(struct mmc_card *, - struct mmc_async_req *); void (*cmdq_shutdown)(struct mmc_queue *); /* * FIXME: this counter is not a very reliable way of keeping -- GitLab From c15e43c5936ace4b03a08d2cb83defa503f5b5a3 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Thu, 14 Jun 2018 18:38:59 +0530 Subject: [PATCH 0262/1299] soc: qcom: add CDSP request manager for CPU L3 clock voting CDSPRM module consists of a rpmsg based driver to receive requests from CDSP subsystem for CPU L3 clock frequency and QoS requirements. L3 frequency requests are forwarded to the devfreq governor. QoS requests are handled within this driver by using pm qos APIs. CDSP votes for L3 clock to improve IOcoherent bandwidth for better performance and votes for QoS latency to reduce FastRPC overhead. Change-Id: Ib6acb3f25e535592ea63388a019fca3c44342190 Acked-by: Sreekanth Gande Signed-off-by: Tharun Kumar Merugu --- .../devicetree/bindings/soc/qcom/cdsprm.txt | 43 ++ drivers/soc/qcom/Kconfig | 9 + drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/cdsprm.c | 487 ++++++++++++++++++ include/linux/soc/qcom/cdsprm.h | 52 ++ 5 files changed, 592 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/qcom/cdsprm.txt create mode 100644 drivers/soc/qcom/cdsprm.c create mode 100644 include/linux/soc/qcom/cdsprm.h diff --git a/Documentation/devicetree/bindings/soc/qcom/cdsprm.txt b/Documentation/devicetree/bindings/soc/qcom/cdsprm.txt new file mode 100644 index 000000000000..92304dc56a42 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/cdsprm.txt @@ -0,0 +1,43 @@ +Qualcomm Technologies, Inc. CDSP Request Manager driver + +CDSP Request Manager driver implements an rpmsg interface with +CDSP subsystem to serve L3 frequency and CPU QoS requests from CDSP. + +Required properties: +- compatible: Must be "qcom,msm-cdsprm-rpmsg" +- qcom,glink-channels: Glink channel for communication with CDSP +- qcom,intents: A list of + +- qcom,msm-cdsp-rm: A sub-device node to define CDSPM RM configuration + parameters + Required properties: + - compatible: Must be "qcom,msm-cdsp-rm" + - qcom,qos-latency-us: pm_qos latency vote to be applied on CDSP request in + micro seconds + - qcom,qos-maxhold-ms: Maximum hold time for pm_qos latency vote from CDSP + in milli seconds + +- qcom,cdsp-l3: A sub-device node to define CDSP L3 target device for L3 + clock voting + Required properties: + - compatible: Must be "qcom,cdsp-l3" + - qcom,target-dev: The DT device that corresponds to the CDSP L3 + devfreq-simple-dev + +Example: + qcom,msm_cdsprm_rpmsg { + compatible = "qcom,msm-cdsprm-rpmsg"; + qcom,glink-channels = "cdsprmglink-apps-dsp"; + qcom,intents = <0x14 64>; + + qcom,cdsp-l3 { + compatible = "qcom,cdsp-l3"; + qcom,target-dev = <&cdsp-cdsp-l3-lat>; + }; + + qcom,msm_cdsp_rm { + compatible = "qcom,msm-cdsp-rm"; + qcom,qos-latency-us = <100>; + qcom,qos-maxhold-ms = <20>; + }; + }; diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 4ddf289ab169..42f1833680cb 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -768,4 +768,13 @@ config QCOM_SMP2P_SLEEPSTATE When this option is enabled, notifications are sent to remote procs for the power state changes on the local processor. The notifications are sent through the smp2p framework. + +config QCOM_CDSP_RM + bool "CDSP request manager" + depends on QCOM_GLINK + help + This driver serves CDSP requests for CPU L3 clock and CPU QoS thus + improving CDSP performance. Using this driver, CDSP can set appropriate + CPU L3 clock for improving IO-Coherent throughput and opt for QoS mode + to improve RPC latency. endmenu diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 4a8af4747d08..9c537bf3c813 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -90,3 +90,4 @@ obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd-debug.o endif obj-$(CONFIG_QCOM_SMP2P_SLEEPSTATE) += smp2p_sleepstate.o obj-$(CONFIG_QCOM_MEM_OFFLINE) += mem-offline.o +obj-$(CONFIG_QCOM_CDSP_RM) += cdsprm.o diff --git a/drivers/soc/qcom/cdsprm.c b/drivers/soc/qcom/cdsprm.c new file mode 100644 index 000000000000..d23b3be2f9ea --- /dev/null +++ b/drivers/soc/qcom/cdsprm.c @@ -0,0 +1,487 @@ +/* + * CDSP Request Manager + * + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* This module uses rpmsg to communicate with CDSP and receive requests + * for CPU L3 frequency and QoS. + */ + +#define pr_fmt(fmt) "cdsprm: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SYSMON_CDSP_FEATURE_L3 1 +#define SYSMON_CDSP_FEATURE_RM 2 +#define SYSMON_CDSP_QOS_FLAG_IGNORE 0 +#define SYSMON_CDSP_QOS_FLAG_ENABLE 1 +#define SYSMON_CDSP_QOS_FLAG_DISABLE 2 +#define QOS_LATENCY_DISABLE_VALUE -1 +#define SYS_CLK_TICKS_PER_MS 19200 +#define CDSPRM_MSG_QUEUE_DEPTH 10 + +struct sysmon_l3_msg { + unsigned int l3_clock_khz; +}; + +struct sysmon_rm_msg { + unsigned int b_qos_flag; + unsigned int timetick_low; + unsigned int timetick_high; +}; + +struct sysmon_msg { + unsigned int feature_id; + union { + struct sysmon_l3_msg l3_struct; + struct sysmon_rm_msg rm_struct; + } feature_struct; + unsigned int size; +}; + +enum delay_state { + CDSP_DELAY_THREAD_NOT_STARTED = 0, + CDSP_DELAY_THREAD_STARTED = 1, + CDSP_DELAY_THREAD_BEFORE_SLEEP = 2, + CDSP_DELAY_THREAD_AFTER_SLEEP = 3, + CDSP_DELAY_THREAD_EXITING = 4, +}; + +struct cdsprm_request { + struct list_head node; + struct sysmon_msg msg; + bool busy; +}; + +struct cdsprm { + unsigned int event; + struct completion msg_avail; + struct cdsprm_request msg_queue[CDSPRM_MSG_QUEUE_DEPTH]; + unsigned int msg_queue_idx; + struct workqueue_struct *work_queue; + struct workqueue_struct *delay_work_queue; + struct work_struct cdsprm_work; + struct work_struct cdsprm_delay_work; + struct mutex rm_lock; + spinlock_t l3_lock; + spinlock_t list_lock; + struct rpmsg_device *rpmsgdev; + enum delay_state dt_state; + enum delay_state work_state; + unsigned long long timestamp; + struct pm_qos_request pm_qos_req; + unsigned int qos_latency_us; + unsigned int qos_max_ms; + bool qos_request; + bool b_rpmsg_register; + bool b_qosinitdone; + int latency_request; + int (*set_l3_freq)(unsigned int freq_khz); + int (*set_l3_freq_cached)(unsigned int freq_khz); +}; + +static struct cdsprm gcdsprm; +static LIST_HEAD(cdsprm_list); + +/** + * cdsprm_register_cdspl3gov() - Register a method to set L3 clock + * frequency + * @arg: cdsprm_l3 structure with set L3 clock frequency method + * + * Note: To be called from cdspl3 governor only. Called when the governor is + * started. + */ +void cdsprm_register_cdspl3gov(struct cdsprm_l3 *arg) +{ + if (!arg) + return; + + spin_lock(&gcdsprm.l3_lock); + gcdsprm.set_l3_freq = arg->set_l3_freq; + spin_unlock(&gcdsprm.l3_lock); +} +EXPORT_SYMBOL(cdsprm_register_cdspl3gov); + +/** + * cdsprm_unregister_cdspl3gov() - Unregister the method to set L3 clock + * frequency + * + * Note: To be called from cdspl3 governor only. Called when the governor is + * stopped + */ +void cdsprm_unregister_cdspl3gov(void) +{ + spin_lock(&gcdsprm.l3_lock); + gcdsprm.set_l3_freq = NULL; + spin_unlock(&gcdsprm.l3_lock); +} +EXPORT_SYMBOL(cdsprm_unregister_cdspl3gov); + +static void set_qos_latency(int latency) +{ + if (!gcdsprm.qos_request) { + pm_qos_add_request(&gcdsprm.pm_qos_req, + PM_QOS_CPU_DMA_LATENCY, latency); + gcdsprm.qos_request = true; + } else { + pm_qos_update_request(&gcdsprm.pm_qos_req, + latency); + } +} + +static void process_rm_request(struct sysmon_msg *msg) +{ + struct sysmon_rm_msg *rm_msg; + + if (!msg) + return; + + if (msg->feature_id == SYSMON_CDSP_FEATURE_RM) { + mutex_lock(&gcdsprm.rm_lock); + rm_msg = &msg->feature_struct.rm_struct; + if (rm_msg->b_qos_flag == + SYSMON_CDSP_QOS_FLAG_ENABLE) { + if (gcdsprm.latency_request != + gcdsprm.qos_latency_us) { + set_qos_latency(gcdsprm.qos_latency_us); + gcdsprm.latency_request = + gcdsprm.qos_latency_us; + pr_debug("Set qos latency to %d\n", + gcdsprm.latency_request); + } + gcdsprm.timestamp = ((rm_msg->timetick_low) | + ((unsigned long long)rm_msg->timetick_high << 32)); + if (gcdsprm.dt_state >= CDSP_DELAY_THREAD_AFTER_SLEEP) { + flush_workqueue(gcdsprm.delay_work_queue); + if (gcdsprm.dt_state == + CDSP_DELAY_THREAD_EXITING) { + gcdsprm.dt_state = + CDSP_DELAY_THREAD_STARTED; + queue_work(gcdsprm.delay_work_queue, + &gcdsprm.cdsprm_delay_work); + } + } else if (gcdsprm.dt_state == + CDSP_DELAY_THREAD_NOT_STARTED) { + gcdsprm.dt_state = CDSP_DELAY_THREAD_STARTED; + queue_work(gcdsprm.delay_work_queue, + &gcdsprm.cdsprm_delay_work); + } + } else if ((rm_msg->b_qos_flag == + SYSMON_CDSP_QOS_FLAG_DISABLE) && + (gcdsprm.latency_request != + QOS_LATENCY_DISABLE_VALUE)) { + set_qos_latency(QOS_LATENCY_DISABLE_VALUE); + gcdsprm.latency_request = QOS_LATENCY_DISABLE_VALUE; + pr_debug("Set qos latency to %d\n", + gcdsprm.latency_request); + } + mutex_unlock(&gcdsprm.rm_lock); + } else { + pr_err("Received incorrect msg on rm queue: %d\n", + msg->feature_id); + } +} + +static void process_delayed_rm_request(struct work_struct *work) +{ + unsigned long long timestamp, curr_timestamp; + unsigned int time_ms = 0; + + mutex_lock(&gcdsprm.rm_lock); + + timestamp = gcdsprm.timestamp; + curr_timestamp = arch_counter_get_cntvct(); + + while ((gcdsprm.latency_request == + gcdsprm.qos_latency_us) && + (curr_timestamp < timestamp)) { + if ((timestamp - curr_timestamp) < + (gcdsprm.qos_max_ms * SYS_CLK_TICKS_PER_MS)) + time_ms = (timestamp - curr_timestamp) / + SYS_CLK_TICKS_PER_MS; + else + break; + gcdsprm.dt_state = CDSP_DELAY_THREAD_BEFORE_SLEEP; + + mutex_unlock(&gcdsprm.rm_lock); + usleep_range(time_ms * 1000, (time_ms + 2) * 1000); + mutex_lock(&gcdsprm.rm_lock); + + gcdsprm.dt_state = CDSP_DELAY_THREAD_AFTER_SLEEP; + timestamp = gcdsprm.timestamp; + curr_timestamp = arch_counter_get_cntvct(); + } + + set_qos_latency(QOS_LATENCY_DISABLE_VALUE); + gcdsprm.latency_request = QOS_LATENCY_DISABLE_VALUE; + pr_debug("Set qos latency to %d\n", gcdsprm.latency_request); + gcdsprm.dt_state = CDSP_DELAY_THREAD_EXITING; + + mutex_unlock(&gcdsprm.rm_lock); +} + +static void process_cdsp_request(struct work_struct *work) +{ + struct cdsprm_request *req = NULL; + struct sysmon_msg *msg = NULL; + unsigned int l3_clock_khz; + + while (gcdsprm.work_state == + CDSP_DELAY_THREAD_STARTED) { + req = list_first_entry_or_null(&cdsprm_list, + struct cdsprm_request, node); + if (req) { + msg = &req->msg; + if (!msg) { + spin_lock(&gcdsprm.list_lock); + list_del(&req->node); + req->busy = false; + spin_unlock(&gcdsprm.list_lock); + continue; + } + if ((msg->feature_id == SYSMON_CDSP_FEATURE_RM) && + gcdsprm.b_qosinitdone) { + process_rm_request(msg); + } else if (msg->feature_id == SYSMON_CDSP_FEATURE_L3) { + l3_clock_khz = + msg->feature_struct.l3_struct.l3_clock_khz; + spin_lock(&gcdsprm.l3_lock); + gcdsprm.set_l3_freq_cached = + gcdsprm.set_l3_freq; + spin_unlock(&gcdsprm.l3_lock); + if (gcdsprm.set_l3_freq_cached) { + gcdsprm.set_l3_freq_cached( + l3_clock_khz); + pr_debug("Set L3 clock %d done\n", + l3_clock_khz); + } + } + spin_lock(&gcdsprm.list_lock); + list_del(&req->node); + req->busy = false; + spin_unlock(&gcdsprm.list_lock); + } else { + wait_for_completion(&gcdsprm.msg_avail); + } + } +} + +static int cdsprm_rpmsg_probe(struct rpmsg_device *dev) +{ + /* Populate child nodes as platform devices */ + of_platform_populate(dev->dev.of_node, NULL, NULL, &dev->dev); + gcdsprm.rpmsgdev = dev; + dev_dbg(&dev->dev, "rpmsg probe called for cdsp\n"); + return 0; +} + +static void cdsprm_rpmsg_remove(struct rpmsg_device *dev) +{ + gcdsprm.rpmsgdev = NULL; +} + +static int cdsprm_rpmsg_callback(struct rpmsg_device *dev, void *data, + int len, void *priv, u32 addr) +{ + struct sysmon_msg *msg = (struct sysmon_msg *)data; + bool b_valid = false; + struct cdsprm_request *req; + + if (!data || (len < sizeof(*msg))) { + dev_err(&dev->dev, + "Invalid message in rpmsg callback, length: %d, expected: %d\n", + len, sizeof(*msg)); + return -EINVAL; + } + + if ((msg->feature_id == SYSMON_CDSP_FEATURE_RM) && + gcdsprm.b_qosinitdone) { + dev_dbg(&dev->dev, "Processing RM request\n"); + b_valid = true; + } else if (msg->feature_id == SYSMON_CDSP_FEATURE_L3) { + dev_dbg(&dev->dev, "Processing L3 request\n"); + spin_lock(&gcdsprm.l3_lock); + gcdsprm.set_l3_freq_cached = gcdsprm.set_l3_freq; + spin_unlock(&gcdsprm.l3_lock); + if (gcdsprm.set_l3_freq_cached) + b_valid = true; + } + + if (b_valid) { + spin_lock(&gcdsprm.list_lock); + if (!gcdsprm.msg_queue[gcdsprm.msg_queue_idx].busy) { + req = &gcdsprm.msg_queue[gcdsprm.msg_queue_idx]; + req->busy = true; + req->msg = *msg; + if (gcdsprm.msg_queue_idx < + (CDSPRM_MSG_QUEUE_DEPTH - 1)) + gcdsprm.msg_queue_idx++; + else + gcdsprm.msg_queue_idx = 0; + } else { + spin_unlock(&gcdsprm.list_lock); + dev_err(&dev->dev, + "Unable to queue cdsp request, no memory\n"); + return -ENOMEM; + } + list_add_tail(&req->node, &cdsprm_list); + spin_unlock(&gcdsprm.list_lock); + if (gcdsprm.work_state == + CDSP_DELAY_THREAD_NOT_STARTED) { + gcdsprm.work_state = + CDSP_DELAY_THREAD_STARTED; + queue_work(gcdsprm.work_queue, + &gcdsprm.cdsprm_work); + } else { + complete(&gcdsprm.msg_avail); + } + } + + return 0; +} + +static int cdsp_rm_driver_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + if (of_property_read_u32(dev->of_node, + "qcom,qos-latency-us", &gcdsprm.qos_latency_us)) { + return -EINVAL; + } + + if (of_property_read_u32(dev->of_node, + "qcom,qos-maxhold-ms", &gcdsprm.qos_max_ms)) { + return -EINVAL; + } + + dev_info(dev, "CDSP request manager driver probe called\n"); + gcdsprm.b_qosinitdone = true; + + return 0; +} + +static const struct rpmsg_device_id cdsprm_rpmsg_match[] = { + { "cdsprmglink-apps-dsp" }, + { }, +}; + +static const struct of_device_id cdsprm_rpmsg_of_match[] = { + { .compatible = "qcom,msm-cdsprm-rpmsg" }, + { }, +}; +MODULE_DEVICE_TABLE(of, cdsprm_rpmsg_of_match); + +static struct rpmsg_driver cdsprm_rpmsg_client = { + .id_table = cdsprm_rpmsg_match, + .probe = cdsprm_rpmsg_probe, + .remove = cdsprm_rpmsg_remove, + .callback = cdsprm_rpmsg_callback, + .drv = { + .name = "qcom,msm_cdsprm_rpmsg", + .of_match_table = cdsprm_rpmsg_of_match, + }, +}; + +static const struct of_device_id cdsp_rm_match_table[] = { + { .compatible = "qcom,msm-cdsp-rm" }, + { }, +}; + +static struct platform_driver cdsp_rm = { + .probe = cdsp_rm_driver_probe, + .driver = { + .name = "msm_cdsp_rm", + .of_match_table = cdsp_rm_match_table, + }, +}; + +static int __init cdsprm_init(void) +{ + int err; + + mutex_init(&gcdsprm.rm_lock); + spin_lock_init(&gcdsprm.l3_lock); + spin_lock_init(&gcdsprm.list_lock); + init_completion(&gcdsprm.msg_avail); + gcdsprm.work_queue = create_singlethread_workqueue("cdsprm-wq"); + if (!gcdsprm.work_queue) { + pr_err("Failed to create rm work queue\n"); + return -ENOMEM; + } + + gcdsprm.delay_work_queue = + create_singlethread_workqueue("cdsprm-wq-delay"); + if (!gcdsprm.delay_work_queue) { + err = -ENOMEM; + pr_err("Failed to create rm delay work queue\n"); + goto err_wq; + } + + INIT_WORK(&gcdsprm.cdsprm_delay_work, process_delayed_rm_request); + INIT_WORK(&gcdsprm.cdsprm_work, process_cdsp_request); + err = platform_driver_register(&cdsp_rm); + if (err) { + pr_err("Failed to register cdsprm platform driver: %d\n", + err); + goto bail; + } + + err = register_rpmsg_driver(&cdsprm_rpmsg_client); + if (err) { + pr_err("Failed registering rpmsg driver with return %d\n", + err); + goto bail; + } + + gcdsprm.b_rpmsg_register = true; + pr_debug("Init successful\n"); + return 0; +bail: + destroy_workqueue(gcdsprm.delay_work_queue); +err_wq: + destroy_workqueue(gcdsprm.work_queue); + return err; +} + +static void __exit cdsprm_exit(void) +{ + if (gcdsprm.b_rpmsg_register) + unregister_rpmsg_driver(&cdsprm_rpmsg_client); + + platform_driver_unregister(&cdsp_rm); + gcdsprm.work_state = CDSP_DELAY_THREAD_NOT_STARTED; + complete(&gcdsprm.msg_avail); + destroy_workqueue(gcdsprm.work_queue); + destroy_workqueue(gcdsprm.delay_work_queue); +} + +module_init(cdsprm_init); +module_exit(cdsprm_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/soc/qcom/cdsprm.h b/include/linux/soc/qcom/cdsprm.h new file mode 100644 index 000000000000..828446961bcf --- /dev/null +++ b/include/linux/soc/qcom/cdsprm.h @@ -0,0 +1,52 @@ +/* + * cdsprm.h + * + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * This header is for cdspl3 devfreq governor in drivers/devfreq. + */ + +#ifndef __QCOM_CDSPRM_H__ +#define __QCOM_CDSPRM_H__ + +/** + * struct cdsprm_l3 - register with set L3 clock frequency method + * @set_l3_freq: Sets desired L3 clock frequency in kilo-hertz. + * cdsprm module would call this method to set L3 + * clock frequency as requested by CDSP subsystem. + */ +struct cdsprm_l3 { + int (*set_l3_freq)(unsigned int freq_khz); +}; + +/** + * cdsprm_register_cdspl3gov() - Register a method to set L3 clock + * frequency + * @arg: cdsprm_l3 structure with set L3 clock frequency method + * + * Note: To be called from cdspl3 governor only. Called when the governor is + * started. + */ +void cdsprm_register_cdspl3gov(struct cdsprm_l3 *arg); + +/** + * cdsprm_unregister_cdspl3gov() - Unregister the method to set L3 clock + * frequency + * + * Note: To be called from cdspl3 governor only. Called when the governor is + * stopped + */ +void cdsprm_unregister_cdspl3gov(void); + +#endif -- GitLab From 28e361b3853c85bcb19c7030afc1350a8e0622f9 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Thu, 14 Jun 2018 15:59:58 +0530 Subject: [PATCH 0263/1299] devfreq: add CDSP L3 governor Add CDSP L3 governor to honor L3 clock requests from CDSP via CDSPRM module. Change-Id: I1bb9bd3bdff36021dc9570eeac1b0cbcfe1d884d Acked-by: Sreekanth Gande Signed-off-by: Tharun Kumar Merugu --- drivers/devfreq/Kconfig | 7 ++ drivers/devfreq/Makefile | 1 + drivers/devfreq/governor_cdsp_l3.c | 166 +++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 drivers/devfreq/governor_cdsp_l3.c diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 52c2706df556..70d8bcb2a93e 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -255,6 +255,13 @@ config DEVFREQ_SPDM This driver allows any SPDM based client to vote for bandwidth. Used with the QTI SPDM Hypervisor Governor. +config DEVFREQ_GOV_CDSPL3 + bool "QTI DEVFREQ governor for CDSP L3 requests" + depends on QCOM_CDSP_RM + help + CDSP resource manager will use this governor to vote for L3 clock + for IO-coherent traffic generated from CDSP + source "drivers/devfreq/event/Kconfig" endif # PM_DEVFREQ diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index 0f669c91334e..f819efc03a1e 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON) += governor_bw_hwmon.o obj-$(CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON) += governor_cache_hwmon.o obj-$(CONFIG_DEVFREQ_GOV_SPDM_HYP) += governor_spdm_bw_hyp.o obj-$(CONFIG_DEVFREQ_GOV_MEMLAT) += governor_memlat.o +obj-$(CONFIG_DEVFREQ_GOV_CDSPL3) += governor_cdsp_l3.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o diff --git a/drivers/devfreq/governor_cdsp_l3.c b/drivers/devfreq/governor_cdsp_l3.c new file mode 100644 index 000000000000..a5ece4b43741 --- /dev/null +++ b/drivers/devfreq/governor_cdsp_l3.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define pr_fmt(fmt) "governor_cdspl3: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "governor.h" + +struct cdspl3 { + struct device_node *of_node; + struct devfreq *df; + unsigned int l3_freq_hz; +}; + +static struct cdspl3 p_me; + +static int cdsp_l3_request_callback(unsigned int freq_khz) +{ + if (p_me.df) { + mutex_lock(&p_me.df->lock); + p_me.l3_freq_hz = freq_khz * 1000; + update_devfreq(p_me.df); + mutex_unlock(&p_me.df->lock); + } else { + pr_err("CDSP L3 request for %dKHz not served", freq_khz); + return -ENODEV; + } + return 0; +} + +static struct cdsprm_l3 cdsprm = { + .set_l3_freq = cdsp_l3_request_callback, +}; + +static int devfreq_get_target_freq(struct devfreq *df, + unsigned long *freq) +{ + if (freq) + *freq = (unsigned long)p_me.l3_freq_hz; + return 0; +} + +static int gov_start(struct devfreq *df) +{ + if (p_me.of_node != df->dev.parent->of_node) { + dev_err(df->dev.parent, + "Device match error in CDSP L3 frequency governor\n"); + return -ENODEV; + } + p_me.df = df; + p_me.l3_freq_hz = 0; + /* + * Send governor start message to CDSP RM driver + */ + cdsprm_register_cdspl3gov(&cdsprm); + return 0; +} + +static int gov_stop(struct devfreq *df) +{ + p_me.df = 0; + p_me.l3_freq_hz = 0; + /* + * Send governor stop message to CDSP RM driver + */ + cdsprm_unregister_cdspl3gov(); + return 0; +} + +static int devfreq_event_handler(struct devfreq *df, + unsigned int event, void *data) +{ + int ret; + + switch (event) { + case DEVFREQ_GOV_START: + ret = gov_start(df); + if (ret) + return ret; + dev_info(df->dev.parent, + "Successfully started CDSP L3 governor\n"); + break; + case DEVFREQ_GOV_STOP: + dev_info(df->dev.parent, + "Received stop CDSP L3 governor event\n"); + ret = gov_stop(df); + if (ret) + return ret; + break; + default: + break; + } + return 0; +} + +static struct devfreq_governor cdsp_l3_gov = { + .name = "cdspl3", + .get_target_freq = devfreq_get_target_freq, + .event_handler = devfreq_event_handler, +}; + +static int cdsp_l3_driver_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int ret; + + p_me.of_node = of_parse_phandle(dev->of_node, "qcom,target-dev", 0); + if (!p_me.of_node) { + dev_err(dev, "Couldn't find a target device\n"); + return -ENODEV; + } + ret = devfreq_add_governor(&cdsp_l3_gov); + if (ret) + dev_err(dev, "Failed registering CDSP L3 requests %d\n", + ret); + return ret; +} + +static const struct of_device_id cdsp_l3_match_table[] = { + { .compatible = "qcom,cdsp-l3" }, + {} +}; + +static struct platform_driver cdsp_l3 = { + .probe = cdsp_l3_driver_probe, + .driver = { + .name = "cdsp-l3", + .of_match_table = cdsp_l3_match_table, + } +}; + +static int __init cdsp_l3_gov_module_init(void) +{ + return platform_driver_register(&cdsp_l3); + +} +module_init(cdsp_l3_gov_module_init); + +static void __exit cdsp_l3_gov_module_exit(void) +{ + devfreq_remove_governor(&cdsp_l3_gov); + platform_driver_unregister(&cdsp_l3); +} +module_exit(cdsp_l3_gov_module_exit); +MODULE_LICENSE("GPL v2"); -- GitLab From 0daa0b4e03b0b73ccd62e11cf67cb7cbce36289c Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Tue, 5 Jun 2018 21:52:09 +0530 Subject: [PATCH 0264/1299] ARM: dts: msm: Add cdsp rpmsg entry in sm8150 Add cdsp rpmsg entry to define a new rpmsg channel with CDSP. Sub-nodes define cdsp request manager and cdspl3 governor parameters. Change-Id: Ie925b23ec463ed4566eb9eeda7b31552bd9d4e51 Acked-by: Sreekanth Gande Signed-off-by: Tharun Kumar Merugu --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index 9cc5b518afd8..8c6b9db22666 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -2668,6 +2668,23 @@ qcom,intents = <0x64 64>; }; + qcom,msm_cdsprm_rpmsg { + compatible = "qcom,msm-cdsprm-rpmsg"; + qcom,glink-channels = "cdsprmglink-apps-dsp"; + qcom,intents = <0x20 12>; + + qcom,cdsp-cdsp-l3-gov { + compatible = "qcom,cdsp-l3"; + qcom,target-dev = <&cdsp_cdsp_l3_lat>; + }; + + qcom,msm_cdsp_rm { + compatible = "qcom,msm-cdsp-rm"; + qcom,qos-latency-us = <100>; + qcom,qos-maxhold-ms = <20>; + }; + }; + qcom,cdsp_glink_ssr { qcom,glink-channels = "glink_ssr"; qcom,notify-edges = <&glink_modem>, -- GitLab From 9c5305af73c4bb0235c6b8a18b91e4f5906ee165 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Mon, 11 Jun 2018 22:52:09 -0700 Subject: [PATCH 0265/1299] mhi: controller: generate firmware information based on device id MHI bus framework no longer gets firmware information from devicetree, therefore pass the firmware information to MHI bus framework. CRs-Fixed: 2258358 Change-Id: I1a3b0c262933f59c75736a213c8b85e5303923c7 Signed-off-by: Sujeev Dias --- drivers/bus/mhi/controllers/mhi_qcom.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/bus/mhi/controllers/mhi_qcom.c b/drivers/bus/mhi/controllers/mhi_qcom.c index 03d244e4563a..178720a2d86a 100644 --- a/drivers/bus/mhi/controllers/mhi_qcom.c +++ b/drivers/bus/mhi/controllers/mhi_qcom.c @@ -24,6 +24,19 @@ #include #include "mhi_qcom.h" +struct firmware_info { + unsigned int dev_id; + const char *fw_image; + const char *edl_image; +}; + +static const struct firmware_info firmware_table[] = { + {.dev_id = 0x305, .fw_image = "sdx50m/sbl1.mbn"}, + {.dev_id = 0x304, .fw_image = "sbl.mbn", .edl_image = "edl.mbn"}, + /* default, set to debug.mbn */ + {.fw_image = "debug.mbn"}, +}; + void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl) { struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); @@ -332,9 +345,10 @@ static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev) struct mhi_controller *mhi_cntrl; struct mhi_dev *mhi_dev; struct device_node *of_node = pci_dev->dev.of_node; + const struct firmware_info *firmware_info; bool use_bb; u64 addr_win[2]; - int ret; + int ret, i; if (!of_node) return ERR_PTR(-ENODEV); @@ -404,6 +418,15 @@ static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev) if (ret) goto error_register; + for (i = 0; i < ARRAY_SIZE(firmware_table); i++) { + firmware_info = firmware_table + i; + if (mhi_cntrl->dev_id == firmware_info->dev_id) + break; + } + + mhi_cntrl->fw_image = firmware_info->fw_image; + mhi_cntrl->edl_image = firmware_info->edl_image; + return mhi_cntrl; error_register: -- GitLab From 2ffb2b021dee11bd4e6bfde08ad5aa59ddadb5cc Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Tue, 12 Jun 2018 09:28:18 -0700 Subject: [PATCH 0266/1299] mhi: core: rename iova address to dma_addr dma_addr are not necessarily same as physical address if iova is enabled, rename to correct name to avoid confusions. CRs-Fixed: 2258358 Change-Id: If55418500f94fcc9ebdc08786adea8bbf398cad3 Signed-off-by: Sujeev Dias --- drivers/bus/mhi/core/mhi_boot.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_boot.c b/drivers/bus/mhi/core/mhi_boot.c index 47276a3ed03e..a94447f58367 100644 --- a/drivers/bus/mhi/core/mhi_boot.c +++ b/drivers/bus/mhi/core/mhi_boot.c @@ -275,8 +275,8 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, int i, ret; void __iomem *base = mhi_cntrl->bhi; rwlock_t *pm_lock = &mhi_cntrl->pm_lock; - dma_addr_t phys = dma_map_single(mhi_cntrl->dev, buf, size, - DMA_TO_DEVICE); + dma_addr_t dma_addr = dma_map_single(mhi_cntrl->dev, buf, size, + DMA_TO_DEVICE); struct { char *name; u32 offset; @@ -288,7 +288,7 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, { NULL }, }; - if (dma_mapping_error(mhi_cntrl->dev, phys)) + if (dma_mapping_error(mhi_cntrl->dev, dma_addr)) return -ENOMEM; MHI_LOG("Starting BHI programming\n"); @@ -301,8 +301,10 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, } mhi_write_reg(mhi_cntrl, base, BHI_STATUS, 0); - mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH, upper_32_bits(phys)); - mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW, lower_32_bits(phys)); + mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH, + upper_32_bits(dma_addr)); + mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW, + lower_32_bits(dma_addr)); mhi_write_reg(mhi_cntrl, base, BHI_IMGSIZE, size); mhi_cntrl->session_id = prandom_u32() & BHI_TXDB_SEQNUM_BMSK; mhi_write_reg(mhi_cntrl, base, BHI_IMGTXDB, mhi_cntrl->session_id); @@ -337,12 +339,12 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, goto invalid_pm_state; } - dma_unmap_single(mhi_cntrl->dev, phys, size, DMA_TO_DEVICE); + dma_unmap_single(mhi_cntrl->dev, dma_addr, size, DMA_TO_DEVICE); return (tx_status == BHI_STATUS_SUCCESS) ? 0 : -ETIMEDOUT; invalid_pm_state: - dma_unmap_single(mhi_cntrl->dev, phys, size, DMA_TO_DEVICE); + dma_unmap_single(mhi_cntrl->dev, dma_addr, size, DMA_TO_DEVICE); return -EIO; } -- GitLab From 169ec2d62bcf6c4756804585685a05981bcb6d94 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Wed, 13 Jun 2018 10:22:24 -0700 Subject: [PATCH 0267/1299] mhi: core: bind control device into mhi_bus Add mhi control device to mhi_bus so all devices associated with mhi is properly linked to mhi_bus. CRs-Fixed: 2258358 Change-Id: If67fe0a16a42ffd30fe3a6f426e055b3f1384bb1 Signed-off-by: Sujeev Dias --- drivers/bus/mhi/core/mhi_init.c | 45 ++++++++++++++++++++++++++++++--- drivers/bus/mhi/core/mhi_main.c | 38 +++++++++++++++++++++++----- include/linux/mhi.h | 3 +++ 3 files changed, 77 insertions(+), 9 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 949f3084bef6..2febfd0d5718 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -1061,6 +1061,7 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl) struct mhi_event *mhi_event; struct mhi_chan *mhi_chan; struct mhi_cmd *mhi_cmd; + struct mhi_device *mhi_dev; if (!mhi_cntrl->of_node) return -EINVAL; @@ -1082,8 +1083,10 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl) mhi_cntrl->mhi_cmd = kcalloc(NR_OF_CMD_RINGS, sizeof(*mhi_cntrl->mhi_cmd), GFP_KERNEL); - if (!mhi_cntrl->mhi_cmd) + if (!mhi_cntrl->mhi_cmd) { + ret = -ENOMEM; goto error_alloc_cmd; + } INIT_LIST_HEAD(&mhi_cntrl->transition_list); mutex_init(&mhi_cntrl->pm_mutex); @@ -1138,31 +1141,59 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl) mhi_cntrl->unmap_single = mhi_unmap_single_no_bb; } + /* register controller with mhi_bus */ + mhi_dev = mhi_alloc_device(mhi_cntrl); + if (!mhi_dev) { + ret = -ENOMEM; + goto error_alloc_dev; + } + + mhi_dev->dev_type = MHI_CONTROLLER_TYPE; + mhi_dev->mhi_cntrl = mhi_cntrl; + dev_set_name(&mhi_dev->dev, "%04x_%02u.%02u.%02u", mhi_dev->dev_id, + mhi_dev->domain, mhi_dev->bus, mhi_dev->slot); + ret = device_add(&mhi_dev->dev); + if (ret) + goto error_add_dev; + + mhi_cntrl->mhi_dev = mhi_dev; + mhi_cntrl->parent = mhi_bus.dentry; mhi_cntrl->klog_lvl = MHI_MSG_LVL_ERROR; - /* add to list */ + /* adding it to this list only for debug purpose */ mutex_lock(&mhi_bus.lock); list_add_tail(&mhi_cntrl->node, &mhi_bus.controller_list); mutex_unlock(&mhi_bus.lock); return 0; +error_add_dev: + mhi_dealloc_device(mhi_cntrl, mhi_dev); + +error_alloc_dev: + kfree(mhi_cntrl->mhi_cmd); + error_alloc_cmd: kfree(mhi_cntrl->mhi_chan); kfree(mhi_cntrl->mhi_event); - return -ENOMEM; + return ret; }; EXPORT_SYMBOL(of_register_mhi_controller); void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl) { + struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; + kfree(mhi_cntrl->mhi_cmd); kfree(mhi_cntrl->mhi_event); kfree(mhi_cntrl->mhi_chan); kfree(mhi_cntrl->mhi_tsync); + device_del(&mhi_dev->dev); + put_device(&mhi_dev->dev); + mutex_lock(&mhi_bus.lock); list_del(&mhi_cntrl->node); mutex_unlock(&mhi_bus.lock); @@ -1256,6 +1287,10 @@ static int mhi_match(struct device *dev, struct device_driver *drv) struct mhi_driver *mhi_drv = to_mhi_driver(drv); const struct mhi_device_id *id; + /* if controller type there is no client driver associated with it */ + if (mhi_dev->dev_type == MHI_CONTROLLER_TYPE) + return 0; + for (id = mhi_drv->id_table; id->chan; id++) if (!strcmp(mhi_dev->chan_name, id->chan)) { mhi_dev->id = id; @@ -1348,6 +1383,10 @@ static int mhi_driver_remove(struct device *dev) }; int dir; + /* control device has no work to do */ + if (mhi_dev->dev_type == MHI_CONTROLLER_TYPE) + return 0; + MHI_LOG("Removing device for chan:%s\n", mhi_dev->chan_name); /* reset both channels */ diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c index e80d5790f15c..67acfa93dc95 100644 --- a/drivers/bus/mhi/core/mhi_main.c +++ b/drivers/bus/mhi/core/mhi_main.c @@ -559,6 +559,10 @@ int mhi_destroy_device(struct device *dev, void *data) mhi_dev = to_mhi_device(dev); mhi_cntrl = mhi_dev->mhi_cntrl; + /* only destroying virtual devices thats attached to bus */ + if (mhi_dev->dev_type == MHI_CONTROLLER_TYPE) + return 0; + MHI_LOG("destroy device for chan:%s\n", mhi_dev->chan_name); /* notify the client and remove the device from mhi bus */ @@ -1722,19 +1726,41 @@ int mhi_get_no_free_descriptors(struct mhi_device *mhi_dev, } EXPORT_SYMBOL(mhi_get_no_free_descriptors); +static int __mhi_bdf_to_controller(struct device *dev, void *tmp) +{ + struct mhi_device *mhi_dev = to_mhi_device(dev); + struct mhi_device *match = tmp; + + /* return any none-zero value if match */ + if (mhi_dev->dev_type == MHI_CONTROLLER_TYPE && + mhi_dev->domain == match->domain && mhi_dev->bus == match->bus && + mhi_dev->slot == match->slot && mhi_dev->dev_id == match->dev_id) + return 1; + + return 0; +} + struct mhi_controller *mhi_bdf_to_controller(u32 domain, u32 bus, u32 slot, u32 dev_id) { - struct mhi_controller *itr, *tmp; + struct mhi_device tmp, *mhi_dev; + struct device *dev; + + tmp.domain = domain; + tmp.bus = bus; + tmp.slot = slot; + tmp.dev_id = dev_id; - list_for_each_entry_safe(itr, tmp, &mhi_bus.controller_list, node) - if (itr->domain == domain && itr->bus == bus && - itr->slot == slot && itr->dev_id == dev_id) - return itr; + dev = bus_find_device(&mhi_bus_type, NULL, &tmp, + __mhi_bdf_to_controller); + if (!dev) + return NULL; + + mhi_dev = to_mhi_device(dev); - return NULL; + return mhi_dev->mhi_cntrl; } EXPORT_SYMBOL(mhi_bdf_to_controller); diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 006c253ca45b..807c75340394 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -64,10 +64,12 @@ enum MHI_FLAGS { * enum mhi_device_type - Device types * @MHI_XFER_TYPE: Handles data transfer * @MHI_TIMESYNC_TYPE: Use for timesync feature + * @MHI_CONTROLLER_TYPE: Control device */ enum mhi_device_type { MHI_XFER_TYPE, MHI_TIMESYNC_TYPE, + MHI_CONTROLLER_TYPE, }; /** @@ -129,6 +131,7 @@ struct image_info { */ struct mhi_controller { struct list_head node; + struct mhi_device *mhi_dev; /* device node for iommu ops */ struct device *dev; -- GitLab From da6584222b577a27d258c6fbc84277abdbc0c1df Mon Sep 17 00:00:00 2001 From: Govinda Rajulu Chenna Date: Wed, 13 Jun 2018 16:11:29 -0400 Subject: [PATCH 0268/1299] drm/msm/dp: fix reading of edid extension blocks EDID extension block reads are failing due to the reset of offset variable at incorrect state. This change removes the offset variable reset to use the correct offset value in reading the EDID extension blocks. CRs-Fixed: 2256731 Change-Id: I90b599520aa0562e12157193505181ea2573bca1 Signed-off-by: Govinda Rajulu Chenna --- drivers/gpu/drm/msm/dp/dp_aux.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index 7731b96aac30..8fe0ec856e52 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -371,11 +371,8 @@ static void dp_aux_transfer_helper(struct dp_aux_private *aux, bool i2c_read = input_msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ); - if (!i2c_mot || !i2c_read || (input_msg->size == 0)) { - /* reset the offset for all other transaction types */ - aux->offset = 0; + if (!i2c_mot || !i2c_read || (input_msg->size == 0)) return; - } /* * Sending the segment value and EDID offset will be performed @@ -498,12 +495,6 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux, goto address_error; } - if ((msg->size + aux->offset) > SZ_256) { - pr_err("invalid edid access: offset=0x%x, size=0x%x\n", - aux->offset, msg->size); - goto address_error; - } - if (aux->native) { if (aux->read) { aux->dp_aux.reg = msg->address; -- GitLab From e93096a4437d8467c16adda5cfa792d46d7fdc6d Mon Sep 17 00:00:00 2001 From: Govinda Rajulu Chenna Date: Fri, 1 Jun 2018 15:40:53 -0400 Subject: [PATCH 0269/1299] drm/msm/dp: add debugfs node to set/get max pclk Add debug fs node, max_pclk_khz, to configure the maximum PCLK supported. The maximum PCLK value limits the maximum resolution and fps supported for the connected external display. Example: To set 650MHz PCLK: echo 650000 > /d/drm_dp/max_pclk_khz CRs-Fixed: 2252931 Change-Id: If17989616e31ed44256affee120917b92ef892e9 Signed-off-by: Govinda Rajulu Chenna --- drivers/gpu/drm/msm/dp/dp_debug.c | 80 +++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_debug.h | 2 + drivers/gpu/drm/msm/dp/dp_display.c | 7 ++- 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index c39051b8bd4a..875be87084f5 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -399,6 +399,72 @@ static ssize_t dp_debug_mst_mode_write(struct file *file, return len; } +static ssize_t dp_debug_max_pclk_khz_write(struct file *file, + const char __user *user_buff, size_t count, loff_t *ppos) +{ + struct dp_debug_private *debug = file->private_data; + char buf[SZ_8]; + size_t len = 0; + u32 max_pclk = 0; + + if (!debug) + return -ENODEV; + + if (*ppos) + return 0; + + len = min_t(size_t, count, SZ_8 - 1); + if (copy_from_user(buf, user_buff, len)) + return 0; + + buf[len] = '\0'; + + if (kstrtoint(buf, 10, &max_pclk) != 0) + return 0; + + if (max_pclk > debug->parser->max_pclk_khz) + pr_err("requested: %d, max_pclk_khz:%d\n", max_pclk, + debug->parser->max_pclk_khz); + else + debug->dp_debug.max_pclk_khz = max_pclk; + + pr_debug("max_pclk_khz: %d\n", max_pclk); + + return len; +} + +static ssize_t dp_debug_max_pclk_khz_read(struct file *file, + char __user *user_buff, size_t count, loff_t *ppos) +{ + struct dp_debug_private *debug = file->private_data; + char *buf; + u32 len = 0; + + if (!debug) + return -ENODEV; + + if (*ppos) + return 0; + + buf = kzalloc(SZ_4K, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + len += snprintf(buf + len, (SZ_4K - len), + "max_pclk_khz = %d, org: %d\n", + debug->dp_debug.max_pclk_khz, + debug->parser->max_pclk_khz); + + if (copy_to_user(user_buff, buf, len)) { + kfree(buf); + return -EFAULT; + } + + *ppos += len; + kfree(buf); + return len; +} + static ssize_t dp_debug_mst_sideband_mode_write(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) { @@ -1154,6 +1220,12 @@ static const struct file_operations mst_sideband_mode_fops = { .write = dp_debug_mst_sideband_mode_write, }; +static const struct file_operations max_pclk_khz_fops = { + .open = simple_open, + .write = dp_debug_max_pclk_khz_write, + .read = dp_debug_max_pclk_khz_read, +}; + static int dp_debug_init(struct dp_debug *dp_debug) { int rc = 0; @@ -1309,6 +1381,14 @@ static int dp_debug_init(struct dp_debug *dp_debug) DEBUG_NAME, rc); } + file = debugfs_create_file("max_pclk_khz", 0644, dir, + debug, &max_pclk_khz_fops); + if (IS_ERR_OR_NULL(file)) { + rc = PTR_ERR(file); + pr_err("[%s] debugfs max_pclk_khz failed, rc=%d\n", + DEBUG_NAME, rc); + } + return 0; error_remove_dir: diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h index ef989628e7b9..a38f1c1e1643 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.h +++ b/drivers/gpu/drm/msm/dp/dp_debug.h @@ -27,6 +27,7 @@ * @hdisplay: used to filter out hdisplay value * @vrefresh: used to filter out vrefresh value * @tpg_state: specifies whether tpg feature is enabled + * @max_pclk_khz: max pclk supported */ struct dp_debug { bool debug_en; @@ -37,6 +38,7 @@ struct dp_debug { int hdisplay; int vrefresh; bool tpg_state; + u32 max_pclk_khz; u8 *(*get_edid)(struct dp_debug *dp_debug); }; diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 0c7bbda8f675..5747295c3057 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -564,7 +564,12 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->link->process_request(dp->link); dp->panel->handle_sink_request(dp->panel); - dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz; + if (dp->debug->max_pclk_khz) + dp->dp_display.max_pclk_khz = dp->debug->max_pclk_khz; + else + dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz; + + pr_debug("dp max_pclk_khz = %d\n", dp->dp_display.max_pclk_khz); dp_display_process_mst_hpd_high(dp); notify: -- GitLab From b7dec8b72daf974b3b8539485861b3a5ae3c251d Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Fri, 8 Jun 2018 10:10:12 -0700 Subject: [PATCH 0270/1299] usb: pd: qpnp-pdphy: Switch to hrtimer-based wait Currently wait_event_interruptible_timeout() is used when sending a message or hard reset signal to wait for a completion interrupt. However, the jiffies-based timer is not accurate for the short timeout durations used (15ms TX, 5ms hard reset) and can result in timing out too early. Switch to hrtimer-based wait_event_interruptible_hrtimeout() for better accuracy. Change-Id: I1c9866114b548ce849ec6002c0eb1362ac9a7786 Signed-off-by: Jack Pham --- drivers/usb/pd/qpnp-pdphy.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/usb/pd/qpnp-pdphy.c b/drivers/usb/pd/qpnp-pdphy.c index dfbd53c7414e..cb956b16ce3c 100644 --- a/drivers/usb/pd/qpnp-pdphy.c +++ b/drivers/usb/pd/qpnp-pdphy.c @@ -443,12 +443,12 @@ int pd_phy_signal(enum pd_sig_type sig) if (ret) return ret; - ret = wait_event_interruptible_timeout(pdphy->tx_waitq, + ret = wait_event_interruptible_hrtimeout(pdphy->tx_waitq, pdphy->tx_status != -EINPROGRESS, - msecs_to_jiffies(HARD_RESET_COMPLETE_TIME)); - if (ret <= 0) { + ms_to_ktime(HARD_RESET_COMPLETE_TIME)); + if (ret) { dev_err(pdphy->dev, "%s: failed ret %d", __func__, ret); - return ret ? ret : -ETIMEDOUT; + return ret; } ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, 0); @@ -532,12 +532,12 @@ int pd_phy_write(u16 hdr, const u8 *data, size_t data_len, enum pd_sop_type sop) if (ret) return ret; - ret = wait_event_interruptible_timeout(pdphy->tx_waitq, + ret = wait_event_interruptible_hrtimeout(pdphy->tx_waitq, pdphy->tx_status != -EINPROGRESS, - msecs_to_jiffies(RECEIVER_RESPONSE_TIME)); - if (ret <= 0) { + ms_to_ktime(RECEIVER_RESPONSE_TIME)); + if (ret) { dev_err(pdphy->dev, "%s: failed ret %d", __func__, ret); - return ret ? ret : -ETIMEDOUT; + return ret; } if (hdr && !pdphy->tx_status) -- GitLab From ea7db3baffbec3e370295843688169a304d99304 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 7 Jun 2018 10:29:15 -0700 Subject: [PATCH 0271/1299] usb: pd: qpnp-pdphy: Set nRetryCount based on PD spec rev PD 3.0 changed nRetryCount to 2 whereas it was 3 on PD 2.0. This affects how many times a failed TX message will be attempted in pd_phy_write(). Add a check for the spec rev field of the message header to determine what value to set for TX_CONTROL_RETRY_COUNT. Change-Id: I342262e6555734184222e5a97aac03a148bc900b Signed-off-by: Jack Pham --- drivers/usb/pd/qpnp-pdphy.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/usb/pd/qpnp-pdphy.c b/drivers/usb/pd/qpnp-pdphy.c index cb956b16ce3c..81227a55e2cb 100644 --- a/drivers/usb/pd/qpnp-pdphy.c +++ b/drivers/usb/pd/qpnp-pdphy.c @@ -50,7 +50,7 @@ #define TX_SIZE_MASK 0xF #define USB_PDPHY_TX_CONTROL 0x44 -#define TX_CONTROL_RETRY_COUNT (BIT(6) | BIT(5)) +#define TX_CONTROL_RETRY_COUNT(n) (((n) & 0x3) << 5) #define TX_CONTROL_FRAME_TYPE (BIT(4) | BIT(3) | BIT(2)) #define TX_CONTROL_FRAME_TYPE_CABLE_RESET (0x1 << 2) #define TX_CONTROL_SEND_SIGNAL BIT(1) @@ -77,6 +77,9 @@ #define VDD_PDPHY_VOL_MAX 3300000 /* uV */ #define VDD_PDPHY_HPM_LOAD 3000 /* uA */ +/* Message Spec Rev field */ +#define PD_MSG_HDR_REV(hdr) (((hdr) >> 6) & 3) + /* timers */ #define RECEIVER_RESPONSE_TIME 15 /* tReceiverResponse */ #define HARD_RESET_COMPLETE_TIME 5 /* tHardResetComplete */ @@ -526,7 +529,13 @@ int pd_phy_write(u16 hdr, const u8 *data, size_t data_len, enum pd_sop_type sop) usleep_range(2, 3); - val = TX_CONTROL_RETRY_COUNT | (sop << 2) | TX_CONTROL_SEND_MSG; + val = (sop << 2) | TX_CONTROL_SEND_MSG; + + /* nRetryCount == 2 for PD 3.0, 3 for PD 2.0 */ + if (PD_MSG_HDR_REV(hdr) == USBPD_REV_30) + val |= TX_CONTROL_RETRY_COUNT(2); + else + val |= TX_CONTROL_RETRY_COUNT(3); ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, val); if (ret) -- GitLab From 3bef32740f372de4ae6a652580585fc90b66fb2d Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 7 Jun 2018 19:29:52 -0700 Subject: [PATCH 0272/1299] usb: pd: Fix Alert/Get_Status handling When an ALERT message is received, GET_STATUS should not be sent right away as that is not part of its atomic message sequence. Further, as a sink, this also violates collision avoidance rules since the ALERT is sent during SinkTxNG. Instead, queue up the GET_STATUS to be sent when Rp is back to SinkTxOk. In addition, replace the ado sysfs entry with get_status since the former is not very useful to userspace. Reading from this entry will trigger a GET_STATUS to be sent and block until the STATUS is received. Change-Id: I6943e1e8fab300c13ec94c516e89fc466dac8209 Signed-off-by: Jack Pham --- drivers/usb/pd/policy_engine.c | 71 ++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index feca4ded2b30..af8c261d9e9a 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -371,7 +371,6 @@ struct usbpd { struct rx_msg *rx_ext_msg; u32 received_pdos[PD_MAX_DATA_OBJ]; - u32 received_ado; u16 src_cap_id; u8 selected_pdo; u8 requested_pdo; @@ -439,6 +438,7 @@ struct usbpd { u8 src_cap_ext_db[PD_SRC_CAP_EXT_DB_LEN]; bool send_get_pps_status; u32 pps_status_db; + bool send_get_status; u8 status_db[PD_STATUS_DB_LEN]; bool send_get_battery_cap; u8 get_battery_cap_db; @@ -2585,23 +2585,32 @@ static void usbpd_sm(struct work_struct *w) sizeof(pd->pps_status_db)); complete(&pd->is_ready); } else if (IS_DATA(rx_msg, MSG_ALERT)) { - if (rx_msg->data_len != sizeof(pd->received_ado)) { + u32 ado; + + if (rx_msg->data_len != sizeof(ado)) { usbpd_err(&pd->dev, "Invalid ado\n"); break; } - memcpy(&pd->received_ado, rx_msg->payload, - sizeof(pd->received_ado)); - ret = pd_send_msg(pd, MSG_GET_STATUS, NULL, - 0, SOP_MSG); + memcpy(&ado, rx_msg->payload, sizeof(ado)); + usbpd_dbg(&pd->dev, "Received Alert 0x%08x\n", ado); + + /* + * Don't send Get_Status right away so we can coalesce + * multiple Alerts. 150ms should be enough to not get + * in the way of any other AMS that might happen. + */ + pd->send_get_status = true; + kick_sm(pd, 150); + } else if (pd->send_get_status && is_sink_tx_ok(pd)) { + pd->send_get_status = false; + ret = pd_send_msg(pd, MSG_GET_STATUS, NULL, 0, SOP_MSG); if (ret) { - dev_err(&pd->dev, - "Error sending get_status\n"); + usbpd_err(&pd->dev, "Error sending get_status\n"); usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET); break; } kick_sm(pd, SENDER_RESPONSE_TIME); - } else if (rx_msg && - IS_EXT(rx_msg, MSG_STATUS)) { + } else if (rx_msg && IS_EXT(rx_msg, MSG_STATUS)) { if (rx_msg->data_len != PD_STATUS_DB_LEN) { usbpd_err(&pd->dev, "Invalid status db\n"); break; @@ -3293,9 +3302,9 @@ static int usbpd_uevent(struct device *dev, struct kobj_uevent_env *env) "explicit" : "implicit"); add_uevent_var(env, "ALT_MODE=%d", pd->vdm_state == MODE_ENTERED); - add_uevent_var(env, "ADO=%08x", pd->received_ado); - for (i = 0; i < PD_STATUS_DB_LEN; i++) - add_uevent_var(env, "SDB%d=%08x", i, pd->status_db[i]); + add_uevent_var(env, "SDB=%02x %02x %02x %02x %02x", pd->status_db[0], + pd->status_db[1], pd->status_db[2], pd->status_db[3], + pd->status_db[4]); return 0; } @@ -3696,32 +3705,46 @@ static ssize_t get_src_cap_ext_show(struct device *dev, } static DEVICE_ATTR_RO(get_src_cap_ext); -static ssize_t get_pps_status_show(struct device *dev, +static ssize_t get_status_show(struct device *dev, struct device_attribute *attr, char *buf) { - int ret; + int i, ret, len = 0; struct usbpd *pd = dev_get_drvdata(dev); if (pd->spec_rev == USBPD_REV_20) return -EINVAL; - ret = trigger_tx_msg(pd, &pd->send_get_pps_status); + ret = trigger_tx_msg(pd, &pd->send_get_status); if (ret) return ret; - return snprintf(buf, PAGE_SIZE, "0x%08x\n", pd->pps_status_db); + for (i = 0; i < PD_STATUS_DB_LEN; i++) + len += snprintf(buf + len, PAGE_SIZE - len, "%s0x%02x", + i ? " " : "", pd->status_db[i]); + + buf[len++] = '\n'; + buf[len] = '\0'; + + return len; } -static DEVICE_ATTR_RO(get_pps_status); +static DEVICE_ATTR_RO(get_status); -static ssize_t rx_ado_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t get_pps_status_show(struct device *dev, + struct device_attribute *attr, char *buf) { + int ret; struct usbpd *pd = dev_get_drvdata(dev); - /* dump the ADO as a hex string */ - return snprintf(buf, PAGE_SIZE, "%08x\n", pd->received_ado); + if (pd->spec_rev == USBPD_REV_20) + return -EINVAL; + + ret = trigger_tx_msg(pd, &pd->send_get_pps_status); + if (ret) + return ret; + + return snprintf(buf, PAGE_SIZE, "0x%08x\n", pd->pps_status_db); } -static DEVICE_ATTR_RO(rx_ado); +static DEVICE_ATTR_RO(get_pps_status); static ssize_t get_battery_cap_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) @@ -3811,8 +3834,8 @@ static struct attribute *usbpd_attrs[] = { &dev_attr_rdo_h.attr, &dev_attr_hard_reset.attr, &dev_attr_get_src_cap_ext.attr, + &dev_attr_get_status.attr, &dev_attr_get_pps_status.attr, - &dev_attr_rx_ado.attr, &dev_attr_get_battery_cap.attr, &dev_attr_get_battery_status.attr, NULL, -- GitLab From a69cbea28e1204dd55e0e596adafb70d269dbbdc Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 7 Jun 2018 19:33:58 -0700 Subject: [PATCH 0273/1299] usb: pd: Replace dev_err with usbpd_err Replace a number of instances of dev_err with usbpd_err so that they can also be logged using the IPC log mechanism. Change-Id: I84207c4fc31570fc347f84aa321a9e5e81480f81 Signed-off-by: Jack Pham --- drivers/usb/pd/policy_engine.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index af8c261d9e9a..1045a88cfd37 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -2256,7 +2256,7 @@ static void usbpd_sm(struct work_struct *w) pd->send_pr_swap = false; ret = pd_send_msg(pd, MSG_PR_SWAP, NULL, 0, SOP_MSG); if (ret) { - dev_err(&pd->dev, "Error sending PR Swap\n"); + usbpd_err(&pd->dev, "Error sending PR Swap\n"); usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET); break; } @@ -2267,7 +2267,7 @@ static void usbpd_sm(struct work_struct *w) pd->send_dr_swap = false; ret = pd_send_msg(pd, MSG_DR_SWAP, NULL, 0, SOP_MSG); if (ret) { - dev_err(&pd->dev, "Error sending DR Swap\n"); + usbpd_err(&pd->dev, "Error sending DR Swap\n"); usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET); break; } @@ -2549,8 +2549,7 @@ static void usbpd_sm(struct work_struct *w) ret = pd_send_msg(pd, MSG_GET_SOURCE_CAP_EXTENDED, NULL, 0, SOP_MSG); if (ret) { - dev_err(&pd->dev, - "Error sending get_src_cap_ext\n"); + usbpd_err(&pd->dev, "Error sending get_src_cap_ext\n"); usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET); break; } @@ -2569,8 +2568,7 @@ static void usbpd_sm(struct work_struct *w) ret = pd_send_msg(pd, MSG_GET_PPS_STATUS, NULL, 0, SOP_MSG); if (ret) { - dev_err(&pd->dev, - "Error sending get_pps_status\n"); + usbpd_err(&pd->dev, "Error sending get_pps_status\n"); usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET); break; } @@ -2623,8 +2621,7 @@ static void usbpd_sm(struct work_struct *w) ret = pd_send_ext_msg(pd, MSG_GET_BATTERY_CAP, &pd->get_battery_cap_db, 1, SOP_MSG); if (ret) { - dev_err(&pd->dev, - "Error sending get_battery_cap\n"); + usbpd_err(&pd->dev, "Error sending get_battery_cap\n"); usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET); break; } @@ -2643,8 +2640,7 @@ static void usbpd_sm(struct work_struct *w) ret = pd_send_ext_msg(pd, MSG_GET_BATTERY_STATUS, &pd->get_battery_status_db, 1, SOP_MSG); if (ret) { - dev_err(&pd->dev, - "Error sending get_battery_status\n"); + usbpd_err(&pd->dev, "Error sending get_battery_status\n"); usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET); break; } @@ -2674,7 +2670,7 @@ static void usbpd_sm(struct work_struct *w) pd->send_pr_swap = false; ret = pd_send_msg(pd, MSG_PR_SWAP, NULL, 0, SOP_MSG); if (ret) { - dev_err(&pd->dev, "Error sending PR Swap\n"); + usbpd_err(&pd->dev, "Error sending PR Swap\n"); usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET); break; } @@ -2685,7 +2681,7 @@ static void usbpd_sm(struct work_struct *w) pd->send_dr_swap = false; ret = pd_send_msg(pd, MSG_DR_SWAP, NULL, 0, SOP_MSG); if (ret) { - dev_err(&pd->dev, "Error sending DR Swap\n"); + usbpd_err(&pd->dev, "Error sending DR Swap\n"); usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET); break; } -- GitLab From c3539a58d76647b8f8e6e1ee40e2b85ea2855f8f Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Mon, 11 Jun 2018 15:08:44 -0400 Subject: [PATCH 0274/1299] msm: npu: Enable npu cti/apb/atb clocks Enable npu cti/apb/atb clocks to support QDSS hw events. Change-Id: I6fbe8eb9887ef5cccd5840685b1fe574f70c551a Signed-off-by: Jilai Wang --- drivers/media/platform/msm/npu/npu_dev.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/msm/npu/npu_dev.c b/drivers/media/platform/msm/npu/npu_dev.c index 2cc21518989c..1df4e8363e58 100644 --- a/drivers/media/platform/msm/npu/npu_dev.c +++ b/drivers/media/platform/msm/npu/npu_dev.c @@ -99,13 +99,13 @@ static void __exit npu_exit(void); * ------------------------------------------------------------------------- */ static const char * const npu_clock_order[] = { + "at_clk", + "trig_clk", "armwic_core_clk", - "cal_dp_clk_src", "cal_dp_clk", "cal_dp_cdc_clk", "conf_noc_ahb_clk", "comp_noc_axi_clk", - "npu_core_clk_src", "npu_core_clk", "npu_core_cti_clk", "npu_core_apb_clk", @@ -126,18 +126,16 @@ static const char * const npu_post_clocks[] = { }; static const char * const npu_exclude_clocks[] = { - "npu_core_clk_src", - "cal_dp_clk_src", "perf_cnt_clk", - "npu_core_cti_clk", - "npu_core_apb_clk", - "npu_core_atb_clk" }; static const char * const npu_exclude_rate_clocks[] = { + "at_clk", + "trig_clk", "sleep_clk", "xo_clk", "conf_noc_ahb_clk", + "comp_noc_axi_clk", "npu_core_cti_clk", "npu_core_apb_clk", "npu_core_atb_clk", @@ -557,7 +555,7 @@ static int npu_enable_core_clocks(struct npu_device *npu_dev, bool post_pil) rc = clk_set_rate(core_clks[i].clk, pwrlevel->clk_freq[i]); if (rc) { - pr_debug("clk_set_rate %s to %ld failed\n", + pr_err("clk_set_rate %s to %ld failed\n", core_clks[i].clk_name, pwrlevel->clk_freq[i]); break; -- GitLab From 754644eb8f7ec560c149289024ca01b98749b49d Mon Sep 17 00:00:00 2001 From: David Collins Date: Mon, 11 Jun 2018 11:39:41 -0700 Subject: [PATCH 0275/1299] ARM: dts: msm: use PM8150 LDO 18 for USB SS supply on SM8150 QRD DVT boards The VDDA_USB1_SS_DP_CORE supply has been changed from PM8150 LDO 5 to LDO 18 on SM8150 QRD DVT boards. Override the USB SS vdd-supply property with the new mapping. Also, increase the voltage for this supply from 880 mV to 912 mV to improve USB performance. Change-Id: I7b54c422ef1e95ba497034a4b277658bebaacf87 Signed-off-by: David Collins --- arch/arm64/boot/dts/qcom/sm8150-qrd-dvt.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd-dvt.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd-dvt.dtsi index 2aeddc2e51e7..a737d8ff24fd 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qrd-dvt.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd-dvt.dtsi @@ -11,3 +11,8 @@ */ #include "sm8150-qrd.dtsi" + +&usb_qmp_dp_phy { + vdd-supply = <&pm8150_l18>; + qcom,vdd-voltage-level = <0 912000 912000>; +}; -- GitLab From 00e8fb8972028c29ed0b4a25dfabad039e8c1ae5 Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Thu, 14 Jun 2018 12:15:20 -0700 Subject: [PATCH 0276/1299] msm: vidc: Enable batching for H264/HEVC/VP9 formats only Decode batching is required only for H264/HEVC/VP9 formats only and need not be enabled for other formats. Change-Id: I2085e38d68d39cd21b99ca832fc7cab26daa1e3f Signed-off-by: Maheshwar Ajja --- drivers/media/platform/msm/vidc/msm_vidc_common.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 16d504c55501..1e94430f5f20 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -2752,14 +2752,17 @@ bool is_batching_allowed(struct msm_vidc_inst *inst) /* * Enable decode batching based on below conditions - * - decode session * - platform supports batching + * - decode session and H264/HEVC/VP9 format * - session resolution <= 1080p * - low latency not enabled * - not a thumbnail session * - UBWC color format */ - if (is_decode_session(inst) && inst->core->resources.decode_batching && + if (inst->core->resources.decode_batching && is_decode_session(inst) && + (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_H264 || + inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_HEVC || + inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) && (msm_vidc_get_mbs_per_frame(inst) <= NUM_MBS_PER_FRAME(MAX_DEC_BATCH_HEIGHT, MAX_DEC_BATCH_WIDTH)) && !inst->clk_data.low_latency_mode && -- GitLab From 6c6d8d45540acfdaa37c62646df058a088b6eefb Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Samavedam Date: Thu, 7 Jun 2018 13:17:21 -0700 Subject: [PATCH 0277/1299] usb: dwc3: Disable USB20 internal retry feature Disable USB20 internal retry feature for dwc3 version 170A-GA to avoid controller lockup due to snps star:'9001346572:Host stops transfers to other EPs when a single USB2.0 EP NAKs continuously' Change-Id: I71f1d272f74dc51fed4617b7ea12c044160a69c7 Signed-off-by: Vamsi Krishna Samavedam --- drivers/usb/dwc3/core.c | 12 ++++++++++++ drivers/usb/dwc3/core.h | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 08928b19a995..42916cf571fc 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -846,6 +846,18 @@ int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); } + /* + * STAR: 9001346572:Host stops transfers to other EPs when a single + * USB2.0 EP NAKs continuously requires to disable internal retry + * feature + */ + if ((dwc->revision == DWC3_USB31_REVISION_170A) && + (dwc->versiontype == DWC3_USB31_VER_TYPE_GA)) { + reg = dwc3_readl(dwc->regs, DWC3_GUCTL3); + reg |= DWC3_GUCTL3_USB20_RETRY_DISABLE; + dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); + } + dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT); return 0; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index a8100092d469..801df6273ce8 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -113,6 +113,7 @@ #define DWC3_GPRTBIMAP_FS0 0xc188 #define DWC3_GPRTBIMAP_FS1 0xc18c #define DWC3_GUCTL2 0xc19c +#define DWC3_GUCTL3 0xc60c #define DWC3_VER_NUMBER 0xc1a0 #define DWC3_VER_TYPE 0xc1a4 @@ -326,6 +327,9 @@ /* Global User Control Register 2 */ #define DWC3_GUCTL2_RST_ACTBITLATER BIT(14) +/* Global User Control Register 3 */ +#define DWC3_GUCTL3_USB20_RETRY_DISABLE BIT(16) + /* Device Configuration Register */ #define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) #define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f) @@ -1071,6 +1075,7 @@ struct dwc3 { /* valid only for dwc31 configuraitons */ u32 versiontype; #define DWC3_USB31_VER_TYPE_EA06 0x65613036 +#define DWC3_USB31_VER_TYPE_GA 0x67612a2a enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; -- GitLab From 4844b0256b44aca5095279e03ffe09f02d5199a1 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Samavedam Date: Thu, 7 Jun 2018 16:42:51 -0700 Subject: [PATCH 0278/1299] ARM: dts: msm: Disable usb host mode u1/u2 on SM8150 Disable USB Host mode u1/u2 functionality to avoid endpoint bandwidth error due to snps star:'9001329597:Host: Controller may Report Bandwidth Error for Gen1 Device Behind Gen2 Hub'. Change-Id: Ib804bceeade0f6d403432f1ddb92147f798af698 Signed-off-by: Vamsi Krishna Samavedam --- arch/arm64/boot/dts/qcom/sm8150-usb.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-usb.dtsi b/arch/arm64/boot/dts/qcom/sm8150-usb.dtsi index 36261b8c6982..05afdee85db2 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-usb.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-usb.dtsi @@ -84,7 +84,6 @@ snps,disable-clk-gating; snps,has-lpm-erratum; snps,hird-threshold = /bits/ 8 <0x10>; - snps,usb3_lpm_capable; snps,ssp-u3-u0-quirk; snps,usb3-u1u2-disable; usb-core-id = <0>; -- GitLab From 95c74738817668b87f44a4cb9e2114eb7e272c91 Mon Sep 17 00:00:00 2001 From: Prasad Sodagudi Date: Wed, 13 Jun 2018 16:59:30 -0700 Subject: [PATCH 0279/1299] genirq/cpuhotplug: Reduce logging level for couple of prints During the cpu hot plug stress testing, couple of messages continuous flooding on to the console is causing timers migration delay. Delayed time migrations from hot plugging core is causing device instability with watchdog. So reduce log level for couple of prints in cpu hot plug flow. Change-Id: I14f034765b063fb2a83a2a9489c664eb2504a770 Signed-off-by: Prasad Sodagudi --- arch/arm64/kernel/smp.c | 2 +- kernel/irq/cpuhotplug.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index a6c8d9455fa0..043f562dde16 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -355,7 +355,7 @@ void __cpu_die(unsigned int cpu) pr_crit("CPU%u: cpu didn't die\n", cpu); return; } - pr_notice("CPU%u: shutdown\n", cpu); + pr_info("CPU%u: shutdown\n", cpu); /* * Now that the dying CPU is beyond the point of no return w.r.t. diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c index 1c87ea49e5df..244332198a59 100644 --- a/kernel/irq/cpuhotplug.c +++ b/kernel/irq/cpuhotplug.c @@ -41,7 +41,7 @@ static inline bool irq_needs_fixup(struct irq_data *d) * If this happens then there was a missed IRQ fixup at some * point. Warn about it and enforce fixup. */ - pr_warn("Eff. affinity %*pbl of IRQ %u contains only offline CPUs after offlining CPU %u\n", + pr_info("Eff. affinity %*pbl of IRQ %u contains only offline CPUs after offlining CPU %u\n", cpumask_pr_args(m), d->irq, cpu); return true; } @@ -176,7 +176,7 @@ void irq_migrate_all_off_this_cpu(void) raw_spin_unlock(&desc->lock); if (affinity_broken) { - pr_warn_ratelimited("IRQ %u: no longer affine to CPU%u\n", + pr_info_ratelimited("IRQ %u: no longer affine to CPU%u\n", irq, smp_processor_id()); } } -- GitLab From 2b8784e4415f28bec428c1e2c35d62362b6dd119 Mon Sep 17 00:00:00 2001 From: Michael Adisumarta Date: Wed, 13 Jun 2018 15:21:07 -0700 Subject: [PATCH 0280/1299] msm: ipa4: Remove IPA registers dump from dmesg Print out IPA registers only to ipc logs to remove some clutter from DMESG for panic handlling. Keep the dmesg prints for debugfs. Change-Id: I28f07e138853ab516d25f550a9e5a50187ac1c7f Signed-off-by: Michael Adisumarta --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 2 +- drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c | 2 +- drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h | 8 ++++++++ .../platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c | 15 +++++++++++---- .../platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h | 2 +- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index fa6885254c94..6dc9075b18a9 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -4422,7 +4422,7 @@ static int ipa3_panic_notifier(struct notifier_block *this, IPAERR("uC panic handler failed %d\n", res); if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) != 0) - ipahal_print_all_regs(); + ipahal_print_all_regs(false); return NOTIFY_DONE; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index 7bed9e06a695..3454073fec4f 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -1947,7 +1947,7 @@ static ssize_t ipa3_read_ipahal_regs(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { IPA_ACTIVE_CLIENTS_INC_SIMPLE(); - ipahal_print_all_regs(); + ipahal_print_all_regs(true); IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); return 0; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h index 26b7f0fc005e..d46f13ca8499 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h @@ -55,6 +55,14 @@ " %s:%d " fmt, ## args); \ } while (0) +#define IPAHAL_DBG_REG_IPC_ONLY(fmt, args...) \ + do { \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + " %s:%d " fmt, ## args); \ + } while (0) + #define IPAHAL_ERR_RL(fmt, args...) \ do { \ pr_err_ratelimited_ipa(IPAHAL_DRV_NAME " %s:%d " fmt, \ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c index 44a2ce4c486f..13ca985f22f8 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c @@ -2280,7 +2280,7 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = { 0x00000830, 0x70, 8, 17, 1}, }; -int ipahal_print_all_regs(void) +int ipahal_print_all_regs(bool print_to_dmesg) { int i, j; @@ -2299,9 +2299,16 @@ int ipahal_print_all_regs(void) j = ipahal_reg_objs[ipahal_ctx->hw_type][i].n_start; - if (j == ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end) - IPAHAL_DBG_REG("%s=0x%x\n", ipahal_reg_name_str(i), - ipahal_read_reg_n(i, j)); + if (j == ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end) { + if (print_to_dmesg) + IPAHAL_DBG_REG("%s=0x%x\n", + ipahal_reg_name_str(i), + ipahal_read_reg_n(i, j)); + else + IPAHAL_DBG_REG_IPC_ONLY("%s=0x%x\n", + ipahal_reg_name_str(i), + ipahal_read_reg_n(i, j)); + } for (; j < ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end; j++) IPAHAL_DBG_REG("%s_%u=0x%x\n", ipahal_reg_name_str(i), diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h index 0bece888a50c..8d2da38fa5a4 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h @@ -535,7 +535,7 @@ struct ipahal_ep_cfg_ctrl_scnd { }; -int ipahal_print_all_regs(void); +int ipahal_print_all_regs(bool print_to_dmesg); /* * ipahal_reg_name_str() - returns string that represent the register -- GitLab From 7984ef2e482dc2de7025e1fa629cebf4f1bb5c0c Mon Sep 17 00:00:00 2001 From: Chinmay Sawarkar Date: Mon, 11 Jun 2018 18:06:26 -0700 Subject: [PATCH 0281/1299] msm: vidc: Modify multislice config before start - Cap number of slices to max 10. - Slice supported only for H264 and H265 with, ratecontrol CBR or RCOFF. - MB based slice is supported upto UHD 60fps. - Byte based slice is supported upto 1080p 30fps. CRs-Fixed: 2259088 Change-Id: I92235237521713a6a2ca7fedd8336e18264d3f21 Signed-off-by: Chinmay Sawarkar --- drivers/media/platform/msm/vidc/msm_venc.c | 24 +++------ drivers/media/platform/msm/vidc/msm_vidc.c | 59 ++++++++++++++++++++++ 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 405575f8f904..ece0dd8c44a8 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -1506,15 +1506,16 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) } case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: { int temp = 0; - - enable.enable = false; + if (inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC && + inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_H264) { + return rc; + } switch (ctrl->val) { case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB: temp = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB; break; case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES: temp = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES; - enable.enable = true; break; case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE: default: @@ -1522,19 +1523,6 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) break; } - temp_ctrl = - TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE); - if (!temp_ctrl->val) { - rc = msm_comm_try_set_prop(inst, - HAL_PARAM_VENC_LOW_LATENCY, &enable.enable); - if (rc) - dprintk(VIDC_ERR, - "SliceMode Low Latency enable fail\n"); - else - inst->clk_data.low_latency_mode = - (bool) enable.enable; - } - if (temp) temp_ctrl = TRY_GET_CTRL(temp); @@ -1547,6 +1535,10 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) } case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: + if (inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC && + inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_H264) { + return rc; + } temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE); property_id = HAL_PARAM_VENC_MULTI_SLICE_CONTROL; diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index 3b8e85fe7001..87e146960414 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -913,7 +913,11 @@ int msm_vidc_set_internal_config(struct msm_vidc_inst *inst) struct hal_vbv_hdr_buf_size hrd_buf_size; struct hal_enable latency; struct hfi_device *hdev; + struct hal_multi_slice_control multi_slice_control; u32 codec; + u32 mbps, mb_per_frame, fps, bitrate; + u32 slice_val, slice_mode, max_avg_slicesize; + u32 output_width, output_height; if (!inst || !inst->core || !inst->core->device) { dprintk(VIDC_WARN, "%s: Invalid parameter\n", __func__); @@ -965,6 +969,61 @@ int msm_vidc_set_internal_config(struct msm_vidc_inst *inst) inst->clk_data.low_latency_mode = latency.enable; } + /* Update Slice Config */ + slice_mode = msm_comm_g_ctrl_for_id(inst, + V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE); + + if ((codec == V4L2_PIX_FMT_H264 || codec == V4L2_PIX_FMT_HEVC) && + slice_mode != V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) { + + output_height = inst->prop.height[CAPTURE_PORT]; + output_width = inst->prop.width[CAPTURE_PORT]; + fps = inst->prop.fps; + bitrate = inst->clk_data.bitrate; + mb_per_frame = NUM_MBS_PER_FRAME(output_height, output_width); + mbps = NUM_MBS_PER_SEC(output_height, output_width, fps); + + if (rc_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_RC_OFF && + rc_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR && + rc_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) { + slice_mode = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + slice_val = 0; + } else if (slice_mode == + V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) { + if (output_width > 3840 || output_height > 3840 || + mb_per_frame > NUM_MBS_PER_FRAME(3840, 2160) || + fps > 60) { + slice_mode = + V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + slice_val = 0; + } else { + slice_val = msm_comm_g_ctrl_for_id(inst, + V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB); + slice_val = max(slice_val, mb_per_frame / 10); + } + } else { + if (output_width > 1920 || output_height > 1920 || + mb_per_frame > NUM_MBS_PER_FRAME(1920, 1088) || + fps > 30) { + slice_mode = + V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + slice_val = 0; + } else { + slice_val = msm_comm_g_ctrl_for_id(inst, + V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES); + max_avg_slicesize = ((bitrate / fps) / 8) / 10; + slice_val = + max(slice_val, max_avg_slicesize); + } + } + + multi_slice_control.multi_slice = slice_mode; + multi_slice_control.slice_size = slice_val; + + rc = call_hfi_op(hdev, session_set_property, + (void *)inst->session, HAL_PARAM_VENC_MULTI_SLICE_CONTROL, + (void *)&multi_slice_control); + } return rc; } -- GitLab From 50dc4590c46bfc0572c2f599b5e1629dd0965399 Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Thu, 14 Jun 2018 14:56:54 -0700 Subject: [PATCH 0282/1299] trace/sched: fix compilation issue for UP systems sched_enq_deq_task trace point calls cpu_util which is only available for SMP systems and leads to compilation issue on UP systems. Also, cpu_util only accounts for CFS tasks. Change-Id: I8b15d1c2bcba6de65397bbeb0b6772fefcc464a2 Signed-off-by: Satya Durga Srinivasu Prabhala --- include/trace/events/sched.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index e63888bcf208..3d23e8d12ddb 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -82,7 +82,7 @@ TRACE_EVENT(sched_enq_deq_task, __entry->cpu = task_cpu(p); __entry->enqueue = enqueue; __entry->nr_running = task_rq(p)->nr_running; - __entry->cpu_load = cpu_util(task_cpu(p)); + __entry->cpu_load = task_rq(p)->cpu_load[0]; __entry->rt_nr_running = task_rq(p)->rt.rt_nr_running; __entry->cpus_allowed = cpus_allowed; __entry->demand = task_load(p); -- GitLab From f8b1d28cfa01cc07c5e1e949b8094ff6025f307c Mon Sep 17 00:00:00 2001 From: Kyle Piefer Date: Mon, 11 Jun 2018 13:53:11 -0700 Subject: [PATCH 0283/1299] msm: kgsl: Clear OOB for CP init if HFI start fails If the HFI start message fails, the outstanding OOB must be cleared in the error path. If it does not get cleared, the GMU will never idle on the way to slumber. Change-Id: I242d8aac6def483999d35efc70bd6e23be1648dd Signed-off-by: Kyle Piefer --- drivers/gpu/msm/adreno.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index a9775a341b7a..d9551ee19192 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1841,7 +1841,7 @@ static int _adreno_start(struct adreno_device *adreno_dev) if (gmu_dev_ops->hfi_start_msg) { status = gmu_dev_ops->hfi_start_msg(adreno_dev); if (status) - goto error_mmu_off; + goto error_oob_clear; } /* Enable 64 bit gpu addr if feature is set */ -- GitLab From bb997b07bfb0abf0785f6a2ab19d1491a756c11d Mon Sep 17 00:00:00 2001 From: Kyle Piefer Date: Tue, 5 Jun 2018 11:08:14 -0700 Subject: [PATCH 0284/1299] msm: kgsl: Retry reset only on older GPUs If the first reset fails, it is highly unlikely that a subsequent retry of reset will work. Stop doing the reset retry loop on newer GPUs to prevent log spam from repeated reset failures. Change-Id: Ica5b49252669c3c6d54772c17868be3cde69429c Signed-off-by: Kyle Piefer --- drivers/gpu/msm/adreno.c | 18 +++++++++++------- drivers/gpu/msm/adreno.h | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index a9775a341b7a..b95831881dca 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2218,13 +2218,17 @@ int adreno_reset(struct kgsl_device *device, int fault) /* since device is officially off now clear start bit */ clear_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv); - /* Keep trying to start the device until it works */ - for (i = 0; i < NUM_TIMES_RESET_RETRY; i++) { - ret = adreno_start(device, 0); - if (!ret) - break; - - msleep(20); + /* Try to reset the device */ + ret = adreno_start(device, 0); + + /* On some GPUS, keep trying until it works */ + if (ret && ADRENO_GPUREV(adreno_dev) < 600) { + for (i = 0; i < NUM_TIMES_RESET_RETRY; i++) { + msleep(20); + ret = adreno_start(device, 0); + if (!ret) + break; + } } } if (ret) diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 1209103e868f..be9e210a10f1 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -171,8 +171,8 @@ #define KGSL_END_OF_PROFILE_IDENTIFIER 0x2DEFADE2 #define KGSL_PWRON_FIXUP_IDENTIFIER 0x2AFAFAFA -/* Number of times to try hard reset */ -#define NUM_TIMES_RESET_RETRY 5 +/* Number of times to try hard reset for pre-a6xx GPUs */ +#define NUM_TIMES_RESET_RETRY 4 /* Number of times to poll the AHB fence in ISR */ #define FENCE_RETRY_MAX 100 -- GitLab From 88c55517682ecf593e6f6a760e98eea423ab1809 Mon Sep 17 00:00:00 2001 From: Kyle Piefer Date: Thu, 31 May 2018 14:59:16 -0700 Subject: [PATCH 0285/1299] msm: kgsl: Update the HFI error message format The structure of the HFI error message that gets sent by the GMU to the CPU has changed. It now has a payload of 16 dwords instead of 2. Change-Id: I69b7ba3e27529fa45254ebdd4d4eefa16b6fac55 Signed-off-by: Kyle Piefer --- drivers/gpu/msm/kgsl_hfi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/msm/kgsl_hfi.h b/drivers/gpu/msm/kgsl_hfi.h index a3013225b60c..7bb6d1edc598 100644 --- a/drivers/gpu/msm/kgsl_hfi.h +++ b/drivers/gpu/msm/kgsl_hfi.h @@ -406,7 +406,7 @@ struct hfi_prep_slumber_cmd { struct hfi_err_cmd { uint32_t hdr; uint32_t error_code; - uint32_t data[2]; + uint32_t data[16]; }; /* F2H */ -- GitLab From fb8236a52c11d8da3ee92e870b09566557de5bf9 Mon Sep 17 00:00:00 2001 From: Kyle Piefer Date: Thu, 31 May 2018 11:16:02 -0700 Subject: [PATCH 0286/1299] msm: kgsl: Add the GMU core header to the GMU header The GMU header uses some defines from the GMU core header. Include that header to prevent compilation failures from include ordering. Change-Id: Iad6185f05a46b672e2f1e65177638de512f00375 Signed-off-by: Kyle Piefer --- drivers/gpu/msm/kgsl_gmu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h index efbe5f7ad846..b8e097e8e854 100644 --- a/drivers/gpu/msm/kgsl_gmu.h +++ b/drivers/gpu/msm/kgsl_gmu.h @@ -13,6 +13,7 @@ #ifndef __KGSL_GMU_H #define __KGSL_GMU_H +#include "kgsl_gmu_core.h" #include "kgsl_hfi.h" #define MAX_GMUFW_SIZE 0x2000 /* in bytes */ -- GitLab From 1eea2bf30575a0b1991cf6c3d486f05dccd2dd2c Mon Sep 17 00:00:00 2001 From: Kyle Piefer Date: Tue, 29 May 2018 10:09:00 -0700 Subject: [PATCH 0287/1299] msm: kgsl: Fix the DCVS table definition The structure of the HFI DCVS table that gets sent by the CPU to the GMU has changed for HFI version 2. It now has an ACD value for only the GX portion of the table. Change-Id: I425aebdf1c87832ca16d12fdad6e13b63c7d122b Signed-off-by: Kyle Piefer --- drivers/gpu/msm/kgsl_hfi.c | 33 ++++++++++++++++++++++++++++++++- drivers/gpu/msm/kgsl_hfi.h | 18 ++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c index c54e19504ed9..3f585ec41436 100644 --- a/drivers/gpu/msm/kgsl_hfi.c +++ b/drivers/gpu/msm/kgsl_hfi.c @@ -396,6 +396,29 @@ static int hfi_send_feature_ctrls(struct gmu_device *gmu) return 0; } +static int hfi_send_dcvstbl_v1(struct gmu_device *gmu) +{ + struct hfi_dcvstable_v1_cmd cmd = { + .hdr = CMD_MSG_HDR(H2F_MSG_PERF_TBL, sizeof(cmd)), + .gpu_level_num = gmu->num_gpupwrlevels, + .gmu_level_num = gmu->num_gmupwrlevels, + }; + int i; + + for (i = 0; i < gmu->num_gpupwrlevels; i++) { + cmd.gx_votes[i].vote = gmu->rpmh_votes.gx_votes[i]; + /* Divide by 1000 to convert to kHz */ + cmd.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000; + } + + for (i = 0; i < gmu->num_gmupwrlevels; i++) { + cmd.cx_votes[i].vote = gmu->rpmh_votes.cx_votes[i]; + cmd.cx_votes[i].freq = gmu->gmu_freqs[i] / 1000; + } + + return hfi_send_generic_req(gmu, HFI_CMD_IDX, &cmd); +} + static int hfi_send_dcvstbl(struct gmu_device *gmu) { struct hfi_dcvstable_cmd cmd = { @@ -407,6 +430,11 @@ static int hfi_send_dcvstbl(struct gmu_device *gmu) for (i = 0; i < gmu->num_gpupwrlevels; i++) { cmd.gx_votes[i].vote = gmu->rpmh_votes.gx_votes[i]; + /* + * Set ACD threshold to the maximum value as a default. + * At this level, ACD will never activate. + */ + cmd.gx_votes[i].acd = 0xFFFFFFFF; /* Divide by 1000 to convert to kHz */ cmd.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000; } @@ -619,7 +647,10 @@ int hfi_start(struct kgsl_device *device, if (result) return result; - result = hfi_send_dcvstbl(gmu); + if (HFI_VER_MAJOR(&gmu->hfi) < 2) + result = hfi_send_dcvstbl_v1(gmu); + else + result = hfi_send_dcvstbl(gmu); if (result) return result; diff --git a/drivers/gpu/msm/kgsl_hfi.h b/drivers/gpu/msm/kgsl_hfi.h index a3013225b60c..0ba4edd6c741 100644 --- a/drivers/gpu/msm/kgsl_hfi.h +++ b/drivers/gpu/msm/kgsl_hfi.h @@ -249,14 +249,19 @@ struct hfi_bwbuf { uint32_t arr[NUM_BW_LEVELS]; }; -struct opp_desc { +struct opp_gx_desc { uint32_t vote; uint32_t acd; uint32_t freq; }; +struct opp_desc { + uint32_t vote; + uint32_t freq; +}; + /* H2F */ -struct hfi_dcvstable_cmd { +struct hfi_dcvstable_v1_cmd { uint32_t hdr; uint32_t gpu_level_num; uint32_t gmu_level_num; @@ -264,6 +269,15 @@ struct hfi_dcvstable_cmd { struct opp_desc cx_votes[MAX_CX_LEVELS]; }; +/* H2F */ +struct hfi_dcvstable_cmd { + uint32_t hdr; + uint32_t gpu_level_num; + uint32_t gmu_level_num; + struct opp_gx_desc gx_votes[MAX_GX_LEVELS]; + struct opp_desc cx_votes[MAX_CX_LEVELS]; +}; + /* H2F */ struct hfi_test_cmd { uint32_t hdr; -- GitLab From ad23b1d46c151c7a953a3ca9f86e4d19b777ca70 Mon Sep 17 00:00:00 2001 From: Kyle Piefer Date: Thu, 17 May 2018 16:52:30 -0700 Subject: [PATCH 0288/1299] msm: kgsl: Refactor the setting of features over HFI There will be more features added to be disabled or enabled over HFI. Some of these will change at runtime. Refactor the code that sends these HFIs to make adding new ones easier. Also, make the printing of feature setting errors prettier. Change-Id: Idf1576c320f5d2f997633d35fc8e1e1069b85882 Signed-off-by: Kyle Piefer --- drivers/gpu/msm/kgsl_hfi.c | 64 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c index 3f585ec41436..c3bea2eabd0b 100644 --- a/drivers/gpu/msm/kgsl_hfi.c +++ b/drivers/gpu/msm/kgsl_hfi.c @@ -312,7 +312,13 @@ static int hfi_send_generic_req(struct gmu_device *gmu, uint32_t queue, if (rc) return rc; - return ret_cmd.results[2]; + if (ret_cmd.results[2]) + dev_err(&gmu->pdev->dev, + "HFI ACK failure: Req 0x%8.8X Error 0x%X\n", + ret_cmd.results[1], + ret_cmd.results[2]); + + return ret_cmd.results[2] ? -EINVAL : 0; } static int hfi_send_gmu_init(struct gmu_device *gmu, uint32_t boot_state) @@ -364,36 +370,37 @@ static int hfi_send_core_fw_start(struct gmu_device *gmu) return hfi_send_generic_req(gmu, HFI_CMD_IDX, &cmd); } -static struct hfi_feature { - uint32_t feature; - uint32_t enable; - uint32_t data; -} hfi_features[] = { - { HFI_FEATURE_ECP, 0, 0}, +static const char * const hfi_features[] = { + [HFI_FEATURE_ECP] = "ECP", }; -static int hfi_send_feature_ctrls(struct gmu_device *gmu) +static const char *feature_to_string(uint32_t feature) { - struct hfi_feature_ctrl_cmd cmd; - int ret = 0, i; - - for (i = 0; i < ARRAY_SIZE(hfi_features); i++) { - cmd.hdr = CMD_MSG_HDR(H2F_MSG_FEATURE_CTRL, sizeof(cmd)); - cmd.feature = hfi_features[i].feature; - cmd.enable = hfi_features[i].enable; - cmd.data = hfi_features[i].data; - - ret = hfi_send_generic_req(gmu, HFI_CMD_IDX, &cmd); - if (ret) { - pr_err("KGSL: setfeature fail:%d [%d:%d:0x%x]\n", ret, - hfi_features[i].feature, - hfi_features[i].enable, - hfi_features[i].data); - return ret; - } - } + if (feature < ARRAY_SIZE(hfi_features) && hfi_features[feature]) + return hfi_features[feature]; - return 0; + return "unknown"; +} + +static int hfi_send_feature_ctrl(struct gmu_device *gmu, + uint32_t feature, uint32_t enable, uint32_t data) +{ + struct hfi_feature_ctrl_cmd cmd = { + .hdr = CMD_MSG_HDR(H2F_MSG_FEATURE_CTRL, sizeof(cmd)), + .feature = feature, + .enable = enable, + .data = data, + }; + int ret; + + ret = hfi_send_generic_req(gmu, HFI_CMD_IDX, &cmd); + if (ret) + dev_err(&gmu->pdev->dev, + "Unable to %s feature %s (%d)\n", + enable ? "enable" : "disable", + feature_to_string(feature), + feature); + return ret; } static int hfi_send_dcvstbl_v1(struct gmu_device *gmu) @@ -663,9 +670,8 @@ int hfi_start(struct kgsl_device *device, * we are sending no more HFIs until the next boot otherwise * send H2F_MSG_CORE_FW_START and features for A640 devices */ - if (HFI_VER_MAJOR(&gmu->hfi) >= 2) { - result = hfi_send_feature_ctrls(gmu); + result = hfi_send_feature_ctrl(gmu, HFI_FEATURE_ECP, 0, 0); if (result) return result; -- GitLab From 0c473b76a8ddda723691157dfc86e0d532c7d1a8 Mon Sep 17 00:00:00 2001 From: Shashank Babu Chinta Venkata Date: Thu, 31 May 2018 15:12:09 -0700 Subject: [PATCH 0289/1299] ARM: dts: msm: add default display for SM8150+SDX50 MTP Add truly 2k display command mode as default display for SM8150+SDX50 MTP platform. Change-Id: I0afc7db432b45e56a3127bce12a18e576d1a88f8 Signed-off-by: Shashank Babu Chinta Venkata --- .../sm8150-sdx50m-mtp-2.5k-panel-overlay.dts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts index 4e590ea853d3..a95714ac5865 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts @@ -28,3 +28,33 @@ compatible = "qcom,sm8150-mtp", "qcom,sm8150", "qcom,mtp"; qcom,board-id = <0x01010008 0x1>; }; + +&dsi_sharp_4k_dsc_cmd_display { + /delete-property/ qcom,dsi-display-active; +}; + +&dsi_dual_nt35597_truly_video { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-mode-sel-gpio-state = "dual_port"; + qcom,panel-mode-gpio = <&tlmm 7 0>; + qcom,platform-te-gpio = <&tlmm 8 0>; + qcom,platform-reset-gpio = <&tlmm 6 0>; +}; + +&dsi_dual_nt35597_truly_cmd { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-mode-sel-gpio-state = "dual_port"; + qcom,panel-mode-gpio = <&tlmm 7 0>; + qcom,platform-te-gpio = <&tlmm 8 0>; + qcom,platform-reset-gpio = <&tlmm 6 0>; +}; + +&dsi_dual_nt35597_truly_cmd_display { + qcom,dsi-display-active; +}; -- GitLab From 683f20ce1366d66365f57fc25c88ff41c00b0e39 Mon Sep 17 00:00:00 2001 From: Steve Cohen Date: Wed, 13 Jun 2018 15:04:47 -0400 Subject: [PATCH 0290/1299] drm/msm/sde: don't setup AVR for displays not supporting qsync Avoid calling avr setup function for panels which don't support this feature. Only video mode DSI panels with a valid setting for the qcom,mdss-dsi-qsync-min-refresh-rate node in the device tree should call in to this function. Change-Id: Ia624576ca74bc93de6cf238cb7b577c5e8897bc1 Signed-off-by: Steve Cohen --- .../gpu/drm/msm/sde/sde_encoder_phys_vid.c | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index ea0fb886776f..324c042b01f0 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -343,7 +343,7 @@ static bool sde_encoder_phys_vid_mode_fixup( /* vid_enc timing_params must be configured before calling this function */ static void _sde_encoder_phys_vid_setup_avr( - struct sde_encoder_phys *phys_enc) + struct sde_encoder_phys *phys_enc, u32 qsync_min_fps) { struct sde_encoder_phys_vid *vid_enc; struct drm_display_mode mode; @@ -352,18 +352,13 @@ static void _sde_encoder_phys_vid_setup_avr( mode = phys_enc->cached_mode; if (vid_enc->base.hw_intf->ops.avr_setup) { struct intf_avr_params avr_params = {0}; - u32 qsync_min_fps = 0; u32 default_fps = mode.vrefresh; int ret; - if (phys_enc->parent_ops.get_qsync_fps) - phys_enc->parent_ops.get_qsync_fps( - phys_enc->parent, &qsync_min_fps); - - if (!qsync_min_fps || !default_fps) { + if (!default_fps) { SDE_ERROR_VIDENC(vid_enc, - "wrong qsync params %d %d\n", - qsync_min_fps, default_fps); + "invalid default fps %d\n", + default_fps); return; } @@ -397,6 +392,7 @@ static void sde_encoder_phys_vid_setup_timing_engine( struct intf_timing_params timing_params = { 0 }; const struct sde_format *fmt = NULL; u32 fmt_fourcc = DRM_FORMAT_RGB888; + u32 qsync_min_fps = 0; unsigned long lock_flags; struct sde_hw_intf_cfg intf_cfg = { 0 }; @@ -462,7 +458,13 @@ static void sde_encoder_phys_vid_setup_timing_engine( programmable_fetch_config(phys_enc, &timing_params); exit: - _sde_encoder_phys_vid_setup_avr(phys_enc); + if (phys_enc->parent_ops.get_qsync_fps) + phys_enc->parent_ops.get_qsync_fps( + phys_enc->parent, &qsync_min_fps); + + /* only panels which support qsync will have a non-zero min fps */ + if (qsync_min_fps) + _sde_encoder_phys_vid_setup_avr(phys_enc, qsync_min_fps); } static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) -- GitLab From 061b9e8ecfe763c28d5d3a69ef56cbb02a602508 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Wed, 13 Jun 2018 16:19:25 -0700 Subject: [PATCH 0291/1299] usb: xhci-plat: Remove system PM call backs system PM callbacks are just calling xhci_suspend() and xhci_resume() functions which are already called from runtime PM callbacks. Calling it from system PM again results into un-clocked register access. Change-Id: I4e3216773246e5f4ec94d8e921b98c51fff2654d Signed-off-by: Hemant Kumar --- drivers/usb/host/xhci-plat.c | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 4fa503a37c7b..b52c8955209b 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -437,35 +437,6 @@ static int xhci_plat_remove(struct platform_device *dev) return 0; } -static int __maybe_unused xhci_plat_suspend(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - - /* - * xhci_suspend() needs `do_wakeup` to know whether host is allowed - * to do wakeup during suspend. Since xhci_plat_suspend is currently - * only designed for system suspend, device_may_wakeup() is enough - * to dertermine whether host is allowed to do wakeup. Need to - * reconsider this when xhci_plat_suspend enlarges its scope, e.g., - * also applies to runtime suspend. - */ - return xhci_suspend(xhci, device_may_wakeup(dev)); -} - -static int __maybe_unused xhci_plat_resume(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - int ret; - - ret = xhci_priv_resume_quirk(hcd); - if (ret) - return ret; - - return xhci_resume(xhci, 0); -} - static int __maybe_unused xhci_plat_runtime_idle(struct device *dev) { /* @@ -507,6 +478,10 @@ static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) dev_dbg(dev, "xhci-plat runtime resume\n"); + ret = xhci_priv_resume_quirk(hcd); + if (ret) + return ret; + ret = xhci_resume(xhci, false); pm_runtime_mark_last_busy(dev); @@ -514,7 +489,7 @@ static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) } static const struct dev_pm_ops xhci_plat_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume) + SET_SYSTEM_SLEEP_PM_OPS(NULL, NULL) SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume, -- GitLab From 8eab8926a96d54fd443d9f809d4e644bee9b90f5 Mon Sep 17 00:00:00 2001 From: Bryan Huntsman Date: Mon, 4 Jun 2018 16:02:31 -0700 Subject: [PATCH 0292/1299] defconfig: move vendor defconfigs to vendor/ subdirectory Move all defconfigs down one level to vendor/. Create symlinks as necessary for userspace components that are still hard-coded to the older location. Change-Id: I4628a10349139e760758071eca96c5020337aff9 Signed-off-by: Bryan Huntsman --- arch/arm64/configs/sm8150-perf_defconfig | 639 +--------------- arch/arm64/configs/sm8150_defconfig | 721 +----------------- .../{ => vendor}/sdmshrike-perf_defconfig | 0 .../configs/{ => vendor}/sdmshrike_defconfig | 0 .../{ => vendor}/sdmsteppe-perf_defconfig | 0 .../configs/{ => vendor}/sdmsteppe_defconfig | 0 .../{ => vendor}/sm8150-auto-perf_defconfig | 0 .../{ => vendor}/sm8150-auto_defconfig | 0 .../configs/vendor/sm8150-perf_defconfig | 638 ++++++++++++++++ arch/arm64/configs/vendor/sm8150_defconfig | 720 +++++++++++++++++ 10 files changed, 1360 insertions(+), 1358 deletions(-) mode change 100644 => 120000 arch/arm64/configs/sm8150-perf_defconfig mode change 100644 => 120000 arch/arm64/configs/sm8150_defconfig rename arch/arm64/configs/{ => vendor}/sdmshrike-perf_defconfig (100%) rename arch/arm64/configs/{ => vendor}/sdmshrike_defconfig (100%) rename arch/arm64/configs/{ => vendor}/sdmsteppe-perf_defconfig (100%) rename arch/arm64/configs/{ => vendor}/sdmsteppe_defconfig (100%) rename arch/arm64/configs/{ => vendor}/sm8150-auto-perf_defconfig (100%) rename arch/arm64/configs/{ => vendor}/sm8150-auto_defconfig (100%) create mode 100644 arch/arm64/configs/vendor/sm8150-perf_defconfig create mode 100644 arch/arm64/configs/vendor/sm8150_defconfig diff --git a/arch/arm64/configs/sm8150-perf_defconfig b/arch/arm64/configs/sm8150-perf_defconfig deleted file mode 100644 index 83d8f020491f..000000000000 --- a/arch/arm64/configs/sm8150-perf_defconfig +++ /dev/null @@ -1,638 +0,0 @@ -CONFIG_LOCALVERSION="-perf" -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_AUDIT=y -# CONFIG_AUDITSYSCALL is not set -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_SCHED_WALT=y -CONFIG_TASKSTATS=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_RCU_EXPERT=y -CONFIG_RCU_FAST_NO_HZ=y -CONFIG_RCU_NOCB_CPU=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 -CONFIG_MEMCG=y -CONFIG_MEMCG_SWAP=y -CONFIG_BLK_CGROUP=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_CGROUP_FREEZER=y -CONFIG_CPUSETS=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_CGROUP_BPF=y -CONFIG_SCHED_CORE_CTL=y -CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set -# CONFIG_PID_NS is not set -CONFIG_SCHED_AUTOGROUP=y -CONFIG_SCHED_TUNE=y -CONFIG_DEFAULT_USE_ENERGY_AWARE=y -CONFIG_BLK_DEV_INITRD=y -# CONFIG_RD_XZ is not set -# CONFIG_RD_LZO is not set -# CONFIG_RD_LZ4 is not set -CONFIG_KALLSYMS_ALL=y -CONFIG_BPF_SYSCALL=y -# CONFIG_MEMBARRIER is not set -CONFIG_EMBEDDED=y -# CONFIG_SLUB_DEBUG is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_SLAB_FREELIST_RANDOM=y -CONFIG_SLAB_FREELIST_HARDENED=y -CONFIG_PROFILING=y -CONFIG_CC_STACKPROTECTOR_STRONG=y -CONFIG_REFCOUNT_FULL=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SIG=y -CONFIG_MODULE_SIG_FORCE=y -CONFIG_MODULE_SIG_SHA512=y -CONFIG_PARTITION_ADVANCED=y -CONFIG_CFQ_GROUP_IOSCHED=y -CONFIG_ARCH_QCOM=y -CONFIG_ARCH_SM8150=y -CONFIG_PCI=y -CONFIG_PCI_MSM=y -CONFIG_SCHED_MC=y -CONFIG_NR_CPUS=8 -CONFIG_PREEMPT=y -CONFIG_HZ_100=y -CONFIG_CMA=y -CONFIG_ZSMALLOC=y -CONFIG_SECCOMP=y -# CONFIG_UNMAP_KERNEL_AT_EL0 is not set -# CONFIG_HARDEN_BRANCH_PREDICTOR is not set -CONFIG_ARMV8_DEPRECATED=y -CONFIG_SWP_EMULATION=y -CONFIG_CP15_BARRIER_EMULATION=y -CONFIG_SETEND_EMULATION=y -# CONFIG_ARM64_VHE is not set -CONFIG_RANDOMIZE_BASE=y -# CONFIG_EFI is not set -CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_COMPAT=y -CONFIG_PM_AUTOSLEEP=y -CONFIG_PM_WAKELOCKS=y -CONFIG_PM_WAKELOCKS_LIMIT=0 -# CONFIG_PM_WAKELOCKS_GC is not set -CONFIG_CPU_IDLE=y -CONFIG_ARM_CPUIDLE=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_BOOST=y -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_XFRM_STATISTICS=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_NET_IPVTI=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -CONFIG_INET_DIAG_DESTROY=y -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_ROUTE_INFO=y -CONFIG_IPV6_OPTIMISTIC_DAD=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_IPV6_MIP6=y -CONFIG_IPV6_VTI=y -CONFIG_IPV6_MULTIPLE_TABLES=y -CONFIG_IPV6_SUBTREES=y -CONFIG_NETFILTER=y -CONFIG_NF_CONNTRACK=y -CONFIG_NF_CONNTRACK_SECMARK=y -CONFIG_NF_CONNTRACK_EVENTS=y -CONFIG_NF_CONNTRACK_AMANDA=y -CONFIG_NF_CONNTRACK_FTP=y -CONFIG_NF_CONNTRACK_H323=y -CONFIG_NF_CONNTRACK_IRC=y -CONFIG_NF_CONNTRACK_NETBIOS_NS=y -CONFIG_NF_CONNTRACK_PPTP=y -CONFIG_NF_CONNTRACK_SANE=y -CONFIG_NF_CONNTRACK_TFTP=y -CONFIG_NF_CT_NETLINK=y -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y -CONFIG_NETFILTER_XT_TARGET_CONNMARK=y -CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y -CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y -CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y -CONFIG_NETFILTER_XT_TARGET_LOG=y -CONFIG_NETFILTER_XT_TARGET_MARK=y -CONFIG_NETFILTER_XT_TARGET_NFLOG=y -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y -CONFIG_NETFILTER_XT_TARGET_NOTRACK=y -CONFIG_NETFILTER_XT_TARGET_TEE=y -CONFIG_NETFILTER_XT_TARGET_TPROXY=y -CONFIG_NETFILTER_XT_TARGET_TRACE=y -CONFIG_NETFILTER_XT_TARGET_SECMARK=y -CONFIG_NETFILTER_XT_TARGET_TCPMSS=y -CONFIG_NETFILTER_XT_MATCH_BPF=y -CONFIG_NETFILTER_XT_MATCH_COMMENT=y -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y -CONFIG_NETFILTER_XT_MATCH_CONNMARK=y -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -CONFIG_NETFILTER_XT_MATCH_DSCP=y -CONFIG_NETFILTER_XT_MATCH_ESP=y -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y -CONFIG_NETFILTER_XT_MATCH_HELPER=y -CONFIG_NETFILTER_XT_MATCH_IPRANGE=y -# CONFIG_NETFILTER_XT_MATCH_L2TP is not set -CONFIG_NETFILTER_XT_MATCH_LENGTH=y -CONFIG_NETFILTER_XT_MATCH_LIMIT=y -CONFIG_NETFILTER_XT_MATCH_MAC=y -CONFIG_NETFILTER_XT_MATCH_MARK=y -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y -CONFIG_NETFILTER_XT_MATCH_POLICY=y -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y -CONFIG_NETFILTER_XT_MATCH_QTAGUID=y -CONFIG_NETFILTER_XT_MATCH_QUOTA=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y -CONFIG_NETFILTER_XT_MATCH_SOCKET=y -CONFIG_NETFILTER_XT_MATCH_STATE=y -CONFIG_NETFILTER_XT_MATCH_STATISTIC=y -CONFIG_NETFILTER_XT_MATCH_STRING=y -CONFIG_NETFILTER_XT_MATCH_TIME=y -CONFIG_NETFILTER_XT_MATCH_U32=y -CONFIG_NF_CONNTRACK_IPV4=y -CONFIG_NF_SOCKET_IPV4=y -CONFIG_IP_NF_IPTABLES=y -CONFIG_IP_NF_MATCH_AH=y -CONFIG_IP_NF_MATCH_ECN=y -CONFIG_IP_NF_MATCH_RPFILTER=y -CONFIG_IP_NF_MATCH_TTL=y -CONFIG_IP_NF_FILTER=y -CONFIG_IP_NF_TARGET_REJECT=y -CONFIG_IP_NF_NAT=y -CONFIG_IP_NF_TARGET_MASQUERADE=y -CONFIG_IP_NF_TARGET_NETMAP=y -CONFIG_IP_NF_TARGET_REDIRECT=y -CONFIG_IP_NF_MANGLE=y -CONFIG_IP_NF_RAW=y -CONFIG_IP_NF_SECURITY=y -CONFIG_IP_NF_ARPTABLES=y -CONFIG_IP_NF_ARPFILTER=y -CONFIG_IP_NF_ARP_MANGLE=y -CONFIG_NF_CONNTRACK_IPV6=y -CONFIG_NF_SOCKET_IPV6=y -CONFIG_IP6_NF_IPTABLES=y -CONFIG_IP6_NF_MATCH_RPFILTER=y -CONFIG_IP6_NF_FILTER=y -CONFIG_IP6_NF_TARGET_REJECT=y -CONFIG_IP6_NF_MANGLE=y -CONFIG_IP6_NF_RAW=y -CONFIG_BRIDGE_NF_EBTABLES=y -CONFIG_BRIDGE_EBT_BROUTE=y -CONFIG_L2TP=y -CONFIG_L2TP_V3=y -CONFIG_L2TP_IP=y -CONFIG_L2TP_ETH=y -CONFIG_BRIDGE=y -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_HTB=y -CONFIG_NET_SCH_PRIO=y -CONFIG_NET_SCH_MULTIQ=y -CONFIG_NET_SCH_INGRESS=y -CONFIG_NET_CLS_FW=y -CONFIG_NET_CLS_U32=y -CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_FLOW=y -CONFIG_NET_EMATCH=y -CONFIG_NET_EMATCH_CMP=y -CONFIG_NET_EMATCH_NBYTE=y -CONFIG_NET_EMATCH_U32=y -CONFIG_NET_EMATCH_META=y -CONFIG_NET_EMATCH_TEXT=y -CONFIG_NET_CLS_ACT=y -CONFIG_NET_ACT_GACT=y -CONFIG_NET_ACT_MIRRED=y -CONFIG_NET_ACT_SKBEDIT=y -CONFIG_QRTR=y -CONFIG_QRTR_SMD=y -CONFIG_QRTR_MHI=y -CONFIG_RMNET_DATA=y -CONFIG_RMNET_DATA_FC=y -CONFIG_RMNET_DATA_DEBUG_PKT=y -CONFIG_SOCKEV_NLMCAST=y -CONFIG_BT=y -CONFIG_MSM_BT_POWER=y -CONFIG_CFG80211=y -CONFIG_CFG80211_CERTIFICATION_ONUS=y -CONFIG_CFG80211_REG_CELLULAR_HINTS=y -CONFIG_CFG80211_INTERNAL_REGDB=y -CONFIG_RFKILL=y -CONFIG_NFC_NQ=y -CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y -CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y -CONFIG_DMA_CMA=y -CONFIG_MHI_BUS=y -CONFIG_MHI_QCOM=y -CONFIG_MHI_NETDEV=y -CONFIG_MHI_UCI=y -CONFIG_ZRAM=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_HDCP_QSEECOM=y -CONFIG_QSEECOM=y -CONFIG_UID_SYS_STATS=y -CONFIG_MEMORY_STATE_TIME=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_SG=y -CONFIG_CHR_DEV_SCH=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_UFSHCD=y -CONFIG_SCSI_UFSHCD_PLATFORM=y -CONFIG_SCSI_UFS_QCOM=y -CONFIG_SCSI_UFS_QCOM_ICE=y -CONFIG_MD=y -CONFIG_BLK_DEV_DM=y -CONFIG_DM_UEVENT=y -CONFIG_DM_VERITY=y -CONFIG_DM_VERITY_FEC=y -CONFIG_NETDEVICES=y -CONFIG_BONDING=y -CONFIG_DUMMY=y -CONFIG_TUN=y -CONFIG_SKY2=y -CONFIG_RMNET=y -CONFIG_SMSC911X=y -CONFIG_PPP=y -CONFIG_PPP_BSDCOMP=y -CONFIG_PPP_DEFLATE=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=y -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOE=y -CONFIG_PPPOL2TP=y -CONFIG_PPPOLAC=y -CONFIG_PPPOPNS=y -CONFIG_PPP_ASYNC=y -CONFIG_PPP_SYNC_TTY=y -CONFIG_USB_USBNET=y -CONFIG_WIL6210=m -CONFIG_WCNSS_MEM_PRE_ALLOC=y -CONFIG_CLD_LL_CORE=y -CONFIG_INPUT_EVDEV=y -CONFIG_KEYBOARD_GPIO=y -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ST=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_HBTP_INPUT=y -CONFIG_INPUT_QPNP_POWER_ON=y -CONFIG_INPUT_UINPUT=y -# CONFIG_SERIO_SERPORT is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVMEM is not set -CONFIG_SERIAL_MSM_GENI=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_MSM_LEGACY=y -CONFIG_DIAG_CHAR=y -CONFIG_MSM_FASTCVPD=y -CONFIG_MSM_ADSPRPC=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_QCOM_GENI=y -CONFIG_SPI=y -CONFIG_SPI_QCOM_GENI=y -CONFIG_SPI_SPIDEV=y -CONFIG_SPMI=y -CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y -CONFIG_SPMI_SIMULATOR=y -CONFIG_PM8150_PMIC_SIMULATOR=y -CONFIG_PM8150B_PMIC_SIMULATOR=y -CONFIG_PM8150L_PMIC_SIMULATOR=y -CONFIG_SLIMBUS_MSM_NGD=y -CONFIG_PINCTRL_QCOM_SPMI_PMIC=y -CONFIG_PINCTRL_SM8150=y -CONFIG_GPIO_SYSFS=y -CONFIG_POWER_RESET_QCOM=y -CONFIG_QCOM_DLOAD_MODE=y -CONFIG_POWER_RESET_XGENE=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_QPNP_FG_GEN4=y -CONFIG_SMB1355_SLAVE_CHARGER=y -CONFIG_QPNP_SMB5=y -CONFIG_SMB1390_CHARGE_PUMP=y -CONFIG_THERMAL=y -CONFIG_THERMAL_WRITABLE_TRIPS=y -CONFIG_THERMAL_GOV_USER_SPACE=y -CONFIG_THERMAL_GOV_LOW_LIMITS=y -CONFIG_CPU_THERMAL=y -CONFIG_DEVFREQ_THERMAL=y -CONFIG_QCOM_SPMI_TEMP_ALARM=y -CONFIG_THERMAL_TSENS=y -CONFIG_QTI_THERMAL_LIMITS_DCVS=y -CONFIG_QTI_VIRTUAL_SENSOR=y -CONFIG_QTI_AOP_REG_COOLING_DEVICE=y -CONFIG_QTI_QMI_COOLING_DEVICE=y -CONFIG_REGULATOR_COOLING_DEVICE=y -CONFIG_QTI_BCL_PMIC5=y -CONFIG_QTI_BCL_SOC_DRIVER=y -CONFIG_QTI_ADC_TM=y -CONFIG_MFD_I2C_PMIC=y -CONFIG_MFD_SPMI_PMIC=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_PROXY_CONSUMER=y -CONFIG_REGULATOR_QPNP_LCDB=y -CONFIG_REGULATOR_REFGEN=y -CONFIG_REGULATOR_RPMH=y -CONFIG_REGULATOR_STUB=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_MEDIA_CONTROLLER=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y -CONFIG_VIDEO_ADV_DEBUG=y -CONFIG_VIDEO_FIXED_MINOR_RANGES=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_SPECTRA_CAMERA=y -CONFIG_MSM_VIDC_V4L2=y -CONFIG_MSM_VIDC_GOVERNORS=y -CONFIG_MSM_SDE_ROTATOR=y -CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y -CONFIG_MSM_NPU=y -CONFIG_DRM=y -CONFIG_DRM_MSM_REGISTER_LOGGING=y -CONFIG_DRM_SDE_EVTLOG_DEBUG=y -CONFIG_DRM_SDE_RSC=y -CONFIG_FB_ARMCLCD=y -CONFIG_BACKLIGHT_QCOM_SPMI_WLED=y -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_DYNAMIC_MINORS=y -CONFIG_SND_USB_AUDIO=y -CONFIG_SND_USB_AUDIO_QMI=y -CONFIG_SND_SOC=y -CONFIG_UHID=y -CONFIG_HID_APPLE=y -CONFIG_HID_ELECOM=y -CONFIG_HID_MAGICMOUSE=y -CONFIG_HID_MICROSOFT=y -CONFIG_HID_MULTITOUCH=y -CONFIG_HID_PLANTRONICS=y -CONFIG_USB=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_HCD_PLATFORM=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_OHCI_HCD_PLATFORM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_DWC3=y -CONFIG_USB_DWC3_MSM=y -CONFIG_USB_ISP1760=y -CONFIG_USB_ISP1760_HOST_ROLE=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_USB_QCOM_EMU_PHY=y -CONFIG_USB_MSM_SSPHY_QMP=y -CONFIG_MSM_HSUSB_PHY=y -CONFIG_DUAL_ROLE_USB_INTF=y -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_VBUS_DRAW=900 -CONFIG_USB_CONFIGFS=y -CONFIG_USB_CONFIGFS_NCM=y -CONFIG_USB_CONFIGFS_MASS_STORAGE=y -CONFIG_USB_CONFIGFS_F_FS=y -CONFIG_USB_CONFIGFS_F_MTP=y -CONFIG_USB_CONFIGFS_F_PTP=y -CONFIG_USB_CONFIGFS_F_ACC=y -CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y -CONFIG_USB_CONFIGFS_UEVENT=y -CONFIG_USB_CONFIGFS_F_MIDI=y -CONFIG_USB_CONFIGFS_F_HID=y -CONFIG_USB_CONFIGFS_F_DIAG=y -CONFIG_USB_CONFIGFS_F_CDEV=y -CONFIG_USB_CONFIGFS_F_CCID=y -CONFIG_USB_CONFIGFS_F_GSI=y -CONFIG_USB_CONFIGFS_F_QDSS=y -CONFIG_USB_PD_POLICY=y -CONFIG_QPNP_USB_PDPHY=y -CONFIG_MMC=y -CONFIG_MMC_PERF_PROFILING=y -CONFIG_MMC_BLOCK_MINORS=32 -CONFIG_MMC_BLOCK_DEFERRED_RESUME=y -CONFIG_MMC_TEST=y -CONFIG_MMC_PARANOID_SD_INIT=y -CONFIG_MMC_CLKGATE=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_MSM=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_QPNP_FLASH_V2=y -CONFIG_LEDS_QPNP_HAPTICS=y -CONFIG_LEDS_QTI_TRI_LED=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_EDAC=y -CONFIG_EDAC_KRYO_ARM64=y -CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE=y -CONFIG_EDAC_KRYO_ARM64_PANIC_ON_UE=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_QPNP=y -CONFIG_DMADEVICES=y -CONFIG_QCOM_GPI_DMA=y -CONFIG_UIO=y -CONFIG_UIO_MSM_SHAREDMEM=y -CONFIG_STAGING=y -CONFIG_ASHMEM=y -CONFIG_ION=y -CONFIG_QCOM_GENI_SE=y -CONFIG_QPNP_REVID=y -CONFIG_SPS=y -CONFIG_SPS_SUPPORT_NDP_BAM=y -CONFIG_USB_BAM=y -CONFIG_IPA3=y -CONFIG_IPA_WDI_UNIFIED_API=y -CONFIG_RMNET_IPA3=y -CONFIG_RNDIS_IPA=y -CONFIG_IPA3_MHI_PROXY=y -CONFIG_IPA_UT=y -CONFIG_MSM_11AD=m -CONFIG_SEEMP_CORE=y -CONFIG_QCOM_MDSS_PLL=y -CONFIG_SPMI_PMIC_CLKDIV=y -CONFIG_MSM_CLK_AOP_QMP=y -CONFIG_MSM_GCC_SM8150=y -CONFIG_MSM_NPUCC_SM8150=y -CONFIG_MSM_VIDEOCC_SM8150=y -CONFIG_MSM_CAMCC_SM8150=y -CONFIG_CLOCK_CPU_OSM=y -CONFIG_MSM_DISPCC_SM8150=y -CONFIG_MSM_DEBUGCC_SM8150=y -CONFIG_MSM_CLK_RPMH=y -CONFIG_MSM_GPUCC_SM8150=y -CONFIG_HWSPINLOCK=y -CONFIG_HWSPINLOCK_QCOM=y -CONFIG_QCOM_APCS_IPC=y -CONFIG_MSM_QMP=y -CONFIG_IOMMU_IO_PGTABLE_FAST=y -CONFIG_ARM_SMMU=y -CONFIG_QCOM_LAZY_MAPPING=y -CONFIG_IOMMU_DEBUG=y -CONFIG_IOMMU_DEBUG_TRACKING=y -CONFIG_IOMMU_TESTS=y -CONFIG_RPMSG_CHAR=y -CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_RPMSG_QCOM_GLINK_SPSS=y -CONFIG_RPMSG_QCOM_GLINK_SPI=y -CONFIG_QCOM_CPUSS_DUMP=y -CONFIG_QCOM_RUN_QUEUE_STATS=y -CONFIG_QCOM_LLCC=y -CONFIG_QCOM_SM8150_LLCC=y -CONFIG_QCOM_LLCC_PERFMON=m -CONFIG_QCOM_QMI_HELPERS=y -CONFIG_QCOM_SMEM=y -CONFIG_QCOM_MEMORY_DUMP_V2=y -CONFIG_QCOM_WATCHDOG_V2=y -CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y -CONFIG_QCOM_SMP2P=y -CONFIG_MSM_SERVICE_LOCATOR=y -CONFIG_MSM_SERVICE_NOTIFIER=y -CONFIG_MSM_SUBSYSTEM_RESTART=y -CONFIG_MSM_PIL=y -CONFIG_MSM_SYSMON_QMI_COMM=y -CONFIG_MSM_PIL_SSR_GENERIC=y -CONFIG_MSM_BOOT_STATS=y -CONFIG_QCOM_DCC_V2=y -CONFIG_QCOM_SECURE_BUFFER=y -CONFIG_ICNSS=y -CONFIG_ICNSS_QMI=y -CONFIG_QCOM_EUD=y -CONFIG_QCOM_MINIDUMP=y -CONFIG_QCOM_BUS_SCALING=y -CONFIG_QCOM_BUS_CONFIG_RPMH=y -CONFIG_QCOM_COMMAND_DB=y -CONFIG_QCOM_EARLY_RANDOM=y -CONFIG_MSM_SPSS_UTILS=y -CONFIG_MSM_SPCOM=y -CONFIG_QTI_RPMH_API=y -CONFIG_QSEE_IPC_IRQ_BRIDGE=y -CONFIG_QCOM_GLINK=y -CONFIG_QCOM_GLINK_PKT=y -CONFIG_QCOM_QDSS_BRIDGE=y -CONFIG_QTI_RPM_STATS_LOG=y -CONFIG_MSM_CDSP_LOADER=y -CONFIG_QCOM_SMCINVOKE=y -CONFIG_MSM_EVENT_TIMER=y -CONFIG_MSM_PM=y -CONFIG_MSM_QBT1000=y -CONFIG_QCOM_FSA4480_I2C=y -CONFIG_MSM_PERFORMANCE=y -CONFIG_QMP_DEBUGFS_CLIENT=y -CONFIG_QCOM_SMP2P_SLEEPSTATE=y -CONFIG_DEVFREQ_GOV_PASSIVE=y -CONFIG_QCOM_BIMC_BWMON=y -CONFIG_ARM_MEMLAT_MON=y -CONFIG_QCOMCCI_HWMON=y -CONFIG_QCOM_M4M_HWMON=y -CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y -CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y -CONFIG_DEVFREQ_GOV_MEMLAT=y -CONFIG_DEVFREQ_SIMPLE_DEV=y -CONFIG_QCOM_DEVFREQ_DEVBW=y -CONFIG_EXTCON_USB_GPIO=y -CONFIG_IIO=y -CONFIG_QCOM_SPMI_ADC5=y -CONFIG_PWM=y -CONFIG_PWM_QTI_LPG=y -CONFIG_QCOM_KGSL=y -CONFIG_ARM_GIC_V3_ACL=y -CONFIG_ARM_DSU_PMU=y -CONFIG_QCOM_LLCC_PMU=y -CONFIG_RAS=y -CONFIG_ANDROID=y -CONFIG_ANDROID_BINDER_IPC=y -CONFIG_NVMEM_SPMI_SDAM=y -CONFIG_SENSORS_SSC=y -CONFIG_ESOC=y -CONFIG_ESOC_DEV=y -CONFIG_ESOC_CLIENT=y -CONFIG_ESOC_MDM_4x=y -CONFIG_ESOC_MDM_DRV=y -CONFIG_ESOC_MDM_DBG_ENG=y -CONFIG_MSM_TZ_LOG=y -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_SECURITY=y -CONFIG_EXT4_ENCRYPTION=y -CONFIG_EXT4_FS_ENCRYPTION=y -CONFIG_EXT4_FS_ICE_ENCRYPTION=y -CONFIG_QUOTA=y -CONFIG_QUOTA_NETLINK_INTERFACE=y -CONFIG_FUSE_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_ECRYPT_FS=y -CONFIG_ECRYPT_FS_MESSAGING=y -CONFIG_SDCARD_FS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_PRINTK_TIME=y -CONFIG_DEBUG_INFO=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_PANIC_TIMEOUT=5 -CONFIG_SCHEDSTATS=y -# CONFIG_DEBUG_PREEMPT is not set -CONFIG_IPC_LOGGING=y -CONFIG_DEBUG_ALIGN_RODATA=y -CONFIG_CORESIGHT=y -CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y -CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y -CONFIG_CORESIGHT_STM=y -CONFIG_CORESIGHT_CTI=y -CONFIG_CORESIGHT_TPDA=y -CONFIG_CORESIGHT_TPDM=y -CONFIG_CORESIGHT_HWEVENT=y -CONFIG_CORESIGHT_DUMMY=y -CONFIG_CORESIGHT_REMOTE_ETM=y -CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 -CONFIG_CORESIGHT_TGU=y -CONFIG_CORESIGHT_EVENT=y -CONFIG_PFK=y -CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y -CONFIG_SECURITY=y -CONFIG_HARDENED_USERCOPY=y -CONFIG_FORTIFY_SOURCE=y -CONFIG_SECURITY_SELINUX=y -CONFIG_SECURITY_SMACK=y -CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_ANSI_CPRNG=y -CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y -CONFIG_CRYPTO_DEV_QCRYPTO=y -CONFIG_CRYPTO_DEV_QCEDEV=y -CONFIG_CRYPTO_DEV_QCOM_ICE=y -CONFIG_ARM64_CRYPTO=y -CONFIG_CRYPTO_SHA1_ARM64_CE=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y diff --git a/arch/arm64/configs/sm8150-perf_defconfig b/arch/arm64/configs/sm8150-perf_defconfig new file mode 120000 index 000000000000..faafc59228ee --- /dev/null +++ b/arch/arm64/configs/sm8150-perf_defconfig @@ -0,0 +1 @@ +vendor/sm8150-perf_defconfig \ No newline at end of file diff --git a/arch/arm64/configs/sm8150_defconfig b/arch/arm64/configs/sm8150_defconfig deleted file mode 100644 index 3b919f593861..000000000000 --- a/arch/arm64/configs/sm8150_defconfig +++ /dev/null @@ -1,720 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_AUDIT=y -# CONFIG_AUDITSYSCALL is not set -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_SCHED_WALT=y -CONFIG_TASKSTATS=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_RCU_EXPERT=y -CONFIG_RCU_FAST_NO_HZ=y -CONFIG_RCU_NOCB_CPU=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 -CONFIG_MEMCG=y -CONFIG_MEMCG_SWAP=y -CONFIG_BLK_CGROUP=y -CONFIG_DEBUG_BLK_CGROUP=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_CGROUP_FREEZER=y -CONFIG_CPUSETS=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_CGROUP_BPF=y -CONFIG_CGROUP_DEBUG=y -CONFIG_SCHED_CORE_CTL=y -CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set -# CONFIG_PID_NS is not set -CONFIG_SCHED_AUTOGROUP=y -CONFIG_SCHED_TUNE=y -CONFIG_DEFAULT_USE_ENERGY_AWARE=y -CONFIG_BLK_DEV_INITRD=y -# CONFIG_RD_XZ is not set -# CONFIG_RD_LZO is not set -# CONFIG_RD_LZ4 is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_KALLSYMS_ALL=y -CONFIG_BPF_SYSCALL=y -# CONFIG_MEMBARRIER is not set -CONFIG_EMBEDDED=y -# CONFIG_COMPAT_BRK is not set -CONFIG_SLAB_FREELIST_RANDOM=y -CONFIG_SLAB_FREELIST_HARDENED=y -CONFIG_PROFILING=y -CONFIG_CC_STACKPROTECTOR_STRONG=y -CONFIG_REFCOUNT_FULL=y -CONFIG_PANIC_ON_REFCOUNT_ERROR=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SIG=y -CONFIG_MODULE_SIG_FORCE=y -CONFIG_MODULE_SIG_SHA512=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_PARTITION_ADVANCED=y -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_CFQ_GROUP_IOSCHED=y -CONFIG_ARCH_QCOM=y -CONFIG_ARCH_SM8150=y -CONFIG_PCI=y -CONFIG_PCI_MSM=y -CONFIG_SCHED_MC=y -CONFIG_NR_CPUS=8 -CONFIG_PREEMPT=y -CONFIG_HZ_100=y -CONFIG_CLEANCACHE=y -CONFIG_CMA=y -CONFIG_CMA_DEBUGFS=y -CONFIG_ZSMALLOC=y -CONFIG_SECCOMP=y -# CONFIG_UNMAP_KERNEL_AT_EL0 is not set -# CONFIG_HARDEN_BRANCH_PREDICTOR is not set -CONFIG_PRINT_VMEMLAYOUT=y -CONFIG_ARMV8_DEPRECATED=y -CONFIG_SWP_EMULATION=y -CONFIG_CP15_BARRIER_EMULATION=y -CONFIG_SETEND_EMULATION=y -# CONFIG_ARM64_VHE is not set -CONFIG_RANDOMIZE_BASE=y -CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_COMPAT=y -CONFIG_PM_AUTOSLEEP=y -CONFIG_PM_WAKELOCKS=y -CONFIG_PM_WAKELOCKS_LIMIT=0 -# CONFIG_PM_WAKELOCKS_GC is not set -CONFIG_PM_DEBUG=y -CONFIG_CPU_IDLE=y -CONFIG_ARM_CPUIDLE=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_BOOST=y -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_XFRM_STATISTICS=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_NET_IPVTI=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -CONFIG_INET_DIAG_DESTROY=y -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_ROUTE_INFO=y -CONFIG_IPV6_OPTIMISTIC_DAD=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_IPV6_MIP6=y -CONFIG_IPV6_VTI=y -CONFIG_IPV6_MULTIPLE_TABLES=y -CONFIG_IPV6_SUBTREES=y -CONFIG_NETFILTER=y -CONFIG_NF_CONNTRACK=y -CONFIG_NF_CONNTRACK_SECMARK=y -CONFIG_NF_CONNTRACK_EVENTS=y -CONFIG_NF_CONNTRACK_AMANDA=y -CONFIG_NF_CONNTRACK_FTP=y -CONFIG_NF_CONNTRACK_H323=y -CONFIG_NF_CONNTRACK_IRC=y -CONFIG_NF_CONNTRACK_NETBIOS_NS=y -CONFIG_NF_CONNTRACK_PPTP=y -CONFIG_NF_CONNTRACK_SANE=y -CONFIG_NF_CONNTRACK_TFTP=y -CONFIG_NF_CT_NETLINK=y -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y -CONFIG_NETFILTER_XT_TARGET_CONNMARK=y -CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y -CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y -CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y -CONFIG_NETFILTER_XT_TARGET_LOG=y -CONFIG_NETFILTER_XT_TARGET_MARK=y -CONFIG_NETFILTER_XT_TARGET_NFLOG=y -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y -CONFIG_NETFILTER_XT_TARGET_NOTRACK=y -CONFIG_NETFILTER_XT_TARGET_TEE=y -CONFIG_NETFILTER_XT_TARGET_TPROXY=y -CONFIG_NETFILTER_XT_TARGET_TRACE=y -CONFIG_NETFILTER_XT_TARGET_SECMARK=y -CONFIG_NETFILTER_XT_TARGET_TCPMSS=y -CONFIG_NETFILTER_XT_MATCH_BPF=y -CONFIG_NETFILTER_XT_MATCH_COMMENT=y -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y -CONFIG_NETFILTER_XT_MATCH_CONNMARK=y -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -CONFIG_NETFILTER_XT_MATCH_DSCP=y -CONFIG_NETFILTER_XT_MATCH_ESP=y -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y -CONFIG_NETFILTER_XT_MATCH_HELPER=y -CONFIG_NETFILTER_XT_MATCH_IPRANGE=y -# CONFIG_NETFILTER_XT_MATCH_L2TP is not set -CONFIG_NETFILTER_XT_MATCH_LENGTH=y -CONFIG_NETFILTER_XT_MATCH_LIMIT=y -CONFIG_NETFILTER_XT_MATCH_MAC=y -CONFIG_NETFILTER_XT_MATCH_MARK=y -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y -CONFIG_NETFILTER_XT_MATCH_POLICY=y -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y -CONFIG_NETFILTER_XT_MATCH_QTAGUID=y -CONFIG_NETFILTER_XT_MATCH_QUOTA=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y -CONFIG_NETFILTER_XT_MATCH_SOCKET=y -CONFIG_NETFILTER_XT_MATCH_STATE=y -CONFIG_NETFILTER_XT_MATCH_STATISTIC=y -CONFIG_NETFILTER_XT_MATCH_STRING=y -CONFIG_NETFILTER_XT_MATCH_TIME=y -CONFIG_NETFILTER_XT_MATCH_U32=y -CONFIG_NF_CONNTRACK_IPV4=y -CONFIG_NF_SOCKET_IPV4=y -CONFIG_IP_NF_IPTABLES=y -CONFIG_IP_NF_MATCH_AH=y -CONFIG_IP_NF_MATCH_ECN=y -CONFIG_IP_NF_MATCH_RPFILTER=y -CONFIG_IP_NF_MATCH_TTL=y -CONFIG_IP_NF_FILTER=y -CONFIG_IP_NF_TARGET_REJECT=y -CONFIG_IP_NF_NAT=y -CONFIG_IP_NF_TARGET_MASQUERADE=y -CONFIG_IP_NF_TARGET_NETMAP=y -CONFIG_IP_NF_TARGET_REDIRECT=y -CONFIG_IP_NF_MANGLE=y -CONFIG_IP_NF_RAW=y -CONFIG_IP_NF_SECURITY=y -CONFIG_IP_NF_ARPTABLES=y -CONFIG_IP_NF_ARPFILTER=y -CONFIG_IP_NF_ARP_MANGLE=y -CONFIG_NF_CONNTRACK_IPV6=y -CONFIG_NF_SOCKET_IPV6=y -CONFIG_IP6_NF_IPTABLES=y -CONFIG_IP6_NF_MATCH_RPFILTER=y -CONFIG_IP6_NF_FILTER=y -CONFIG_IP6_NF_TARGET_REJECT=y -CONFIG_IP6_NF_MANGLE=y -CONFIG_IP6_NF_RAW=y -CONFIG_BRIDGE_NF_EBTABLES=y -CONFIG_BRIDGE_EBT_BROUTE=y -CONFIG_L2TP=y -CONFIG_L2TP_DEBUGFS=y -CONFIG_L2TP_V3=y -CONFIG_L2TP_IP=y -CONFIG_L2TP_ETH=y -CONFIG_BRIDGE=y -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_HTB=y -CONFIG_NET_SCH_PRIO=y -CONFIG_NET_SCH_MULTIQ=y -CONFIG_NET_SCH_INGRESS=y -CONFIG_NET_CLS_FW=y -CONFIG_NET_CLS_U32=y -CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_FLOW=y -CONFIG_NET_EMATCH=y -CONFIG_NET_EMATCH_CMP=y -CONFIG_NET_EMATCH_NBYTE=y -CONFIG_NET_EMATCH_U32=y -CONFIG_NET_EMATCH_META=y -CONFIG_NET_EMATCH_TEXT=y -CONFIG_NET_CLS_ACT=y -CONFIG_NET_ACT_GACT=y -CONFIG_NET_ACT_MIRRED=y -CONFIG_NET_ACT_SKBEDIT=y -CONFIG_DNS_RESOLVER=y -CONFIG_QRTR=y -CONFIG_QRTR_SMD=y -CONFIG_QRTR_MHI=y -CONFIG_RMNET_DATA=y -CONFIG_RMNET_DATA_FC=y -CONFIG_RMNET_DATA_DEBUG_PKT=y -CONFIG_SOCKEV_NLMCAST=y -CONFIG_BT=y -CONFIG_MSM_BT_POWER=y -CONFIG_CFG80211=y -CONFIG_CFG80211_CERTIFICATION_ONUS=y -CONFIG_CFG80211_REG_CELLULAR_HINTS=y -CONFIG_CFG80211_INTERNAL_REGDB=y -# CONFIG_CFG80211_CRDA_SUPPORT is not set -CONFIG_RFKILL=y -CONFIG_NFC_NQ=y -CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y -CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y -CONFIG_DMA_CMA=y -CONFIG_MHI_BUS=y -CONFIG_MHI_DEBUG=y -CONFIG_MHI_QCOM=y -CONFIG_MHI_NETDEV=y -CONFIG_MHI_UCI=y -CONFIG_ZRAM=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_HDCP_QSEECOM=y -CONFIG_QSEECOM=y -CONFIG_UID_SYS_STATS=y -CONFIG_MEMORY_STATE_TIME=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_SG=y -CONFIG_CHR_DEV_SCH=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_UFSHCD=y -CONFIG_SCSI_UFSHCD_PLATFORM=y -CONFIG_SCSI_UFS_QCOM=y -CONFIG_SCSI_UFS_QCOM_ICE=y -CONFIG_SCSI_UFSHCD_CMD_LOGGING=y -CONFIG_MD=y -CONFIG_BLK_DEV_DM=y -CONFIG_DM_UEVENT=y -CONFIG_DM_VERITY=y -CONFIG_DM_VERITY_FEC=y -CONFIG_NETDEVICES=y -CONFIG_BONDING=y -CONFIG_DUMMY=y -CONFIG_TUN=y -CONFIG_RMNET=y -CONFIG_PHYLIB=y -CONFIG_PPP=y -CONFIG_PPP_BSDCOMP=y -CONFIG_PPP_DEFLATE=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=y -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOE=y -CONFIG_PPPOL2TP=y -CONFIG_PPPOLAC=y -CONFIG_PPPOPNS=y -CONFIG_PPP_ASYNC=y -CONFIG_PPP_SYNC_TTY=y -CONFIG_WIL6210=m -CONFIG_WCNSS_MEM_PRE_ALLOC=y -CONFIG_CLD_LL_CORE=y -CONFIG_INPUT_EVDEV=y -CONFIG_KEYBOARD_GPIO=y -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_JOYSTICK=y -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ST=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_HBTP_INPUT=y -CONFIG_INPUT_QPNP_POWER_ON=y -CONFIG_INPUT_UINPUT=y -# CONFIG_SERIO_SERPORT is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_MSM_GENI=y -CONFIG_SERIAL_MSM_GENI_CONSOLE=y -CONFIG_SERIAL_DEV_BUS=y -CONFIG_TTY_PRINTK=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_MSM_LEGACY=y -CONFIG_DIAG_CHAR=y -CONFIG_MSM_FASTCVPD=y -CONFIG_MSM_ADSPRPC=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_QCOM_GENI=y -CONFIG_SPI=y -CONFIG_SPI_QCOM_GENI=y -CONFIG_SPI_SPIDEV=y -CONFIG_SPMI=y -CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y -CONFIG_SPMI_SIMULATOR=y -CONFIG_PM8150_PMIC_SIMULATOR=y -CONFIG_PM8150B_PMIC_SIMULATOR=y -CONFIG_PM8150L_PMIC_SIMULATOR=y -CONFIG_SLIMBUS_MSM_NGD=y -CONFIG_PINCTRL_QCOM_SPMI_PMIC=y -CONFIG_PINCTRL_SM8150=y -CONFIG_GPIO_SYSFS=y -CONFIG_POWER_RESET_QCOM=y -CONFIG_QCOM_DLOAD_MODE=y -CONFIG_POWER_RESET_XGENE=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_QPNP_FG_GEN4=y -CONFIG_SMB1355_SLAVE_CHARGER=y -CONFIG_QPNP_SMB5=y -CONFIG_SMB1390_CHARGE_PUMP=y -CONFIG_THERMAL=y -CONFIG_THERMAL_WRITABLE_TRIPS=y -CONFIG_THERMAL_GOV_USER_SPACE=y -CONFIG_THERMAL_GOV_LOW_LIMITS=y -CONFIG_CPU_THERMAL=y -CONFIG_DEVFREQ_THERMAL=y -CONFIG_QCOM_SPMI_TEMP_ALARM=y -CONFIG_THERMAL_TSENS=y -CONFIG_QTI_THERMAL_LIMITS_DCVS=y -CONFIG_QTI_VIRTUAL_SENSOR=y -CONFIG_QTI_AOP_REG_COOLING_DEVICE=y -CONFIG_QTI_QMI_COOLING_DEVICE=y -CONFIG_REGULATOR_COOLING_DEVICE=y -CONFIG_QTI_BCL_PMIC5=y -CONFIG_QTI_BCL_SOC_DRIVER=y -CONFIG_QTI_ADC_TM=y -CONFIG_MFD_I2C_PMIC=y -CONFIG_MFD_SPMI_PMIC=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_PROXY_CONSUMER=y -CONFIG_REGULATOR_QPNP_LCDB=y -CONFIG_REGULATOR_REFGEN=y -CONFIG_REGULATOR_RPMH=y -CONFIG_REGULATOR_STUB=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_MEDIA_CONTROLLER=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y -CONFIG_VIDEO_ADV_DEBUG=y -CONFIG_VIDEO_FIXED_MINOR_RANGES=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_SPECTRA_CAMERA=y -CONFIG_MSM_VIDC_V4L2=y -CONFIG_MSM_VIDC_GOVERNORS=y -CONFIG_MSM_SDE_ROTATOR=y -CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y -CONFIG_MSM_NPU=y -CONFIG_DRM=y -CONFIG_DRM_MSM_REGISTER_LOGGING=y -CONFIG_DRM_SDE_EVTLOG_DEBUG=y -CONFIG_DRM_SDE_RSC=y -CONFIG_FB_VIRTUAL=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_QCOM_SPMI_WLED=y -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_DYNAMIC_MINORS=y -CONFIG_SND_USB_AUDIO=y -CONFIG_SND_USB_AUDIO_QMI=y -CONFIG_SND_SOC=y -CONFIG_UHID=y -CONFIG_HID_APPLE=y -CONFIG_HID_ELECOM=y -CONFIG_HID_MAGICMOUSE=y -CONFIG_HID_MICROSOFT=y -CONFIG_HID_MULTITOUCH=y -CONFIG_HID_PLANTRONICS=y -CONFIG_USB=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_HCD_PLATFORM=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_OHCI_HCD_PLATFORM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_DWC3=y -CONFIG_USB_DWC3_MSM=y -CONFIG_USB_ISP1760=y -CONFIG_USB_ISP1760_HOST_ROLE=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_USB_QCOM_EMU_PHY=y -CONFIG_USB_MSM_SSPHY_QMP=y -CONFIG_MSM_HSUSB_PHY=y -CONFIG_DUAL_ROLE_USB_INTF=y -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_VBUS_DRAW=900 -CONFIG_USB_CONFIGFS=y -CONFIG_USB_CONFIGFS_NCM=y -CONFIG_USB_CONFIGFS_MASS_STORAGE=y -CONFIG_USB_CONFIGFS_F_FS=y -CONFIG_USB_CONFIGFS_F_MTP=y -CONFIG_USB_CONFIGFS_F_PTP=y -CONFIG_USB_CONFIGFS_F_ACC=y -CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y -CONFIG_USB_CONFIGFS_UEVENT=y -CONFIG_USB_CONFIGFS_F_MIDI=y -CONFIG_USB_CONFIGFS_F_HID=y -CONFIG_USB_CONFIGFS_F_DIAG=y -CONFIG_USB_CONFIGFS_F_CDEV=y -CONFIG_USB_CONFIGFS_F_CCID=y -CONFIG_USB_CONFIGFS_F_GSI=y -CONFIG_USB_CONFIGFS_F_QDSS=y -CONFIG_USB_PD_POLICY=y -CONFIG_QPNP_USB_PDPHY=y -CONFIG_MMC=y -CONFIG_MMC_PERF_PROFILING=y -CONFIG_MMC_BLOCK_MINORS=32 -CONFIG_MMC_BLOCK_DEFERRED_RESUME=y -CONFIG_MMC_TEST=y -CONFIG_MMC_RING_BUFFER=y -CONFIG_MMC_PARANOID_SD_INIT=y -CONFIG_MMC_CLKGATE=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_MSM=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_QPNP_FLASH_V2=y -CONFIG_LEDS_QPNP_HAPTICS=y -CONFIG_LEDS_QTI_TRI_LED=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_EDAC=y -CONFIG_EDAC_KRYO_ARM64=y -CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE=y -CONFIG_EDAC_KRYO_ARM64_PANIC_ON_UE=y -CONFIG_EDAC_QCOM_LLCC=y -CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE=y -CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_QPNP=y -CONFIG_DMADEVICES=y -CONFIG_QCOM_GPI_DMA=y -CONFIG_QCOM_GPI_DMA_DEBUG=y -CONFIG_UIO=y -CONFIG_UIO_MSM_SHAREDMEM=y -CONFIG_STAGING=y -CONFIG_ASHMEM=y -CONFIG_ION=y -CONFIG_QCOM_GENI_SE=y -CONFIG_QPNP_REVID=y -CONFIG_SPS=y -CONFIG_SPS_SUPPORT_NDP_BAM=y -CONFIG_USB_BAM=y -CONFIG_IPA3=y -CONFIG_IPA_WDI_UNIFIED_API=y -CONFIG_RMNET_IPA3=y -CONFIG_RNDIS_IPA=y -CONFIG_IPA3_MHI_PROXY=y -CONFIG_IPA_UT=y -CONFIG_MSM_11AD=m -CONFIG_SEEMP_CORE=y -CONFIG_QCOM_MDSS_PLL=y -CONFIG_SPMI_PMIC_CLKDIV=y -CONFIG_MSM_CLK_AOP_QMP=y -CONFIG_MSM_GCC_SM8150=y -CONFIG_MSM_NPUCC_SM8150=y -CONFIG_MSM_VIDEOCC_SM8150=y -CONFIG_MSM_CAMCC_SM8150=y -CONFIG_CLOCK_CPU_OSM=y -CONFIG_MSM_DISPCC_SM8150=y -CONFIG_MSM_DEBUGCC_SM8150=y -CONFIG_MSM_CLK_RPMH=y -CONFIG_MSM_GPUCC_SM8150=y -CONFIG_HWSPINLOCK=y -CONFIG_HWSPINLOCK_QCOM=y -CONFIG_QCOM_APCS_IPC=y -CONFIG_MSM_QMP=y -CONFIG_IOMMU_IO_PGTABLE_FAST=y -CONFIG_ARM_SMMU=y -CONFIG_QCOM_LAZY_MAPPING=y -CONFIG_IOMMU_DEBUG=y -CONFIG_IOMMU_DEBUG_TRACKING=y -CONFIG_IOMMU_TESTS=y -CONFIG_RPMSG_CHAR=y -CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_RPMSG_QCOM_GLINK_SPSS=y -CONFIG_RPMSG_QCOM_GLINK_SPI=y -CONFIG_QCOM_CPUSS_DUMP=y -CONFIG_QCOM_RUN_QUEUE_STATS=y -CONFIG_QCOM_LLCC=y -CONFIG_QCOM_SM8150_LLCC=y -CONFIG_QCOM_LLCC_PERFMON=m -CONFIG_QCOM_QMI_HELPERS=y -CONFIG_QCOM_SMEM=y -CONFIG_QCOM_MEMORY_DUMP_V2=y -CONFIG_QCOM_WATCHDOG_V2=y -CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y -CONFIG_QCOM_WDOG_IPI_ENABLE=y -CONFIG_QCOM_SMP2P=y -CONFIG_MSM_SERVICE_LOCATOR=y -CONFIG_MSM_SERVICE_NOTIFIER=y -CONFIG_MSM_SUBSYSTEM_RESTART=y -CONFIG_MSM_PIL=y -CONFIG_MSM_SYSMON_QMI_COMM=y -CONFIG_MSM_PIL_SSR_GENERIC=y -CONFIG_MSM_BOOT_STATS=y -CONFIG_MSM_CORE_HANG_DETECT=y -CONFIG_QCOM_DCC_V2=y -CONFIG_MSM_GLADIATOR_HANG_DETECT=y -CONFIG_QCOM_SECURE_BUFFER=y -CONFIG_ICNSS=y -CONFIG_ICNSS_DEBUG=y -CONFIG_ICNSS_QMI=y -CONFIG_QCOM_EUD=y -CONFIG_QCOM_MINIDUMP=y -CONFIG_QCOM_BUS_SCALING=y -CONFIG_QCOM_BUS_CONFIG_RPMH=y -CONFIG_QCOM_COMMAND_DB=y -CONFIG_QCOM_EARLY_RANDOM=y -CONFIG_MSM_SPSS_UTILS=y -CONFIG_MSM_SPCOM=y -CONFIG_QTI_RPMH_API=y -CONFIG_QSEE_IPC_IRQ_BRIDGE=y -CONFIG_QCOM_GLINK=y -CONFIG_QCOM_GLINK_PKT=y -CONFIG_QCOM_QDSS_BRIDGE=y -CONFIG_QTI_RPM_STATS_LOG=y -CONFIG_MSM_CDSP_LOADER=y -CONFIG_QCOM_SMCINVOKE=y -CONFIG_MSM_EVENT_TIMER=y -CONFIG_MSM_PM=y -CONFIG_MSM_QBT1000=y -CONFIG_QCOM_FSA4480_I2C=y -CONFIG_MSM_PERFORMANCE=y -CONFIG_QMP_DEBUGFS_CLIENT=y -CONFIG_QCOM_SMP2P_SLEEPSTATE=y -CONFIG_DEVFREQ_GOV_PASSIVE=y -CONFIG_QCOM_BIMC_BWMON=y -CONFIG_ARM_MEMLAT_MON=y -CONFIG_QCOMCCI_HWMON=y -CONFIG_QCOM_M4M_HWMON=y -CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y -CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y -CONFIG_DEVFREQ_GOV_MEMLAT=y -CONFIG_DEVFREQ_SIMPLE_DEV=y -CONFIG_QCOM_DEVFREQ_DEVBW=y -CONFIG_EXTCON_USB_GPIO=y -CONFIG_IIO=y -CONFIG_QCOM_SPMI_ADC5=y -CONFIG_PWM=y -CONFIG_PWM_QTI_LPG=y -CONFIG_QCOM_KGSL=y -CONFIG_ARM_GIC_V3_ACL=y -CONFIG_PHY_XGENE=y -CONFIG_ARM_DSU_PMU=y -CONFIG_QCOM_LLCC_PMU=y -CONFIG_RAS=y -CONFIG_ANDROID=y -CONFIG_ANDROID_BINDER_IPC=y -CONFIG_NVMEM_SPMI_SDAM=y -CONFIG_SENSORS_SSC=y -CONFIG_ESOC=y -CONFIG_ESOC_DEV=y -CONFIG_ESOC_CLIENT=y -CONFIG_ESOC_DEBUG=y -CONFIG_ESOC_MDM_4x=y -CONFIG_ESOC_MDM_DRV=y -CONFIG_ESOC_MDM_DBG_ENG=y -CONFIG_MSM_TZ_LOG=y -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_SECURITY=y -CONFIG_EXT4_ENCRYPTION=y -CONFIG_EXT4_FS_ENCRYPTION=y -CONFIG_EXT4_FS_ICE_ENCRYPTION=y -CONFIG_QUOTA=y -CONFIG_QUOTA_NETLINK_INTERFACE=y -CONFIG_FUSE_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_EFIVAR_FS=y -CONFIG_ECRYPT_FS=y -CONFIG_ECRYPT_FS_MESSAGING=y -CONFIG_SDCARD_FS=y -# CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_PRINTK_TIME=y -CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_INFO=y -CONFIG_PAGE_OWNER=y -CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y -CONFIG_DEBUG_SECTION_MISMATCH=y -# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_PAGEALLOC=y -CONFIG_SLUB_DEBUG_PANIC_ON=y -CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y -CONFIG_PAGE_POISONING=y -CONFIG_DEBUG_OBJECTS=y -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_WORK=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_SLUB_DEBUG_ON=y -CONFIG_DEBUG_KMEMLEAK=y -CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 -CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y -CONFIG_DEBUG_STACK_USAGE=y -CONFIG_DEBUG_MEMORY_INIT=y -CONFIG_SOFTLOCKUP_DETECTOR=y -CONFIG_WQ_WATCHDOG=y -CONFIG_PANIC_TIMEOUT=5 -CONFIG_PANIC_ON_SCHED_BUG=y -CONFIG_PANIC_ON_RT_THROTTLING=y -CONFIG_SCHEDSTATS=y -CONFIG_SCHED_STACK_END_CHECK=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_ATOMIC_SLEEP=y -CONFIG_LOCK_TORTURE_TEST=m -CONFIG_DEBUG_SG=y -CONFIG_DEBUG_NOTIFIERS=y -CONFIG_DEBUG_CREDENTIALS=y -CONFIG_RCU_TORTURE_TEST=m -CONFIG_FAULT_INJECTION=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_UFS_FAULT_INJECTION=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_IPC_LOGGING=y -CONFIG_QCOM_RTB=y -CONFIG_QCOM_RTB_SEPARATE_CPUS=y -CONFIG_FUNCTION_TRACER=y -CONFIG_PREEMPTIRQ_EVENTS=y -CONFIG_IRQSOFF_TRACER=y -CONFIG_PREEMPT_TRACER=y -CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_LKDTM=m -CONFIG_ATOMIC64_SELFTEST=m -CONFIG_TEST_USER_COPY=m -CONFIG_MEMTEST=y -CONFIG_BUG_ON_DATA_CORRUPTION=y -CONFIG_PID_IN_CONTEXTIDR=y -CONFIG_ARM64_STRICT_BREAK_BEFORE_MAKE=y -CONFIG_CORESIGHT=y -CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y -CONFIG_CORESIGHT_SOURCE_ETM4X=y -CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y -CONFIG_CORESIGHT_STM=y -CONFIG_CORESIGHT_CTI=y -CONFIG_CORESIGHT_TPDA=y -CONFIG_CORESIGHT_TPDM=y -CONFIG_CORESIGHT_HWEVENT=y -CONFIG_CORESIGHT_DUMMY=y -CONFIG_CORESIGHT_REMOTE_ETM=y -CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 -CONFIG_CORESIGHT_TGU=y -CONFIG_CORESIGHT_EVENT=y -CONFIG_PFK=y -CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y -CONFIG_SECURITY=y -CONFIG_HARDENED_USERCOPY=y -CONFIG_HARDENED_USERCOPY_PAGESPAN=y -CONFIG_FORTIFY_SOURCE=y -CONFIG_SECURITY_SELINUX=y -CONFIG_SECURITY_SMACK=y -CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_ANSI_CPRNG=y -CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y -CONFIG_CRYPTO_DEV_QCRYPTO=y -CONFIG_CRYPTO_DEV_QCEDEV=y -CONFIG_CRYPTO_DEV_QCOM_ICE=y -CONFIG_ARM64_CRYPTO=y -CONFIG_CRYPTO_SHA1_ARM64_CE=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y -CONFIG_XZ_DEC=y diff --git a/arch/arm64/configs/sm8150_defconfig b/arch/arm64/configs/sm8150_defconfig new file mode 120000 index 000000000000..4ff005a12e64 --- /dev/null +++ b/arch/arm64/configs/sm8150_defconfig @@ -0,0 +1 @@ +vendor/sm8150_defconfig \ No newline at end of file diff --git a/arch/arm64/configs/sdmshrike-perf_defconfig b/arch/arm64/configs/vendor/sdmshrike-perf_defconfig similarity index 100% rename from arch/arm64/configs/sdmshrike-perf_defconfig rename to arch/arm64/configs/vendor/sdmshrike-perf_defconfig diff --git a/arch/arm64/configs/sdmshrike_defconfig b/arch/arm64/configs/vendor/sdmshrike_defconfig similarity index 100% rename from arch/arm64/configs/sdmshrike_defconfig rename to arch/arm64/configs/vendor/sdmshrike_defconfig diff --git a/arch/arm64/configs/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig similarity index 100% rename from arch/arm64/configs/sdmsteppe-perf_defconfig rename to arch/arm64/configs/vendor/sdmsteppe-perf_defconfig diff --git a/arch/arm64/configs/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig similarity index 100% rename from arch/arm64/configs/sdmsteppe_defconfig rename to arch/arm64/configs/vendor/sdmsteppe_defconfig diff --git a/arch/arm64/configs/sm8150-auto-perf_defconfig b/arch/arm64/configs/vendor/sm8150-auto-perf_defconfig similarity index 100% rename from arch/arm64/configs/sm8150-auto-perf_defconfig rename to arch/arm64/configs/vendor/sm8150-auto-perf_defconfig diff --git a/arch/arm64/configs/sm8150-auto_defconfig b/arch/arm64/configs/vendor/sm8150-auto_defconfig similarity index 100% rename from arch/arm64/configs/sm8150-auto_defconfig rename to arch/arm64/configs/vendor/sm8150-auto_defconfig diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig new file mode 100644 index 000000000000..83d8f020491f --- /dev/null +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -0,0 +1,638 @@ +CONFIG_LOCALVERSION="-perf" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_SCHED_WALT=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_RCU_EXPERT=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_BLK_CGROUP=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_SCHED_CORE_CTL=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_SCHED_AUTOGROUP=y +CONFIG_SCHED_TUNE=y +CONFIG_DEFAULT_USE_ENERGY_AWARE=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_KALLSYMS_ALL=y +CONFIG_BPF_SYSCALL=y +# CONFIG_MEMBARRIER is not set +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB_FREELIST_RANDOM=y +CONFIG_SLAB_FREELIST_HARDENED=y +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_STRONG=y +CONFIG_REFCOUNT_FULL=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_FORCE=y +CONFIG_MODULE_SIG_SHA512=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_SM8150=y +CONFIG_PCI=y +CONFIG_PCI_MSM=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT=y +CONFIG_HZ_100=y +CONFIG_CMA=y +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +# CONFIG_HARDEN_BRANCH_PREDICTOR is not set +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +# CONFIG_ARM64_VHE is not set +CONFIG_RANDOMIZE_BASE=y +# CONFIG_EFI is not set +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_BOOST=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPVTI=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_BPF=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_SOCKET_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_NF_SOCKET_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_L2TP=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_MULTIQ=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_GACT=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_SKBEDIT=y +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +CONFIG_QRTR_MHI=y +CONFIG_RMNET_DATA=y +CONFIG_RMNET_DATA_FC=y +CONFIG_RMNET_DATA_DEBUG_PKT=y +CONFIG_SOCKEV_NLMCAST=y +CONFIG_BT=y +CONFIG_MSM_BT_POWER=y +CONFIG_CFG80211=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_RFKILL=y +CONFIG_NFC_NQ=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_CMA=y +CONFIG_MHI_BUS=y +CONFIG_MHI_QCOM=y +CONFIG_MHI_NETDEV=y +CONFIG_MHI_UCI=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_HDCP_QSEECOM=y +CONFIG_QSEECOM=y +CONFIG_UID_SYS_STATS=y +CONFIG_MEMORY_STATE_TIME=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_BONDING=y +CONFIG_DUMMY=y +CONFIG_TUN=y +CONFIG_SKY2=y +CONFIG_RMNET=y +CONFIG_SMSC911X=y +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_USBNET=y +CONFIG_WIL6210=m +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ST=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +CONFIG_SERIAL_MSM_GENI=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM_LEGACY=y +CONFIG_DIAG_CHAR=y +CONFIG_MSM_FASTCVPD=y +CONFIG_MSM_ADSPRPC=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_QCOM_GENI=y +CONFIG_SPI=y +CONFIG_SPI_QCOM_GENI=y +CONFIG_SPI_SPIDEV=y +CONFIG_SPMI=y +CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y +CONFIG_SPMI_SIMULATOR=y +CONFIG_PM8150_PMIC_SIMULATOR=y +CONFIG_PM8150B_PMIC_SIMULATOR=y +CONFIG_PM8150L_PMIC_SIMULATOR=y +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_PINCTRL_SM8150=y +CONFIG_GPIO_SYSFS=y +CONFIG_POWER_RESET_QCOM=y +CONFIG_QCOM_DLOAD_MODE=y +CONFIG_POWER_RESET_XGENE=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_QPNP_FG_GEN4=y +CONFIG_SMB1355_SLAVE_CHARGER=y +CONFIG_QPNP_SMB5=y +CONFIG_SMB1390_CHARGE_PUMP=y +CONFIG_THERMAL=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_LOW_LIMITS=y +CONFIG_CPU_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_QCOM_SPMI_TEMP_ALARM=y +CONFIG_THERMAL_TSENS=y +CONFIG_QTI_THERMAL_LIMITS_DCVS=y +CONFIG_QTI_VIRTUAL_SENSOR=y +CONFIG_QTI_AOP_REG_COOLING_DEVICE=y +CONFIG_QTI_QMI_COOLING_DEVICE=y +CONFIG_REGULATOR_COOLING_DEVICE=y +CONFIG_QTI_BCL_PMIC5=y +CONFIG_QTI_BCL_SOC_DRIVER=y +CONFIG_QTI_ADC_TM=y +CONFIG_MFD_I2C_PMIC=y +CONFIG_MFD_SPMI_PMIC=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_PROXY_CONSUMER=y +CONFIG_REGULATOR_QPNP_LCDB=y +CONFIG_REGULATOR_REFGEN=y +CONFIG_REGULATOR_RPMH=y +CONFIG_REGULATOR_STUB=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_FIXED_MINOR_RANGES=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SPECTRA_CAMERA=y +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_GOVERNORS=y +CONFIG_MSM_SDE_ROTATOR=y +CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y +CONFIG_MSM_NPU=y +CONFIG_DRM=y +CONFIG_DRM_MSM_REGISTER_LOGGING=y +CONFIG_DRM_SDE_EVTLOG_DEBUG=y +CONFIG_DRM_SDE_RSC=y +CONFIG_FB_ARMCLCD=y +CONFIG_BACKLIGHT_QCOM_SPMI_WLED=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_USB_AUDIO_QMI=y +CONFIG_SND_SOC=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_PLANTRONICS=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_MSM=y +CONFIG_USB_ISP1760=y +CONFIG_USB_ISP1760_HOST_ROLE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_QCOM_EMU_PHY=y +CONFIG_USB_MSM_SSPHY_QMP=y +CONFIG_MSM_HSUSB_PHY=y +CONFIG_DUAL_ROLE_USB_INTF=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=900 +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_MTP=y +CONFIG_USB_CONFIGFS_F_PTP=y +CONFIG_USB_CONFIGFS_F_ACC=y +CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y +CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_DIAG=y +CONFIG_USB_CONFIGFS_F_CDEV=y +CONFIG_USB_CONFIGFS_F_CCID=y +CONFIG_USB_CONFIGFS_F_GSI=y +CONFIG_USB_CONFIGFS_F_QDSS=y +CONFIG_USB_PD_POLICY=y +CONFIG_QPNP_USB_PDPHY=y +CONFIG_MMC=y +CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_DEFERRED_RESUME=y +CONFIG_MMC_TEST=y +CONFIG_MMC_PARANOID_SD_INIT=y +CONFIG_MMC_CLKGATE=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_QPNP_FLASH_V2=y +CONFIG_LEDS_QPNP_HAPTICS=y +CONFIG_LEDS_QTI_TRI_LED=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_EDAC=y +CONFIG_EDAC_KRYO_ARM64=y +CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE=y +CONFIG_EDAC_KRYO_ARM64_PANIC_ON_UE=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_QPNP=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_GPI_DMA=y +CONFIG_UIO=y +CONFIG_UIO_MSM_SHAREDMEM=y +CONFIG_STAGING=y +CONFIG_ASHMEM=y +CONFIG_ION=y +CONFIG_QCOM_GENI_SE=y +CONFIG_QPNP_REVID=y +CONFIG_SPS=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_USB_BAM=y +CONFIG_IPA3=y +CONFIG_IPA_WDI_UNIFIED_API=y +CONFIG_RMNET_IPA3=y +CONFIG_RNDIS_IPA=y +CONFIG_IPA3_MHI_PROXY=y +CONFIG_IPA_UT=y +CONFIG_MSM_11AD=m +CONFIG_SEEMP_CORE=y +CONFIG_QCOM_MDSS_PLL=y +CONFIG_SPMI_PMIC_CLKDIV=y +CONFIG_MSM_CLK_AOP_QMP=y +CONFIG_MSM_GCC_SM8150=y +CONFIG_MSM_NPUCC_SM8150=y +CONFIG_MSM_VIDEOCC_SM8150=y +CONFIG_MSM_CAMCC_SM8150=y +CONFIG_CLOCK_CPU_OSM=y +CONFIG_MSM_DISPCC_SM8150=y +CONFIG_MSM_DEBUGCC_SM8150=y +CONFIG_MSM_CLK_RPMH=y +CONFIG_MSM_GPUCC_SM8150=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_QCOM_APCS_IPC=y +CONFIG_MSM_QMP=y +CONFIG_IOMMU_IO_PGTABLE_FAST=y +CONFIG_ARM_SMMU=y +CONFIG_QCOM_LAZY_MAPPING=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_DEBUG_TRACKING=y +CONFIG_IOMMU_TESTS=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_GLINK_SPSS=y +CONFIG_RPMSG_QCOM_GLINK_SPI=y +CONFIG_QCOM_CPUSS_DUMP=y +CONFIG_QCOM_RUN_QUEUE_STATS=y +CONFIG_QCOM_LLCC=y +CONFIG_QCOM_SM8150_LLCC=y +CONFIG_QCOM_LLCC_PERFMON=m +CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_MEMORY_DUMP_V2=y +CONFIG_QCOM_WATCHDOG_V2=y +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_QCOM_SMP2P=y +CONFIG_MSM_SERVICE_LOCATOR=y +CONFIG_MSM_SERVICE_NOTIFIER=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_QCOM_DCC_V2=y +CONFIG_QCOM_SECURE_BUFFER=y +CONFIG_ICNSS=y +CONFIG_ICNSS_QMI=y +CONFIG_QCOM_EUD=y +CONFIG_QCOM_MINIDUMP=y +CONFIG_QCOM_BUS_SCALING=y +CONFIG_QCOM_BUS_CONFIG_RPMH=y +CONFIG_QCOM_COMMAND_DB=y +CONFIG_QCOM_EARLY_RANDOM=y +CONFIG_MSM_SPSS_UTILS=y +CONFIG_MSM_SPCOM=y +CONFIG_QTI_RPMH_API=y +CONFIG_QSEE_IPC_IRQ_BRIDGE=y +CONFIG_QCOM_GLINK=y +CONFIG_QCOM_GLINK_PKT=y +CONFIG_QCOM_QDSS_BRIDGE=y +CONFIG_QTI_RPM_STATS_LOG=y +CONFIG_MSM_CDSP_LOADER=y +CONFIG_QCOM_SMCINVOKE=y +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_PM=y +CONFIG_MSM_QBT1000=y +CONFIG_QCOM_FSA4480_I2C=y +CONFIG_MSM_PERFORMANCE=y +CONFIG_QMP_DEBUGFS_CLIENT=y +CONFIG_QCOM_SMP2P_SLEEPSTATE=y +CONFIG_DEVFREQ_GOV_PASSIVE=y +CONFIG_QCOM_BIMC_BWMON=y +CONFIG_ARM_MEMLAT_MON=y +CONFIG_QCOMCCI_HWMON=y +CONFIG_QCOM_M4M_HWMON=y +CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y +CONFIG_DEVFREQ_GOV_MEMLAT=y +CONFIG_DEVFREQ_SIMPLE_DEV=y +CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_EXTCON_USB_GPIO=y +CONFIG_IIO=y +CONFIG_QCOM_SPMI_ADC5=y +CONFIG_PWM=y +CONFIG_PWM_QTI_LPG=y +CONFIG_QCOM_KGSL=y +CONFIG_ARM_GIC_V3_ACL=y +CONFIG_ARM_DSU_PMU=y +CONFIG_QCOM_LLCC_PMU=y +CONFIG_RAS=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_NVMEM_SPMI_SDAM=y +CONFIG_SENSORS_SSC=y +CONFIG_ESOC=y +CONFIG_ESOC_DEV=y +CONFIG_ESOC_CLIENT=y +CONFIG_ESOC_MDM_4x=y +CONFIG_ESOC_MDM_DRV=y +CONFIG_ESOC_MDM_DBG_ENG=y +CONFIG_MSM_TZ_LOG=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_EXT4_FS_ENCRYPTION=y +CONFIG_EXT4_FS_ICE_ENCRYPTION=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_FUSE_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_ECRYPT_FS=y +CONFIG_ECRYPT_FS_MESSAGING=y +CONFIG_SDCARD_FS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_IPC_LOGGING=y +CONFIG_DEBUG_ALIGN_RODATA=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +CONFIG_CORESIGHT_HWEVENT=y +CONFIG_CORESIGHT_DUMMY=y +CONFIG_CORESIGHT_REMOTE_ETM=y +CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 +CONFIG_CORESIGHT_TGU=y +CONFIG_CORESIGHT_EVENT=y +CONFIG_PFK=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_HARDENED_USERCOPY=y +CONFIG_FORTIFY_SOURCE=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SMACK=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig new file mode 100644 index 000000000000..3b919f593861 --- /dev/null +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -0,0 +1,720 @@ +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_SCHED_WALT=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_RCU_EXPERT=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_BLK_CGROUP=y +CONFIG_DEBUG_BLK_CGROUP=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_CGROUP_DEBUG=y +CONFIG_SCHED_CORE_CTL=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_SCHED_AUTOGROUP=y +CONFIG_SCHED_TUNE=y +CONFIG_DEFAULT_USE_ENERGY_AWARE=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KALLSYMS_ALL=y +CONFIG_BPF_SYSCALL=y +# CONFIG_MEMBARRIER is not set +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB_FREELIST_RANDOM=y +CONFIG_SLAB_FREELIST_HARDENED=y +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_STRONG=y +CONFIG_REFCOUNT_FULL=y +CONFIG_PANIC_ON_REFCOUNT_ERROR=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_FORCE=y +CONFIG_MODULE_SIG_SHA512=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_SM8150=y +CONFIG_PCI=y +CONFIG_PCI_MSM=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_PREEMPT=y +CONFIG_HZ_100=y +CONFIG_CLEANCACHE=y +CONFIG_CMA=y +CONFIG_CMA_DEBUGFS=y +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +# CONFIG_HARDEN_BRANCH_PREDICTOR is not set +CONFIG_PRINT_VMEMLAYOUT=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +# CONFIG_ARM64_VHE is not set +CONFIG_RANDOMIZE_BASE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_DEBUG=y +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_BOOST=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPVTI=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_BPF=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_SOCKET_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_NF_SOCKET_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_L2TP=y +CONFIG_L2TP_DEBUGFS=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_MULTIQ=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_GACT=y +CONFIG_NET_ACT_MIRRED=y +CONFIG_NET_ACT_SKBEDIT=y +CONFIG_DNS_RESOLVER=y +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +CONFIG_QRTR_MHI=y +CONFIG_RMNET_DATA=y +CONFIG_RMNET_DATA_FC=y +CONFIG_RMNET_DATA_DEBUG_PKT=y +CONFIG_SOCKEV_NLMCAST=y +CONFIG_BT=y +CONFIG_MSM_BT_POWER=y +CONFIG_CFG80211=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +# CONFIG_CFG80211_CRDA_SUPPORT is not set +CONFIG_RFKILL=y +CONFIG_NFC_NQ=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_CMA=y +CONFIG_MHI_BUS=y +CONFIG_MHI_DEBUG=y +CONFIG_MHI_QCOM=y +CONFIG_MHI_NETDEV=y +CONFIG_MHI_UCI=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_HDCP_QSEECOM=y +CONFIG_QSEECOM=y +CONFIG_UID_SYS_STATS=y +CONFIG_MEMORY_STATE_TIME=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y +CONFIG_SCSI_UFSHCD_CMD_LOGGING=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_BONDING=y +CONFIG_DUMMY=y +CONFIG_TUN=y +CONFIG_RMNET=y +CONFIG_PHYLIB=y +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_WIL6210=m +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ST=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_MSM_GENI=y +CONFIG_SERIAL_MSM_GENI_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM_LEGACY=y +CONFIG_DIAG_CHAR=y +CONFIG_MSM_FASTCVPD=y +CONFIG_MSM_ADSPRPC=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_QCOM_GENI=y +CONFIG_SPI=y +CONFIG_SPI_QCOM_GENI=y +CONFIG_SPI_SPIDEV=y +CONFIG_SPMI=y +CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y +CONFIG_SPMI_SIMULATOR=y +CONFIG_PM8150_PMIC_SIMULATOR=y +CONFIG_PM8150B_PMIC_SIMULATOR=y +CONFIG_PM8150L_PMIC_SIMULATOR=y +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_PINCTRL_SM8150=y +CONFIG_GPIO_SYSFS=y +CONFIG_POWER_RESET_QCOM=y +CONFIG_QCOM_DLOAD_MODE=y +CONFIG_POWER_RESET_XGENE=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_QPNP_FG_GEN4=y +CONFIG_SMB1355_SLAVE_CHARGER=y +CONFIG_QPNP_SMB5=y +CONFIG_SMB1390_CHARGE_PUMP=y +CONFIG_THERMAL=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_LOW_LIMITS=y +CONFIG_CPU_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_QCOM_SPMI_TEMP_ALARM=y +CONFIG_THERMAL_TSENS=y +CONFIG_QTI_THERMAL_LIMITS_DCVS=y +CONFIG_QTI_VIRTUAL_SENSOR=y +CONFIG_QTI_AOP_REG_COOLING_DEVICE=y +CONFIG_QTI_QMI_COOLING_DEVICE=y +CONFIG_REGULATOR_COOLING_DEVICE=y +CONFIG_QTI_BCL_PMIC5=y +CONFIG_QTI_BCL_SOC_DRIVER=y +CONFIG_QTI_ADC_TM=y +CONFIG_MFD_I2C_PMIC=y +CONFIG_MFD_SPMI_PMIC=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_PROXY_CONSUMER=y +CONFIG_REGULATOR_QPNP_LCDB=y +CONFIG_REGULATOR_REFGEN=y +CONFIG_REGULATOR_RPMH=y +CONFIG_REGULATOR_STUB=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_FIXED_MINOR_RANGES=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SPECTRA_CAMERA=y +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_GOVERNORS=y +CONFIG_MSM_SDE_ROTATOR=y +CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y +CONFIG_MSM_NPU=y +CONFIG_DRM=y +CONFIG_DRM_MSM_REGISTER_LOGGING=y +CONFIG_DRM_SDE_EVTLOG_DEBUG=y +CONFIG_DRM_SDE_RSC=y +CONFIG_FB_VIRTUAL=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_QCOM_SPMI_WLED=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_USB_AUDIO_QMI=y +CONFIG_SND_SOC=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_PLANTRONICS=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_MSM=y +CONFIG_USB_ISP1760=y +CONFIG_USB_ISP1760_HOST_ROLE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_QCOM_EMU_PHY=y +CONFIG_USB_MSM_SSPHY_QMP=y +CONFIG_MSM_HSUSB_PHY=y +CONFIG_DUAL_ROLE_USB_INTF=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=900 +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_MTP=y +CONFIG_USB_CONFIGFS_F_PTP=y +CONFIG_USB_CONFIGFS_F_ACC=y +CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y +CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_DIAG=y +CONFIG_USB_CONFIGFS_F_CDEV=y +CONFIG_USB_CONFIGFS_F_CCID=y +CONFIG_USB_CONFIGFS_F_GSI=y +CONFIG_USB_CONFIGFS_F_QDSS=y +CONFIG_USB_PD_POLICY=y +CONFIG_QPNP_USB_PDPHY=y +CONFIG_MMC=y +CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_DEFERRED_RESUME=y +CONFIG_MMC_TEST=y +CONFIG_MMC_RING_BUFFER=y +CONFIG_MMC_PARANOID_SD_INIT=y +CONFIG_MMC_CLKGATE=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_QPNP_FLASH_V2=y +CONFIG_LEDS_QPNP_HAPTICS=y +CONFIG_LEDS_QTI_TRI_LED=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_EDAC=y +CONFIG_EDAC_KRYO_ARM64=y +CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE=y +CONFIG_EDAC_KRYO_ARM64_PANIC_ON_UE=y +CONFIG_EDAC_QCOM_LLCC=y +CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE=y +CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_QPNP=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_GPI_DMA=y +CONFIG_QCOM_GPI_DMA_DEBUG=y +CONFIG_UIO=y +CONFIG_UIO_MSM_SHAREDMEM=y +CONFIG_STAGING=y +CONFIG_ASHMEM=y +CONFIG_ION=y +CONFIG_QCOM_GENI_SE=y +CONFIG_QPNP_REVID=y +CONFIG_SPS=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_USB_BAM=y +CONFIG_IPA3=y +CONFIG_IPA_WDI_UNIFIED_API=y +CONFIG_RMNET_IPA3=y +CONFIG_RNDIS_IPA=y +CONFIG_IPA3_MHI_PROXY=y +CONFIG_IPA_UT=y +CONFIG_MSM_11AD=m +CONFIG_SEEMP_CORE=y +CONFIG_QCOM_MDSS_PLL=y +CONFIG_SPMI_PMIC_CLKDIV=y +CONFIG_MSM_CLK_AOP_QMP=y +CONFIG_MSM_GCC_SM8150=y +CONFIG_MSM_NPUCC_SM8150=y +CONFIG_MSM_VIDEOCC_SM8150=y +CONFIG_MSM_CAMCC_SM8150=y +CONFIG_CLOCK_CPU_OSM=y +CONFIG_MSM_DISPCC_SM8150=y +CONFIG_MSM_DEBUGCC_SM8150=y +CONFIG_MSM_CLK_RPMH=y +CONFIG_MSM_GPUCC_SM8150=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_QCOM_APCS_IPC=y +CONFIG_MSM_QMP=y +CONFIG_IOMMU_IO_PGTABLE_FAST=y +CONFIG_ARM_SMMU=y +CONFIG_QCOM_LAZY_MAPPING=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_DEBUG_TRACKING=y +CONFIG_IOMMU_TESTS=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_GLINK_SPSS=y +CONFIG_RPMSG_QCOM_GLINK_SPI=y +CONFIG_QCOM_CPUSS_DUMP=y +CONFIG_QCOM_RUN_QUEUE_STATS=y +CONFIG_QCOM_LLCC=y +CONFIG_QCOM_SM8150_LLCC=y +CONFIG_QCOM_LLCC_PERFMON=m +CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_MEMORY_DUMP_V2=y +CONFIG_QCOM_WATCHDOG_V2=y +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_QCOM_WDOG_IPI_ENABLE=y +CONFIG_QCOM_SMP2P=y +CONFIG_MSM_SERVICE_LOCATOR=y +CONFIG_MSM_SERVICE_NOTIFIER=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_MSM_CORE_HANG_DETECT=y +CONFIG_QCOM_DCC_V2=y +CONFIG_MSM_GLADIATOR_HANG_DETECT=y +CONFIG_QCOM_SECURE_BUFFER=y +CONFIG_ICNSS=y +CONFIG_ICNSS_DEBUG=y +CONFIG_ICNSS_QMI=y +CONFIG_QCOM_EUD=y +CONFIG_QCOM_MINIDUMP=y +CONFIG_QCOM_BUS_SCALING=y +CONFIG_QCOM_BUS_CONFIG_RPMH=y +CONFIG_QCOM_COMMAND_DB=y +CONFIG_QCOM_EARLY_RANDOM=y +CONFIG_MSM_SPSS_UTILS=y +CONFIG_MSM_SPCOM=y +CONFIG_QTI_RPMH_API=y +CONFIG_QSEE_IPC_IRQ_BRIDGE=y +CONFIG_QCOM_GLINK=y +CONFIG_QCOM_GLINK_PKT=y +CONFIG_QCOM_QDSS_BRIDGE=y +CONFIG_QTI_RPM_STATS_LOG=y +CONFIG_MSM_CDSP_LOADER=y +CONFIG_QCOM_SMCINVOKE=y +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_PM=y +CONFIG_MSM_QBT1000=y +CONFIG_QCOM_FSA4480_I2C=y +CONFIG_MSM_PERFORMANCE=y +CONFIG_QMP_DEBUGFS_CLIENT=y +CONFIG_QCOM_SMP2P_SLEEPSTATE=y +CONFIG_DEVFREQ_GOV_PASSIVE=y +CONFIG_QCOM_BIMC_BWMON=y +CONFIG_ARM_MEMLAT_MON=y +CONFIG_QCOMCCI_HWMON=y +CONFIG_QCOM_M4M_HWMON=y +CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y +CONFIG_DEVFREQ_GOV_MEMLAT=y +CONFIG_DEVFREQ_SIMPLE_DEV=y +CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_EXTCON_USB_GPIO=y +CONFIG_IIO=y +CONFIG_QCOM_SPMI_ADC5=y +CONFIG_PWM=y +CONFIG_PWM_QTI_LPG=y +CONFIG_QCOM_KGSL=y +CONFIG_ARM_GIC_V3_ACL=y +CONFIG_PHY_XGENE=y +CONFIG_ARM_DSU_PMU=y +CONFIG_QCOM_LLCC_PMU=y +CONFIG_RAS=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_NVMEM_SPMI_SDAM=y +CONFIG_SENSORS_SSC=y +CONFIG_ESOC=y +CONFIG_ESOC_DEV=y +CONFIG_ESOC_CLIENT=y +CONFIG_ESOC_DEBUG=y +CONFIG_ESOC_MDM_4x=y +CONFIG_ESOC_MDM_DRV=y +CONFIG_ESOC_MDM_DBG_ENG=y +CONFIG_MSM_TZ_LOG=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_EXT4_FS_ENCRYPTION=y +CONFIG_EXT4_FS_ICE_ENCRYPTION=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_FUSE_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_EFIVAR_FS=y +CONFIG_ECRYPT_FS=y +CONFIG_ECRYPT_FS_MESSAGING=y +CONFIG_SDCARD_FS=y +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_PAGE_OWNER=y +CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y +CONFIG_DEBUG_SECTION_MISMATCH=y +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_PAGEALLOC=y +CONFIG_SLUB_DEBUG_PANIC_ON=y +CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y +CONFIG_PAGE_POISONING=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_WORK=y +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_SLUB_DEBUG_ON=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SOFTLOCKUP_DETECTOR=y +CONFIG_WQ_WATCHDOG=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANIC_ON_SCHED_BUG=y +CONFIG_PANIC_ON_RT_THROTTLING=y +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_STACK_END_CHECK=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_LOCK_TORTURE_TEST=m +CONFIG_DEBUG_SG=y +CONFIG_DEBUG_NOTIFIERS=y +CONFIG_DEBUG_CREDENTIALS=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_FAULT_INJECTION=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_UFS_FAULT_INJECTION=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_IPC_LOGGING=y +CONFIG_QCOM_RTB=y +CONFIG_QCOM_RTB_SEPARATE_CPUS=y +CONFIG_FUNCTION_TRACER=y +CONFIG_PREEMPTIRQ_EVENTS=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_PREEMPT_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LKDTM=m +CONFIG_ATOMIC64_SELFTEST=m +CONFIG_TEST_USER_COPY=m +CONFIG_MEMTEST=y +CONFIG_BUG_ON_DATA_CORRUPTION=y +CONFIG_PID_IN_CONTEXTIDR=y +CONFIG_ARM64_STRICT_BREAK_BEFORE_MAKE=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_SOURCE_ETM4X=y +CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +CONFIG_CORESIGHT_HWEVENT=y +CONFIG_CORESIGHT_DUMMY=y +CONFIG_CORESIGHT_REMOTE_ETM=y +CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 +CONFIG_CORESIGHT_TGU=y +CONFIG_CORESIGHT_EVENT=y +CONFIG_PFK=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_HARDENED_USERCOPY=y +CONFIG_HARDENED_USERCOPY_PAGESPAN=y +CONFIG_FORTIFY_SOURCE=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SMACK=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_XZ_DEC=y -- GitLab From 472b565b16496a83eca6320a4bd022cc8471b038 Mon Sep 17 00:00:00 2001 From: Bryan Huntsman Date: Mon, 4 Jun 2018 15:16:23 -0700 Subject: [PATCH 0293/1299] scripts/build-all: remove pattern-based defconfig detection All the defconfigs we care about should be in arch/arm[64]/configs/vendor/ so remove the pattern-based detection logic. Change-Id: I1359db11caffb618d8fb44e02ea2c08efb4041fa Signed-off-by: Bryan Huntsman --- scripts/build-all.py | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/scripts/build-all.py b/scripts/build-all.py index 7f2a2764dc73..ec2f5e64e2e1 100755 --- a/scripts/build-all.py +++ b/scripts/build-all.py @@ -287,29 +287,6 @@ class Builder(): def scan_configs(): """Get the full list of defconfigs appropriate for this tree.""" names = [] - arch_pats = ( - r'[fm]sm[0-9]*_defconfig', - r'apq*_defconfig', - r'qsd*_defconfig', - r'mpq*_defconfig', - r'sdm*_defconfig', - r'sdx*_defconfig', - ) - arch64_pats = ( - r'msm*_defconfig', - r'sm*_defconfig', - r'sdm*_defconfig', - r'sdx*_defconfig', - ) - for p in arch_pats: - for n in glob.glob('arch/arm/configs/' + p): - name = os.path.basename(n)[:-10] + "-llvm" - names.append(Builder(name, n)) - if 'CROSS_COMPILE64' in os.environ: - for p in arch64_pats: - for n in glob.glob('arch/arm64/configs/' + p): - name = os.path.basename(n)[:-10] + "-llvm" + "-64" - names.append(Builder(name, n)) for defconfig in glob.glob('arch/arm*/configs/vendor/*_defconfig'): target = os.path.basename(defconfig)[:-10] name = target + "-llvm" -- GitLab From 308cb81a9a9501dcc9c60b0f3665e305e4b8e6f9 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Wed, 13 Jun 2018 15:53:04 -0700 Subject: [PATCH 0294/1299] power: qpnp-fg-gen4: Change profile compare length Currently, we're reading the entire profile partition to see if the profile loaded onto FG SRAM is matching with the profile available from battery profile. Based on the parameters defined in the battery profile, some of the words in the profile region would be modified after loading the profile. Hence reduce the profile compare length to 24 bytes to determine whether the profile is different. Change-Id: Id156f837bd6b9d330f0bc251e4dbbb9e2f054ed6 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/qpnp-fg-gen4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 7def4a238a2f..d7b35ca86040 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -33,7 +33,7 @@ #define FG_SRAM_LEN 960 #define PROFILE_LEN 416 -#define PROFILE_COMP_LEN 208 +#define PROFILE_COMP_LEN 24 #define KI_COEFF_SOC_LEVELS 3 #define KI_COEFF_MAX 15564 #define SLOPE_LIMIT_NUM_COEFFS 4 -- GitLab From b8fbbafb6785c5f6b78e1bc1ede58102dceeec47 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Wed, 13 Jun 2018 13:26:15 -0700 Subject: [PATCH 0295/1299] power: qpnp-fg-gen4: Disable Rslow compensation for PM8150B v1 As per the hardware recommendation, disable Rslow compensation for PM8150B v1 to prevent Rslow flooring. Change-Id: Ic579450050b2fc47cc20def8e0f1f43d97ef27d4 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-core.h | 1 + drivers/power/supply/qcom/qpnp-fg-gen4.c | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 4b77a2d03025..3561f1c57217 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -257,6 +257,7 @@ enum wa_flags { PMI8998_V1_REV_WA = BIT(0), PM660_TSMC_OSC_WA = BIT(1), PM8150B_V1_DMA_WA = BIT(2), + PM8150B_V1_RSLOW_COMP_WA = BIT(3), }; enum slope_limit_status { diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index d7b35ca86040..eabca93eb47f 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -90,6 +90,8 @@ #define VBATT_LOW_OFFSET 1 #define PROFILE_LOAD_WORD 65 #define PROFILE_LOAD_OFFSET 0 +#define RSLOW_CONFIG_WORD 241 +#define RSLOW_CONFIG_OFFSET 0 #define NOM_CAP_WORD 271 #define NOM_CAP_OFFSET 0 #define RCONN_WORD 275 @@ -2638,6 +2640,18 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip) } } + if (fg->wa_flags & PM8150B_V1_RSLOW_COMP_WA) { + val = 0; + mask = BIT(1); + rc = fg_sram_masked_write(fg, RSLOW_CONFIG_WORD, + RSLOW_CONFIG_OFFSET, mask, val, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing RSLOW_CONFIG_WORD, rc=%d\n", + rc); + return rc; + } + } + rc = restore_cycle_count(chip->counter); if (rc < 0) { pr_err("Error in restoring cycle_count, rc=%d\n", rc); @@ -2833,8 +2847,10 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip) fg->version = GEN4_FG; fg->use_dma = true; fg->sp = pm8150_sram_params; - if (fg->pmic_rev_id->rev4 == PM8150B_V1P0_REV4) + if (fg->pmic_rev_id->rev4 == PM8150B_V1P0_REV4) { fg->wa_flags |= PM8150B_V1_DMA_WA; + fg->wa_flags |= PM8150B_V1_RSLOW_COMP_WA; + } break; default: return -EINVAL; -- GitLab From 069bda8581508c0c89d84444764dafc23a66e00d Mon Sep 17 00:00:00 2001 From: Vamshi Krishna B V Date: Wed, 6 Jun 2018 14:02:11 +0530 Subject: [PATCH 0296/1299] power_supply: Add SOH, ESR_Actual and ESR_Nominal properties Add State of Health (SOH) property which indicates battery state of health based on ESR and learned capacity. Also add ESR_Actual and ESR_Nominal for SOH calculations. CRs-Fixed: 2259538 Change-Id: Icefa262627296b5dc232ea706a8253cb854288b6 Signed-off-by: Vamshi Krishna B V Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/power_supply_sysfs.c | 3 +++ include/linux/power_supply.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index 616b450119eb..4885c669b937 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -369,6 +369,9 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(recharge_soc), POWER_SUPPLY_ATTR(hvdcp_opti_allowed), POWER_SUPPLY_ATTR(smb_en_mode), + POWER_SUPPLY_ATTR(esr_actual), + POWER_SUPPLY_ATTR(esr_nominal), + POWER_SUPPLY_ATTR(soh), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index a4fe711aea33..4ed565058a7f 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -295,6 +295,9 @@ enum power_supply_property { POWER_SUPPLY_PROP_RECHARGE_SOC, POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED, POWER_SUPPLY_PROP_SMB_EN_MODE, + POWER_SUPPLY_PROP_ESR_ACTUAL, + POWER_SUPPLY_PROP_ESR_NOMINAL, + POWER_SUPPLY_PROP_SOH, /* Local extensions of type int64_t */ POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, /* Properties of type `const char *' */ -- GitLab From a545179889342e59a4f2b5603ca699382bc7001a Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 12 Jun 2018 18:45:46 -0700 Subject: [PATCH 0297/1299] power: qpnp-fg-gen4: Add support for SOH calculation Battery SOH (State of Health) is calculated based on ESR_ACTUAL and ESR_NOMINAL properties. SOH is calculated based on them and written back. Add support for it. Change-Id: Iaa83709dcf066470d9a501c8784d0e72dad3ec8d Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-core.h | 3 + drivers/power/supply/qcom/qpnp-fg-gen4.c | 86 ++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 3561f1c57217..77aafa95dda1 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -82,6 +82,7 @@ #define DEBUG_BATT_SOC 67 #define BATT_MISS_SOC 50 +#define ESR_SOH_SOC 50 #define EMPTY_SOC 0 enum prof_load_status { @@ -165,6 +166,8 @@ enum fg_sram_param_id { FG_SRAM_VOLTAGE_PRED, FG_SRAM_OCV, FG_SRAM_ESR, + FG_SRAM_ESR_MDL, + FG_SRAM_ESR_ACT, FG_SRAM_RSLOW, FG_SRAM_ALG_FLAGS, FG_SRAM_CC_SOC, diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index eabca93eb47f..1ea5899400eb 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -104,6 +104,10 @@ #define PROFILE_INTEGRITY_OFFSET 0 #define ESR_WORD 331 #define ESR_OFFSET 0 +#define ESR_MDL_WORD 335 +#define ESR_MDL_OFFSET 0 +#define ESR_ACT_WORD 342 +#define ESR_ACT_OFFSET 0 #define RSLOW_WORD 368 #define RSLOW_OFFSET 0 #define OCV_WORD 417 @@ -163,6 +167,9 @@ struct fg_gen4_chip { struct ttf *ttf; char batt_profile[PROFILE_LEN]; int recharge_soc_thr; + int esr_actual; + int esr_nominal; + int soh; bool ki_coeff_dischg_en; bool slope_limit_en; }; @@ -202,6 +209,10 @@ static struct fg_sram_param pm8150_sram_params[] = { fg_decode_voltage_15b), PARAM(ESR, ESR_WORD, ESR_OFFSET, 2, 1000, 244141, 0, fg_encode_default, fg_decode_value_16b), + PARAM(ESR_MDL, ESR_MDL_WORD, ESR_MDL_OFFSET, 2, 1000, 244141, 0, + fg_encode_default, fg_decode_value_16b), + PARAM(ESR_ACT, ESR_ACT_WORD, ESR_ACT_OFFSET, 2, 1000, 244141, 0, + fg_encode_default, fg_decode_value_16b), PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 1000, 244141, 0, NULL, fg_decode_value_16b), PARAM(CC_SOC, CC_SOC_WORD, CC_SOC_OFFSET, 4, 1, 1, 0, NULL, @@ -1218,6 +1229,53 @@ static void get_batt_psy_props(struct fg_dev *fg) } } +static int fg_gen4_esr_soh_update(struct fg_dev *fg) +{ + struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); + int rc, msoc, esr_uohms; + + if (!fg->soc_reporting_ready || fg->battery_missing) { + chip->esr_actual = -EINVAL; + chip->esr_nominal = -EINVAL; + return 0; + } + + if (fg->charge_status == POWER_SUPPLY_STATUS_CHARGING) { + rc = fg_get_msoc(fg, &msoc); + if (rc < 0) { + pr_err("Error in getting msoc, rc=%d\n", rc); + return rc; + } + + if (msoc == ESR_SOH_SOC) { + rc = fg_get_sram_prop(fg, FG_SRAM_ESR_ACT, &esr_uohms); + if (rc < 0) { + pr_err("Error in getting esr_actual, rc=%d\n", + rc); + return rc; + } + chip->esr_actual = esr_uohms; + + rc = fg_get_sram_prop(fg, FG_SRAM_ESR_MDL, &esr_uohms); + if (rc < 0) { + pr_err("Error in getting esr_nominal, rc=%d\n", + rc); + chip->esr_actual = -EINVAL; + return rc; + } + chip->esr_nominal = esr_uohms; + + fg_dbg(fg, FG_STATUS, "esr_actual: %d esr_nominal: %d\n", + chip->esr_actual, chip->esr_nominal); + + if (fg->batt_psy) + power_supply_changed(fg->batt_psy); + } + } + + return 0; +} + static int fg_gen4_update_maint_soc(struct fg_dev *fg) { struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); @@ -1666,6 +1724,10 @@ static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data) if (rc < 0) pr_err("Error in charge_full_update, rc=%d\n", rc); + rc = fg_gen4_esr_soh_update(fg); + if (rc < 0) + pr_err("Error in updating ESR for SOH, rc=%d\n", rc); + rc = fg_gen4_update_maint_soc(fg); if (rc < 0) pr_err("Error in updating maint_soc, rc=%d\n", rc); @@ -2044,6 +2106,12 @@ static int fg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_RESISTANCE: rc = fg_get_battery_resistance(fg, &pval->intval); break; + case POWER_SUPPLY_PROP_ESR_ACTUAL: + pval->intval = chip->esr_actual; + break; + case POWER_SUPPLY_PROP_ESR_NOMINAL: + pval->intval = chip->esr_nominal; + break; case POWER_SUPPLY_PROP_VOLTAGE_OCV: rc = fg_get_sram_prop(fg, FG_SRAM_OCV, &pval->intval); break; @@ -2086,6 +2154,9 @@ static int fg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_SOC_REPORTING_READY: pval->intval = fg->soc_reporting_ready; break; + case POWER_SUPPLY_PROP_SOH: + pval->intval = chip->soh; + break; case POWER_SUPPLY_PROP_DEBUG_BATTERY: pval->intval = is_debug_batt_id(fg); break; @@ -2167,6 +2238,15 @@ static int fg_psy_set_property(struct power_supply *psy, return -EINVAL; } break; + case POWER_SUPPLY_PROP_ESR_ACTUAL: + chip->esr_actual = pval->intval; + break; + case POWER_SUPPLY_PROP_ESR_NOMINAL: + chip->esr_nominal = pval->intval; + break; + case POWER_SUPPLY_PROP_SOH: + chip->soh = pval->intval; + break; default: break; } @@ -2181,6 +2261,9 @@ static int fg_property_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_CHARGE_FULL: case POWER_SUPPLY_PROP_CC_STEP: case POWER_SUPPLY_PROP_CC_STEP_SEL: + case POWER_SUPPLY_PROP_ESR_ACTUAL: + case POWER_SUPPLY_PROP_ESR_NOMINAL: + case POWER_SUPPLY_PROP_SOH: return 1; default: break; @@ -2198,6 +2281,8 @@ static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_RESISTANCE_ID, POWER_SUPPLY_PROP_RESISTANCE, + POWER_SUPPLY_PROP_ESR_ACTUAL, + POWER_SUPPLY_PROP_ESR_NOMINAL, POWER_SUPPLY_PROP_BATTERY_TYPE, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, @@ -2207,6 +2292,7 @@ static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_CHARGE_COUNTER_SHADOW, POWER_SUPPLY_PROP_CYCLE_COUNTS, POWER_SUPPLY_PROP_SOC_REPORTING_READY, + POWER_SUPPLY_PROP_SOH, POWER_SUPPLY_PROP_DEBUG_BATTERY, POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, -- GitLab From f6e40f20738b1e77370ffa81a90e3948ecf6f044 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Wed, 13 Jun 2018 11:54:48 -0700 Subject: [PATCH 0298/1299] power: qpnp-fg-gen4: Configure Rslow coefficients based on temperature Based on the Rslow coefficients specified under the battery profile, add support to configure it in GEN4 FG driver. When the battery temperature goes below 0 C, apply the coefficients for low temperature. Else, apply the normal coefficients. Change-Id: If769b2515de972cb4db871e5b79a49bb70310875 Signed-off-by: Subbaraman Narayanamurthy --- .../bindings/batterydata/batterydata.txt | 6 + drivers/power/supply/qcom/fg-core.h | 2 + drivers/power/supply/qcom/qpnp-fg-gen4.c | 161 +++++++++++++++--- 3 files changed, 143 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/batterydata/batterydata.txt b/Documentation/devicetree/bindings/batterydata/batterydata.txt index 9d80eb9d1859..8cc89e3e62c1 100644 --- a/Documentation/devicetree/bindings/batterydata/batterydata.txt +++ b/Documentation/devicetree/bindings/batterydata/batterydata.txt @@ -69,6 +69,12 @@ Profile data node optional properties: size 5. - qcom,therm-center-offset: Specifies the resistor divide ratio between pull-up resistor and the thermistor for GEN4 FG. +- qcom,rslow-normal-coeffs: Array of Rslow coefficients that will be applied + when the battery temperature is greater than 0 degree + Celsius for GEN4 FG. This should be exactly of size 4. +- qcom,rslow-low-coeffs: Array of Rslow coefficients that will be applied + when the battery temperature is lower than 0 degree + Celsius for GEN4 FG. This should be exactly of size 4. - qcom,soc-based-step-chg: A bool property to indicate if the battery will perform SoC (State of Charge) based step charging. If yes, the low and high thresholds defined in diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 77aafa95dda1..ab5a4ecb18da 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -291,6 +291,8 @@ struct fg_batt_props { int fastchg_curr_ma; int *therm_coeffs; int therm_ctr_offset; + int *rslow_normal_coeffs; + int *rslow_low_coeffs; }; struct fg_cyc_ctr_data { diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 1ea5899400eb..6dce5eb504a1 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -39,6 +39,7 @@ #define SLOPE_LIMIT_NUM_COEFFS 4 #define SLOPE_LIMIT_COEFF_MAX 31128 #define BATT_THERM_NUM_COEFFS 5 +#define RSLOW_NUM_COEFFS 4 /* SRAM address/offset definitions in ascending order */ #define BATT_THERM_CONFIG_WORD 3 @@ -90,6 +91,8 @@ #define VBATT_LOW_OFFSET 1 #define PROFILE_LOAD_WORD 65 #define PROFILE_LOAD_OFFSET 0 +#define RSLOW_COEFF_DISCHG_WORD 78 +#define RSLOW_COEFF_LOW_OFFSET 0 #define RSLOW_CONFIG_WORD 241 #define RSLOW_CONFIG_OFFSET 0 #define NOM_CAP_WORD 271 @@ -172,6 +175,7 @@ struct fg_gen4_chip { int soh; bool ki_coeff_dischg_en; bool slope_limit_en; + bool rslow_low; }; struct bias_config { @@ -774,6 +778,67 @@ static int fg_gen4_store_count(void *data, u16 *buf, int id, int length) /* All worker and helper functions below */ +static int fg_parse_dt_property_u32_array(struct device_node *node, + const char *prop_name, int *buf, int len) +{ + int rc; + + rc = of_property_count_elems_of_size(node, prop_name, sizeof(u32)); + if (rc < 0) { + if (rc == -EINVAL) + return 0; + else + return rc; + } else if (rc != len) { + pr_err("Incorrect length %d for %s, rc=%d\n", len, prop_name, + rc); + return -EINVAL; + } + + rc = of_property_read_u32_array(node, prop_name, buf, len); + if (rc < 0) { + pr_err("Error in reading %s, rc=%d\n", prop_name, rc); + return rc; + } + + return 0; +} + +static void fg_gen4_update_rslow_coeff(struct fg_dev *fg, int batt_temp) +{ + struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); + int rc, i; + bool rslow_low = false; + u8 buf[RSLOW_NUM_COEFFS]; + + if (!fg->bp.rslow_normal_coeffs || !fg->bp.rslow_low_coeffs) + return; + + /* Update Rslow low coefficients when Tbatt is < 0 C */ + if (batt_temp < 0) + rslow_low = true; + + if (chip->rslow_low == rslow_low) + return; + + for (i = 0; i < RSLOW_NUM_COEFFS; i++) { + if (rslow_low) + buf[i] = fg->bp.rslow_low_coeffs[i] & 0xFF; + else + buf[i] = fg->bp.rslow_normal_coeffs[i] & 0xFF; + } + + rc = fg_sram_write(fg, RSLOW_COEFF_DISCHG_WORD, RSLOW_COEFF_LOW_OFFSET, + buf, RSLOW_NUM_COEFFS, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Failed to write RLOW_COEFF_DISCHG_WORD rc=%d\n", rc); + } else { + chip->rslow_low = rslow_low; + fg_dbg(fg, FG_STATUS, "Updated Rslow %s coefficients\n", + rslow_low ? "low" : "normal"); + } +} + #define KI_COEFF_LOW_DISCHG_DEFAULT 428 #define KI_COEFF_MED_DISCHG_DEFAULT 245 #define KI_COEFF_HI_DISCHG_DEFAULT 123 @@ -934,6 +999,50 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) } } + if (of_find_property(profile_node, "qcom,rslow-normal-coeffs", NULL) && + of_find_property(profile_node, "qcom,rslow-low-coeffs", NULL)) { + if (!fg->bp.rslow_normal_coeffs) { + fg->bp.rslow_normal_coeffs = devm_kcalloc(fg->dev, + RSLOW_NUM_COEFFS, sizeof(u32), + GFP_KERNEL); + if (!fg->bp.rslow_normal_coeffs) + return -ENOMEM; + } + + if (!fg->bp.rslow_low_coeffs) { + fg->bp.rslow_low_coeffs = devm_kcalloc(fg->dev, + RSLOW_NUM_COEFFS, sizeof(u32), + GFP_KERNEL); + if (!fg->bp.rslow_low_coeffs) { + devm_kfree(fg->dev, fg->bp.rslow_normal_coeffs); + fg->bp.rslow_normal_coeffs = NULL; + return -ENOMEM; + } + } + + rc = fg_parse_dt_property_u32_array(profile_node, + "qcom,rslow-normal-coeffs", + fg->bp.rslow_normal_coeffs, RSLOW_NUM_COEFFS); + if (rc < 0) { + devm_kfree(fg->dev, fg->bp.rslow_normal_coeffs); + fg->bp.rslow_normal_coeffs = NULL; + devm_kfree(fg->dev, fg->bp.rslow_low_coeffs); + fg->bp.rslow_low_coeffs = NULL; + return rc; + } + + rc = fg_parse_dt_property_u32_array(profile_node, + "qcom,rslow-low-coeffs", + fg->bp.rslow_low_coeffs, RSLOW_NUM_COEFFS); + if (rc < 0) { + devm_kfree(fg->dev, fg->bp.rslow_normal_coeffs); + fg->bp.rslow_normal_coeffs = NULL; + devm_kfree(fg->dev, fg->bp.rslow_low_coeffs); + fg->bp.rslow_low_coeffs = NULL; + return rc; + } + } + data = of_get_property(profile_node, "qcom,fg-profile-data", &len); if (!data) { pr_err("No profile data available\n"); @@ -953,8 +1062,10 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) static int fg_gen4_bp_params_config(struct fg_dev *fg) { + struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int rc, i; u8 buf, therm_coeffs[BATT_THERM_NUM_COEFFS * 2]; + u8 rslow_coeffs[RSLOW_NUM_COEFFS]; if (fg->bp.vbatt_full_mv > 0) { rc = fg_set_constant_chg_voltage(fg, @@ -987,6 +1098,29 @@ static int fg_gen4_bp_params_config(struct fg_dev *fg) } } + if (fg->bp.rslow_normal_coeffs && fg->bp.rslow_low_coeffs) { + rc = fg_sram_read(fg, RSLOW_COEFF_DISCHG_WORD, + RSLOW_COEFF_LOW_OFFSET, rslow_coeffs, + RSLOW_NUM_COEFFS, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Failed to read RLOW_COEFF_DISCHG_WORD rc=%d\n", + rc); + return rc; + } + + /* Read Rslow coefficients back and set the status */ + for (i = 0; i < RSLOW_NUM_COEFFS; i++) { + buf = fg->bp.rslow_low_coeffs[i] & 0xFF; + if (rslow_coeffs[i] == buf) { + chip->rslow_low = true; + } else { + chip->rslow_low = false; + break; + } + } + fg_dbg(fg, FG_STATUS, "Rslow_low: %d\n", chip->rslow_low); + } + return 0; } @@ -1659,6 +1793,7 @@ static irqreturn_t fg_delta_batt_temp_irq_handler(int irq, void *data) if (batt_psy_initialized(fg)) power_supply_changed(fg->batt_psy); + fg_gen4_update_rslow_coeff(fg, batt_temp); return IRQ_HANDLED; } @@ -2747,32 +2882,6 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip) return 0; } -static int fg_parse_dt_property_u32_array(struct device_node *node, - const char *prop_name, int *buf, int len) -{ - int rc; - - rc = of_property_count_elems_of_size(node, prop_name, sizeof(u32)); - if (rc < 0) { - if (rc == -EINVAL) - return 0; - else - return rc; - } else if (rc != len) { - pr_err("Incorrect length %d for %s, rc=%d\n", len, prop_name, - rc); - return -EINVAL; - } - - rc = of_property_read_u32_array(node, prop_name, buf, len); - if (rc < 0) { - pr_err("Error in reading %s, rc=%d\n", prop_name, rc); - return rc; - } - - return 0; -} - static int fg_parse_slope_limit_coefficients(struct fg_dev *fg) { struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); -- GitLab From d13fd69c2eef34629d19322eb3525398dbe2bb25 Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Tue, 6 Feb 2018 09:31:30 -0800 Subject: [PATCH 0299/1299] staging: android: ion: Properly zero cached carveout allocations There is a contract that ION returns zeroed memory. When the carveout used by the ion carveout heap is mapped into the kernel with a cached mapping, such as through the logical kernel address mapping, then there are two cases where the ion carveout heap is not properly zeroing its memory. Case #1: In ion_carveout_heap_create() the memory is being flushed and then it is being zeroed using an uncached mapping. It is possible that speculative access has put data (which could be non-zero) into the cache between the flush and the uncached zeroing. If this memory was allocated using a cached ION allocation then the client would see non-zero values. Case #2: In ion_carveout_heap_free() if an uncached allocation is being freed then the code zeros the memory using an uncached mapping and doesn't do any cache maintenance. Speculative access to this memory, before it was freed, could have resulted in non-zero data being placed into the cache. If after this memory is freed it is allocated using a cached ION allocation then the client would see non-zero values. The likely impact of these bugs is that any ion carveout heap clients who are allocating cached memory, and who are relying on the zeroing, could see functional issues due to their memory having garbage values. Fix by invalidating the cache when cached memory is allocated. Change-Id: Ica4362c850497ef90ff82780dc70ee62da9d112b Signed-off-by: Liam Mark --- drivers/staging/android/ion/ion_carveout_heap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 88dc7995fb3f..d66398d946dd 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -64,6 +64,7 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, struct sg_table *table; phys_addr_t paddr; int ret; + struct device *dev = heap->priv; table = kmalloc(sizeof(*table), GFP_KERNEL); if (!table) @@ -81,6 +82,10 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(paddr)), size, 0); buffer->sg_table = table; + if (ion_buffer_cached(buffer)) + ion_pages_sync_for_device(dev, sg_page(table->sgl), + buffer->size, DMA_FROM_DEVICE); + return 0; err_free_table: -- GitLab From 67b6a27f7caab1ff51a44d34d9a70467863d708f Mon Sep 17 00:00:00 2001 From: Yuan Zhao Date: Wed, 30 May 2018 16:40:45 +0800 Subject: [PATCH 0300/1299] ARM: dts: msm: Add sw43404 panel video mode support for QRD SM8150 This display driver IC support video mode, so add the video mode support. Change-Id: I606514726c5962744aac05efb4a995e48e8d4efb Signed-off-by: Yuan Zhao --- ...i-panel-sw43404-amoled-dsc-wqhd-video.dtsi | 87 +++++++++++++++++++ arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi | 15 +++- .../boot/dts/qcom/sm8150-sde-display.dtsi | 27 +++++- 3 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-video.dtsi diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-video.dtsi new file mode 100644 index 000000000000..aa0962b3e4b4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-video.dtsi @@ -0,0 +1,87 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_sw43404_amoled_video: qcom,mdss_dsi_sw43404_amoled_wqhd_video { + qcom,mdss-dsi-panel-name = + "sw43404 amoled video mode dsi boe panel with DSC"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-traffic-mode = "non_burst_sync_event"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,adjust-timer-wakeup-ms = <1>; + qcom,mdss-dsi-display-timings { + timing@0{ + qcom,mdss-dsi-panel-width = <1440>; + qcom,mdss-dsi-panel-height = <2880>; + qcom,mdss-dsi-h-front-porch = <10>; + qcom,mdss-dsi-h-back-porch = <10>; + qcom,mdss-dsi-h-pulse-width = <12>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <10>; + qcom,mdss-dsi-v-front-porch = <10>; + qcom,mdss-dsi-v-pulse-width = <1>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-on-command = [ + 07 01 00 00 00 00 02 01 00 + 39 01 00 00 00 00 03 b0 a5 00 + 39 01 00 00 00 00 06 b2 00 5d 04 80 49 + 15 01 00 00 00 00 02 3d 10 + 15 01 00 00 00 00 02 36 00 + 15 01 00 00 00 00 02 55 0c + 39 01 00 00 00 00 09 f8 00 08 10 08 2d + 00 00 2d + 39 01 00 00 3c 00 03 51 00 00 + 05 01 00 00 50 00 02 11 00 + 39 01 00 00 00 00 03 b0 34 04 + 39 01 00 00 00 00 05 c1 00 00 00 46 + 0a 01 00 00 00 00 80 11 00 00 89 30 80 + 0B 40 05 A0 02 d0 02 D0 02 D0 02 00 + 02 68 00 20 4e a8 00 0A 00 0C 00 23 + 00 1c 18 00 10 F0 03 0C 20 00 06 0B + 0B 33 0E 1C 2A 38 46 54 62 69 70 77 + 79 7B 7D 7E 01 02 01 00 09 40 09 BE + 19 FC 19 FA 19 F8 1A 38 1A 78 1A B6 + 2A F6 2B 34 2B 74 3B 74 6B F4 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 + 05 01 00 00 78 00 02 29 00 + ]; + qcom,mdss-dsi-off-command = [05 01 00 00 78 00 + 02 28 00 05 01 00 00 78 00 02 10 00]; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + qcom,compression-mode = "dsc"; + qcom,mdss-dsc-slice-height = <720>; + qcom,mdss-dsc-slice-width = <720>; + qcom,mdss-dsc-slice-per-pkt = <2>; + qcom,mdss-dsc-bit-per-component = <8>; + qcom,mdss-dsc-bit-per-pixel = <8>; + qcom,mdss-dsc-block-prediction-enable; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi index caa51c71c686..fb880952c6e2 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi @@ -171,7 +171,20 @@ qcom,panel-supply-entries = <&dsi_panel_pwr_supply_vdd_no_labibb>; qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs"; qcom,mdss-dsi-bl-min-level = <1>; - qcom,mdss-dsi-bl-max-level = <1023>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-brightness-max-level = <1023>; + qcom,mdss-dsi-mode-sel-gpio-state = "single_port"; + qcom,panel-mode-gpio = <&tlmm 7 0>; + qcom,platform-te-gpio = <&tlmm 8 0>; + qcom,platform-reset-gpio = <&tlmm 6 0>; +}; + +&dsi_sw43404_amoled_video { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply_vdd_no_labibb>; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-brightness-max-level = <1023>; qcom,mdss-dsi-mode-sel-gpio-state = "single_port"; qcom,panel-mode-gpio = <&tlmm 7 0>; qcom,platform-te-gpio = <&tlmm 8 0>; diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi index be2723b07647..e0f20a32eef3 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi @@ -28,6 +28,7 @@ #include "dsi-panel-sharp-dualmipi-1080p-120hz.dtsi" #include "dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi" #include "dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi" +#include "dsi-panel-sw43404-amoled-dsc-wqhd-video.dtsi" #include &tlmm { @@ -321,6 +322,17 @@ qcom,dsi-panel = <&dsi_nt35695b_truly_fhd_video>; }; + dsi_sw43404_amoled_video_display: qcom,dsi-display@17 { + label = "dsi_sw43404_amoled_video_display"; + qcom,display-type = "primary"; + + qcom,dsi-ctrl-num = <0>; + qcom,dsi-phy-num = <0>; + qcom,dsi-select-clocks = "src_byte_clk0", "src_pixel_clk0"; + + qcom,dsi-panel = <&dsi_sw43404_amoled_video>; + }; + sde_dsi: qcom,dsi-display { compatible = "qcom,dsi-display"; @@ -362,7 +374,8 @@ &dsi_dual_sim_dsc_375_cmd_display &dsi_sw43404_amoled_cmd_display &dsi_nt35695b_truly_fhd_cmd_display - &dsi_nt35695b_truly_fhd_video_display>; + &dsi_nt35695b_truly_fhd_video_display + &dsi_sw43404_amoled_video_display>; }; sde_wb: qcom,wb-display@0 { @@ -658,3 +671,15 @@ }; }; }; + +&dsi_sw43404_amoled_video { + qcom,mdss-dsi-display-timings { + timing@0 { + qcom,mdss-dsi-panel-phy-timings = [00 1a 07 06 22 21 07 + 07 04 03 04 00 16 16]; + /*qcom,mdss-dsi-panel-clockrate = <700000000>;*/ + qcom,display-topology = <2 2 1>; + qcom,default-topology-index = <0>; + }; + }; +}; -- GitLab From 4bedc5a2864e39942417871593f9d3b4443b32c5 Mon Sep 17 00:00:00 2001 From: Tirupathi Reddy Date: Tue, 12 Jun 2018 09:11:27 +0530 Subject: [PATCH 0301/1299] leds: vibrator-ldo: Disable LDO if VREG_READY is not set If the LDO does not settle within the expected time, disable it. CRs-Fixed: 2257990 Change-Id: Ic8d5777fa356d166a722d3961a5a31cf06942e30 Signed-off-by: Tirupathi Reddy --- drivers/leds/leds-qpnp-vibrator-ldo.c | 39 +++++++++++++++++---------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/leds/leds-qpnp-vibrator-ldo.c b/drivers/leds/leds-qpnp-vibrator-ldo.c index 6a143247cd9b..488bb9979d86 100644 --- a/drivers/leds/leds-qpnp-vibrator-ldo.c +++ b/drivers/leds/leds-qpnp-vibrator-ldo.c @@ -65,9 +65,29 @@ struct vib_ldo_chip { bool disable_overdrive; }; -static int qpnp_vib_ldo_set_voltage(struct vib_ldo_chip *chip, int new_uV) +static inline int qpnp_vib_ldo_poll_status(struct vib_ldo_chip *chip) { unsigned int val; + int ret; + + ret = regmap_read_poll_timeout(chip->regmap, + chip->base + QPNP_VIB_LDO_REG_STATUS1, val, + val & QPNP_VIB_LDO_VREG_READY, 100, 1000); + if (ret < 0) { + pr_err("Vibrator LDO vreg_ready timeout, status=0x%02x, ret=%d\n", + val, ret); + + /* Keep VIB_LDO disabled */ + regmap_update_bits(chip->regmap, + chip->base + QPNP_VIB_LDO_REG_EN_CTL, + QPNP_VIB_LDO_EN, 0); + } + + return ret; +} + +static int qpnp_vib_ldo_set_voltage(struct vib_ldo_chip *chip, int new_uV) +{ u32 vlevel; u8 reg[2]; int ret; @@ -86,13 +106,9 @@ static int qpnp_vib_ldo_set_voltage(struct vib_ldo_chip *chip, int new_uV) } if (chip->vib_enabled) { - ret = regmap_read_poll_timeout(chip->regmap, - chip->base + QPNP_VIB_LDO_REG_STATUS1, - val, val & QPNP_VIB_LDO_VREG_READY, - 100, 1000); + ret = qpnp_vib_ldo_poll_status(chip); if (ret < 0) { - pr_err("Vibrator LDO vreg_ready timeout, status=0x%02x, ret=%d\n", - val, ret); + pr_err("Vibrator LDO status polling timedout\n"); return ret; } } @@ -103,7 +119,6 @@ static int qpnp_vib_ldo_set_voltage(struct vib_ldo_chip *chip, int new_uV) static inline int qpnp_vib_ldo_enable(struct vib_ldo_chip *chip, bool enable) { - unsigned int val; int ret; if (chip->vib_enabled == enable) @@ -120,13 +135,9 @@ static inline int qpnp_vib_ldo_enable(struct vib_ldo_chip *chip, bool enable) } if (enable) { - ret = regmap_read_poll_timeout(chip->regmap, - chip->base + QPNP_VIB_LDO_REG_STATUS1, - val, val & QPNP_VIB_LDO_VREG_READY, - 100, 1000); + ret = qpnp_vib_ldo_poll_status(chip); if (ret < 0) { - pr_err("Vibrator LDO vreg_ready timeout, status=0x%02x, ret=%d\n", - val, ret); + pr_err("Vibrator LDO status polling timedout\n"); return ret; } } -- GitLab From 9a9df21e493ffa760047f7c69220b174ed026c0e Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Tue, 29 May 2018 12:12:39 +0530 Subject: [PATCH 0302/1299] ARM: dts: qcom: Enable iommu bus voting for sm6150 Vote for the bus clock rate required to access iommu registers on sm6150. Change-Id: I23d898238b0fe3724a8c073d2a2e35988f3c590c Signed-off-by: Vijayanand Jitta --- .../boot/dts/qcom/msm-arm-smmu-sm6150.dtsi | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi index f3b34e457e33..3f224c133e65 100644 --- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm6150.dtsi @@ -11,6 +11,7 @@ */ #include +#include &soc { kgsl_smmu: kgsl-smmu@0x50a0000 { @@ -138,6 +139,17 @@ , , ; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; anoc_1_tbu: anoc_1_tbu@0x150c5000 { compatible = "qcom,qsmmuv500-tbu"; @@ -147,6 +159,17 @@ qcom,stream-id-range = <0x0 0x400>; qcom,regulator-names = "vdd"; vdd-supply = <&hlos1_vote_aggre_noc_mmu_tbu1_gdsc>; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; }; anoc_2_tbu: anoc_2_tbu@0x150c9000 { @@ -157,6 +180,17 @@ qcom,stream-id-range = <0x400 0x400>; qcom,regulator-names = "vdd"; vdd-supply = <&hlos1_vote_aggre_noc_mmu_tbu2_gdsc>; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; }; mnoc_hf_0_tbu: mnoc_hf_0_tbu@0x150cd000 { @@ -167,6 +201,17 @@ qcom,stream-id-range = <0x800 0x400>; qcom,regulator-names = "vdd"; vdd-supply = <&hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc>; + qcom,msm-bus,name = "mnoc_hf_0_tbu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; }; mnoc_sf_0_tbu: mnoc_sf_0_tbu@0x150d1000 { @@ -177,6 +222,17 @@ qcom,stream-id-range = <0xc00 0x400>; qcom,regulator-names = "vdd"; vdd-supply = <&hlos1_vote_mmnoc_mmu_tbu_sf_gdsc>; + qcom,msm-bus,name = "mnoc_sf_0_tbu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; }; compute_dsp_tbu: compute_dsp_tbu@0x150d5000 { @@ -186,6 +242,17 @@ reg-names = "base", "status-reg"; qcom,stream-id-range = <0x1000 0x400>; /* No GDSC */ + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; }; adsp_tbu: adsp_tbu@0x150d9000 { @@ -196,6 +263,17 @@ qcom,stream-id-range = <0x1400 0x400>; qcom,regulator-names = "vdd"; vdd-supply = <&hlos1_vote_aggre_noc_mmu_audio_tbu_gdsc>; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; }; }; -- GitLab From ac587dd20f0c44050ff2800dd60a2f8f788e9076 Mon Sep 17 00:00:00 2001 From: Tirupathi Reddy Date: Fri, 15 Jun 2018 09:14:11 +0530 Subject: [PATCH 0303/1299] ARM: dts: msm: add PMS405 DIV CLK device PMS405 DIV CLK module provides clock input for audio codec in QCS405. Change-Id: I4a4194e287da09c6da74f7760b5be2114f22b361 Signed-off-by: Tirupathi Reddy --- arch/arm64/boot/dts/qcom/pms405.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pms405.dtsi b/arch/arm64/boot/dts/qcom/pms405.dtsi index 159c47c4daa7..3717e39aa861 100644 --- a/arch/arm64/boot/dts/qcom/pms405.dtsi +++ b/arch/arm64/boot/dts/qcom/pms405.dtsi @@ -103,6 +103,19 @@ reg = <0x900 0x100>; }; + pms405_clkdiv: clock-controller@5b00 { + compatible = "qcom,spmi-clkdiv"; + reg = <0x5b00 0x100>; + #clock-cells = <1>; + qcom,num-clkdivs = <1>; + clock-output-names = "pms405_div_clk1"; + clocks = <&clock_rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "xo"; + + assigned-clocks = <&pms405_clkdiv 1>; + assigned-clock-rates = <9600000>; + }; + /* QCS405 + PMS405 GPIO configuration */ pms405_gpios: pinctrl@c000 { compatible = "qcom,spmi-gpio"; -- GitLab From 34efb6abd29548a09fa7899c9c2c4a6348a4784b Mon Sep 17 00:00:00 2001 From: Tirupathi Reddy Date: Fri, 15 Jun 2018 11:51:48 +0530 Subject: [PATCH 0304/1299] defconfig: enable spmi-pmic-clkdiv driver for QCS405 spmi-pmic-clkdiv driver configures PMIC DIV_CLK module for providing clock input to audio codec module. Change-Id: Id988d07fc380c280930e7a9bdf3a95803cf09489 Signed-off-by: Tirupathi Reddy --- arch/arm/configs/qcs405_defconfig | 1 + arch/arm64/configs/qcs405_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/qcs405_defconfig b/arch/arm/configs/qcs405_defconfig index 98b6eaa91bc0..b92a11e91923 100644 --- a/arch/arm/configs/qcs405_defconfig +++ b/arch/arm/configs/qcs405_defconfig @@ -377,6 +377,7 @@ CONFIG_SPS=y CONFIG_SPS_SUPPORT_NDP_BAM=y CONFIG_COMMON_CLK_QCOM=y CONFIG_QCOM_CLK_SMD_RPM=y +CONFIG_SPMI_PMIC_CLKDIV=y CONFIG_MDM_GCC_QCS405=y CONFIG_MDM_DEBUGCC_QCS405=y CONFIG_CLOCK_CPU_QCS405=y diff --git a/arch/arm64/configs/qcs405_defconfig b/arch/arm64/configs/qcs405_defconfig index f0201a61cebd..719eddc6dbda 100644 --- a/arch/arm64/configs/qcs405_defconfig +++ b/arch/arm64/configs/qcs405_defconfig @@ -378,6 +378,7 @@ CONFIG_QPNP_REVID=y CONFIG_SPS=y CONFIG_SPS_SUPPORT_NDP_BAM=y CONFIG_QCOM_CLK_SMD_RPM=y +CONFIG_SPMI_PMIC_CLKDIV=y CONFIG_MDM_GCC_QCS405=y CONFIG_MDM_DEBUGCC_QCS405=y CONFIG_CLOCK_CPU_QCS405=y -- GitLab From a0a0a84474db7fd1cfdad568229fc994f67feaac Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Wed, 16 May 2018 08:50:18 +0800 Subject: [PATCH 0305/1299] power: qpnp-qnovo5: Add driver to support Qnovo5 Qnovo5 is a PBS based pulse charging engine which has different pulse train pattern and register mapping with the legacy Qnovo module. Add the driver to export the registers of the hardware module and the parameters of the charging status to allow the userspace code to diagnose and control the charging phase. Change-Id: Ic51a286ce52ea177b81fe216955196f6ad1d17f6 Signed-off-by: Fenglin Wu --- .../power/supply/qcom/qpnp-qnovo5.txt | 40 + drivers/power/supply/qcom/Kconfig | 9 + drivers/power/supply/qcom/Makefile | 1 + drivers/power/supply/qcom/qpnp-qnovo5.c | 1401 +++++++++++++++++ 4 files changed, 1451 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/qcom/qpnp-qnovo5.txt create mode 100644 drivers/power/supply/qcom/qpnp-qnovo5.c diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qnovo5.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qnovo5.txt new file mode 100644 index 000000000000..f27cb33a7335 --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qnovo5.txt @@ -0,0 +1,40 @@ +QPNP Qnovo5 pulse engine + +QPNP Qnovo5 is a PBS based pulse charging engine which works in tandem with the +QPNP SMB5 Charger device. It configures the QPNP SMB5 charger to +charge/discharge as per pulse characteristics. + +The QPNP Qnovo5 pulse engine has a single peripheral assigned to it. + +Properties: +- compatible: + Usage: required + Value type: + Definition: It must be "qcom,qpnp-qnovo5". + +- reg: + Usage: required + Value type: + Definition: Specifies the base address of the module. Qnovo5 is using a + SDAM peripheral so this is the address of the SDAM module + being used. + +- interrupts: + Usage: required + Value type: + Definition: Specifies the interrupt associated with Qnovo5. + +- interrupt-names: + Usage: required + Value type: + Definition: Specifies the interrupt name for Qnovo5. There is only one + interrupt named as "ptrain-done". + +Example: + +qcom,qpnp-qnovo@b000 { + compatible = "qcom,qpnp-qnovo5"; + reg = <0xb000 0x100>; + interrupts = <0x2 0xb0 0x0 IRQ_TYPE_NONE>; + interrupt-names = "ptrain-done"; +}; diff --git a/drivers/power/supply/qcom/Kconfig b/drivers/power/supply/qcom/Kconfig index db0f56e3c6aa..a116e49dca82 100644 --- a/drivers/power/supply/qcom/Kconfig +++ b/drivers/power/supply/qcom/Kconfig @@ -94,6 +94,15 @@ config QPNP_QNOVO module. It also allows userspace code to read diagnostics of voltage and current measured during certain phases of the pulses. +config QPNP_QNOVO5 + bool "QPNP QNOVO5 driver" + depends on MFD_SPMI_PMIC + help + Say Y here to enable the Qnovo5 PBS-based pulse charging engine. + Qnovo5 driver accepts pulse parameters via sysfs entries and programs + the hardware module. It also allows userspace code to read diagnostics + of voltage and current measured during certain phases of the pulses. + config SMB1390_CHARGE_PUMP tristate "SMB1390 Charge Pump" depends on MFD_I2C_PMIC diff --git a/drivers/power/supply/qcom/Makefile b/drivers/power/supply/qcom/Makefile index 22c326e5ebff..026409243ed5 100644 --- a/drivers/power/supply/qcom/Makefile +++ b/drivers/power/supply/qcom/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_SMB1355_SLAVE_CHARGER) += smb1355-charger.o pmic-voter.o obj-$(CONFIG_QPNP_SMB2) += step-chg-jeita.o battery.o qpnp-smb2.o smb-lib.o pmic-voter.o storm-watch.o obj-$(CONFIG_SMB138X_CHARGER) += step-chg-jeita.o smb138x-charger.o smb-lib.o pmic-voter.o storm-watch.o battery.o obj-$(CONFIG_QPNP_QNOVO) += qpnp-qnovo.o battery.o +obj-$(CONFIG_QPNP_QNOVO5) += qpnp-qnovo5.o battery.o obj-$(CONFIG_QPNP_SMB5) += step-chg-jeita.o battery.o qpnp-smb5.o smb5-lib.o pmic-voter.o storm-watch.o schgm-flash.o obj-$(CONFIG_SMB1390_CHARGE_PUMP) += smb1390-charger.o pmic-voter.o diff --git a/drivers/power/supply/qcom/qpnp-qnovo5.c b/drivers/power/supply/qcom/qpnp-qnovo5.c new file mode 100644 index 000000000000..5037fa25e42c --- /dev/null +++ b/drivers/power/supply/qcom/qpnp-qnovo5.c @@ -0,0 +1,1401 @@ +/* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define QNOVO_PE_CTRL 0x45 +#define QNOVO_PTRAIN_EN_BIT BIT(7) + +#define QNOVO_NREST1_CTRL 0x4A +#define QNOVO_NPULS1_CTRL 0x4B +#define QNOVO_PREST1_CTRL 0x4C +#define QNOVO_NREST2_CTRL 0x4D +#define QNOVO_NPULS2_CTRL 0x4E +#define QNOVO_NREST3_CTRL 0x4F +#define QNOVO_NPULS3_CTRL 0x50 +#define QNOVO_ERROR_MASK 0x51 +#define QNOVO_VLIM1_LSB_CTRL 0x52 +#define QNOVO_VLIM1_MSB_CTRL 0x53 +#define QNOVO_VLIM2_LSB_CTRL 0x54 +#define QNOVO_VLIM2_MSB_CTRL 0x55 +#define QNOVO_PVOLT1_LSB 0x56 +#define QNOVO_PVOLT1_MSB 0x57 +#define QNOVO_RVOLT2_LSB 0x58 +#define QNOVO_RVOLT2_MSB 0x59 +#define QNOVO_PVOLT2_LSB 0x5A +#define QNOVO_PVOLT2_MSB 0x5B +#define QNOVO_PCURR1_LSB 0x5C +#define QNOVO_PCURR1_MSB 0x5D +#define QNOVO_PCURR2_LSB 0x5E +#define QNOVO_PCURR2_MSB 0x5F +#define QNOVO_PCURR1_SUM_LSB 0x60 +#define QNOVO_PCURR1_SUM_MSB 0x61 +#define QNOVO_PCURR1_TERMINAL_LSB 0x62 +#define QNOVO_PCURR1_TERMINAL_MSB 0x63 +#define QNOVO_PTTIME_LSB 0x64 +#define QNOVO_PTTIME_MSB 0x65 +#define QNOVO_PPCNT 0x66 +#define QNOVO_PPCNT_MAX_CTRL 0x67 +#define QNOVO_RVOLT3_VMAX_LSB 0x68 +#define QNOVO_RVOLT3_VMAX_MSB 0x69 +#define QNOVO_RVOLT3_VMAX_SNUM 0x6A +#define QNOVO_PTTIME_MAX_LSB 0x6C +#define QNOVO_PTTIME_MAX_MSB 0x6D +#define QNOVO_PHASE 0x6E +#define QNOVO_P2_TICK 0x6F +#define QNOVO_PTRAIN_STS 0x70 +#define QNOVO_ERROR_STS 0x71 + +/* QNOVO_ERROR_STS */ +#define ERR_CHARGING_DISABLED BIT(6) +#define ERR_JEITA_HARD_CONDITION BIT(5) +#define ERR_JEITA_SOFT_CONDITION BIT(4) +#define ERR_CV_MODE BIT(3) +#define ERR_SAFETY_TIMER_EXPIRED BIT(2) +#define ERR_BAT_OV BIT(1) +#define ERR_BATTERY_MISSING BIT(0) + +#define DRV_MAJOR_VERSION 1 +#define DRV_MINOR_VERSION 1 + +#define USER_VOTER "user_voter" +#define SHUTDOWN_VOTER "user_voter" +#define OK_TO_QNOVO_VOTER "ok_to_qnovo_voter" + +#define QNOVO_VOTER "qnovo_voter" +#define QNOVO_OVERALL_VOTER "QNOVO_OVERALL_VOTER" +#define QNI_PT_VOTER "QNI_PT_VOTER" + +#define HW_OK_TO_QNOVO_VOTER "HW_OK_TO_QNOVO_VOTER" +#define CHG_READY_VOTER "CHG_READY_VOTER" +#define USB_READY_VOTER "USB_READY_VOTER" + +#define CLASS_ATTR_IDX_RO(_name, _func) \ +static ssize_t _name##_show(struct class *c, struct class_attribute *attr, \ + char *ubuf) \ +{ \ + return _func##_show(c, attr, ubuf); \ +}; \ +static CLASS_ATTR_RO(_name) + +#define CLASS_ATTR_IDX_RW(_name, _func) \ +static ssize_t _name##_show(struct class *c, struct class_attribute *attr, \ + char *ubuf) \ +{ \ + return _func##_show(c, attr, ubuf); \ +}; \ +static ssize_t _name##_store(struct class *c, struct class_attribute *attr, \ + const char *ubuf, size_t count) \ +{ \ + return _func##_store(c, attr, ubuf, count); \ +}; \ +static CLASS_ATTR_RW(_name) + +struct qnovo { + struct regmap *regmap; + struct device *dev; + struct mutex write_lock; + struct class qnovo_class; + struct power_supply *batt_psy; + struct power_supply *usb_psy; + struct notifier_block nb; + struct votable *disable_votable; + struct votable *pt_dis_votable; + struct votable *not_ok_to_qnovo_votable; + struct votable *chg_ready_votable; + struct votable *awake_votable; + struct work_struct status_change_work; + struct delayed_work usb_debounce_work; + int base; + int fv_uV_request; + int fcc_uA_request; + int usb_present; +}; + +static int debug_mask; +module_param_named(debug_mask, debug_mask, int, 0600); + +#define qnovo_dbg(chip, reason, fmt, ...) \ + do { \ + if (debug_mask & (reason)) \ + dev_info(chip->dev, fmt, ##__VA_ARGS__); \ + else \ + dev_dbg(chip->dev, fmt, ##__VA_ARGS__); \ + } while (0) + +static int qnovo5_read(struct qnovo *chip, u16 addr, u8 *buf, int len) +{ + return regmap_bulk_read(chip->regmap, chip->base + addr, buf, len); +} + +static int qnovo5_masked_write(struct qnovo *chip, u16 addr, u8 mask, u8 val) +{ + return regmap_update_bits(chip->regmap, chip->base + addr, mask, val); +} + +static int qnovo5_write(struct qnovo *chip, u16 addr, u8 *buf, int len) +{ + return regmap_bulk_write(chip->regmap, chip->base + addr, buf, len); +} + +static bool is_batt_available(struct qnovo *chip) +{ + if (!chip->batt_psy) + chip->batt_psy = power_supply_get_by_name("battery"); + + if (!chip->batt_psy) + return false; + + return true; +} + +static bool is_usb_available(struct qnovo *chip) +{ + if (!chip->usb_psy) + chip->usb_psy = power_supply_get_by_name("usb"); + + if (!chip->usb_psy) + return false; + + return true; +} + +static int qnovo_batt_psy_update(struct qnovo *chip, bool disable) +{ + union power_supply_propval pval = {0}; + int rc = 0; + + if (!is_batt_available(chip)) + return -EINVAL; + + if (chip->fv_uV_request != -EINVAL) { + pval.intval = disable ? -EINVAL : chip->fv_uV_request; + rc = power_supply_set_property(chip->batt_psy, + POWER_SUPPLY_PROP_VOLTAGE_QNOVO, + &pval); + if (rc < 0) { + pr_err("Couldn't set prop qnovo_fv rc = %d\n", rc); + return -EINVAL; + } + } + + if (chip->fcc_uA_request != -EINVAL) { + pval.intval = disable ? -EINVAL : chip->fcc_uA_request; + rc = power_supply_set_property(chip->batt_psy, + POWER_SUPPLY_PROP_CURRENT_QNOVO, + &pval); + if (rc < 0) { + pr_err("Couldn't set prop qnovo_fcc rc = %d\n", rc); + return -EINVAL; + } + } + + return rc; +} + +static int qnovo_disable_cb(struct votable *votable, void *data, int disable, + const char *client) +{ + struct qnovo *chip = data; + int rc; + + vote(chip->pt_dis_votable, QNOVO_OVERALL_VOTER, disable, 0); + rc = qnovo_batt_psy_update(chip, disable); + return rc; +} + +static int pt_dis_votable_cb(struct votable *votable, void *data, int disable, + const char *client) +{ + struct qnovo *chip = data; + int rc; + + rc = qnovo5_masked_write(chip, QNOVO_PE_CTRL, QNOVO_PTRAIN_EN_BIT, + (bool)disable ? 0 : QNOVO_PTRAIN_EN_BIT); + if (rc < 0) { + dev_err(chip->dev, "Couldn't %s pulse train rc=%d\n", + (bool)disable ? "disable" : "enable", rc); + return rc; + } + + return 0; +} + +static int not_ok_to_qnovo_cb(struct votable *votable, void *data, + int not_ok_to_qnovo, + const char *client) +{ + struct qnovo *chip = data; + + vote(chip->disable_votable, OK_TO_QNOVO_VOTER, not_ok_to_qnovo, 0); + if (not_ok_to_qnovo) + vote(chip->disable_votable, USER_VOTER, true, 0); + + kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE); + return 0; +} + +static int chg_ready_cb(struct votable *votable, void *data, int ready, + const char *client) +{ + struct qnovo *chip = data; + + vote(chip->not_ok_to_qnovo_votable, CHG_READY_VOTER, !ready, 0); + + return 0; +} + +static int awake_cb(struct votable *votable, void *data, int awake, + const char *client) +{ + struct qnovo *chip = data; + + if (awake) + pm_stay_awake(chip->dev); + else + pm_relax(chip->dev); + + return 0; +} + +static int qnovo5_parse_dt(struct qnovo *chip) +{ + struct device_node *node = chip->dev->of_node; + int rc; + + if (!node) { + pr_err("device tree node missing\n"); + return -EINVAL; + } + + rc = of_property_read_u32(node, "reg", &chip->base); + if (rc < 0) { + pr_err("Couldn't read base rc = %d\n", rc); + return rc; + } + + return 0; +} + +enum { + VER = 0, + OK_TO_QNOVO, + QNOVO_ENABLE, + PT_ENABLE, + FV_REQUEST, + FCC_REQUEST, + PE_CTRL_REG, + PTRAIN_STS_REG, + ERR_STS_REG, + PREST1, + NREST1, + NPULS1, + PPCNT, + PPCNT_MAX, + VLIM1, + PVOLT1, + PCURR1, + PCURR1_SUM, + PCURR1_TERMINAL, + PTTIME, + PTTIME_MAX, + NREST2, + NPULS2, + VLIM2, + PVOLT2, + RVOLT2, + PCURR2, + NREST3, + NPULS3, + RVOLT3_VMAX, + RVOLT3_VMAX_SNUM, + VBATT, + IBATT, + BATTTEMP, + BATTSOC, + MAX_PROP +}; + +struct param_info { + char *name; + int start_addr; + int num_regs; + int reg_to_unit_multiplier; + int reg_to_unit_divider; + int reg_to_unit_offset; + int min_val; + int max_val; + char *units_str; +}; + +static struct param_info params[] = { + [FV_REQUEST] = { + .units_str = "uV", + }, + [FCC_REQUEST] = { + .units_str = "uA", + }, + [PE_CTRL_REG] = { + .name = "CTRL_REG", + .start_addr = QNOVO_PE_CTRL, + .num_regs = 1, + .units_str = "", + }, + [PTRAIN_STS_REG] = { + .name = "PTRAIN_STS", + .start_addr = QNOVO_PTRAIN_STS, + .num_regs = 1, + .units_str = "", + }, + [ERR_STS_REG] = { + .name = "RAW_CHGR_ERR", + .start_addr = QNOVO_ERROR_STS, + .num_regs = 1, + .units_str = "", + }, + [PREST1] = { + .name = "PREST1", + .start_addr = QNOVO_PREST1_CTRL, + .num_regs = 1, + .reg_to_unit_multiplier = 976650, + .reg_to_unit_divider = 1000, + .min_val = 0, + .max_val = 249135, + .units_str = "uS", + }, + [NREST1] = { + .name = "NREST1", + .start_addr = QNOVO_NREST1_CTRL, + .num_regs = 1, + .reg_to_unit_multiplier = 976650, + .reg_to_unit_divider = 1000, + .min_val = 0, + .max_val = 249135, + .units_str = "uS", + }, + [NPULS1] = { + .name = "NPULS1", + .start_addr = QNOVO_NPULS1_CTRL, + .num_regs = 1, + .reg_to_unit_multiplier = 976650, + .reg_to_unit_divider = 1000, + .min_val = 0, + .max_val = 249135, + .units_str = "uS", + }, + [PPCNT] = { + .name = "PPCNT", + .start_addr = QNOVO_PPCNT, + .num_regs = 1, + .reg_to_unit_multiplier = 1, + .reg_to_unit_divider = 1, + .min_val = 1, + .max_val = 255, + .units_str = "pulses", + }, + [PPCNT_MAX] = { + .name = "PPCNT_MAX", + .start_addr = QNOVO_PPCNT_MAX_CTRL, + .num_regs = 1, + .reg_to_unit_multiplier = 1, + .reg_to_unit_divider = 1, + .min_val = 1, + .max_val = 255, + .units_str = "pulses", + }, + [VLIM1] = { + .name = "VLIM1", + .start_addr = QNOVO_VLIM1_LSB_CTRL, + .num_regs = 2, + .reg_to_unit_multiplier = 194637, /* converts to nV */ + .reg_to_unit_divider = 1, + .min_val = 2200000, + .max_val = 4500000, + .units_str = "uV", + }, + [PVOLT1] = { + .name = "PVOLT1", + .start_addr = QNOVO_PVOLT1_LSB, + .num_regs = 2, + .reg_to_unit_multiplier = 194637, /* converts to nV */ + .reg_to_unit_divider = 1, + .units_str = "uV", + }, + [PCURR1] = { + .name = "PCURR1", + .start_addr = QNOVO_PCURR1_LSB, + .num_regs = 2, + .reg_to_unit_multiplier = 305185, /* converts to nA */ + .reg_to_unit_divider = 1, + .units_str = "uA", + }, + [PCURR1_SUM] = { + .name = "PCURR1_SUM", + .start_addr = QNOVO_PCURR1_SUM_LSB, + .num_regs = 2, + .reg_to_unit_multiplier = 305185, /* converts to nA */ + .reg_to_unit_divider = 1, + .units_str = "uA", + }, + [PCURR1_TERMINAL] = { + .name = "PCURR1_TERMINAL", + .start_addr = QNOVO_PCURR1_TERMINAL_LSB, + .num_regs = 2, + .reg_to_unit_multiplier = 305185, /* converts to nA */ + .reg_to_unit_divider = 1, + .units_str = "uA", + }, + [PTTIME] = { + .name = "PTTIME", + .start_addr = QNOVO_PTTIME_LSB, + .num_regs = 2, + .reg_to_unit_multiplier = 1, + .reg_to_unit_divider = 1, + .units_str = "S", + }, + [PTTIME_MAX] = { + .name = "PTTIME_MAX", + .start_addr = QNOVO_PTTIME_MAX_LSB, + .num_regs = 2, + .reg_to_unit_multiplier = 1, + .reg_to_unit_divider = 1, + .units_str = "S", + }, + [NREST2] = { + .name = "NREST2", + .start_addr = QNOVO_NREST2_CTRL, + .num_regs = 1, + .reg_to_unit_multiplier = 976650, + .reg_to_unit_divider = 1000, + .min_val = 0, + .max_val = 249135, + .units_str = "uS", + }, + [NPULS2] = { + .name = "NPULS2", + .start_addr = QNOVO_NPULS2_CTRL, + .num_regs = 1, + .reg_to_unit_multiplier = 976650, + .reg_to_unit_divider = 1000, + .min_val = 0, + .max_val = 249135, + .units_str = "uS", + }, + [VLIM2] = { + .name = "VLIM2", + .start_addr = QNOVO_VLIM2_LSB_CTRL, + .num_regs = 2, + .reg_to_unit_multiplier = 194637, /* converts to nV */ + .reg_to_unit_divider = 1, + .min_val = 2200000, + .max_val = 4500000, + .units_str = "uV", + }, + [PVOLT2] = { + .name = "PVOLT2", + .start_addr = QNOVO_PVOLT2_LSB, + .num_regs = 2, + .reg_to_unit_multiplier = 194637, /* converts to nV */ + .reg_to_unit_divider = 1, + .units_str = "uV", + }, + [RVOLT2] = { + .name = "RVOLT2", + .start_addr = QNOVO_RVOLT2_LSB, + .num_regs = 2, + .reg_to_unit_multiplier = 194637, + .reg_to_unit_divider = 1, + .units_str = "uV", + }, + [PCURR2] = { + .name = "PCURR2", + .start_addr = QNOVO_PCURR2_LSB, + .num_regs = 2, + .reg_to_unit_multiplier = 305185, /* converts to nA */ + .reg_to_unit_divider = 1, + .units_str = "uA", + }, + [NREST3] = { + .name = "NREST3", + .start_addr = QNOVO_NREST3_CTRL, + .num_regs = 1, + .reg_to_unit_multiplier = 976650, + .reg_to_unit_divider = 1000, + .min_val = 0, + .max_val = 249135, + .units_str = "uS", + }, + [NPULS3] = { + .name = "NPULS3", + .start_addr = QNOVO_NPULS3_CTRL, + .num_regs = 1, + .reg_to_unit_multiplier = 976650, + .reg_to_unit_divider = 1000, + .min_val = 0, + .max_val = 249135, + .units_str = "uS", + }, + [RVOLT3_VMAX] = { + .name = "RVOLT3_VMAX", + .start_addr = QNOVO_RVOLT3_VMAX_LSB, + .num_regs = 2, + .reg_to_unit_multiplier = 194637, /* converts to nV */ + .reg_to_unit_divider = 1, + .units_str = "uV", + }, + [RVOLT3_VMAX_SNUM] = { + .name = "SNUM", + .start_addr = QNOVO_RVOLT3_VMAX_SNUM, + .num_regs = 1, + .reg_to_unit_multiplier = 1, + .reg_to_unit_divider = 1, + .units_str = "pulses", + }, + [VBATT] = { + .name = "POWER_SUPPLY_PROP_VOLTAGE_NOW", + .start_addr = POWER_SUPPLY_PROP_VOLTAGE_NOW, + .units_str = "uV", + }, + [IBATT] = { + .name = "POWER_SUPPLY_PROP_CURRENT_NOW", + .start_addr = POWER_SUPPLY_PROP_CURRENT_NOW, + .units_str = "uA", + }, + [BATTTEMP] = { + .name = "POWER_SUPPLY_PROP_TEMP", + .start_addr = POWER_SUPPLY_PROP_TEMP, + .units_str = "uV", + }, + [BATTSOC] = { + .name = "POWER_SUPPLY_PROP_CAPACITY", + .start_addr = POWER_SUPPLY_PROP_CAPACITY, + .units_str = "%", + }, +}; + +static struct attribute *qnovo_class_attrs[]; + +static int __find_attr_idx(struct attribute *attr) +{ + int i; + + for (i = 0; i < MAX_PROP; i++) + if (attr == qnovo_class_attrs[i]) + break; + + if (i == MAX_PROP) + return -EINVAL; + + return i; +} + +static ssize_t version_show(struct class *c, struct class_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d.%d\n", + DRV_MAJOR_VERSION, DRV_MINOR_VERSION); +} +static CLASS_ATTR_RO(version); + +static ssize_t ok_to_qnovo_show(struct class *c, struct class_attribute *attr, + char *buf) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + int val = get_effective_result(chip->not_ok_to_qnovo_votable); + + return snprintf(buf, PAGE_SIZE, "%d\n", !val); +} +static CLASS_ATTR_RO(ok_to_qnovo); + +static ssize_t qnovo_enable_show(struct class *c, struct class_attribute *attr, + char *ubuf) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + int val = get_effective_result(chip->disable_votable); + + return snprintf(ubuf, PAGE_SIZE, "%d\n", !val); +} + +static ssize_t qnovo_enable_store(struct class *c, struct class_attribute *attr, + const char *ubuf, size_t count) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + unsigned long val; + + if (kstrtoul(ubuf, 0, &val)) + return -EINVAL; + + vote(chip->disable_votable, USER_VOTER, !val, 0); + + return count; +} +static CLASS_ATTR_RW(qnovo_enable); + +static ssize_t pt_enable_show(struct class *c, struct class_attribute *attr, + char *ubuf) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + int val = get_effective_result(chip->pt_dis_votable); + + return snprintf(ubuf, PAGE_SIZE, "%d\n", !val); +} + +static ssize_t pt_enable_store(struct class *c, struct class_attribute *attr, + const char *ubuf, size_t count) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + unsigned long val; + + if (kstrtoul(ubuf, 0, &val)) + return -EINVAL; + + /* val being 0, userspace wishes to disable pt so vote true */ + vote(chip->pt_dis_votable, QNI_PT_VOTER, val ? false : true, 0); + + return count; +} +static CLASS_ATTR_RW(pt_enable); + + +static ssize_t val_show(struct class *c, struct class_attribute *attr, + char *ubuf) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + int i; + int val = 0; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + if (i == FV_REQUEST) + val = chip->fv_uV_request; + + if (i == FCC_REQUEST) + val = chip->fcc_uA_request; + + return snprintf(ubuf, PAGE_SIZE, "%d\n", val); +} + +static ssize_t val_store(struct class *c, struct class_attribute *attr, + const char *ubuf, size_t count) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + int i; + unsigned long val; + + if (kstrtoul(ubuf, 0, &val)) + return -EINVAL; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + if (i == FV_REQUEST) + chip->fv_uV_request = val; + + if (i == FCC_REQUEST) + chip->fcc_uA_request = val; + + if (!get_effective_result(chip->disable_votable)) + qnovo_batt_psy_update(chip, false); + + return count; +} + +static ssize_t reg_show(struct class *c, struct class_attribute *attr, + char *ubuf) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + u8 buf[2] = {0, 0}; + u16 regval; + int rc, i; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + rc = qnovo5_read(chip, params[i].start_addr, buf, params[i].num_regs); + if (rc < 0) { + pr_err("Couldn't read %s rc = %d\n", params[i].name, rc); + return -EINVAL; + } + regval = buf[1] << 8 | buf[0]; + + return snprintf(ubuf, PAGE_SIZE, "0x%04x\n", regval); +} + +static ssize_t reg_store(struct class *c, struct class_attribute *attr, + const char *ubuf, size_t count) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + u8 buf[2] = {0, 0}; + unsigned long val; + int rc, i; + + if (kstrtoul(ubuf, 0, &val)) + return -EINVAL; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + buf[0] = val & 0xFF; + buf[1] = (val >> 8) & 0xFF; + + rc = qnovo5_write(chip, params[i].start_addr, buf, params[i].num_regs); + if (rc < 0) { + pr_err("Couldn't write %s rc = %d\n", params[i].name, rc); + return -EINVAL; + } + return count; +} + +static ssize_t time_show(struct class *c, struct class_attribute *attr, + char *ubuf) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + u8 buf[2] = {0, 0}; + u16 regval; + int val; + int rc, i; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + rc = qnovo5_read(chip, params[i].start_addr, buf, params[i].num_regs); + if (rc < 0) { + pr_err("Couldn't read %s rc = %d\n", params[i].name, rc); + return -EINVAL; + } + regval = buf[1] << 8 | buf[0]; + + val = ((regval * params[i].reg_to_unit_multiplier) + / params[i].reg_to_unit_divider) + - params[i].reg_to_unit_offset; + + return snprintf(ubuf, PAGE_SIZE, "%d\n", val); +} + +static ssize_t time_store(struct class *c, struct class_attribute *attr, + const char *ubuf, size_t count) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + u8 buf[2] = {0, 0}; + u16 regval; + unsigned long val; + int rc, i; + + if (kstrtoul(ubuf, 0, &val)) + return -EINVAL; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + if (val < params[i].min_val || val > params[i].max_val) { + pr_err("Out of Range %d%s for %s\n", (int)val, + params[i].units_str, + params[i].name); + return -ERANGE; + } + + regval = (((int)val + params[i].reg_to_unit_offset) + * params[i].reg_to_unit_divider) + / params[i].reg_to_unit_multiplier; + buf[0] = regval & 0xFF; + buf[1] = (regval >> 8) & 0xFF; + + rc = qnovo5_write(chip, params[i].start_addr, buf, params[i].num_regs); + if (rc < 0) { + pr_err("Couldn't write %s rc = %d\n", params[i].name, rc); + return -EINVAL; + } + + return count; +} + +static ssize_t current_show(struct class *c, struct class_attribute *attr, + char *ubuf) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + u8 buf[2] = {0, 0}; + int rc, i, regval_uA; + s64 regval_nA; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + rc = qnovo5_read(chip, params[i].start_addr, buf, params[i].num_regs); + if (rc < 0) { + pr_err("Couldn't read %s rc = %d\n", params[i].name, rc); + return -EINVAL; + } + + regval_nA = (s16)(buf[1] << 8 | buf[0]); + regval_nA = div_s64(regval_nA * params[i].reg_to_unit_multiplier, + params[i].reg_to_unit_divider) + - params[i].reg_to_unit_offset; + + regval_uA = div_s64(regval_nA, 1000); + + return snprintf(ubuf, PAGE_SIZE, "%d\n", regval_uA); +} + +static ssize_t current_store(struct class *c, struct class_attribute *attr, + const char *ubuf, size_t count) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + u8 buf[2] = {0, 0}; + int rc, i; + long val_uA; + s64 regval_nA; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + if (kstrtoul(ubuf, 0, &val_uA)) + return -EINVAL; + + if (val_uA < params[i].min_val || val_uA > params[i].max_val) { + pr_err("Out of Range %d%s for %s\n", (int)val_uA, + params[i].units_str, + params[i].name); + return -ERANGE; + } + + regval_nA = (s64)val_uA * 1000; + regval_nA = div_s64((regval_nA + params[i].reg_to_unit_offset) + * params[i].reg_to_unit_divider, + params[i].reg_to_unit_multiplier); + buf[0] = regval_nA & 0xFF; + buf[1] = (regval_nA >> 8) & 0xFF; + + rc = qnovo5_write(chip, params[i].start_addr, buf, params[i].num_regs); + if (rc < 0) { + pr_err("Couldn't write %s rc = %d\n", params[i].name, rc); + return -EINVAL; + } + + return count; +} + +static ssize_t voltage_show(struct class *c, struct class_attribute *attr, + char *ubuf) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + u8 buf[2] = {0, 0}; + int rc, i, regval_uV; + s64 regval_nV; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + rc = qnovo5_read(chip, params[i].start_addr, buf, params[i].num_regs); + if (rc < 0) { + pr_err("Couldn't read %s rc = %d\n", params[i].name, rc); + return -EINVAL; + } + regval_nV = buf[1] << 8 | buf[0]; + regval_nV = div_s64(regval_nV * params[i].reg_to_unit_multiplier, + params[i].reg_to_unit_divider) + - params[i].reg_to_unit_offset; + + regval_uV = div_s64(regval_nV, 1000); + + return snprintf(ubuf, PAGE_SIZE, "%d\n", regval_uV); +} + +static ssize_t voltage_store(struct class *c, struct class_attribute *attr, + const char *ubuf, size_t count) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + u8 buf[2] = {0, 0}; + int rc, i; + unsigned long val_uV; + s64 regval_nV; + + if (kstrtoul(ubuf, 0, &val_uV)) + return -EINVAL; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + if (val_uV < params[i].min_val || val_uV > params[i].max_val) { + pr_err("Out of Range %d%s for %s\n", (int)val_uV, + params[i].units_str, + params[i].name); + return -ERANGE; + } + + regval_nV = (s64)val_uV * 1000; + regval_nV = div_s64((regval_nV + params[i].reg_to_unit_offset) + * params[i].reg_to_unit_divider, + params[i].reg_to_unit_multiplier); + buf[0] = regval_nV & 0xFF; + buf[1] = ((u64)regval_nV >> 8) & 0xFF; + + rc = qnovo5_write(chip, params[i].start_addr, buf, params[i].num_regs); + if (rc < 0) { + pr_err("Couldn't write %s rc = %d\n", params[i].name, rc); + return -EINVAL; + } + + return count; +} + +static ssize_t batt_prop_show(struct class *c, struct class_attribute *attr, + char *ubuf) +{ + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + union power_supply_propval pval = {0}; + int i, prop, rc = -EINVAL; + + if (!is_batt_available(chip)) + return -EINVAL; + + i = __find_attr_idx(&attr->attr); + if (i < 0) + return -EINVAL; + + prop = params[i].start_addr; + + rc = power_supply_get_property(chip->batt_psy, prop, &pval); + if (rc < 0) { + pr_err("Couldn't read battery prop %s rc = %d\n", + params[i].name, rc); + return -EINVAL; + } + + return snprintf(ubuf, PAGE_SIZE, "%d\n", pval.intval); +} + +CLASS_ATTR_IDX_RW(fv_uV_request, val); +CLASS_ATTR_IDX_RW(fcc_uA_request, val); +CLASS_ATTR_IDX_RW(PE_CTRL_REG, reg); +CLASS_ATTR_IDX_RO(PTRAIN_STS_REG, reg); +CLASS_ATTR_IDX_RO(ERR_STS_REG, reg); +CLASS_ATTR_IDX_RW(PREST1_uS, time); +CLASS_ATTR_IDX_RW(NREST1_uS, time); +CLASS_ATTR_IDX_RW(NPULS1_uS, time); +CLASS_ATTR_IDX_RO(PPCNT, time); +CLASS_ATTR_IDX_RW(PPCNT_MAX, time); +CLASS_ATTR_IDX_RW(VLIM1_uV, voltage); +CLASS_ATTR_IDX_RO(PVOLT1_uV, voltage); +CLASS_ATTR_IDX_RO(PCURR1_uA, current); +CLASS_ATTR_IDX_RO(PCURR1_SUM_uA, current); +CLASS_ATTR_IDX_RW(PCURR1_TERMINAL_uA, current); +CLASS_ATTR_IDX_RO(PTTIME_S, time); +CLASS_ATTR_IDX_RW(PTTIME_MAX_S, time); +CLASS_ATTR_IDX_RW(NREST2_uS, time); +CLASS_ATTR_IDX_RW(NPULS2_uS, time); +CLASS_ATTR_IDX_RW(VLIM2_uV, voltage); +CLASS_ATTR_IDX_RO(PVOLT2_uV, voltage); +CLASS_ATTR_IDX_RO(RVOLT2_uV, voltage); +CLASS_ATTR_IDX_RO(PCURR2_uA, current); +CLASS_ATTR_IDX_RW(NREST3_uS, time); +CLASS_ATTR_IDX_RW(NPULS3_uS, time); +CLASS_ATTR_IDX_RO(RVOLT3_VMAX_uV, voltage); +CLASS_ATTR_IDX_RO(RVOLT3_VMAX_SNUM, time); +CLASS_ATTR_IDX_RO(VBATT_uV, batt_prop); +CLASS_ATTR_IDX_RO(IBATT_uA, batt_prop); +CLASS_ATTR_IDX_RO(BATTTEMP_deciDegC, batt_prop); +CLASS_ATTR_IDX_RO(BATTSOC, batt_prop); + +static struct attribute *qnovo_class_attrs[] = { + [VER] = &class_attr_version.attr, + [OK_TO_QNOVO] = &class_attr_ok_to_qnovo.attr, + [QNOVO_ENABLE] = &class_attr_qnovo_enable.attr, + [PT_ENABLE] = &class_attr_pt_enable.attr, + [FV_REQUEST] = &class_attr_fv_uV_request.attr, + [FCC_REQUEST] = &class_attr_fcc_uA_request.attr, + [PE_CTRL_REG] = &class_attr_PE_CTRL_REG.attr, + [PTRAIN_STS_REG] = &class_attr_PTRAIN_STS_REG.attr, + [ERR_STS_REG] = &class_attr_ERR_STS_REG.attr, + [PREST1] = &class_attr_PREST1_uS.attr, + [NREST1] = &class_attr_NREST1_uS.attr, + [NPULS1] = &class_attr_NPULS1_uS.attr, + [PPCNT] = &class_attr_PPCNT.attr, + [PPCNT_MAX] = &class_attr_PPCNT_MAX.attr, + [VLIM1] = &class_attr_VLIM1_uV.attr, + [PVOLT1] = &class_attr_PVOLT1_uV.attr, + [PCURR1] = &class_attr_PCURR1_uA.attr, + [PCURR1_SUM] = &class_attr_PCURR1_SUM_uA.attr, + [PCURR1_TERMINAL] = &class_attr_PCURR1_TERMINAL_uA.attr, + [PTTIME] = &class_attr_PTTIME_S.attr, + [PTTIME_MAX] = &class_attr_PTTIME_MAX_S.attr, + [NREST2] = &class_attr_NREST2_uS.attr, + [NPULS2] = &class_attr_NPULS2_uS.attr, + [VLIM2] = &class_attr_VLIM2_uV.attr, + [PVOLT2] = &class_attr_PVOLT2_uV.attr, + [RVOLT2] = &class_attr_RVOLT2_uV.attr, + [PCURR2] = &class_attr_PCURR2_uA.attr, + [NREST3] = &class_attr_NREST3_uS.attr, + [NPULS3] = &class_attr_NPULS3_uS.attr, + [RVOLT3_VMAX] = &class_attr_RVOLT3_VMAX_uV.attr, + [RVOLT3_VMAX_SNUM] = &class_attr_RVOLT3_VMAX_SNUM.attr, + [VBATT] = &class_attr_VBATT_uV.attr, + [IBATT] = &class_attr_IBATT_uA.attr, + [BATTTEMP] = &class_attr_BATTTEMP_deciDegC.attr, + [BATTSOC] = &class_attr_BATTSOC.attr, + NULL, +}; +ATTRIBUTE_GROUPS(qnovo_class); + +static int qnovo5_update_status(struct qnovo *chip) +{ + u8 val = 0; + int rc; + bool hw_ok_to_qnovo; + + rc = qnovo5_read(chip, QNOVO_ERROR_STS, &val, 1); + if (rc < 0) { + pr_err("Couldn't read error sts rc = %d\n", rc); + hw_ok_to_qnovo = false; + } else { + /* + * For CV mode keep qnovo enabled, userspace is expected to + * disable it after few runs + */ + hw_ok_to_qnovo = (val == ERR_CV_MODE || val == 0) ? + true : false; + } + + vote(chip->not_ok_to_qnovo_votable, HW_OK_TO_QNOVO_VOTER, + !hw_ok_to_qnovo, 0); + return 0; +} + +static void usb_debounce_work(struct work_struct *work) +{ + struct qnovo *chip = container_of(work, + struct qnovo, usb_debounce_work.work); + + vote(chip->chg_ready_votable, USB_READY_VOTER, true, 0); + vote(chip->awake_votable, USB_READY_VOTER, false, 0); +} + +#define DEBOUNCE_MS 15000 /* 15 seconds */ +static void status_change_work(struct work_struct *work) +{ + struct qnovo *chip = container_of(work, + struct qnovo, status_change_work); + union power_supply_propval pval; + bool usb_present = false; + int rc; + + if (is_usb_available(chip)) { + rc = power_supply_get_property(chip->usb_psy, + POWER_SUPPLY_PROP_PRESENT, &pval); + usb_present = (rc < 0) ? 0 : pval.intval; + } + + if (chip->usb_present && !usb_present) { + /* removal */ + chip->usb_present = 0; + cancel_delayed_work_sync(&chip->usb_debounce_work); + vote(chip->awake_votable, USB_READY_VOTER, false, 0); + vote(chip->chg_ready_votable, USB_READY_VOTER, false, 0); + } else if (!chip->usb_present && usb_present) { + /* insertion */ + chip->usb_present = 1; + vote(chip->awake_votable, USB_READY_VOTER, true, 0); + schedule_delayed_work(&chip->usb_debounce_work, + msecs_to_jiffies(DEBOUNCE_MS)); + } + + qnovo5_update_status(chip); +} + +static int qnovo_notifier_call(struct notifier_block *nb, + unsigned long ev, void *v) +{ + struct power_supply *psy = v; + struct qnovo *chip = container_of(nb, struct qnovo, nb); + + if (ev != PSY_EVENT_PROP_CHANGED) + return NOTIFY_OK; + + if (strcmp(psy->desc->name, "battery") == 0 + || strcmp(psy->desc->name, "bms") == 0 + || strcmp(psy->desc->name, "usb") == 0) + schedule_work(&chip->status_change_work); + + return NOTIFY_OK; +} + +static irqreturn_t handle_ptrain_done(int irq, void *data) +{ + struct qnovo *chip = data; + + qnovo5_update_status(chip); + + /* + * hw resets pt_en bit once ptrain_done triggers. + * vote on behalf of QNI to disable it such that + * once QNI enables it, the votable state changes + * and the callback that sets it is indeed invoked + */ + vote(chip->pt_dis_votable, QNI_PT_VOTER, true, 0); + + kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE); + return IRQ_HANDLED; +} + +static int qnovo5_hw_init(struct qnovo *chip) +{ + int rc; + u8 val; + + vote(chip->chg_ready_votable, USB_READY_VOTER, false, 0); + + vote(chip->disable_votable, USER_VOTER, true, 0); + + vote(chip->pt_dis_votable, QNI_PT_VOTER, true, 0); + vote(chip->pt_dis_votable, QNOVO_OVERALL_VOTER, true, 0); + + /* allow charger error conditions to disable qnovo, CV mode excluded */ + val = ERR_JEITA_SOFT_CONDITION | ERR_BAT_OV | + ERR_BATTERY_MISSING | ERR_SAFETY_TIMER_EXPIRED | + ERR_CHARGING_DISABLED | ERR_JEITA_HARD_CONDITION; + rc = qnovo5_write(chip, QNOVO_ERROR_MASK, &val, 1); + if (rc < 0) { + pr_err("Couldn't write QNOVO_ERROR_MASK rc = %d\n", rc); + return rc; + } + + return 0; +} + +static int qnovo5_register_notifier(struct qnovo *chip) +{ + int rc; + + chip->nb.notifier_call = qnovo_notifier_call; + rc = power_supply_reg_notifier(&chip->nb); + if (rc < 0) { + pr_err("Couldn't register psy notifier rc = %d\n", rc); + return rc; + } + + return 0; +} + +static int qnovo5_determine_initial_status(struct qnovo *chip) +{ + status_change_work(&chip->status_change_work); + return 0; +} + +static int qnovo5_request_interrupts(struct qnovo *chip) +{ + int rc = 0; + int irq_ptrain_done = of_irq_get_byname(chip->dev->of_node, + "ptrain-done"); + + rc = devm_request_threaded_irq(chip->dev, irq_ptrain_done, NULL, + handle_ptrain_done, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "ptrain-done", chip); + if (rc < 0) { + pr_err("Couldn't request irq %d rc = %d\n", + irq_ptrain_done, rc); + return rc; + } + + enable_irq_wake(irq_ptrain_done); + + return rc; +} + +static int qnovo5_probe(struct platform_device *pdev) +{ + struct qnovo *chip; + int rc = 0; + + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->fv_uV_request = -EINVAL; + chip->fcc_uA_request = -EINVAL; + chip->dev = &pdev->dev; + mutex_init(&chip->write_lock); + + chip->regmap = dev_get_regmap(chip->dev->parent, NULL); + if (!chip->regmap) { + pr_err("parent regmap is missing\n"); + return -EINVAL; + } + + rc = qnovo5_parse_dt(chip); + if (rc < 0) { + pr_err("Couldn't parse device tree rc=%d\n", rc); + return rc; + } + + /* set driver data before resources request it */ + platform_set_drvdata(pdev, chip); + + chip->disable_votable = create_votable("QNOVO_DISABLE", VOTE_SET_ANY, + qnovo_disable_cb, chip); + if (IS_ERR(chip->disable_votable)) { + rc = PTR_ERR(chip->disable_votable); + chip->disable_votable = NULL; + goto cleanup; + } + + chip->pt_dis_votable = create_votable("QNOVO_PT_DIS", VOTE_SET_ANY, + pt_dis_votable_cb, chip); + if (IS_ERR(chip->pt_dis_votable)) { + rc = PTR_ERR(chip->pt_dis_votable); + chip->pt_dis_votable = NULL; + goto destroy_disable_votable; + } + + chip->not_ok_to_qnovo_votable = create_votable("QNOVO_NOT_OK", + VOTE_SET_ANY, + not_ok_to_qnovo_cb, chip); + if (IS_ERR(chip->not_ok_to_qnovo_votable)) { + rc = PTR_ERR(chip->not_ok_to_qnovo_votable); + chip->not_ok_to_qnovo_votable = NULL; + goto destroy_pt_dis_votable; + } + + chip->chg_ready_votable = create_votable("QNOVO_CHG_READY", + VOTE_SET_ANY, + chg_ready_cb, chip); + if (IS_ERR(chip->chg_ready_votable)) { + rc = PTR_ERR(chip->chg_ready_votable); + chip->chg_ready_votable = NULL; + goto destroy_not_ok_to_qnovo_votable; + } + + chip->awake_votable = create_votable("QNOVO_AWAKE", VOTE_SET_ANY, + awake_cb, chip); + if (IS_ERR(chip->awake_votable)) { + rc = PTR_ERR(chip->awake_votable); + chip->awake_votable = NULL; + goto destroy_chg_ready_votable; + } + + INIT_WORK(&chip->status_change_work, status_change_work); + INIT_DELAYED_WORK(&chip->usb_debounce_work, usb_debounce_work); + + rc = qnovo5_hw_init(chip); + if (rc < 0) { + pr_err("Couldn't initialize hardware rc=%d\n", rc); + goto destroy_awake_votable; + } + + rc = qnovo5_register_notifier(chip); + if (rc < 0) { + pr_err("Couldn't register psy notifier rc = %d\n", rc); + goto unreg_notifier; + } + + rc = qnovo5_determine_initial_status(chip); + if (rc < 0) { + pr_err("Couldn't determine initial status rc=%d\n", rc); + goto unreg_notifier; + } + + rc = qnovo5_request_interrupts(chip); + if (rc < 0) { + pr_err("Couldn't request interrupts rc=%d\n", rc); + goto unreg_notifier; + } + chip->qnovo_class.name = "qnovo", + chip->qnovo_class.owner = THIS_MODULE, + chip->qnovo_class.class_groups = qnovo_class_groups; + + rc = class_register(&chip->qnovo_class); + if (rc < 0) { + pr_err("couldn't register qnovo sysfs class rc = %d\n", rc); + goto unreg_notifier; + } + + device_init_wakeup(chip->dev, true); + + return rc; + +unreg_notifier: + power_supply_unreg_notifier(&chip->nb); +destroy_awake_votable: + destroy_votable(chip->awake_votable); +destroy_chg_ready_votable: + destroy_votable(chip->chg_ready_votable); +destroy_not_ok_to_qnovo_votable: + destroy_votable(chip->not_ok_to_qnovo_votable); +destroy_pt_dis_votable: + destroy_votable(chip->pt_dis_votable); +destroy_disable_votable: + destroy_votable(chip->disable_votable); +cleanup: + platform_set_drvdata(pdev, NULL); + return rc; +} + +static int qnovo5_remove(struct platform_device *pdev) +{ + struct qnovo *chip = platform_get_drvdata(pdev); + + class_unregister(&chip->qnovo_class); + power_supply_unreg_notifier(&chip->nb); + destroy_votable(chip->chg_ready_votable); + destroy_votable(chip->not_ok_to_qnovo_votable); + destroy_votable(chip->pt_dis_votable); + destroy_votable(chip->disable_votable); + platform_set_drvdata(pdev, NULL); + return 0; +} + +static void qnovo5_shutdown(struct platform_device *pdev) +{ + struct qnovo *chip = platform_get_drvdata(pdev); + + vote(chip->not_ok_to_qnovo_votable, SHUTDOWN_VOTER, true, 0); +} + +static const struct of_device_id match_table[] = { + { .compatible = "qcom,qpnp-qnovo5", }, + { }, +}; + +static struct platform_driver qnovo5_driver = { + .driver = { + .name = "qcom,qnovo5-driver", + .owner = THIS_MODULE, + .of_match_table = match_table, + }, + .probe = qnovo5_probe, + .remove = qnovo5_remove, + .shutdown = qnovo5_shutdown, +}; +module_platform_driver(qnovo5_driver); + +MODULE_DESCRIPTION("QPNP Qnovo5 Driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From b9eee1697500eda0a52f1592912af6068d147b8d Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Mon, 11 Jun 2018 07:39:44 +0800 Subject: [PATCH 0306/1299] input: qti-haptics: Add enhancements for effect definitions Add following enhancements for effect subnode definition: 1) Allow variable play rate for LRA effects, it can be set different with the resonance period of LRA actuator for a weaker vibration. 2) Update the wf-pattern byte format to include the reverse bit and overdrive bit. 3) Make brake-pattern configurable for each effect. 4) Make auto resonance configurable for each effect. Change-Id: Icc74dba10477527a8dc2af1c6ca2119674529b34 Signed-off-by: Fenglin Wu --- .../devicetree/bindings/input/qti-haptics.txt | 66 +++++---- drivers/input/misc/qti-haptics.c | 139 +++++++++++------- 2 files changed, 124 insertions(+), 81 deletions(-) diff --git a/Documentation/devicetree/bindings/input/qti-haptics.txt b/Documentation/devicetree/bindings/input/qti-haptics.txt index 8982fc733154..2c4f4f02ae34 100644 --- a/Documentation/devicetree/bindings/input/qti-haptics.txt +++ b/Documentation/devicetree/bindings/input/qti-haptics.txt @@ -66,19 +66,6 @@ Properties: specified in the LRA actuator datasheet. Allowed values are: 0 to 20475. If this is not specified, 5715us play rate is used. -- qcom,brake-pattern - Usage: optional - Value type: - Definition: Specifies the brake pattern with 4 elements used to enable the - internal reverse braking. Allowed values for each element are: - 0: no brake; - 1: brake with (Vmax / 2) strength; - 2: brake with Vmax strength; - 3: brake with (2 * Vmax) strength; - If this property is specified with an array of non-zero values, - then the brake pattern is applied at the end of the playing - waveform. - - qcom,external-waveform-source Usage: optional Value type: @@ -108,11 +95,12 @@ Following properties are specific only when LRA actuator is used: values: "sine", "square". If this is not specified, sinusoid resonance driver signal is used. -- qcom,lra-auto-resonance-en +- qcom,lra-allow-variable-play-rate Usage: optional Value type: - Definition: If specified, the hardware feature of LRA auto resonance detection - is enabled for correcting the resonance frequency variation. + Definition: If specified, "qcom,wf-play-rate-us" for LRA defined in each + effect could be different with the resonance period of the + LRA actuator. - qcom,lra-auto-resonance-mode Usage: optional @@ -136,16 +124,20 @@ waveforms/effects: Usage: required Value type: Definition: Specifies the waveform pattern in a byte array that will be - played for the effect-id. Allowed values for each element - are: 0x00 to 0x1F. + played for the effect-id. The bit fields of each byte are: + [7]: drive direction, 0 - forward; 1 - reverse + [6]: overdrive, 0 -- 1x drive; 1 -- 2x drive + [5:1]: waveform amplitude + [0]: reserved. - qcom,wf-play-rate-us Usage: optional Value type: Definition: Specifies the play period in microseconds for each byte pattern. - For LRA actuator, For LRA, it should be set equal to the resonance - period specified in the LRA actuator datasheet. Allowed values - are: 0 to 20475. + Allowed values are: 0 to 20475. For LRA actuator, if + "qcom,lra-allow-variable-play-rate" is defined, it could be + set to other values not equal to the resonance period of the + LRA actuator. - qcom,wf-repeat-count Usage: optional @@ -159,6 +151,25 @@ waveforms/effects: Definition: Specifies the repeat times for each sample defined in qcom,wf-pattern. Allowed values are: 1, 2, 4, 8. +- qcom,wf-brake-pattern + Usage: optional + Value type: + Definition: Specifies the brake pattern with 4 elements used to enable the + internal reverse braking. Allowed values for each element are: + 0: no brake + 1: brake with (Vmax / 2) strength + 2: brake with Vmax strength + 3: brake with (2 * Vmax) strength + If this property is specified with an array of non-zero values, + then the brake pattern is applied at the end of the playing + waveform. + +- qcom,lra-auto-resonance-disable + Usage: optional + Value type: + Definition: If specified, the hardware feature of LRA auto resonance detection + is disabled. + Example: qcom,haptics@c000 { compatible = "qcom,haptics"; @@ -169,20 +180,23 @@ Example: qcom,actuator-type = "lra"; qcom,vmax-mv = <1800>; qcom,ilim-ma = <400>; - qcom,play-rate-us = <4255>; - qcom,brake-pattern = [03 02 01 00]; + qcom,play-rate-us = <8000>; qcom,lra-resonance-sig-shape = "sine"; - qcom,lra-auto-resonance-mode; + qcom,lra-auto-resonance-mode = "qwd"; + qcom,lra-allow-variable-play-rate; wf_0 { /* CLICK effect */ qcom,effect-id = <0>; - qcom,wf-pattern = [0a 14 1f 1f 1f 1f 14 0a]; + qcom,wf-play-rate-us = <6250>; + qcom,wf-pattern = [3e 3e 3e]; + qcom,lra-auto-resonance-disable; }; wf_5 { /* HEAVY_CLICK effect */ qcom,effect-id = <5>; - qcom,wf-pattern = [08 0a 1a 1f 1f 1a 0a 08]; + qcom,wf-play-rate-us = <6250>; + qcom,wf-pattern = [7e 7e 7e]; }; }; diff --git a/drivers/input/misc/qti-haptics.c b/drivers/input/misc/qti-haptics.c index c5be6b1a68f6..ad9dd51f66ba 100644 --- a/drivers/input/misc/qti-haptics.c +++ b/drivers/input/misc/qti-haptics.c @@ -176,6 +176,10 @@ struct qti_hap_effect { u16 play_rate_us; u8 wf_repeat_n; u8 wf_s_repeat_n; + u8 brake[HAP_BRAKE_PATTERN_MAX]; + int brake_pattern_length; + bool brake_en; + bool lra_auto_res_disable; }; struct qti_hap_play_info { @@ -194,9 +198,7 @@ struct qti_hap_config { u16 vmax_mv; u16 ilim_ma; u16 play_rate_us; - u8 brake[HAP_BRAKE_PATTERN_MAX]; - bool brake_en; - bool lra_auto_res_en; + bool lra_allow_variable_play_rate; bool use_ext_wf_src; }; @@ -550,6 +552,21 @@ static int qti_haptics_config_brake(struct qti_hap_chip *chip, u8 *brake) return rc; } +static int qti_haptics_lra_auto_res_enable(struct qti_hap_chip *chip, bool en) +{ + int rc; + u8 addr, val, mask; + + addr = REG_HAP_AUTO_RES_CTRL; + mask = HAP_AUTO_RES_EN_BIT; + val = en ? HAP_AUTO_RES_EN_BIT : 0; + rc = qti_haptics_masked_write(chip, addr, mask, val); + if (rc < 0) + dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", rc); + + return rc; +} + static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip) { struct qti_hap_play_info *play = &chip->play; @@ -571,6 +588,13 @@ static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip) if (rc < 0) return rc; + /* Enable Auto-Resonance when VMAX wf-src is selected */ + if (config->act_type == ACT_LRA) { + rc = qti_haptics_lra_auto_res_enable(chip, true); + if (rc < 0) + return rc; + } + /* Set WF_SOURCE to VMAX */ rc = qti_haptics_config_wf_src(chip, INT_WF_VMAX); if (rc < 0) @@ -626,14 +650,22 @@ static int qti_haptics_load_predefined_effect(struct qti_hap_chip *chip, if (rc < 0) return rc; - /* override play-rate for ERM here, no need for LRA */ - if (config->act_type == ACT_ERM) { - rc = qti_haptics_config_play_rate_us(chip, - play->effect->play_rate_us); + rc = qti_haptics_config_play_rate_us(chip, play->effect->play_rate_us); + if (rc < 0) + return rc; + + if (config->act_type == ACT_LRA) { + rc = qti_haptics_lra_auto_res_enable(chip, + !play->effect->lra_auto_res_disable); if (rc < 0) return rc; } + /* Set brake pattern in the effect */ + rc = qti_haptics_config_brake(chip, play->effect->brake); + if (rc < 0) + return rc; + rc = qti_haptics_config_wf_buffer(chip); if (rc < 0) return rc; @@ -736,16 +768,14 @@ static irqreturn_t qti_haptics_sc_irq_handler(int irq, void *data) static inline void get_play_length(struct qti_hap_play_info *play, int *length_us) { - struct qti_hap_chip *chip = container_of(play, - struct qti_hap_chip, play); struct qti_hap_effect *effect = play->effect; int tmp; tmp = effect->pattern_length * effect->play_rate_us; tmp *= wf_s_repeat[effect->wf_s_repeat_n]; tmp *= wf_repeat[effect->wf_repeat_n]; - if (chip->config.brake_en) - tmp += effect->play_rate_us * HAP_BRAKE_PATTERN_MAX; + if (effect->brake_en) + tmp += effect->play_rate_us * effect->brake_pattern_length; *length_us = tmp; } @@ -954,9 +984,8 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) /* Set HAP_EN_CTL3 */ addr = REG_HAP_EN_CTL3; val = HAP_HBRIDGE_EN_BIT | HAP_PWM_SIGNAL_EN_BIT | HAP_ILIM_EN_BIT | - HAP_ILIM_CC_EN_BIT | HAP_DAC_EN_BIT | HAP_PWM_CTL_EN_BIT; - if (config->act_type == ACT_LRA && config->lra_auto_res_en) - val |= HAP_AUTO_RES_RBIAS_EN_BIT; + HAP_ILIM_CC_EN_BIT | HAP_AUTO_RES_RBIAS_EN_BIT | + HAP_DAC_EN_BIT | HAP_PWM_CTL_EN_BIT; rc = qti_haptics_write(chip, addr, &val, 1); if (rc < 0) { dev_err(chip->dev, "set EN_CTL3 failed, rc=%d\n", rc); @@ -981,11 +1010,6 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) if (rc < 0) return rc; - /* Set default brake pattern */ - rc = qti_haptics_config_brake(chip, config->brake); - if (rc < 0) - return rc; - /* Set external waveform source if it's used */ if (config->use_ext_wf_src) { rc = qti_haptics_config_wf_src(chip, config->ext_src); @@ -1008,10 +1032,6 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) return rc; } - /* Skip configurations below if auto-res-en is not set */ - if (!config->lra_auto_res_en) - return 0; - addr = REG_HAP_AUTO_RES_CFG; mask = HAP_AUTO_RES_MODE_BIT | HAP_CAL_EOP_EN_BIT | HAP_CAL_PERIOD_MASK; val = config->lra_auto_res_mode << HAP_AUTO_RES_MODE_SHIFT; @@ -1023,8 +1043,9 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) } addr = REG_HAP_AUTO_RES_CTRL; - val = HAP_AUTO_RES_EN_BIT | HAP_SEL_AUTO_RES_PERIOD | AUTO_RES_EN_DLY(4) - | AUTO_RES_CNT_ERR_DELTA(2) | HAP_AUTO_RES_ERR_RECOVERY_BIT; + val = HAP_AUTO_RES_EN_BIT | HAP_SEL_AUTO_RES_PERIOD | + AUTO_RES_CNT_ERR_DELTA(2) | HAP_AUTO_RES_ERR_RECOVERY_BIT | + AUTO_RES_EN_DLY(4); rc = qti_haptics_write(chip, addr, &val, 1); if (rc < 0) { dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", @@ -1096,30 +1117,6 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) config->play_rate_us = (tmp >= HAP_PLAY_RATE_US_MAX) ? HAP_PLAY_RATE_US_MAX : tmp; - tmp = of_property_count_elems_of_size(node, "qcom,brake-pattern", - sizeof(u8)); - if (tmp > 0) { - if (tmp != HAP_BRAKE_PATTERN_MAX) { - dev_err(chip->dev, "brake-pattern should be %d bytes\n", - HAP_BRAKE_PATTERN_MAX); - return -EINVAL; - } - - rc = of_property_read_u8_array(node, "qcom,brake-pattern", - config->brake, HAP_BRAKE_PATTERN_MAX); - if (rc < 0) { - dev_err(chip->dev, "Failed to get brake-pattern, rc=%d\n", - rc); - return rc; - } - - for (val = 0, j = 0; j < HAP_BRAKE_PATTERN_MAX; j++) - val |= (config->brake[j] & HAP_BRAKE_PATTERN_MASK) << - j * HAP_BRAKE_PATTERN_SHIFT; - - config->brake_en = (val != 0); - } - if (of_find_property(node, "qcom,external-waveform-source", NULL)) { if (!of_property_read_string(node, "qcom,external-waveform-source", &str)) { @@ -1162,8 +1159,8 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) } } - config->lra_auto_res_en = of_property_read_bool(node, - "qcom,lra-auto-resonance-en"); + config->lra_allow_variable_play_rate = of_property_read_bool( + node, "qcom,lra-allow-variable-play-rate"); config->lra_auto_res_mode = AUTO_RES_MODE_ZXD; rc = of_property_read_string(node, @@ -1233,10 +1230,6 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) return rc; } - for (j = 0; j < effect->pattern_length; j++) - effect->pattern[j] = effect->pattern[j] << - HAP_WF_AMP_SHIFT; - effect->play_rate_us = config->play_rate_us; rc = of_property_read_u32(child_node, "qcom,wf-play-rate-us", &tmp); @@ -1247,6 +1240,7 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) effect->play_rate_us = tmp; if (config->act_type == ACT_LRA && + !config->lra_allow_variable_play_rate && config->play_rate_us != effect->play_rate_us) { dev_warn(chip->dev, "play rate should match with LRA resonance frequency\n"); effect->play_rate_us = config->play_rate_us; @@ -1277,6 +1271,41 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) effect->wf_s_repeat_n = j; } + + effect->lra_auto_res_disable = of_property_read_bool(node, + "qcom,lra-auto-resonance-disable"); + + tmp = of_property_count_elems_of_size(child_node, + "qcom,wf-brake-pattern", sizeof(u8)); + if (tmp <= 0) + continue; + + if (tmp > HAP_BRAKE_PATTERN_MAX) { + dev_err(chip->dev, "wf-brake-pattern shouldn't be more than %d bytes\n", + HAP_BRAKE_PATTERN_MAX); + return -EINVAL; + } + + rc = of_property_read_u8_array(child_node, + "qcom,wf-brake-pattern", effect->brake, tmp); + if (rc < 0) { + dev_err(chip->dev, "Failed to get wf-brake-pattern, rc=%d\n", + rc); + return rc; + } + + effect->brake_pattern_length = tmp; + for (j = tmp - 1; j >= 0; j--) { + if (effect->brake[j] != 0) + break; + effect->brake_pattern_length--; + } + + for (val = 0, j = 0; j < effect->brake_pattern_length; j++) + val |= (effect->brake[j] & HAP_BRAKE_PATTERN_MASK) + << j * HAP_BRAKE_PATTERN_SHIFT; + + effect->brake_en = (val != 0); } return 0; -- GitLab From 71473271ee2f4dc52dda40b2313427b4d1a4fe56 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Fri, 15 Jun 2018 14:27:11 +0530 Subject: [PATCH 0307/1299] defconfig: Enable USB PHY drivers for QCS405 For QCS405 enable the required SNPS HS PHY and SS PHY drivers. Enable extcon-usb-gpio driver to support GPIO based VBUS and ID detection. Change-Id: I9b943934df4815b745fbf61a677884dc2590e6f2 Signed-off-by: Sriharsha Allenki --- arch/arm/configs/qcs405_defconfig | 5 ++++- arch/arm64/configs/qcs405_defconfig | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/qcs405_defconfig b/arch/arm/configs/qcs405_defconfig index 98b6eaa91bc0..a229bdb7e8d9 100644 --- a/arch/arm/configs/qcs405_defconfig +++ b/arch/arm/configs/qcs405_defconfig @@ -342,12 +342,14 @@ CONFIG_USB_DWC3_MSM=y CONFIG_USB_SERIAL=y CONFIG_USB_EHSET_TEST_FIXTURE=y CONFIG_NOP_USB_XCEIV=y +CONFIG_MSM_SNPS_FEMTO_PHY=y +CONFIG_USB_MSM_SSPHY=y CONFIG_USB_QCOM_EMU_PHY=y CONFIG_DUAL_ROLE_USB_INTF=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DEBUG_FILES=y CONFIG_USB_GADGET_DEBUG_FS=y -CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_VBUS_DRAW=900 CONFIG_USB_CONFIGFS=y CONFIG_USB_CONFIGFS_F_FS=y CONFIG_USB_CONFIGFS_F_DIAG=y @@ -414,6 +416,7 @@ CONFIG_QCOM_BUS_SCALING=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y # CONFIG_MSM_JTAGV8 is not set +CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y CONFIG_PWM=y diff --git a/arch/arm64/configs/qcs405_defconfig b/arch/arm64/configs/qcs405_defconfig index f0201a61cebd..9c5e43575c18 100644 --- a/arch/arm64/configs/qcs405_defconfig +++ b/arch/arm64/configs/qcs405_defconfig @@ -343,12 +343,14 @@ CONFIG_USB_DWC3_MSM=y CONFIG_USB_SERIAL=y CONFIG_USB_EHSET_TEST_FIXTURE=y CONFIG_NOP_USB_XCEIV=y +CONFIG_MSM_SNPS_FEMTO_PHY=y +CONFIG_USB_MSM_SSPHY=y CONFIG_USB_QCOM_EMU_PHY=y CONFIG_DUAL_ROLE_USB_INTF=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DEBUG_FILES=y CONFIG_USB_GADGET_DEBUG_FS=y -CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_VBUS_DRAW=900 CONFIG_USB_CONFIGFS=y CONFIG_USB_CONFIGFS_F_FS=y CONFIG_USB_CONFIGFS_F_DIAG=y @@ -414,6 +416,7 @@ CONFIG_QCOM_BUS_SCALING=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y CONFIG_MSM_PM=y +CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y CONFIG_PWM=y -- GitLab From c1ae59e8415dc193c97937da110fb4d4fc573c36 Mon Sep 17 00:00:00 2001 From: Mulu He Date: Wed, 13 Jun 2018 15:53:21 +0800 Subject: [PATCH 0308/1299] coresight: Reset all activated sinks When multi-sink enabled by userspace, all activated sink should be deactivated in call reset interface. Change-Id: Ie0c4f7bcda4adc1b0dc0d60e433e8c3f634568e2 Signed-off-by: Mulu He --- drivers/hwtracing/coresight/coresight.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 591f97040e40..ef79c9efd840 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012, 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -99,6 +99,23 @@ static int coresight_source_is_unique(struct coresight_device *csdev) csdev, coresight_id_match); } +static int coresight_reset_sink(struct device *dev, void *data) +{ + struct coresight_device *csdev = to_coresight_device(dev); + + if ((csdev->type == CORESIGHT_DEV_TYPE_SINK || + csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && + csdev->activated) + csdev->activated = false; + + return 0; +} + +static void coresight_reset_all_sink(void) +{ + bus_for_each_dev(&coresight_bustype, NULL, NULL, coresight_reset_sink); +} + static int coresight_find_link_inport(struct coresight_device *csdev, struct coresight_device *parent) { @@ -1018,6 +1035,9 @@ static ssize_t reset_source_sink_store(struct bus_type *bus, __coresight_disable(csdev); } + /* Reset all activated sinks */ + coresight_reset_all_sink(); + mutex_unlock(&coresight_mutex); return size; } -- GitLab From 9549890d4abab38680ca525186febc70b4fbb546 Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Tue, 12 Jun 2018 18:10:40 -0400 Subject: [PATCH 0309/1299] msm: npu: Return network handle to user instead of id This change is to return network handle from fw to user driver instead of network id in kernel driver. Change-Id: I50b0ed6d7af6f90c5ec1cabaa3951fbdea6e3001 Signed-off-by: Jilai Wang --- drivers/media/platform/msm/npu/npu_mgr.c | 42 +++++++++++++++++++----- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/msm/npu/npu_mgr.c b/drivers/media/platform/msm/npu/npu_mgr.c index 0348b3ef9788..6861455d1101 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.c +++ b/drivers/media/platform/msm/npu/npu_mgr.c @@ -43,7 +43,10 @@ static void host_irq_wq(struct work_struct *work); static void turn_off_fw_logging(struct npu_device *npu_dev); static int wait_for_fw_ready(struct npu_device *npu_dev); static struct npu_network *alloc_network(struct npu_host_ctx *ctx); -static struct npu_network *get_network(struct npu_host_ctx *ctx, int64_t id); +static struct npu_network *get_network_by_hdl(struct npu_host_ctx *ctx, + uint32_t hdl); +static struct npu_network *get_network_by_id(struct npu_host_ctx *ctx, + int64_t id); static void free_network(struct npu_host_ctx *ctx, int64_t id); static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg); static void log_msg_proc(struct npu_device *npu_dev, uint32_t *msg); @@ -361,6 +364,7 @@ static struct npu_network *alloc_network(struct npu_host_ctx *ctx) * by 1 for the next IPC cmd on the same network */ network->ipc_trans_id = 1; + network->network_hdl = 0; break; } network++; @@ -374,7 +378,28 @@ static struct npu_network *alloc_network(struct npu_host_ctx *ctx) return network; } -static struct npu_network *get_network(struct npu_host_ctx *ctx, int64_t id) +static struct npu_network *get_network_by_hdl(struct npu_host_ctx *ctx, + uint32_t hdl) +{ + int32_t i; + struct npu_network *network = ctx->networks; + + for (i = 0; i < MAX_LOADED_NETWORK; i++) { + if (network->network_hdl == hdl) + break; + + network++; + } + if (i == MAX_LOADED_NETWORK) { + pr_err("network hdl invalid %d\n", hdl); + network = NULL; + } + + return network; +} + +static struct npu_network *get_network_by_id(struct npu_host_ctx *ctx, + int64_t id) { if (id >= 1 && id <= MAX_LOADED_NETWORK) return &ctx->networks[id - 1]; @@ -384,7 +409,7 @@ static struct npu_network *get_network(struct npu_host_ctx *ctx, int64_t id) static void free_network(struct npu_host_ctx *ctx, int64_t id) { - struct npu_network *network = get_network(ctx, id); + struct npu_network *network = get_network_by_id(ctx, id); unsigned long flags; if (network) { @@ -440,7 +465,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) * the network ID on the way back */ network_id = load_rsp_pkt->header.flags; - network = get_network(host_ctx, network_id); + network = get_network_by_id(host_ctx, network_id); if (!network) { pr_err("can't find network %d\n", network_id); break; @@ -600,7 +625,6 @@ int32_t npu_host_load_network(struct npu_device *npu_dev, network->first_block_size = load_ioctl->first_block_size; network->priority = load_ioctl->priority; network->perf_mode = load_ioctl->perf_mode; - load_ioctl->network_hdl = network->id; networks_perf_mode = find_networks_perf_mode(host_ctx); @@ -646,6 +670,8 @@ int32_t npu_host_load_network(struct npu_device *npu_dev, goto error_free_network; } + load_ioctl->network_hdl = network->network_hdl; + return ret; error_free_network: @@ -664,7 +690,7 @@ int32_t npu_host_unload_network(struct npu_device *npu_dev, struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; /* get the corresponding network for ipc trans id purpose */ - network = get_network(host_ctx, (int64_t)unload->network_hdl); + network = get_network_by_hdl(host_ctx, unload->network_hdl); if (!network) return -EINVAL; @@ -698,7 +724,7 @@ int32_t npu_host_unload_network(struct npu_device *npu_dev, * free the network on the kernel if the corresponding ACO * handle is unloaded on the firmware side */ - free_network(host_ctx, (int64_t)unload->network_hdl); + free_network(host_ctx, network->id); fw_deinit(npu_dev, true); } @@ -718,7 +744,7 @@ int32_t npu_host_exec_network(struct npu_device *npu_dev, struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; int i = 0; - network = get_network(host_ctx, (int64_t)exec_ioctl->network_hdl); + network = get_network_by_hdl(host_ctx, exec_ioctl->network_hdl); if (!network) return -EINVAL; -- GitLab From 53c0fbe20d8b1fc185e18b738bee98f25389b3f5 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Mon, 11 Jun 2018 12:41:51 +0530 Subject: [PATCH 0310/1299] regulator: qpnp-lcdb: Introduce regulator off-on delay Add turn on delay for LDO and NCP regulators to make sure that these regulators are not turned on before it is fully discharged. Change-Id: Idfb6034c31f3509d002157f85ad0da051abcc7c1 Signed-off-by: Kiran Gunda --- drivers/regulator/qpnp-lcdb-regulator.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c index 28859e35efd9..fe543aecdcd6 100644 --- a/drivers/regulator/qpnp-lcdb-regulator.c +++ b/drivers/regulator/qpnp-lcdb-regulator.c @@ -167,6 +167,8 @@ #define PM660_BST_HEADROOM_DEFAULT_MV 200 #define BST_HEADROOM_DEFAULT_MV 150 +#define PMIC5_LCDB_OFF_ON_DELAY_US 20000 + struct ldo_regulator { struct regulator_desc rdesc; struct regulator_dev *rdev; @@ -1340,22 +1342,27 @@ static struct regulator_ops qpnp_lcdb_ncp_ops = { static int qpnp_lcdb_regulator_register(struct qpnp_lcdb *lcdb, u8 type) { - int rc = 0; + int rc = 0, off_on_delay = 0; struct regulator_init_data *init_data; struct regulator_config cfg = {}; struct regulator_desc *rdesc; struct regulator_dev *rdev; struct device_node *node; + if (lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE) + off_on_delay = PMIC5_LCDB_OFF_ON_DELAY_US; + if (type == LDO) { node = lcdb->ldo.node; rdesc = &lcdb->ldo.rdesc; rdesc->ops = &qpnp_lcdb_ldo_ops; + rdesc->off_on_delay = off_on_delay; rdev = lcdb->ldo.rdev; } else if (type == NCP) { node = lcdb->ncp.node; rdesc = &lcdb->ncp.rdesc; rdesc->ops = &qpnp_lcdb_ncp_ops; + rdesc->off_on_delay = off_on_delay; rdev = lcdb->ncp.rdev; } else { pr_err("Invalid regulator type %d\n", type); -- GitLab From bc284bf9aa05f533ed8fe30772f411fdb3ab07ab Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Fri, 15 Jun 2018 09:30:35 -0700 Subject: [PATCH 0311/1299] staging: android: ion: WARN_ON_ONCE in ion_buffer_destroy Change warning in ion_buffer_destroy to WARN_ON_ONCE to prevent watchdog timeout as a result of the kernel logs being flooded. Change-Id: I27ec980e072a827804a1caa0766944dfde31a75e Signed-off-by: Liam Mark --- drivers/staging/android/ion/ion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 81c7eb4eab1c..29094d9632ef 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -180,7 +180,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, void ion_buffer_destroy(struct ion_buffer *buffer) { - if (WARN_ON(buffer->kmap_cnt > 0)) + if (WARN_ON_ONCE(buffer->kmap_cnt > 0)) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); buffer->heap->ops->free(buffer); kfree(buffer); -- GitLab From dd15d3d0d9093eb73a618a9614f0547c85f8b47a Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Tue, 12 Jun 2018 19:57:29 -0700 Subject: [PATCH 0312/1299] msm: vidc: Add partial cache operations support Do partial buffer cache operations instead of whole buffer size to save power in video usecases. Change-Id: I0027eb0be2fa30c8d04b7c1a574dd2f1df8cfdec Signed-off-by: Maheshwar Ajja --- drivers/media/platform/msm/vidc/msm_smem.c | 45 ++++++ .../media/platform/msm/vidc/msm_vidc_common.c | 143 ++++++++++++++++++ .../media/platform/msm/vidc/msm_vidc_common.h | 4 +- .../platform/msm/vidc/msm_vidc_internal.h | 2 + .../platform/msm/vidc/msm_vidc_res_parse.c | 11 ++ 5 files changed, 203 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c index ca658a6ea288..94a79ad672d3 100644 --- a/drivers/media/platform/msm/vidc/msm_smem.c +++ b/drivers/media/platform/msm/vidc/msm_smem.c @@ -78,6 +78,13 @@ static int msm_dma_get_device_address(struct dma_buf *dbuf, unsigned long align, * Mapping of sg is taken care by map attachment */ attach->dma_map_attrs = DMA_ATTR_DELAYED_UNMAP; + /* + * We do not need dma_map function to perform cache operations + * on the whole buffer size and hence pass skip sync flag. + * We do the required cache operations separately for the + * required buffer size + */ + attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; if (res->sys_cache_present) attach->dma_map_attrs |= DMA_ATTR_IOMMU_USE_UPSTREAM_HINT; @@ -511,6 +518,44 @@ int msm_smem_free(struct msm_smem *smem) return rc; }; +int msm_smem_cache_operations(struct dma_buf *dbuf, + enum smem_cache_ops cache_op, unsigned long offset, unsigned long size) +{ + int rc = 0; + + if (!dbuf) { + dprintk(VIDC_ERR, "%s: Invalid params\n", __func__); + return -EINVAL; + } + + switch (cache_op) { + case SMEM_CACHE_CLEAN: + case SMEM_CACHE_CLEAN_INVALIDATE: + rc = dma_buf_begin_cpu_access_partial(dbuf, DMA_TO_DEVICE, + offset, size); + if (rc) + break; + rc = dma_buf_end_cpu_access_partial(dbuf, DMA_TO_DEVICE, + offset, size); + break; + case SMEM_CACHE_INVALIDATE: + rc = dma_buf_begin_cpu_access_partial(dbuf, DMA_TO_DEVICE, + offset, size); + if (rc) + break; + rc = dma_buf_end_cpu_access_partial(dbuf, DMA_FROM_DEVICE, + offset, size); + break; + default: + dprintk(VIDC_ERR, "%s: cache (%d) operation not supported\n", + __func__, cache_op); + rc = -EINVAL; + break; + } + + return rc; +} + struct context_bank_info *msm_smem_get_context_bank(u32 session_type, bool is_secure, struct msm_vidc_platform_resources *res, enum hal_buffer buffer_type) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 15dbfe3aaec9..a6302aa4d13e 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -2416,6 +2416,11 @@ static void handle_ebd(enum hal_command_response cmd, void *data) update_recon_stats(inst, &empty_buf_done->recon_stats); msm_vidc_clear_freq_entry(inst, mbuf->smem[0].device_addr); + /* + * dma cache operations need to be performed before dma_unmap + * which is done inside msm_comm_put_vidc_buffer() + */ + msm_comm_dqbuf_cache_operations(inst, mbuf); /* * put_buffer should be done before vb2_buffer_done else * client might queue the same buffer before it is unmapped @@ -2601,6 +2606,11 @@ static void handle_fbd(enum hal_command_response cmd, void *data) } mutex_unlock(&inst->registeredbufs.lock); + /* + * dma cache operations need to be performed before dma_unmap + * which is done inside msm_comm_put_vidc_buffer() + */ + msm_comm_dqbuf_cache_operations(inst, mbuf); /* * put_buffer should be done before vb2_buffer_done else * client might queue the same buffer before it is unmapped @@ -6100,6 +6110,137 @@ int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst, return rc; } +int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst, + struct msm_vidc_buffer *mbuf) +{ + int rc = 0, i; + struct vb2_buffer *vb; + bool skip; + + if (!inst || !mbuf) { + dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n", + __func__, inst, mbuf); + return -EINVAL; + } + vb = &mbuf->vvb.vb2_buf; + + for (i = 0; i < vb->num_planes; i++) { + unsigned long offset, size; + enum smem_cache_ops cache_op; + + skip = true; + if (inst->session_type == MSM_VIDC_DECODER) { + if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + if (!i) { /* bitstream */ + skip = false; + offset = vb->planes[i].data_offset; + size = vb->planes[i].bytesused; + cache_op = SMEM_CACHE_CLEAN_INVALIDATE; + } + } else if (vb->type == + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + if (!i) { /* yuv */ + skip = false; + offset = 0; + size = vb->planes[i].length; + cache_op = SMEM_CACHE_INVALIDATE; + } + } + } else if (inst->session_type == MSM_VIDC_ENCODER) { + if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + if (!i) { /* yuv */ + skip = false; + offset = vb->planes[i].data_offset; + size = vb->planes[i].bytesused; + cache_op = SMEM_CACHE_CLEAN_INVALIDATE; + } + } else if (vb->type == + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + if (!i) { /* bitstream */ + skip = false; + offset = 0; + size = vb->planes[i].length; + cache_op = SMEM_CACHE_INVALIDATE; + } + } + } + + if (!skip) { + rc = msm_smem_cache_operations(mbuf->smem[i].dma_buf, + cache_op, offset, size); + if (rc) + print_vidc_buffer(VIDC_ERR, + "qbuf cache ops failed", inst, mbuf); + } + } + + return rc; +} + +int msm_comm_dqbuf_cache_operations(struct msm_vidc_inst *inst, + struct msm_vidc_buffer *mbuf) +{ + int rc = 0, i; + struct vb2_buffer *vb; + bool skip; + + if (!inst || !mbuf) { + dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n", + __func__, inst, mbuf); + return -EINVAL; + } + vb = &mbuf->vvb.vb2_buf; + + for (i = 0; i < vb->num_planes; i++) { + unsigned long offset, size; + enum smem_cache_ops cache_op; + + skip = true; + if (inst->session_type == MSM_VIDC_DECODER) { + if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + /* bitstream and extradata */ + /* we do not need cache operations */ + } else if (vb->type == + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + if (!i) { /* yuv */ + skip = false; + offset = vb->planes[i].data_offset; + size = vb->planes[i].bytesused; + cache_op = SMEM_CACHE_INVALIDATE; + } + } + } else if (inst->session_type == MSM_VIDC_ENCODER) { + if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + /* yuv and extradata */ + /* we do not need cache operations */ + } else if (vb->type == + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + if (!i) { /* bitstream */ + skip = false; + /* + * Include vp8e header bytes as well + * by making offset equal to zero + */ + offset = 0; + size = vb->planes[i].bytesused + + vb->planes[i].data_offset; + cache_op = SMEM_CACHE_INVALIDATE; + } + } + } + + if (!skip) { + rc = msm_smem_cache_operations(mbuf->smem[i].dma_buf, + cache_op, offset, size); + if (rc) + print_vidc_buffer(VIDC_ERR, + "dqbuf cache ops failed", inst, mbuf); + } + } + + return rc; +} + struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) { @@ -6188,6 +6329,8 @@ struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst, goto exit; } } + /* dma cache operations need to be performed after dma_map */ + msm_comm_qbuf_cache_operations(inst, mbuf); /* special handling for decoder */ if (inst->session_type == MSM_VIDC_DECODER) { diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h index b30adad9f10c..cde7ed37996c 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h @@ -204,9 +204,9 @@ bool msm_comm_compare_device_plane(struct msm_vidc_buffer *mbuf, bool msm_comm_compare_device_planes(struct msm_vidc_buffer *mbuf, u32 *planes); int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst, - struct v4l2_buffer *b); + struct msm_vidc_buffer *mbuf); int msm_comm_dqbuf_cache_operations(struct msm_vidc_inst *inst, - struct v4l2_buffer *b); + struct msm_vidc_buffer *mbuf); void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf); void print_vb2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst, diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index 2996fe0555a2..147d98ebf513 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -514,6 +514,8 @@ int msm_smem_map_dma_buf(struct msm_vidc_inst *inst, struct msm_smem *smem); int msm_smem_unmap_dma_buf(struct msm_vidc_inst *inst, struct msm_smem *smem); struct dma_buf *msm_smem_get_dma_buf(int fd); void msm_smem_put_dma_buf(void *dma_buf); +int msm_smem_cache_operations(struct dma_buf *dbuf, + enum smem_cache_ops cache_op, unsigned long offset, unsigned long size); void msm_vidc_fw_unload_handler(struct work_struct *work); void msm_vidc_ssr_handler(struct work_struct *work); /* diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c index f78a50a4a418..c006fdd473b7 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c @@ -981,6 +981,17 @@ static int msm_vidc_setup_context_bank(struct msm_vidc_platform_resources *res, goto release_mapping; } + /* + * configure device segment size and segment boundary to ensure + * iommu mapping returns one mapping (which is required for partial + * cache operations) + */ + if (!dev->dma_parms) + dev->dma_parms = + devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL); + dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + dma_set_seg_boundary(dev, DMA_BIT_MASK(64)); + dprintk(VIDC_DBG, "Attached %s and created mapping\n", dev_name(dev)); dprintk(VIDC_DBG, "Context bank name:%s, buffer_type: %#x, is_secure: %d, address range start: %#x, size: %#x, dev: %pK, mapping: %pK", -- GitLab From 715523db78f8a69e3710f17e651ca4d7954530fe Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Fri, 20 Apr 2018 16:03:57 -0700 Subject: [PATCH 0313/1299] mhi: core: read bhie offset from external modem MHI BHI/E offset is not always at a constant offset. Read the offset from the device at power on. CRs-Fixed: 2261680 Change-Id: I18bfd63a266107bf22d3446da833afc379293ba8 Signed-off-by: Sujeev Dias --- drivers/bus/mhi/core/mhi_boot.c | 6 +++--- drivers/bus/mhi/core/mhi_internal.h | 27 +++++++++++++++------------ drivers/bus/mhi/core/mhi_pm.c | 19 ++++++++++++++++--- include/linux/mhi.h | 2 ++ 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_boot.c b/drivers/bus/mhi/core/mhi_boot.c index a94447f58367..79a25d5a055b 100644 --- a/drivers/bus/mhi/core/mhi_boot.c +++ b/drivers/bus/mhi/core/mhi_boot.c @@ -54,7 +54,7 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) struct image_info *rddm_image = mhi_cntrl->rddm_image; const u32 delayus = 100; u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus; - void __iomem *base = mhi_cntrl->bhi; + void __iomem *base = mhi_cntrl->bhie; MHI_LOG("Entered with pm_state:%s dev_state:%s ee:%s\n", to_mhi_pm_state_str(mhi_cntrl->pm_state), @@ -137,7 +137,7 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) /* download ramdump image from device */ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic) { - void __iomem *base = mhi_cntrl->bhi; + void __iomem *base = mhi_cntrl->bhie; rwlock_t *pm_lock = &mhi_cntrl->pm_lock; struct image_info *rddm_image = mhi_cntrl->rddm_image; struct mhi_buf *mhi_buf; @@ -219,7 +219,7 @@ EXPORT_SYMBOL(mhi_download_rddm_img); static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl, const struct mhi_buf *mhi_buf) { - void __iomem *base = mhi_cntrl->bhi; + void __iomem *base = mhi_cntrl->bhie; rwlock_t *pm_lock = &mhi_cntrl->pm_lock; u32 tx_status; diff --git a/drivers/bus/mhi/core/mhi_internal.h b/drivers/bus/mhi/core/mhi_internal.h index df085301cac4..01f77382d0d3 100644 --- a/drivers/bus/mhi/core/mhi_internal.h +++ b/drivers/bus/mhi/core/mhi_internal.h @@ -48,6 +48,10 @@ extern struct bus_type mhi_bus_type; #define BHIOFF_BHIOFF_MASK (0xFFFFFFFF) #define BHIOFF_BHIOFF_SHIFT (0) +#define BHIEOFF (0x2C) +#define BHIEOFF_BHIEOFF_MASK (0xFFFFFFFF) +#define BHIEOFF_BHIEOFF_SHIFT (0) + #define DEBUGOFF (0x30) #define DEBUGOFF_DEBUGOFF_MASK (0xFFFFFFFF) #define DEBUGOFF_DEBUGOFF_SHIFT (0) @@ -186,15 +190,14 @@ extern struct bus_type mhi_bus_type; #define BHI_STATUS_RESET (0) /* MHI BHIE offsets */ -#define BHIE_OFFSET (0x0124) /* BHIE register space offset from BHI base */ -#define BHIE_MSMSOCID_OFFS (BHIE_OFFSET + 0x0000) -#define BHIE_TXVECADDR_LOW_OFFS (BHIE_OFFSET + 0x002C) -#define BHIE_TXVECADDR_HIGH_OFFS (BHIE_OFFSET + 0x0030) -#define BHIE_TXVECSIZE_OFFS (BHIE_OFFSET + 0x0034) -#define BHIE_TXVECDB_OFFS (BHIE_OFFSET + 0x003C) +#define BHIE_MSMSOCID_OFFS (0x0000) +#define BHIE_TXVECADDR_LOW_OFFS (0x002C) +#define BHIE_TXVECADDR_HIGH_OFFS (0x0030) +#define BHIE_TXVECSIZE_OFFS (0x0034) +#define BHIE_TXVECDB_OFFS (0x003C) #define BHIE_TXVECDB_SEQNUM_BMSK (0x3FFFFFFF) #define BHIE_TXVECDB_SEQNUM_SHFT (0) -#define BHIE_TXVECSTATUS_OFFS (BHIE_OFFSET + 0x0044) +#define BHIE_TXVECSTATUS_OFFS (0x0044) #define BHIE_TXVECSTATUS_SEQNUM_BMSK (0x3FFFFFFF) #define BHIE_TXVECSTATUS_SEQNUM_SHFT (0) #define BHIE_TXVECSTATUS_STATUS_BMSK (0xC0000000) @@ -202,13 +205,13 @@ extern struct bus_type mhi_bus_type; #define BHIE_TXVECSTATUS_STATUS_RESET (0x00) #define BHIE_TXVECSTATUS_STATUS_XFER_COMPL (0x02) #define BHIE_TXVECSTATUS_STATUS_ERROR (0x03) -#define BHIE_RXVECADDR_LOW_OFFS (BHIE_OFFSET + 0x0060) -#define BHIE_RXVECADDR_HIGH_OFFS (BHIE_OFFSET + 0x0064) -#define BHIE_RXVECSIZE_OFFS (BHIE_OFFSET + 0x0068) -#define BHIE_RXVECDB_OFFS (BHIE_OFFSET + 0x0070) +#define BHIE_RXVECADDR_LOW_OFFS (0x0060) +#define BHIE_RXVECADDR_HIGH_OFFS (0x0064) +#define BHIE_RXVECSIZE_OFFS (0x0068) +#define BHIE_RXVECDB_OFFS (0x0070) #define BHIE_RXVECDB_SEQNUM_BMSK (0x3FFFFFFF) #define BHIE_RXVECDB_SEQNUM_SHFT (0) -#define BHIE_RXVECSTATUS_OFFS (BHIE_OFFSET + 0x0078) +#define BHIE_RXVECSTATUS_OFFS (0x0078) #define BHIE_RXVECSTATUS_SEQNUM_BMSK (0x3FFFFFFF) #define BHIE_RXVECSTATUS_SEQNUM_SHFT (0) #define BHIE_RXVECSTATUS_STATUS_BMSK (0xC0000000) diff --git a/drivers/bus/mhi/core/mhi_pm.c b/drivers/bus/mhi/core/mhi_pm.c index 8572f12da49f..80e29c1e99e8 100644 --- a/drivers/bus/mhi/core/mhi_pm.c +++ b/drivers/bus/mhi/core/mhi_pm.c @@ -790,7 +790,7 @@ void mhi_pm_st_worker(struct work_struct *work) int mhi_async_power_up(struct mhi_controller *mhi_cntrl) { int ret; - u32 bhi_offset; + u32 val; enum MHI_EE current_ee; enum MHI_ST_TRANSITION next_state; @@ -825,14 +825,27 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl) /* setup bhi offset & intvec */ write_lock_irq(&mhi_cntrl->pm_lock); - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIOFF, &bhi_offset); + ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIOFF, &val); if (ret) { write_unlock_irq(&mhi_cntrl->pm_lock); MHI_ERR("Error getting bhi offset\n"); goto error_bhi_offset; } - mhi_cntrl->bhi = mhi_cntrl->regs + bhi_offset; + mhi_cntrl->bhi = mhi_cntrl->regs + val; + + /* setup bhie offset */ + if (mhi_cntrl->fbc_download) { + ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF, &val); + if (ret) { + write_unlock_irq(&mhi_cntrl->pm_lock); + MHI_ERR("Error getting bhie offset\n"); + goto error_bhi_offset; + } + + mhi_cntrl->bhie = mhi_cntrl->regs + val; + } + mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, 0); mhi_cntrl->pm_state = MHI_PM_POR; mhi_cntrl->ee = MHI_EE_MAX; diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 006c253ca45b..de8f19d50221 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -87,6 +87,7 @@ struct image_info { * @of_node: DT that has MHI configuration information * @regs: Points to base of MHI MMIO register space * @bhi: Points to base of MHI BHI register space + * @bhie: Points to base of MHI BHIe register space * @wake_db: MHI WAKE doorbell register address * @dev_id: PCIe device id of the external device * @domain: PCIe domain the device connected to @@ -137,6 +138,7 @@ struct mhi_controller { /* mmio base */ void __iomem *regs; void __iomem *bhi; + void __iomem *bhie; void __iomem *wake_db; /* device topology */ -- GitLab From 8d010cbb770f920a45da6824b1a7b33ca00fa9a5 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Thu, 14 Jun 2018 10:47:30 -0700 Subject: [PATCH 0314/1299] mhi: dev: uci: release lock as last step during uci_remove Release device mutex as last step, otherwise uci_release could free device memory while uci_remove still accessing same device node. CRs-Fixed: 2257246 Change-Id: I746eefc704152b528e80be7676f4a8604abcd38d Signed-off-by: Sujeev Dias --- drivers/bus/mhi/devices/mhi_uci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/mhi/devices/mhi_uci.c b/drivers/bus/mhi/devices/mhi_uci.c index bc02e1097924..12934efcd4a8 100644 --- a/drivers/bus/mhi/devices/mhi_uci.c +++ b/drivers/bus/mhi/devices/mhi_uci.c @@ -540,8 +540,8 @@ static void mhi_uci_remove(struct mhi_device *mhi_dev) return; } - mutex_unlock(&uci_dev->mutex); MSG_LOG("Exit\n"); + mutex_unlock(&uci_dev->mutex); } static int mhi_uci_probe(struct mhi_device *mhi_dev, -- GitLab From 0b19bb1a723fa2dac74bbdaaa82c55885fb027c9 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Thu, 14 Jun 2018 11:21:54 -0700 Subject: [PATCH 0315/1299] mhi: dev: uci: update terminal signals bit settings Incorrect bit mask was used when decoding TIOCM_RI bit. Updated to correct bit settings. CRs-Fixed: 2260878 Change-Id: Icd752f3fddf493ad212f489314da25beeb4d4f99 Signed-off-by: Sujeev Dias --- drivers/bus/mhi/core/mhi_dtr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/mhi/core/mhi_dtr.c b/drivers/bus/mhi/core/mhi_dtr.c index af57b942a315..6ffe80163a96 100644 --- a/drivers/bus/mhi/core/mhi_dtr.c +++ b/drivers/bus/mhi/core/mhi_dtr.c @@ -37,7 +37,7 @@ struct __packed dtr_ctrl_msg { #define CTRL_MSG_RTS BIT(1) #define CTRL_MSG_DCD BIT(0) #define CTRL_MSG_DSR BIT(1) -#define CTRL_MSG_RI BIT(2) +#define CTRL_MSG_RI BIT(3) #define CTRL_HOST_STATE (0x10) #define CTRL_DEVICE_STATE (0x11) #define CTRL_GET_CHID(dtr) (dtr->dest_id & 0xFF) -- GitLab From 13b4ffdea9343afbd402f2bf54817a7205c0b4fc Mon Sep 17 00:00:00 2001 From: Tapas Kumar Kundu Date: Tue, 12 Jun 2018 11:01:05 -0700 Subject: [PATCH 0316/1299] msm: vidc: update max mb/sec load This change is to clamp a codec session based on SM8150 capability. SM8150 can support maximum of single 1080p@480fps session or codec sessions adding upto 1080p@480fps. CRs-Fixed: 2259123 Change-Id: I87ec9155cb5b1f4746a41871a58f3088900f0665 Signed-off-by: Tapas Kumar Kundu --- drivers/media/platform/msm/vidc/msm_vidc_platform.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c index 8281ea7fec3d..88e6bb103fd0 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c @@ -196,7 +196,12 @@ static struct msm_vidc_common_data sm8150_common_data[] = { }, { .key = "qcom,max-hw-load", - .value = 4147200, /* 4096x2160/256 MBs@120fps */ + .value = 3916800, /* + * 1920x1088/256 MBs@480fps. It is less + * any other usecases (ex: + * 3840x2160@120fps, 4096x2160@96ps, + * 7680x4320@30fps) + */ }, { .key = "qcom,max-hq-mbs-per-frame", -- GitLab From 384f9d9175ed3959cf14ac1f4f2544f0fbc63b3b Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Thu, 7 Jun 2018 15:54:33 -0700 Subject: [PATCH 0317/1299] diag: diagfwd_socket: Increase socket receive buf Diag expects heavy traffic when maximum logging is enabled. The maximum amount of packets QRTR will deliver before flow control kicks in is 16k * 10. Use setsockopt to increase the rcvbuf for the diag sockets to avoid dropping any packets from the remote. Change-Id: I782997c00e1f4ccefb8cee635b65ae2edb733396 Signed-off-by: Chris Lew --- drivers/char/diag/diagfwd_socket.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c index 13be6d6cdf69..2312c85fad70 100644 --- a/drivers/char/diag/diagfwd_socket.c +++ b/drivers/char/diag/diagfwd_socket.c @@ -52,6 +52,10 @@ #define INST_ID_DCI_CMD 3 #define INST_ID_DCI 4 +#define MAX_BUF_SIZE 0x4400 +#define MAX_NO_PACKETS 10 +#define DIAG_SO_RCVBUF_SIZE (MAX_BUF_SIZE * MAX_NO_PACKETS) + struct qmi_handle *cntl_qmi; static uint64_t bootup_req[NUM_SOCKET_SUBSYSTEMS]; @@ -438,6 +442,7 @@ static void socket_open_server(struct diag_socket_info *info) struct kvec iv = { &pkt, sizeof(pkt) }; int ret; int sl = sizeof(sq); + unsigned int size = DIAG_SO_RCVBUF_SIZE; if (!info || info->port_type != PORT_TYPE_SERVER) return; @@ -456,6 +461,9 @@ static void socket_open_server(struct diag_socket_info *info) return; } + kernel_setsockopt(info->hdl, SOL_SOCKET, SO_RCVBUF, + (char *)&size, sizeof(size)); + write_lock_bh(&info->hdl->sk->sk_callback_lock); info->hdl->sk->sk_user_data = (void *)(info); info->hdl->sk->sk_data_ready = socket_data_ready; -- GitLab From c83f06079b76f5cf3efb443cfb14c91f3d5fcc08 Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Fri, 15 Jun 2018 12:22:31 -0700 Subject: [PATCH 0318/1299] defconfig: Change panic timeout for target sm8150 Change panic timeout for target sm8150 so that the device reboots immediately when a kernel panic is encountered, instead of waiting for 5 seconds. Change-Id: I6d883920e04aac1085109979391532157e63078f Signed-off-by: Isaac J. Manjarres --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 2 +- arch/arm64/configs/vendor/sm8150_defconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 83d8f020491f..64964924bd3a 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -596,7 +596,7 @@ CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO=y CONFIG_MAGIC_SYSRQ=y -CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANIC_TIMEOUT=-1 CONFIG_SCHEDSTATS=y # CONFIG_DEBUG_PREEMPT is not set CONFIG_IPC_LOGGING=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 3b919f593861..3b9dc1534ce0 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -647,7 +647,7 @@ CONFIG_DEBUG_STACK_USAGE=y CONFIG_DEBUG_MEMORY_INIT=y CONFIG_SOFTLOCKUP_DETECTOR=y CONFIG_WQ_WATCHDOG=y -CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANIC_TIMEOUT=-1 CONFIG_PANIC_ON_SCHED_BUG=y CONFIG_PANIC_ON_RT_THROTTLING=y CONFIG_SCHEDSTATS=y -- GitLab From e9077e9470cfde288cbb998eb42518d797341ba0 Mon Sep 17 00:00:00 2001 From: Harshdeep Dhatt Date: Mon, 11 Jun 2018 11:31:21 -0600 Subject: [PATCH 0319/1299] msm: kgsl: Update CP ROQ size for a640 and a680 These targets have ROQ twice as big as a630. So dump the correct size of ROQ in the snapshot. Change-Id: I776ece5062d96584f6431475c6ab6a05d2d426c7 Signed-off-by: Harshdeep Dhatt --- drivers/gpu/msm/adreno_a6xx_snapshot.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c index 4b26b7d50b15..f24247c1ae97 100644 --- a/drivers/gpu/msm/adreno_a6xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c @@ -1495,7 +1495,11 @@ void a6xx_snapshot(struct adreno_device *adreno_dev, struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); struct adreno_snapshot_data *snap_data = gpudev->snapshot_data; bool sptprac_on; - unsigned int i; + unsigned int i, roq_size; + + /* ROQ size is 0x800 DW on a640 and a680 */ + roq_size = adreno_is_a640(adreno_dev) || adreno_is_a680(adreno_dev) ? + (snap_data->sect_sizes->roq * 2) : snap_data->sect_sizes->roq; /* GMU TCM data dumped through AHB */ if (gmu_dev_ops->snapshot) @@ -1547,8 +1551,7 @@ void a6xx_snapshot(struct adreno_device *adreno_dev, /* CP ROQ */ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUG, - snapshot, adreno_snapshot_cp_roq, - &snap_data->sect_sizes->roq); + snapshot, adreno_snapshot_cp_roq, &roq_size); /* SQE Firmware */ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUG, -- GitLab From 89912133d5f1889263c997487b242b5cc2222dcd Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Fri, 8 Jun 2018 13:33:20 -0700 Subject: [PATCH 0320/1299] drm/msm/dp: fix the controller programming sequence Fix the controller programming sequence to ensure that all hardware configuration (MSA, transfer unit, timing, etc.) are done before the timing engine is enabled. This ensures the controller is in the correct state before video data starts flowing. CRs-Fixed: 2250510 Change-Id: Ib77574afe01e5fb88e97bff740de7fba77afa900 Signed-off-by: Tatenda Chipeperekwa --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 40 +++++++++++++++++------------ drivers/gpu/drm/msm/dp/dp_display.c | 7 ++--- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index ba9566e9170c..38bf81205f74 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -147,7 +147,7 @@ static void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl, enum dp_stream_id strm) if (!wait_for_completion_timeout(&ctrl->idle_comp, idle_pattern_completion_timeout_ms)) - pr_warn("PUSH_IDLE pattern timedout\n"); + pr_warn("PUSH_IDLE time out\n"); pr_debug("mainlink off done\n"); } @@ -179,11 +179,11 @@ static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl) ret = wait_for_completion_timeout(&ctrl->video_comp, HZ / 2); if (ret <= 0) { - pr_err("Link Train timedout\n"); - ret = -EINVAL; + pr_err("SEND_VIDEO time out (%d)\n", ret); + return -EINVAL; } - return ret; + return 0; } static int dp_ctrl_update_sink_vx_px(struct dp_ctrl_private *ctrl, @@ -838,21 +838,22 @@ static void dp_ctrl_reset(struct dp_ctrl *dp_ctrl) ctrl->catalog->reset(ctrl->catalog); } +static void dp_ctrl_send_video(struct dp_ctrl_private *ctrl) +{ + ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO); +} + static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, struct dp_panel *panel) { u32 x_int, y_frac_enum, lanes, bw_code; bool act_complete; - if (!ctrl->mst_mode) { - ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO); + if (!ctrl->mst_mode) return 0; - } DP_MST_DEBUG("mst stream channel allocation\n"); - panel->hw_cfg(panel); - ctrl->catalog->channel_alloc(ctrl->catalog, panel->stream_id, panel->channel_start_slot, @@ -875,8 +876,6 @@ static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, DP_MST_DEBUG("mst lane_cnt:%d, bw:%d, x_int:%d, y_frac:%d\n", lanes, bw_code, x_int, y_frac_enum); - ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO); - ctrl->catalog->trigger_act(ctrl->catalog); msleep(20); /* needs 1 frame time */ @@ -897,8 +896,7 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) struct dp_ctrl_private *ctrl; if (!dp_ctrl || !panel) { - rc = -EINVAL; - goto end; + return -EINVAL; } ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); @@ -906,7 +904,7 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) rc = dp_ctrl_enable_stream_clocks(ctrl, panel); if (rc) { pr_err("failure on stream clock enable\n"); - goto end; + return rc; } if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { @@ -914,15 +912,23 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) return 0; } + rc = panel->hw_cfg(panel); + if (rc) + return rc; + + dp_ctrl_send_video(ctrl); + rc = dp_ctrl_mst_stream_setup(ctrl, panel); if (rc) - goto end; + return rc; + + rc = dp_ctrl_wait4video_ready(ctrl); + if (rc) + return rc; - dp_ctrl_wait4video_ready(ctrl); link_ready = ctrl->catalog->mainlink_ready(ctrl->catalog); pr_debug("mainlink %s\n", link_ready ? "READY" : "NOT READY"); -end: return rc; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 7613825f68b8..963bcc0c306e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1262,8 +1262,10 @@ static int dp_display_enable(struct dp_display *dp_display, void *panel) } rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active); - if (!rc) - dp->power_on = true; + if (rc) + goto end; + + dp->power_on = true; stream_setup: rc = dp_display_stream_enable(dp, panel); @@ -1278,7 +1280,6 @@ static void dp_display_stream_post_enable(struct dp_display_private *dp, { dp_panel->spd_config(dp_panel); dp_panel->setup_hdr(dp_panel, NULL); - dp_panel->hw_cfg(dp_panel); dp_panel->audio->register_ext_disp(dp_panel->audio); } -- GitLab From bfde4305ca76ed310b68fdb9ff36ed9cf2239783 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Thu, 7 Jun 2018 11:11:31 -0700 Subject: [PATCH 0321/1299] soc: qcom: qmi: Data flow control updates Optimize the qmi_rmnet change_link path. Fix a dfc bug on module de-init with concurrent packet processing. CRs-Fixed: 2259239 Change-Id: I7124684f5be557bd6cb8545ffc01ebb929e0ec1b Signed-off-by: Subash Abhinov Kasiviswanathan --- .../ethernet/qualcomm/rmnet/rmnet_config.c | 19 +- drivers/soc/qcom/dfc_qmi.c | 226 ++++++------ drivers/soc/qcom/qmi_rmnet.c | 325 ++++++++++-------- drivers/soc/qcom/qmi_rmnet_i.h | 24 +- include/soc/qcom/qmi_rmnet.h | 9 +- include/soc/qcom/rmnet_qmi.h | 4 +- 6 files changed, 331 insertions(+), 276 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c index bbe23053cb33..30de5df17106 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c @@ -256,6 +256,8 @@ static void rmnet_force_unassociate_device(struct net_device *dev) rcu_read_unlock(); unregister_netdevice_many(&list); + qmi_rmnet_qmi_exit(port->qmi_info, port); + rmnet_unregister_real_device(real_dev, port); } @@ -501,7 +503,7 @@ void *rmnet_get_rmnet_port(struct net_device *dev) struct rmnet_priv *priv; if (dev) { - priv = (struct rmnet_priv *)netdev_priv(dev); + priv = netdev_priv(dev); return (void *)rmnet_get_port(priv->real_dev); } @@ -509,13 +511,20 @@ void *rmnet_get_rmnet_port(struct net_device *dev) } EXPORT_SYMBOL(rmnet_get_rmnet_port); -struct net_device *rmnet_get_rmnet_dev(void *port, uint8_t mux_id) +struct net_device *rmnet_get_rmnet_dev(void *port, u8 mux_id) { struct rmnet_endpoint *ep; - ep = rmnet_get_endpoint((struct rmnet_port *)port, mux_id); - if (ep) - return ep->egress_dev; + if (port) { + struct net_device *dev; + + ep = rmnet_get_endpoint((struct rmnet_port *)port, mux_id); + if (ep) { + dev = ep->egress_dev; + + return dev; + } + } return NULL; } diff --git a/drivers/soc/qcom/dfc_qmi.c b/drivers/soc/qcom/dfc_qmi.c index dea5f5c07c50..4ea628924d6c 100644 --- a/drivers/soc/qcom/dfc_qmi.c +++ b/drivers/soc/qcom/dfc_qmi.c @@ -15,6 +15,7 @@ #include #include #include + #include #include "qmi_rmnet_i.h" @@ -27,42 +28,13 @@ #define NO_CHANGE 1 #define UPDATED 2 -struct qmap_header { - uint8_t pad_len:6; - uint8_t reserved_bit:1; - uint8_t cd_bit:1; - uint8_t mux_id; - __be16 pkt_len; -} __aligned(1); - -struct dfc_ack_cmd { - struct qmap_header header; - uint8_t command_name; - uint8_t cmd_type:2; - uint8_t reserved:6; - uint16_t reserved2; - uint32_t transaction_id; - uint8_t qos_ver:2; - uint8_t reserved3:6; - uint8_t qos_type:2; - uint8_t reserved4:6; - uint16_t dfc_seq; - uint8_t reserved5[3]; - uint8_t bearer_id; -} __aligned(1); - -struct dfc_qos_ids { - uint32_t qos_id_valid; - uint32_t qos_id; -}; - struct dfc_work { struct work_struct work; struct net_device *dev; - uint8_t bearer_id; - uint8_t ack_req; - uint16_t seq; - uint8_t mux_id; + u8 bearer_id; + u8 ack_req; + u16 seq; + u8 mux_id; }; struct dfc_qmi_data { @@ -112,7 +84,7 @@ static void dfc_disable_flow(struct work_struct *work); #define QMI_DFC_FLOW_STATUS_IND_V01_MAX_MSG_LEN 471 struct dfc_bind_client_req_msg_v01 { - uint8_t ep_id_valid; + u8 ep_id_valid; struct data_ep_id_type_v01 ep_id; }; @@ -121,8 +93,8 @@ struct dfc_bind_client_resp_msg_v01 { }; struct dfc_indication_register_req_msg_v01 { - uint8_t report_flow_status_valid; - uint8_t report_flow_status; + u8 report_flow_status_valid; + u8 report_flow_status; }; struct dfc_indication_register_resp_msg_v01 { @@ -137,17 +109,17 @@ enum dfc_ip_type_enum_v01 { }; struct dfc_qos_id_type_v01 { - uint32_t qos_id; + u32 qos_id; enum dfc_ip_type_enum_v01 ip_type; }; struct dfc_flow_status_info_type_v01 { - uint8_t subs_id; - uint8_t mux_id; - uint8_t bearer_id; - uint32_t num_bytes; - uint16_t seq_num; - uint8_t qos_ids_len; + u8 subs_id; + u8 mux_id; + u8 bearer_id; + u32 num_bytes; + u16 seq_num; + u8 qos_ids_len; struct dfc_qos_id_type_v01 qos_ids[DFC_MAX_QOS_ID_V01]; }; @@ -155,7 +127,7 @@ static struct qmi_elem_info dfc_qos_id_type_v01_ei[] = { { .data_type = QMI_UNSIGNED_4_BYTE, .elem_len = 1, - .elem_size = sizeof(uint32_t), + .elem_size = sizeof(u32), .is_array = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, .offset = offsetof(struct dfc_qos_id_type_v01, @@ -183,7 +155,7 @@ static struct qmi_elem_info dfc_flow_status_info_type_v01_ei[] = { { .data_type = QMI_UNSIGNED_1_BYTE, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, .offset = offsetof(struct @@ -194,7 +166,7 @@ static struct qmi_elem_info dfc_flow_status_info_type_v01_ei[] = { { .data_type = QMI_UNSIGNED_1_BYTE, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, .offset = offsetof(struct @@ -205,7 +177,7 @@ static struct qmi_elem_info dfc_flow_status_info_type_v01_ei[] = { { .data_type = QMI_UNSIGNED_1_BYTE, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, .offset = offsetof(struct @@ -216,7 +188,7 @@ static struct qmi_elem_info dfc_flow_status_info_type_v01_ei[] = { { .data_type = QMI_UNSIGNED_4_BYTE, .elem_len = 1, - .elem_size = sizeof(uint32_t), + .elem_size = sizeof(u32), .is_array = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, .offset = offsetof(struct @@ -227,7 +199,7 @@ static struct qmi_elem_info dfc_flow_status_info_type_v01_ei[] = { { .data_type = QMI_UNSIGNED_2_BYTE, .elem_len = 1, - .elem_size = sizeof(uint16_t), + .elem_size = sizeof(u16), .is_array = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, .offset = offsetof(struct @@ -238,7 +210,7 @@ static struct qmi_elem_info dfc_flow_status_info_type_v01_ei[] = { { .data_type = QMI_DATA_LEN, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, .offset = offsetof(struct @@ -269,18 +241,18 @@ static struct qmi_elem_info dfc_flow_status_info_type_v01_ei[] = { * that have registered for this event reporting. */ struct dfc_flow_status_ind_msg_v01 { - uint8_t flow_status_valid; - uint8_t flow_status_len; + u8 flow_status_valid; + u8 flow_status_len; struct dfc_flow_status_info_type_v01 flow_status[DFC_MAX_BEARERS_V01]; - uint8_t eod_ack_reqd_valid; - uint8_t eod_ack_reqd; + u8 eod_ack_reqd_valid; + u8 eod_ack_reqd; }; static struct qmi_elem_info dfc_bind_client_req_msg_v01_ei[] = { { .data_type = QMI_OPT_FLAG, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct dfc_bind_client_req_msg_v01, @@ -326,7 +298,7 @@ static struct qmi_elem_info dfc_indication_register_req_msg_v01_ei[] = { { .data_type = QMI_OPT_FLAG, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct @@ -337,7 +309,7 @@ static struct qmi_elem_info dfc_indication_register_req_msg_v01_ei[] = { { .data_type = QMI_UNSIGNED_1_BYTE, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct @@ -375,7 +347,7 @@ static struct qmi_elem_info dfc_flow_status_ind_v01_ei[] = { { .data_type = QMI_OPT_FLAG, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct @@ -386,7 +358,7 @@ static struct qmi_elem_info dfc_flow_status_ind_v01_ei[] = { { .data_type = QMI_DATA_LEN, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct @@ -409,7 +381,7 @@ static struct qmi_elem_info dfc_flow_status_ind_v01_ei[] = { { .data_type = QMI_OPT_FLAG, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct @@ -420,7 +392,7 @@ static struct qmi_elem_info dfc_flow_status_ind_v01_ei[] = { { .data_type = QMI_UNSIGNED_1_BYTE, .elem_len = 1, - .elem_size = sizeof(uint8_t), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct @@ -492,7 +464,7 @@ dfc_bind_client_req(struct qmi_handle *dfc_handle, static int dfc_indication_register_req(struct qmi_handle *dfc_handle, - struct sockaddr_qrtr *ssctl, uint8_t reg) + struct sockaddr_qrtr *ssctl, u8 reg) { struct dfc_indication_register_resp_msg_v01 *resp; struct dfc_indication_register_req_msg_v01 *req; @@ -557,7 +529,7 @@ static int dfc_init_service(struct dfc_qmi_data *data, struct qmi_info *qmi) return dfc_indication_register_req(&data->handle, &data->ssctl, 1); } -static int dfc_disable_bearer_flows(struct net_device *dev, uint8_t bearer_id) +static int dfc_disable_bearer_flows(struct net_device *dev, u8 bearer_id) { struct qos_info *qos = (struct qos_info *)rmnet_get_qos_pt(dev); struct list_head *p; @@ -583,14 +555,12 @@ static int dfc_disable_bearer_flows(struct net_device *dev, uint8_t bearer_id) return rc; } -static int dfc_update_fc_map(struct qos_info *qos, uint8_t ack_req, +static int dfc_update_fc_map(struct qos_info *qos, u8 ack_req, struct dfc_flow_status_info_type_v01 *fc_info) { struct rmnet_bearer_map *itm = NULL; - unsigned long flags; int rc = NO_BEARER; - write_lock_irqsave(&qos->flow_map_lock, flags); itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id); if (itm) { if ((itm->grant_size == fc_info->num_bytes) && @@ -605,11 +575,10 @@ static int dfc_update_fc_map(struct qos_info *qos, uint8_t ack_req, } itm->counter = 0; } - write_unlock_irqrestore(&qos->flow_map_lock, flags); return rc; } -static int dfc_do_fc(struct net_device *dev, uint32_t flow_id, +static int dfc_do_fc(struct net_device *dev, u32 flow_id, int ip_type, int enable) { struct qos_info *qos = (struct qos_info *)rmnet_get_qos_pt(dev); @@ -621,9 +590,7 @@ static int dfc_do_fc(struct net_device *dev, uint32_t flow_id, itm = qmi_rmnet_get_flow_map(qos, flow_id, ip_type); if (itm) { - rtnl_lock(); len = tc_qdisc_flow_control(dev, itm->tcm_handle, enable); - rtnl_unlock(); } return len; } @@ -668,9 +635,26 @@ static void dfc_do_burst_flow_control(struct work_struct *work) struct net_device *dev; struct qos_info *qos; struct dfc_flow_status_info_type_v01 *flow_status; - uint8_t ack_req = ind->eod_ack_reqd_valid ? ind->eod_ack_reqd : 0; + u8 ack_req = ind->eod_ack_reqd_valid ? ind->eod_ack_reqd : 0; int i, rc; + if (!svc_ind->data->rmnet_port) { + kfree(ind); + kfree(svc_ind); + return; + } + + /* This will drop some messages but that is + * unavoidable for now since the notifier callback is + * protected by rtnl_lock() and destroy_workqueue() + * will dead lock with this. + */ + if (!rtnl_trylock()) { + kfree(ind); + kfree(svc_ind); + return; + } + for (i = 0; i < ind->flow_status_len; i++) { flow_status = &ind->flow_status[i]; dev = rmnet_get_rmnet_dev(svc_ind->data->rmnet_port, @@ -703,6 +687,7 @@ static void dfc_do_burst_flow_control(struct work_struct *work) clean_out: kfree(ind); kfree(svc_ind); + rtnl_unlock(); } static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, @@ -713,16 +698,17 @@ static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, struct dfc_flow_status_ind_msg_v01 *ind_msg; struct dfc_svc_ind *svc_ind; - if (qmi != &dfc->handle) { - pr_err("Wrong client\n"); + if (!dfc->rmnet_port) + return; + + if (qmi != &dfc->handle) return; - } ind_msg = (struct dfc_flow_status_ind_msg_v01 *)data; if (ind_msg->flow_status_valid) { if (ind_msg->flow_status_len > DFC_MAX_BEARERS_V01) { - pr_err("Invalid fc info len: %d\n", - ind_msg->flow_status_len); + pr_err("%s() Invalid fc info len: %d\n", + __func__, ind_msg->flow_status_len); return; } @@ -765,7 +751,6 @@ static void dfc_svc_init(struct work_struct *work) } qmi->fc_info[data->modem].dfc_client = (void *)data; - pr_debug("Connection established with the DFC Service\n"); } static int dfc_svc_arrive(struct qmi_handle *qmi, struct qmi_service *svc) @@ -787,14 +772,13 @@ static void dfc_svc_exit(struct qmi_handle *qmi, struct qmi_service *svc) struct dfc_qmi_data *data = container_of(qmi, struct dfc_qmi_data, handle); struct qmi_info *qmi_pt; - int modem; + int client; - pr_debug("Connection with DFC service lost\n"); qmi_pt = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (qmi_pt) { - for (modem = 0; modem < 2; modem++) { - if (qmi_pt->fc_info[modem].dfc_client == (void *)data) - qmi_pt->fc_info[modem].dfc_client = NULL; + for (client = 0; client < 2; client++) { + if (qmi_pt->fc_info[client].dfc_client == (void *)data) + qmi_pt->fc_info[client].dfc_client = NULL; break; } } @@ -818,38 +802,31 @@ static struct qmi_msg_handler qmi_indication_handler[] = { {}, }; -/* **************************************************** */ -int dfc_qmi_client_init(void *port, int modem) +int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) { - struct qmi_info *qmi = rmnet_get_qmi_pt(port); struct dfc_qmi_data *data; - int rc = 0; - - if (!qmi) - return -EINVAL; + int rc = -ENOMEM; - data = kmalloc(sizeof(struct dfc_qmi_data), GFP_KERNEL); + data = kzalloc(sizeof(struct dfc_qmi_data), GFP_KERNEL); if (!data) return -ENOMEM; - memset(data, 0, sizeof(struct dfc_qmi_data)); data->rmnet_port = port; data->modem = modem; data->dfc_wq = create_singlethread_workqueue("dfc_wq"); if (!data->dfc_wq) { pr_err("%s Could not create workqueue\n", __func__); - kfree(data); - return -ENOMEM; + goto err0; } + INIT_WORK(&data->svc_arrive, dfc_svc_init); rc = qmi_handle_init(&data->handle, QMI_DFC_FLOW_STATUS_IND_V01_MAX_MSG_LEN, &server_ops, qmi_indication_handler); if (rc < 0) { pr_err("%s: failed qmi_handle_init - rc[%d]\n", __func__, rc); - kfree(data); - return rc; + goto err1; } rc = qmi_add_lookup(&data->handle, DFC_SERVICE_ID_V01, @@ -857,9 +834,17 @@ int dfc_qmi_client_init(void *port, int modem) qmi->fc_info[modem].svc.instance); if (rc < 0) { pr_err("%s: failed qmi_add_lookup - rc[%d]\n", __func__, rc); - qmi_handle_release(&data->handle); + goto err2; } + return 0; + +err2: + qmi_handle_release(&data->handle); +err1: + destroy_workqueue(data->dfc_wq); +err0: + kfree(data); return rc; } @@ -867,47 +852,48 @@ void dfc_qmi_client_exit(void *dfc_data) { struct dfc_qmi_data *data = (struct dfc_qmi_data *)dfc_data; - if (!data) - return; + /* Skip this call for now due to error in qmi layer + * qmi_handle_release(&data->handle); + */ - qmi_handle_release(&data->handle); + drain_workqueue(data->dfc_wq); + destroy_workqueue(data->dfc_wq); + kfree(data); } void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, struct sk_buff *skb) { - struct dfc_work *svc_check; struct rmnet_bearer_map *bearer; + struct dfc_work *svc_check; struct rmnet_flow_map *itm; - unsigned long flags; int ip_type; if (!qos || !skb) return; + if (!rtnl_trylock()) + return; ip_type = (ip_hdr(skb)->version == IP_VER_6) ? AF_INET6 : AF_INET; - write_lock_irqsave(&qos->flow_map_lock, flags); - itm = qmi_rmnet_get_flow_map(qos, skb->mark, ip_type); - if (!itm) { - write_unlock_irqrestore(&qos->flow_map_lock, flags); - } else { + itm = qmi_rmnet_get_flow_map(qos, skb->mark, ip_type); + if (itm) { bearer = qmi_rmnet_get_bearer_map(qos, itm->bearer_id); if (unlikely(!bearer)) { - write_unlock_irqrestore(&qos->flow_map_lock, flags); + rtnl_unlock(); return; } + bearer->counter += skb->len; - if (bearer->counter < bearer->grant_size) { - write_unlock_irqrestore(&qos->flow_map_lock, flags); - } else { + if (bearer->counter >= bearer->grant_size) { bearer->counter = 0; - write_unlock_irqrestore(&qos->flow_map_lock, flags); svc_check = kmalloc(sizeof(struct dfc_work), GFP_ATOMIC); - if (!svc_check) + if (!svc_check) { + rtnl_unlock(); return; + } INIT_WORK((struct work_struct *)svc_check, dfc_disable_flow); @@ -916,8 +902,24 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, svc_check->ack_req = bearer->ack_req; svc_check->seq = bearer->seq; svc_check->mux_id = qos->mux_id; + rtnl_unlock(); schedule_work((struct work_struct *)svc_check); + } else { + rtnl_unlock(); } + } else { + rtnl_unlock(); + } +} + +void dfc_reset_port_pt(void *dfc_data) +{ + struct dfc_qmi_data *data = (struct dfc_qmi_data *)dfc_data; + + if (data) { + data->rmnet_port = NULL; + dfc_indication_register_req(&data->handle, &data->ssctl, 0); + destroy_workqueue(data->dfc_wq); } } diff --git a/drivers/soc/qcom/qmi_rmnet.c b/drivers/soc/qcom/qmi_rmnet.c index a6a7b2506538..601ac1f8a48a 100644 --- a/drivers/soc/qcom/qmi_rmnet.c +++ b/drivers/soc/qcom/qmi_rmnet.c @@ -14,12 +14,14 @@ #include #include #include +#include #include #include "qmi_rmnet_i.h" -#define MODEM_0_INSTANCE 0 -#define MODEM_0 0 -#define MODEM_1 1 +#define NLMSG_FLOW_ACTIVATE 1 +#define NLMSG_FLOW_DEACTIVATE 2 +#define NLMSG_CLIENT_SETUP 4 +#define NLMSG_CLIENT_DELETE 5 struct qmi_elem_info data_ep_id_type_v01_ei[] = { { @@ -35,7 +37,7 @@ struct qmi_elem_info data_ep_id_type_v01_ei[] = { { .data_type = QMI_UNSIGNED_4_BYTE, .elem_len = 1, - .elem_size = sizeof(uint32_t), + .elem_size = sizeof(u32), .is_array = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, .offset = offsetof(struct data_ep_id_type_v01, @@ -54,19 +56,41 @@ struct qmi_elem_info data_ep_id_type_v01_ei[] = { }; EXPORT_SYMBOL(data_ep_id_type_v01_ei); -static void *qmi_rmnet_qmi_init(void) +static struct qmi_info *qmi_rmnet_qmi_init(void) { struct qmi_info *qmi_info; + int i; qmi_info = kzalloc(sizeof(*qmi_info), GFP_KERNEL); if (!qmi_info) return NULL; - return (void *)qmi_info; + for (i = 0; i < MAX_CLIENT_NUM; i++) + qmi_info->fc_info[i].dfc_client = NULL; + + return qmi_info; +} + +static void qmi_rmnet_clean_flow_list(struct qos_info *qos) +{ + struct rmnet_bearer_map *bearer, *br_tmp; + struct rmnet_flow_map *itm, *fl_tmp; + + ASSERT_RTNL(); + + list_for_each_entry_safe(itm, fl_tmp, &qos->flow_head, list) { + list_del(&itm->list); + kfree(itm); + } + + list_for_each_entry_safe(bearer, br_tmp, &qos->bearer_head, list) { + list_del(&bearer->list); + kfree(bearer); + } } struct rmnet_flow_map * -qmi_rmnet_get_flow_map(struct qos_info *qos, uint32_t flow_id, int ip_type) +qmi_rmnet_get_flow_map(struct qos_info *qos, u32 flow_id, int ip_type) { struct rmnet_flow_map *itm; @@ -74,9 +98,6 @@ qmi_rmnet_get_flow_map(struct qos_info *qos, uint32_t flow_id, int ip_type) return NULL; list_for_each_entry(itm, &qos->flow_head, list) { - if (unlikely(!itm)) - return NULL; - if ((itm->flow_id == flow_id) && (itm->ip_type == ip_type)) return itm; } @@ -92,9 +113,6 @@ qmi_rmnet_get_bearer_map(struct qos_info *qos, uint8_t bearer_id) return NULL; list_for_each_entry(itm, &qos->bearer_head, list) { - if (unlikely(!itm)) - return NULL; - if (itm->bearer_id == bearer_id) return itm; } @@ -110,84 +128,89 @@ static void qmi_rmnet_update_flow_map(struct rmnet_flow_map *itm, itm->tcm_handle = new_map->tcm_handle; } -static int qmi_rmnet_add_flow(struct net_device *dev, struct qmi_info *qmi, - struct rmnet_flow_map *new_map) +static int qmi_rmnet_add_flow(struct net_device *dev, struct tcmsg *tcm) { struct qos_info *qos_info = (struct qos_info *)rmnet_get_qos_pt(dev); - struct rmnet_flow_map *itm; + struct rmnet_flow_map new_map, *itm; struct rmnet_bearer_map *bearer; - unsigned long flags; if (!qos_info) return -EINVAL; - pr_debug("%s() bearer[%u], flow[%u], ip[%u]\n", __func__, - new_map->bearer_id, new_map->flow_id, new_map->ip_type); + ASSERT_RTNL(); - write_lock_irqsave(&qos_info->flow_map_lock, flags); - itm = qmi_rmnet_get_flow_map(qos_info, new_map->flow_id, - new_map->ip_type); + /* flow activate + * tcm->tcm__pad1 - bearer_id, tcm->tcm_parent - flow_id, + * tcm->tcm_ifindex - ip_type, tcm->tcm_handle - tcm_handle + */ + + new_map.bearer_id = tcm->tcm__pad1; + new_map.flow_id = tcm->tcm_parent; + new_map.ip_type = tcm->tcm_ifindex; + new_map.tcm_handle = tcm->tcm_handle; + + itm = qmi_rmnet_get_flow_map(qos_info, new_map.flow_id, + new_map.ip_type); if (itm) { - qmi_rmnet_update_flow_map(itm, new_map); + qmi_rmnet_update_flow_map(itm, &new_map); } else { - write_unlock_irqrestore(&qos_info->flow_map_lock, flags); itm = kzalloc(sizeof(*itm), GFP_KERNEL); if (!itm) return -ENOMEM; - qmi_rmnet_update_flow_map(itm, new_map); - write_lock_irqsave(&qos_info->flow_map_lock, flags); + qmi_rmnet_update_flow_map(itm, &new_map); list_add(&itm->list, &qos_info->flow_head); } - bearer = qmi_rmnet_get_bearer_map(qos_info, new_map->bearer_id); + bearer = qmi_rmnet_get_bearer_map(qos_info, new_map.bearer_id); if (bearer) { bearer->flow_ref++; } else { - write_unlock_irqrestore(&qos_info->flow_map_lock, flags); bearer = kzalloc(sizeof(*bearer), GFP_KERNEL); if (!bearer) return -ENOMEM; - bearer->bearer_id = new_map->bearer_id; + bearer->bearer_id = new_map.bearer_id; bearer->flow_ref = 1; bearer->grant_size = qos_info->default_grant; - write_lock_irqsave(&qos_info->flow_map_lock, flags); list_add(&bearer->list, &qos_info->bearer_head); } - write_unlock_irqrestore(&qos_info->flow_map_lock, flags); + return 0; } static int -qmi_rmnet_del_flow(struct net_device *dev, struct rmnet_flow_map *new_map) +qmi_rmnet_del_flow(struct net_device *dev, struct tcmsg *tcm) { struct qos_info *qos_info = (struct qos_info *)rmnet_get_qos_pt(dev); - struct rmnet_flow_map *itm; + struct rmnet_flow_map new_map, *itm; struct rmnet_bearer_map *bearer; - unsigned long flags; int bearer_removed = 0; - if (!qos_info) { - pr_err("%s() NULL qos info\n", __func__); + if (!qos_info) return -EINVAL; - } - pr_debug("%s() bearer[%u], flow[%u], ip[%u]\n", __func__, - new_map->bearer_id, new_map->flow_id, new_map->ip_type); - write_lock_irqsave(&qos_info->flow_map_lock, flags); - itm = qmi_rmnet_get_flow_map(qos_info, new_map->flow_id, - new_map->ip_type); + ASSERT_RTNL(); + + /* flow deactivate + * tcm->tcm__pad1 - bearer_id, tcm->tcm_parent - flow_id, + * tcm->tcm_ifindex - ip_type + */ + + new_map.bearer_id = tcm->tcm__pad1; + new_map.flow_id = tcm->tcm_parent; + new_map.ip_type = tcm->tcm_ifindex; + itm = qmi_rmnet_get_flow_map(qos_info, new_map.flow_id, + new_map.ip_type); if (itm) list_del(&itm->list); /*clear bearer map*/ - bearer = qmi_rmnet_get_bearer_map(qos_info, new_map->bearer_id); + bearer = qmi_rmnet_get_bearer_map(qos_info, new_map.bearer_id); if (bearer && --bearer->flow_ref == 0) { list_del(&bearer->list); bearer_removed = 1; } - write_unlock_irqrestore(&qos_info->flow_map_lock, flags); kfree(itm); if (bearer_removed) @@ -239,111 +262,110 @@ int qmi_rmnet_reg_dereg_fc_ind(void *port, int reg) EXPORT_SYMBOL(qmi_rmnet_reg_dereg_fc_ind); #endif -void qmi_rmnet_change_link(struct net_device *dev, void *port, void *tcm_pt) +static int +qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) { - struct tcmsg *tcm = (struct tcmsg *)tcm_pt; - struct qmi_info *qmi = (struct qmi_info *)rmnet_get_qmi_pt(port); - struct rmnet_flow_map new_map; int idx; - if (!dev || !port || !tcm_pt) - return; + ASSERT_RTNL(); - switch (tcm->tcm_family) { - case 1: - /* - * flow activate - * tcm->tcm__pad1 - bearer_id, tcm->tcm_parent - flow_id, - * tcm->tcm_ifindex - ip_type, tcm->tcm_handle - tcm_handle - */ + /* client setup + * tcm->tcm_handle - instance, tcm->tcm_info - ep_type, + * tcm->tcm_parent - iface_id, tcm->tcm_ifindex - flags + */ + idx = (tcm->tcm_handle == 0) ? 0 : 1; + + if (!qmi) { + qmi = qmi_rmnet_qmi_init(); if (!qmi) - return; + return -ENOMEM; - new_map.bearer_id = tcm->tcm__pad1; - new_map.flow_id = tcm->tcm_parent; - new_map.ip_type = tcm->tcm_ifindex; - new_map.tcm_handle = tcm->tcm_handle; - qmi_rmnet_add_flow(dev, qmi, &new_map); - break; - case 2: - /* - * flow deactivate - * tcm->tcm__pad1 - bearer_id, tcm->tcm_parent - flow_id, - * tcm->tcm_ifindex - ip_type + rmnet_init_qmi_pt(port, qmi); + } + + if (!qmi->fc_info[idx].dfc_client) { + qmi->client_count++; + + /* we may receive multiple client setup events if userspace + * creates a new dfc client. */ - if (!qmi) + qmi->flag = tcm->tcm_ifindex; + + qmi->fc_info[idx].svc.instance = tcm->tcm_handle; + qmi->fc_info[idx].svc.ep_type = tcm->tcm_info; + qmi->fc_info[idx].svc.iface_id = tcm->tcm_parent; + + return dfc_qmi_client_init(port, idx, qmi); + } + + return 0; +} + +static int +__qmi_rmnet_delete_client(void *port, struct qmi_info *qmi, int idx) +{ + + ASSERT_RTNL(); + + /* dfc_client can be deleted by service request before + * client delete event arrival. Decrease client_count here always + */ + + if (qmi->fc_info[idx].dfc_client) { + qmi->client_count--; + dfc_qmi_client_exit(qmi->fc_info[idx].dfc_client); + qmi->fc_info[idx].dfc_client = NULL; + + if (qmi->client_count == 0) { + rmnet_reset_qmi_pt(port); + kfree(qmi); + return 0; + } + } + + return 1; +} + +static void +qmi_rmnet_delete_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm) +{ + int idx; + + /* client delete: tcm->tcm_handle - instance*/ + idx = (tcm->tcm_handle == 0) ? 0 : 1; + + __qmi_rmnet_delete_client(port, qmi, idx); +} + +void qmi_rmnet_change_link(struct net_device *dev, void *port, void *tcm_pt) +{ + struct qmi_info *qmi = (struct qmi_info *)rmnet_get_qmi_pt(port); + struct tcmsg *tcm = (struct tcmsg *)tcm_pt; + + switch (tcm->tcm_family) { + case NLMSG_FLOW_ACTIVATE: + if (!qmi || !(qmi->flag & 0x01)) return; - new_map.bearer_id = tcm->tcm__pad1; - new_map.flow_id = tcm->tcm_parent; - new_map.ip_type = tcm->tcm_ifindex; - qmi_rmnet_del_flow(dev, &new_map); + qmi_rmnet_add_flow(dev, tcm); break; - case 4: - /* - * modem up - * tcm->tcm_handle - instance, tcm->tcm_info - ep_type, - * tcm->tcm_parent - iface_id, tcm->tcm_ifindex - flags - */ - pr_debug("%s() instance[%u], ep_type[%u], iface[%u]\n", - __func__, tcm->tcm_handle, tcm->tcm_info, - tcm->tcm_parent); + case NLMSG_FLOW_DEACTIVATE: + if (!qmi || !(qmi->flag & 0x01)) + return; - if (tcm->tcm_ifindex != 1) + qmi_rmnet_del_flow(dev, tcm); + break; + case NLMSG_CLIENT_SETUP: + if (!(tcm->tcm_ifindex & 0x01)) return; - if (tcm->tcm_handle == MODEM_0_INSTANCE) - idx = MODEM_0; - else - idx = MODEM_1; - - if (!qmi) { - qmi = (struct qmi_info *)qmi_rmnet_qmi_init(); - if (!qmi) - return; - qmi->modem_count = 1; - rmnet_init_qmi_pt(port, qmi); - } else if (!qmi->fc_info[idx].dfc_client) { - /* - * dfc_client is per modem, we may receive multiple - * modem up events due to netmagrd restarts so only - * increase modem_count when we need to create a new - * dfc client. - */ - qmi->modem_count++; - } - if (qmi->fc_info[idx].dfc_client == NULL) { - qmi->fc_info[idx].svc.instance = tcm->tcm_handle; - qmi->fc_info[idx].svc.ep_type = tcm->tcm_info; - qmi->fc_info[idx].svc.iface_id = tcm->tcm_parent; - if (dfc_qmi_client_init(port, idx) < 0) - pr_err("%s failed[%d]\n", __func__, idx); - } + qmi_rmnet_setup_client(port, qmi, tcm); break; - case 5: - /* modem down: tcm->tcm_handle - instance*/ - pr_debug("%s() instance[%u]\n", __func__, tcm->tcm_handle); + case NLMSG_CLIENT_DELETE: if (!qmi) return; - if (tcm->tcm_handle == MODEM_0_INSTANCE) - idx = MODEM_0; - else - idx = MODEM_1; - - /* - * dfc_client can be deleted by service request before - * modem down event arrival. Decrease modem_count here always - */ - qmi->modem_count--; - if (qmi->fc_info[idx].dfc_client) { - dfc_qmi_client_exit(qmi->fc_info[idx].dfc_client); - qmi->fc_info[idx].dfc_client = NULL; - } - if (qmi->modem_count == 0) { - kfree(qmi); - rmnet_reset_qmi_pt(port); - } + qmi_rmnet_delete_client(port, qmi, tcm); break; default: pr_debug("%s(): No handler\n", __func__); @@ -352,23 +374,22 @@ void qmi_rmnet_change_link(struct net_device *dev, void *port, void *tcm_pt) } EXPORT_SYMBOL(qmi_rmnet_change_link); -void *qmi_rmnet_qos_init(struct net_device *real_dev, uint8_t mux_id) +void *qmi_rmnet_qos_init(struct net_device *real_dev, u8 mux_id) { - struct qos_info *qos_info; + struct qos_info *qos; - qos_info = kmalloc(sizeof(struct qos_info), GFP_KERNEL); - if (!qos_info) + qos = kmalloc(sizeof(*qos), GFP_KERNEL); + if (!qos) return NULL; - qos_info->mux_id = mux_id; - qos_info->real_dev = real_dev; - qos_info->default_grant = 10240; - qos_info->tran_num = 0; - rwlock_init(&qos_info->flow_map_lock); - INIT_LIST_HEAD(&qos_info->flow_head); - INIT_LIST_HEAD(&qos_info->bearer_head); + qos->mux_id = mux_id; + qos->real_dev = real_dev; + qos->default_grant = 10240; + qos->tran_num = 0; + INIT_LIST_HEAD(&qos->flow_head); + INIT_LIST_HEAD(&qos->bearer_head); - return (void *)qos_info; + return qos; } EXPORT_SYMBOL(qmi_rmnet_qos_init); @@ -376,6 +397,22 @@ void qmi_rmnet_qos_exit(struct net_device *dev) { struct qos_info *qos = (struct qos_info *)rmnet_get_qos_pt(dev); + qmi_rmnet_clean_flow_list(qos); kfree(qos); } EXPORT_SYMBOL(qmi_rmnet_qos_exit); + +void qmi_rmnet_qmi_exit(void *qmi_pt, void *port) +{ + struct qmi_info *qmi = (struct qmi_info *)qmi_pt; + int i; + + if (!qmi) + return; + + for (i = 0; i < MAX_CLIENT_NUM; i++) { + if (!__qmi_rmnet_delete_client(port, qmi, i)) + return; + } +} +EXPORT_SYMBOL(qmi_rmnet_qmi_exit); diff --git a/drivers/soc/qcom/qmi_rmnet_i.h b/drivers/soc/qcom/qmi_rmnet_i.h index d2047763b6dd..e87778d98eb5 100644 --- a/drivers/soc/qcom/qmi_rmnet_i.h +++ b/drivers/soc/qcom/qmi_rmnet_i.h @@ -20,7 +20,7 @@ #define IP_VER_4 4 #define IP_VER_6 6 -#define MAX_MODEM_NUM 2 +#define MAX_CLIENT_NUM 2 struct rmnet_flow_map { struct list_head list; @@ -52,18 +52,18 @@ struct fc_info { }; struct qos_info { - uint8_t mux_id; + u8 mux_id; struct net_device *real_dev; - rwlock_t flow_map_lock; struct list_head flow_head; struct list_head bearer_head; - uint32_t default_grant; - uint32_t tran_num; + u32 default_grant; + u32 tran_num; }; struct qmi_info { - int modem_count; - struct fc_info fc_info[MAX_MODEM_NUM]; + int client_count; + int flag; + struct fc_info fc_info[MAX_CLIENT_NUM]; }; enum data_ep_type_enum_v01 { @@ -79,22 +79,24 @@ enum data_ep_type_enum_v01 { struct data_ep_id_type_v01 { enum data_ep_type_enum_v01 ep_type; - uint32_t iface_id; + u32 iface_id; }; extern struct qmi_elem_info data_ep_id_type_v01_ei[]; struct rmnet_flow_map * qmi_rmnet_get_flow_map(struct qos_info *qos_info, - uint32_t flow_id, int ip_type); + u32 flow_id, int ip_type); struct rmnet_bearer_map * -qmi_rmnet_get_bearer_map(struct qos_info *qos_info, uint8_t bearer_id); +qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id); -int dfc_qmi_client_init(void *port, int modem); +int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi); void dfc_qmi_client_exit(void *dfc_data); +void dfc_reset_port_pt(void *dfc_data); + void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, struct sk_buff *skb); diff --git a/include/soc/qcom/qmi_rmnet.h b/include/soc/qcom/qmi_rmnet.h index 152f434210e7..e171d8cf53d1 100644 --- a/include/soc/qcom/qmi_rmnet.h +++ b/include/soc/qcom/qmi_rmnet.h @@ -18,13 +18,14 @@ #include #ifdef CONFIG_QCOM_QMI_DFC -void *qmi_rmnet_qos_init(struct net_device *real_dev, uint8_t mux_id); +void *qmi_rmnet_qos_init(struct net_device *real_dev, u8 mux_id); void qmi_rmnet_qos_exit(struct net_device *dev); +void qmi_rmnet_qmi_exit(void *qmi_pt, void *port); void qmi_rmnet_change_link(struct net_device *dev, void *port, void *tcm_pt); void qmi_rmnet_burst_fc_check(struct net_device *dev, struct sk_buff *skb); #else static inline void *qmi_rmnet_qos_init(struct net_device *real_dev, - uint8_t mux_id) + u8 mux_id) { return NULL; } @@ -33,6 +34,10 @@ static inline void qmi_rmnet_qos_exit(struct net_device *dev) { } +static inline void qmi_rmnet_qmi_exit(void *qmi_pt, void *port) +{ +} + static inline void qmi_rmnet_change_link(struct net_device *dev, void *port, void *tcm_pt) { diff --git a/include/soc/qcom/rmnet_qmi.h b/include/soc/qcom/rmnet_qmi.h index 532c69d008b0..7ab5a6241008 100644 --- a/include/soc/qcom/rmnet_qmi.h +++ b/include/soc/qcom/rmnet_qmi.h @@ -19,7 +19,7 @@ void *rmnet_get_qmi_pt(void *port); void *rmnet_get_qos_pt(struct net_device *dev); void *rmnet_get_rmnet_port(struct net_device *dev); -struct net_device *rmnet_get_rmnet_dev(void *port, uint8_t mux_id); +struct net_device *rmnet_get_rmnet_dev(void *port, u8 mux_id); void rmnet_reset_qmi_pt(void *port); void rmnet_init_qmi_pt(void *port, void *qmi); #else @@ -39,7 +39,7 @@ static inline void *rmnet_get_rmnet_port(struct net_device *dev) } static inline struct net_device *rmnet_get_rmnet_dev(void *port, - uint8_t mux_id) + u8 mux_id) { return NULL; } -- GitLab From db24d160c60417136533be18f80379ae878ac260 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Fri, 15 Jun 2018 14:42:57 -0600 Subject: [PATCH 0322/1299] defconfig: sm8150: Enable data flow control and power save Enable kernel burst mode flow control and power collapse feature. Burst mode Data Flow Control (DFC) is handled in kernel. Flow info is added/deleted to rmnet driver if DFC is supported. Flow is enabled if grant size is larger than 0 on flow status indication. Flow is disabled if grant size is 0 or UL data size larger than grant size. CRs-Fixed: 2259239 Change-Id: I4cef709856133943a2ec3e9a56bcfb55704a129f Signed-off-by: Subash Abhinov Kasiviswanathan --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 2 ++ arch/arm64/configs/vendor/sm8150_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 83d8f020491f..c3adfafea314 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -507,6 +507,8 @@ CONFIG_QCOM_LLCC=y CONFIG_QCOM_SM8150_LLCC=y CONFIG_QCOM_LLCC_PERFMON=m CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_QMI_DFC=y +CONFIG_QCOM_QMI_POWER_COLLAPSE=y CONFIG_QCOM_SMEM=y CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_QCOM_WATCHDOG_V2=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 3b919f593861..162c9a7ab110 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -528,6 +528,8 @@ CONFIG_QCOM_LLCC=y CONFIG_QCOM_SM8150_LLCC=y CONFIG_QCOM_LLCC_PERFMON=m CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_QMI_DFC=y +CONFIG_QCOM_QMI_POWER_COLLAPSE=y CONFIG_QCOM_SMEM=y CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_QCOM_WATCHDOG_V2=y -- GitLab From 9dfd7835a3e093eb36b499bcc0b647155de69bfd Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 25 May 2018 21:48:16 -0700 Subject: [PATCH 0323/1299] net: qrtr: Move resume-tx transmission to recvmsg The confirm-rx bit is used to implement a per port flow control, in order to make sure that no messages are dropped due to resource exhaustion. Move the resume-tx transmission to recvmsg to only confirm messages as they are consumed by the application. Change-Id: I616045b66f5fe227308d559007852afbceca2d07 Signed-off-by: Bjorn Andersson Git-commit: ddef359a31b63e8755f95c5cc82d659c4386f7fd Git-repo: https://github.com/andersson/kernel.git [clew@codeaurora.org: checkpatch format warnings and remove extra variables] Signed-off-by: Chris Lew --- net/qrtr/qrtr.c | 59 ++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index a66b217ba723..8b2b9256d6bc 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -372,23 +372,13 @@ static void qrtr_port_put(struct qrtr_sock *ipc); static void qrtr_node_rx_work(struct work_struct *work) { struct qrtr_node *node = container_of(work, struct qrtr_node, work); - struct qrtr_ctrl_pkt *pkt; - struct sockaddr_qrtr dst; - struct sockaddr_qrtr src; struct sk_buff *skb; while ((skb = skb_dequeue(&node->rx_queue)) != NULL) { struct qrtr_sock *ipc; struct qrtr_cb *cb; - int confirm; cb = (struct qrtr_cb *)skb->cb; - src.sq_node = cb->src_node; - src.sq_port = cb->src_port; - dst.sq_node = cb->dst_node; - dst.sq_port = cb->dst_port; - confirm = !!cb->confirm_rx; - qrtr_node_assign(node, cb->src_node); ipc = qrtr_port_lookup(cb->dst_port); @@ -400,20 +390,6 @@ static void qrtr_node_rx_work(struct work_struct *work) qrtr_port_put(ipc); } - - if (confirm) { - skb = qrtr_alloc_ctrl_packet(&pkt); - if (!skb) - break; - - pkt->cmd = cpu_to_le32(QRTR_TYPE_RESUME_TX); - pkt->client.node = cpu_to_le32(dst.sq_node); - pkt->client.port = cpu_to_le32(dst.sq_port); - - if (qrtr_node_enqueue(node, skb, QRTR_TYPE_RESUME_TX, - &dst, &src)) - break; - } } } @@ -835,6 +811,36 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) return rc; } +static int qrtr_resume_tx(struct qrtr_cb *cb) +{ + struct sockaddr_qrtr remote = { AF_QIPCRTR, + cb->src_node, cb->src_port }; + struct sockaddr_qrtr local = { AF_QIPCRTR, cb->dst_node, cb->dst_port }; + struct qrtr_ctrl_pkt *pkt; + struct qrtr_node *node; + struct sk_buff *skb; + int ret; + + node = qrtr_node_lookup(remote.sq_node); + if (!node) + return -EINVAL; + + skb = qrtr_alloc_ctrl_packet(&pkt); + if (!skb) + return -ENOMEM; + + pkt->cmd = cpu_to_le32(QRTR_TYPE_RESUME_TX); + pkt->client.node = cpu_to_le32(cb->dst_node); + pkt->client.port = cpu_to_le32(cb->dst_port); + + ret = qrtr_node_enqueue(node, skb, QRTR_TYPE_RESUME_TX, + &local, &remote); + + qrtr_node_release(node); + + return ret; +} + static int qrtr_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) { @@ -857,6 +863,7 @@ static int qrtr_recvmsg(struct socket *sock, struct msghdr *msg, release_sock(sk); return rc; } + cb = (struct qrtr_cb *)skb->cb; copied = skb->len; if (copied > size) { @@ -870,7 +877,6 @@ static int qrtr_recvmsg(struct socket *sock, struct msghdr *msg, rc = copied; if (addr) { - cb = (struct qrtr_cb *)skb->cb; addr->sq_family = AF_QIPCRTR; addr->sq_node = cb->src_node; addr->sq_port = cb->src_port; @@ -878,6 +884,9 @@ static int qrtr_recvmsg(struct socket *sock, struct msghdr *msg, } out: + if (cb->confirm_rx) + qrtr_resume_tx(cb); + skb_free_datagram(sk, skb); release_sock(sk); -- GitLab From 7e70b07426fd2e3d22eec5b54b13b2ce14af2d50 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Fri, 15 Jun 2018 15:00:03 -0700 Subject: [PATCH 0324/1299] power: qpnp-fg-gen4: Add support to configure thermistor pull up Battery thermistor pull up resistor configuration for GEN4 FG comes from battery profile. Add support to read the property from the battery profile and configure it. Change-Id: Ib63047c8d141339443770c8e4dcc980f8b12007a Signed-off-by: Subbaraman Narayanamurthy --- .../bindings/batterydata/batterydata.txt | 2 ++ drivers/power/supply/qcom/fg-core.h | 1 + drivers/power/supply/qcom/fg-reg.h | 6 ++++ drivers/power/supply/qcom/qpnp-fg-gen4.c | 33 +++++++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/Documentation/devicetree/bindings/batterydata/batterydata.txt b/Documentation/devicetree/bindings/batterydata/batterydata.txt index 8cc89e3e62c1..d00fd94a4812 100644 --- a/Documentation/devicetree/bindings/batterydata/batterydata.txt +++ b/Documentation/devicetree/bindings/batterydata/batterydata.txt @@ -69,6 +69,8 @@ Profile data node optional properties: size 5. - qcom,therm-center-offset: Specifies the resistor divide ratio between pull-up resistor and the thermistor for GEN4 FG. +- qcom,therm-pull-up: Specifies the thermistor pull-up resistor value in + KOhms. - qcom,rslow-normal-coeffs: Array of Rslow coefficients that will be applied when the battery temperature is greater than 0 degree Celsius for GEN4 FG. This should be exactly of size 4. diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index ab5a4ecb18da..26c7aca5dc65 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -291,6 +291,7 @@ struct fg_batt_props { int fastchg_curr_ma; int *therm_coeffs; int therm_ctr_offset; + int therm_pull_up_kohms; int *rslow_normal_coeffs; int *rslow_low_coeffs; }; diff --git a/drivers/power/supply/qcom/fg-reg.h b/drivers/power/supply/qcom/fg-reg.h index 26e281090e51..931af0b2ed8f 100644 --- a/drivers/power/supply/qcom/fg-reg.h +++ b/drivers/power/supply/qcom/fg-reg.h @@ -35,6 +35,12 @@ #define ADC_RR_BATT_ID_LO_BIAS_LSB(chip) (chip->rradc_base + 0x76) #define ADC_RR_BATT_ID_LO_BIAS_MSB(chip) (chip->rradc_base + 0x77) +#define ADC_RR_BATT_THERM_BASE_CFG1(chip) (chip->rradc_base + 0x81) +#define BATT_THERM_PULL_UP_30K 1 +#define BATT_THERM_PULL_UP_100K 2 +#define BATT_THERM_PULL_UP_400K 3 +#define BATT_THERM_PULL_UP_MASK GENMASK(1, 0) + #define ADC_RR_BATT_TEMP_LSB(chip) (chip->rradc_base + 0x88) #define ADC_RR_BATT_TEMP_MSB(chip) (chip->rradc_base + 0x89) #define GEN4_BATT_TEMP_MSB_MASK GENMASK(1, 0) diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 6dce5eb504a1..e9dca471bf2c 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -999,6 +999,15 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) } } + if (of_find_property(profile_node, "qcom,therm-pull-up", NULL)) { + rc = of_property_read_u32(profile_node, "qcom,therm-pull-up", + &fg->bp.therm_pull_up_kohms); + if (rc < 0) { + pr_err("Couldn't read therm-pull-up, rc:%d\n", rc); + fg->bp.therm_pull_up_kohms = -EINVAL; + } + } + if (of_find_property(profile_node, "qcom,rslow-normal-coeffs", NULL) && of_find_property(profile_node, "qcom,rslow-low-coeffs", NULL)) { if (!fg->bp.rslow_normal_coeffs) { @@ -1121,6 +1130,30 @@ static int fg_gen4_bp_params_config(struct fg_dev *fg) fg_dbg(fg, FG_STATUS, "Rslow_low: %d\n", chip->rslow_low); } + if (fg->bp.therm_pull_up_kohms > 0) { + switch (fg->bp.therm_pull_up_kohms) { + case 30: + buf = BATT_THERM_PULL_UP_30K; + break; + case 100: + buf = BATT_THERM_PULL_UP_100K; + break; + case 400: + buf = BATT_THERM_PULL_UP_400K; + break; + default: + return -EINVAL; + } + + rc = fg_masked_write(fg, ADC_RR_BATT_THERM_BASE_CFG1(fg), + BATT_THERM_PULL_UP_MASK, buf); + if (rc < 0) { + pr_err("failed to write to 0x%04X, rc=%d\n", + ADC_RR_BATT_THERM_BASE_CFG1(fg), rc); + return rc; + } + } + return 0; } -- GitLab From 1836c3de97720f23e469b53a81edb7235edc9e59 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Tue, 12 Jun 2018 18:22:45 -0700 Subject: [PATCH 0325/1299] msm: ipa: disable in order GSI transactions IPAv4 has a HW limitation which causes GSI in order transactions to not complete in order. Need to ensure SW uses out of order transactions only. Change-Id: I8cf4f9dfc15e8a405aac23e6491350bee2859fc0 Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 9e0017c90489..4527986019c9 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -2585,6 +2585,29 @@ static void ipa_comp_cfg(void) IPADBG("ipa_qmb_select_by_address_cons_en = %d\n", comp_cfg.ipa_qmb_select_by_address_cons_en); } + + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) { + ipahal_read_reg_fields(IPA_COMP_CFG, &comp_cfg); + IPADBG("Before comp config\n"); + IPADBG("gsi_multi_inorder_rd_dis = %d\n", + comp_cfg.gsi_multi_inorder_rd_dis); + + IPADBG("gsi_multi_inorder_wr_dis = %d\n", + comp_cfg.gsi_multi_inorder_wr_dis); + + comp_cfg.gsi_multi_inorder_rd_dis = true; + comp_cfg.gsi_multi_inorder_wr_dis = true; + + ipahal_write_reg_fields(IPA_COMP_CFG, &comp_cfg); + + ipahal_read_reg_fields(IPA_COMP_CFG, &comp_cfg); + IPADBG("After comp config\n"); + IPADBG("gsi_multi_inorder_rd_dis = %d\n", + comp_cfg.gsi_multi_inorder_rd_dis); + + IPADBG("gsi_multi_inorder_wr_dis = %d\n", + comp_cfg.gsi_multi_inorder_wr_dis); + } } /** -- GitLab From a7deabb2de9df3bed3c7d4aa2c09163fa9c9df1d Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Tue, 4 Apr 2017 12:25:30 -0700 Subject: [PATCH 0326/1299] iommu/io-pgtable-fast: invalidate TLBs on unmap When not using the "public" fastmap unmap API make sure we take care of invalidating the TLBs. Change-Id: Ia74d4ae7d6352bd9ff57247e9fe2ef74daa1ac1c Signed-off-by: Liam Mark --- drivers/iommu/io-pgtable-fast.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/io-pgtable-fast.c b/drivers/iommu/io-pgtable-fast.c index 67bbd07f68a1..bf34c646fe57 100644 --- a/drivers/iommu/io-pgtable-fast.c +++ b/drivers/iommu/io-pgtable-fast.c @@ -255,16 +255,17 @@ void av8l_fast_unmap_public(av8l_fast_iopte *ptep, size_t size) __av8l_fast_unmap(ptep, size, true); } -/* upper layer must take care of TLB invalidation */ static size_t av8l_fast_unmap(struct io_pgtable_ops *ops, unsigned long iova, size_t size) { struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); + struct io_pgtable *iop = &data->iop; av8l_fast_iopte *ptep = iopte_pmd_offset(data->pmds, iova); unsigned long nptes = size >> AV8L_FAST_PAGE_SHIFT; __av8l_fast_unmap(ptep, size, false); dmac_clean_range(ptep, ptep + nptes); + io_pgtable_tlb_flush_all(iop); return size; } -- GitLab From d7852effeb78699289b0eeeb2892a0193b36ff2c Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Wed, 8 Nov 2017 15:26:34 -0800 Subject: [PATCH 0327/1299] arm64: dma-mapping: Correct variable type The argument is expected to be an int pointer type. Change-Id: Ib10a6379dcb7cbda4fce3bfb822384f1fece35ef Signed-off-by: Patrick Daly Signed-off-by: Sudarshan Rajagopalan --- arch/arm64/mm/dma-mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 9c55acd236e6..195233513c5b 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -1979,7 +1979,7 @@ bitmap_iommu_init_mapping(struct device *dev, struct dma_iommu_mapping *mapping) { unsigned int bitmap_size = BITS_TO_LONGS(mapping->bits) * sizeof(long); int vmid = VMID_HLOS; - bool min_iova_align = 0; + int min_iova_align = 0; iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_QCOM_MMU500_ERRATA_MIN_IOVA_ALIGN, -- GitLab From b682a3fcca4d3c39f9592be0163d9c233bb3ff87 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Fri, 15 Jun 2018 18:44:57 -0600 Subject: [PATCH 0328/1299] defconfig: sm8150: Disable rmnet_data driver Since all map packet processing is handled by upstream rmnet driver, rmnet_data driver can be safely turned off. CRs-Fixed: 2259239 Change-Id: I4165a335a7ce41941bfd48f102d1014076c9c195 Signed-off-by: Subash Abhinov Kasiviswanathan --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 3 --- arch/arm64/configs/vendor/sm8150_defconfig | 3 --- 2 files changed, 6 deletions(-) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 83d8f020491f..0e2fcdb6e111 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -230,9 +230,6 @@ CONFIG_NET_ACT_SKBEDIT=y CONFIG_QRTR=y CONFIG_QRTR_SMD=y CONFIG_QRTR_MHI=y -CONFIG_RMNET_DATA=y -CONFIG_RMNET_DATA_FC=y -CONFIG_RMNET_DATA_DEBUG_PKT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 3b919f593861..1cb5699ba02b 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -239,9 +239,6 @@ CONFIG_DNS_RESOLVER=y CONFIG_QRTR=y CONFIG_QRTR_SMD=y CONFIG_QRTR_MHI=y -CONFIG_RMNET_DATA=y -CONFIG_RMNET_DATA_FC=y -CONFIG_RMNET_DATA_DEBUG_PKT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y -- GitLab From d02ae00ab6d0ebede6b2477dfb7b010793ab53c3 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Wed, 16 May 2018 22:10:37 +0900 Subject: [PATCH 0329/1299] netfilter: nf_tables: fix NULL pointer dereference on nft_ct_helper_obj_dump() commit b71534583f22d08c3e3563bf5100aeb5f5c9fbe5 upstream. In the nft_ct_helper_obj_dump(), always priv->helper4 is dereferenced. But if family is ipv6, priv->helper6 should be dereferenced. Steps to reproduces: #test.nft table ip6 filter { ct helper ftp { type "ftp" protocol tcp } chain input { type filter hook input priority 4; ct helper set "ftp" } } %nft -f test.nft %nft list ruleset we can see the below messages: [ 916.286233] kasan: GPF could be caused by NULL-ptr deref or user memory access [ 916.294777] general protection fault: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI [ 916.302613] Modules linked in: nft_objref nf_conntrack_sip nf_conntrack_snmp nf_conntrack_broadcast nf_conntrack_ftp nft_ct nf_conntrack nf_tables nfnetlink [last unloaded: nfnetlink] [ 916.318758] CPU: 1 PID: 2093 Comm: nft Not tainted 4.17.0-rc4+ #181 [ 916.326772] Hardware name: To be filled by O.E.M. To be filled by O.E.M./Aptio CRB, BIOS 5.6.5 07/08/2015 [ 916.338773] RIP: 0010:strlen+0x1a/0x90 [ 916.342781] RSP: 0018:ffff88010ff0f2f8 EFLAGS: 00010292 [ 916.346773] RAX: dffffc0000000000 RBX: ffff880119b26ee8 RCX: ffff88010c150038 [ 916.354777] RDX: 0000000000000002 RSI: ffff880119b26ee8 RDI: 0000000000000010 [ 916.362773] RBP: 0000000000000010 R08: 0000000000007e88 R09: ffff88010c15003c [ 916.370773] R10: ffff88010c150037 R11: ffffed002182a007 R12: ffff88010ff04040 [ 916.378779] R13: 0000000000000010 R14: ffff880119b26f30 R15: ffff88010ff04110 [ 916.387265] FS: 00007f57a1997700(0000) GS:ffff88011b800000(0000) knlGS:0000000000000000 [ 916.394785] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 916.402778] CR2: 00007f57a0ac80f0 CR3: 000000010ff02000 CR4: 00000000001006e0 [ 916.410772] Call Trace: [ 916.414787] nft_ct_helper_obj_dump+0x94/0x200 [nft_ct] [ 916.418779] ? nft_ct_set_eval+0x560/0x560 [nft_ct] [ 916.426771] ? memset+0x1f/0x40 [ 916.426771] ? __nla_reserve+0x92/0xb0 [ 916.434774] ? memcpy+0x34/0x50 [ 916.434774] nf_tables_fill_obj_info+0x484/0x860 [nf_tables] [ 916.442773] ? __nft_release_basechain+0x600/0x600 [nf_tables] [ 916.450779] ? lock_acquire+0x193/0x380 [ 916.454771] ? lock_acquire+0x193/0x380 [ 916.458789] ? nf_tables_dump_obj+0x148/0xcb0 [nf_tables] [ 916.462777] nf_tables_dump_obj+0x5f0/0xcb0 [nf_tables] [ 916.470769] ? __alloc_skb+0x30b/0x500 [ 916.474779] netlink_dump+0x752/0xb50 [ 916.478775] __netlink_dump_start+0x4d3/0x750 [ 916.482784] nf_tables_getobj+0x27a/0x930 [nf_tables] [ 916.490774] ? nft_obj_notify+0x100/0x100 [nf_tables] [ 916.494772] ? nf_tables_getobj+0x930/0x930 [nf_tables] [ 916.502579] ? nf_tables_dump_flowtable_done+0x70/0x70 [nf_tables] [ 916.506774] ? nft_obj_notify+0x100/0x100 [nf_tables] [ 916.514808] nfnetlink_rcv_msg+0x8ab/0xa86 [nfnetlink] [ 916.518771] ? nfnetlink_rcv_msg+0x550/0xa86 [nfnetlink] [ 916.526782] netlink_rcv_skb+0x23e/0x360 [ 916.530773] ? nfnetlink_bind+0x200/0x200 [nfnetlink] [ 916.534778] ? debug_check_no_locks_freed+0x280/0x280 [ 916.542770] ? netlink_ack+0x870/0x870 [ 916.546786] ? ns_capable_common+0xf4/0x130 [ 916.550765] nfnetlink_rcv+0x172/0x16c0 [nfnetlink] [ 916.554771] ? sched_clock_local+0xe2/0x150 [ 916.558774] ? sched_clock_cpu+0x144/0x180 [ 916.566575] ? lock_acquire+0x380/0x380 [ 916.570775] ? sched_clock_local+0xe2/0x150 [ 916.574765] ? nfnetlink_net_init+0x130/0x130 [nfnetlink] [ 916.578763] ? sched_clock_cpu+0x144/0x180 [ 916.582770] ? lock_acquire+0x193/0x380 [ 916.590771] ? lock_acquire+0x193/0x380 [ 916.594766] ? lock_acquire+0x380/0x380 [ 916.598760] ? netlink_deliver_tap+0x262/0xa60 [ 916.602766] ? lock_acquire+0x193/0x380 [ 916.606766] netlink_unicast+0x3ef/0x5a0 [ 916.610771] ? netlink_attachskb+0x630/0x630 [ 916.614763] netlink_sendmsg+0x72a/0xb00 [ 916.618769] ? netlink_unicast+0x5a0/0x5a0 [ 916.626766] ? _copy_from_user+0x92/0xc0 [ 916.630773] __sys_sendto+0x202/0x300 [ 916.634772] ? __ia32_sys_getpeername+0xb0/0xb0 [ 916.638759] ? lock_acquire+0x380/0x380 [ 916.642769] ? lock_acquire+0x193/0x380 [ 916.646761] ? finish_task_switch+0xf4/0x560 [ 916.650763] ? __schedule+0x582/0x19a0 [ 916.655301] ? __sched_text_start+0x8/0x8 [ 916.655301] ? up_read+0x1c/0x110 [ 916.655301] ? __do_page_fault+0x48b/0xaa0 [ 916.655301] ? entry_SYSCALL_64_after_hwframe+0x59/0xbe [ 916.655301] __x64_sys_sendto+0xdd/0x1b0 [ 916.655301] do_syscall_64+0x96/0x3d0 [ 916.655301] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 916.655301] RIP: 0033:0x7f57a0ff5e03 [ 916.655301] RSP: 002b:00007fff6367e0a8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c [ 916.655301] RAX: ffffffffffffffda RBX: 00007fff6367f1e0 RCX: 00007f57a0ff5e03 [ 916.655301] RDX: 0000000000000020 RSI: 00007fff6367e110 RDI: 0000000000000003 [ 916.655301] RBP: 00007fff6367e100 R08: 00007f57a0ce9160 R09: 000000000000000c [ 916.655301] R10: 0000000000000000 R11: 0000000000000246 R12: 00007fff6367e110 [ 916.655301] R13: 0000000000000020 R14: 00007f57a153c610 R15: 0000562417258de0 [ 916.655301] Code: ff ff ff 0f 1f 40 00 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 fa 53 48 c1 ea 03 48 b8 00 00 00 00 00 fc ff df 48 89 fd 48 83 ec 08 <0f> b6 04 02 48 89 fa 83 e2 07 38 d0 7f [ 916.655301] RIP: strlen+0x1a/0x90 RSP: ffff88010ff0f2f8 [ 916.771929] ---[ end trace 1065e048e72479fe ]--- [ 916.777204] Kernel panic - not syncing: Fatal exception [ 916.778158] Kernel Offset: 0x14000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) Signed-off-by: Taehee Yoo Acked-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nft_ct.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index bd0975d7dd6f..5e0d367a0988 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c @@ -875,22 +875,26 @@ static int nft_ct_helper_obj_dump(struct sk_buff *skb, struct nft_object *obj, bool reset) { const struct nft_ct_helper_obj *priv = nft_obj_data(obj); - const struct nf_conntrack_helper *helper = priv->helper4; + const struct nf_conntrack_helper *helper; u16 family; + if (priv->helper4 && priv->helper6) { + family = NFPROTO_INET; + helper = priv->helper4; + } else if (priv->helper6) { + family = NFPROTO_IPV6; + helper = priv->helper6; + } else { + family = NFPROTO_IPV4; + helper = priv->helper4; + } + if (nla_put_string(skb, NFTA_CT_HELPER_NAME, helper->name)) return -1; if (nla_put_u8(skb, NFTA_CT_HELPER_L4PROTO, priv->l4proto)) return -1; - if (priv->helper4 && priv->helper6) - family = NFPROTO_INET; - else if (priv->helper6) - family = NFPROTO_IPV6; - else - family = NFPROTO_IPV4; - if (nla_put_be16(skb, NFTA_CT_HELPER_L3PROTO, htons(family))) return -1; -- GitLab From 1cbd5ece052790680815c05a8e496512ac6ef920 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 22 May 2018 08:27:22 -0700 Subject: [PATCH 0330/1299] blkdev_report_zones_ioctl(): Use vmalloc() to allocate large buffers commit 327ea4adcfa37194739f1ec7c70568944d292281 upstream. Avoid that complaints similar to the following appear in the kernel log if the number of zones is sufficiently large: fio: page allocation failure: order:9, mode:0x140c0c0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), nodemask=(null) Call Trace: dump_stack+0x63/0x88 warn_alloc+0xf5/0x190 __alloc_pages_slowpath+0x8f0/0xb0d __alloc_pages_nodemask+0x242/0x260 alloc_pages_current+0x6a/0xb0 kmalloc_order+0x18/0x50 kmalloc_order_trace+0x26/0xb0 __kmalloc+0x20e/0x220 blkdev_report_zones_ioctl+0xa5/0x1a0 blkdev_ioctl+0x1ba/0x930 block_ioctl+0x41/0x50 do_vfs_ioctl+0xaa/0x610 SyS_ioctl+0x79/0x90 do_syscall_64+0x79/0x1b0 entry_SYSCALL_64_after_hwframe+0x3d/0xa2 Fixes: 3ed05a987e0f ("blk-zoned: implement ioctls") Signed-off-by: Bart Van Assche Cc: Shaun Tancheff Cc: Damien Le Moal Cc: Christoph Hellwig Cc: Martin K. Petersen Cc: Hannes Reinecke Cc: Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-zoned.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index ff57fb51b338..77fce6f09f78 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -286,7 +286,11 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode, if (!rep.nr_zones) return -EINVAL; - zones = kcalloc(rep.nr_zones, sizeof(struct blk_zone), GFP_KERNEL); + if (rep.nr_zones > INT_MAX / sizeof(struct blk_zone)) + return -ERANGE; + + zones = kvmalloc(rep.nr_zones * sizeof(struct blk_zone), + GFP_KERNEL | __GFP_ZERO); if (!zones) return -ENOMEM; @@ -308,7 +312,7 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode, } out: - kfree(zones); + kvfree(zones); return ret; } -- GitLab From 7d970250cb8dfb71768ed58dd80f06cd74a49c28 Mon Sep 17 00:00:00 2001 From: Kevin Easton Date: Sat, 7 Apr 2018 11:40:33 -0400 Subject: [PATCH 0331/1299] af_key: Always verify length of provided sadb_key commit 4b66af2d6356a00e94bcdea3e7fea324e8b5c6f4 upstream. Key extensions (struct sadb_key) include a user-specified number of key bits. The kernel uses that number to determine how much key data to copy out of the message in pfkey_msg2xfrm_state(). The length of the sadb_key message must be verified to be long enough, even in the case of SADB_X_AALG_NULL. Furthermore, the sadb_key_len value must be long enough to include both the key data and the struct sadb_key itself. Introduce a helper function verify_key_len(), and call it from parse_exthdrs() where other exthdr types are similarly checked for correctness. Signed-off-by: Kevin Easton Reported-by: syzbot+5022a34ca5a3d49b84223653fab632dfb7b4cf37@syzkaller.appspotmail.com Signed-off-by: Steffen Klassert Cc: Zubin Mithra Signed-off-by: Greg Kroah-Hartman --- net/key/af_key.c | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index 2ad693232f74..3b209cbfe1df 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -437,6 +437,24 @@ static int verify_address_len(const void *p) return 0; } +static inline int sadb_key_len(const struct sadb_key *key) +{ + int key_bytes = DIV_ROUND_UP(key->sadb_key_bits, 8); + + return DIV_ROUND_UP(sizeof(struct sadb_key) + key_bytes, + sizeof(uint64_t)); +} + +static int verify_key_len(const void *p) +{ + const struct sadb_key *key = p; + + if (sadb_key_len(key) > key->sadb_key_len) + return -EINVAL; + + return 0; +} + static inline int pfkey_sec_ctx_len(const struct sadb_x_sec_ctx *sec_ctx) { return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) + @@ -533,16 +551,25 @@ static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void * return -EINVAL; if (ext_hdrs[ext_type-1] != NULL) return -EINVAL; - if (ext_type == SADB_EXT_ADDRESS_SRC || - ext_type == SADB_EXT_ADDRESS_DST || - ext_type == SADB_EXT_ADDRESS_PROXY || - ext_type == SADB_X_EXT_NAT_T_OA) { + switch (ext_type) { + case SADB_EXT_ADDRESS_SRC: + case SADB_EXT_ADDRESS_DST: + case SADB_EXT_ADDRESS_PROXY: + case SADB_X_EXT_NAT_T_OA: if (verify_address_len(p)) return -EINVAL; - } - if (ext_type == SADB_X_EXT_SEC_CTX) { + break; + case SADB_X_EXT_SEC_CTX: if (verify_sec_ctx_len(p)) return -EINVAL; + break; + case SADB_EXT_KEY_AUTH: + case SADB_EXT_KEY_ENCRYPT: + if (verify_key_len(p)) + return -EINVAL; + break; + default: + break; } ext_hdrs[ext_type-1] = (void *) p; } @@ -1104,14 +1131,12 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, key = ext_hdrs[SADB_EXT_KEY_AUTH - 1]; if (key != NULL && sa->sadb_sa_auth != SADB_X_AALG_NULL && - ((key->sadb_key_bits+7) / 8 == 0 || - (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t))) + key->sadb_key_bits == 0) return ERR_PTR(-EINVAL); key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; if (key != NULL && sa->sadb_sa_encrypt != SADB_EALG_NULL && - ((key->sadb_key_bits+7) / 8 == 0 || - (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t))) + key->sadb_key_bits == 0) return ERR_PTR(-EINVAL); x = xfrm_state_alloc(net); -- GitLab From c7a372ddc3db9ab90a408917c040f6cc223a115f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 16 Jan 2018 08:29:50 +0100 Subject: [PATCH 0332/1299] gpio: No NULL owner commit 7d18f0a14aa6a0d6bad39111c1fb655f07f71d59 upstream. Sometimes a GPIO is fetched with NULL as parent device, and that is just fine. So under these circumstances, avoid using dev_name() to provide a name for the GPIO line. Signed-off-by: Linus Walleij Cc: Daniel Rosenberg Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpiolib.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 68ea6e712bf9..7e0bfd7347f6 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3313,6 +3313,8 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, struct gpio_desc *desc = NULL; int status; enum gpio_lookup_flags lookupflags = 0; + /* Maybe we have a device name, maybe not */ + const char *devname = dev ? dev_name(dev) : "?"; dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id); @@ -3341,8 +3343,11 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, return desc; } - /* If a connection label was passed use that, else use the device name as label */ - status = gpiod_request(desc, con_id ? con_id : dev_name(dev)); + /* + * If a connection label was passed use that, else attempt to use + * the device name as label + */ + status = gpiod_request(desc, con_id ? con_id : devname); if (status < 0) return ERR_PTR(status); -- GitLab From 9791d9d7e2acede3d38cce1d64a7caf29e27ace4 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Sun, 13 May 2018 02:24:47 -0700 Subject: [PATCH 0333/1299] KVM: X86: Fix reserved bits check for MOV to CR3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a780a3ea628268b2ad0ed43d7f28d90db0ff18be upstream. MSB of CR3 is a reserved bit if the PCIDE bit is not set in CR4. It should be checked when PCIDE bit is not set, however commit 'd1cd3ce900441 ("KVM: MMU: check guest CR3 reserved bits based on its physical address width")' removes the bit 63 checking unconditionally. This patch fixes it by checking bit 63 of CR3 when PCIDE bit is not set in CR4. Fixes: d1cd3ce900441 (KVM: MMU: check guest CR3 reserved bits based on its physical address width) Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Liran Alon Cc: stable@vger.kernel.org Reviewed-by: Junaid Shahid Signed-off-by: Wanpeng Li Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/emulate.c | 4 +++- arch/x86/kvm/x86.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index fab073b19528..3111485b0621 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -4152,7 +4152,9 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt) maxphyaddr = eax & 0xff; else maxphyaddr = 36; - rsvd = rsvd_bits(maxphyaddr, 62); + rsvd = rsvd_bits(maxphyaddr, 63); + if (ctxt->ops->get_cr(ctxt, 4) & X86_CR4_PCIDE) + rsvd &= ~CR3_PCID_INVD; } if (new_val & rsvd) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index adac01d0181a..f46e4c5cdbb6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -836,7 +836,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) } if (is_long_mode(vcpu) && - (cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 62))) + (cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 63))) return 1; else if (is_pae(vcpu) && is_paging(vcpu) && !load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3)) -- GitLab From 3d2f03393267d42bdd8612ac1db265ee6591d14e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 6 Jun 2018 16:43:02 +0200 Subject: [PATCH 0334/1299] KVM: x86: introduce linear_{read,write}_system commit 79367a65743975e5cac8d24d08eccc7fdae832b0 upstream. Wrap the common invocation of ctxt->ops->read_std and ctxt->ops->write_std, so as to have a smaller patch when the functions grow another argument. Fixes: 129a72a0d3c8 ("KVM: x86: Introduce segmented_write_std", 2017-01-12) Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/emulate.c | 64 +++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 3111485b0621..713d8861e5eb 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -811,6 +811,19 @@ static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) return assign_eip_near(ctxt, ctxt->_eip + rel); } +static int linear_read_system(struct x86_emulate_ctxt *ctxt, ulong linear, + void *data, unsigned size) +{ + return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception); +} + +static int linear_write_system(struct x86_emulate_ctxt *ctxt, + ulong linear, void *data, + unsigned int size) +{ + return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception); +} + static int segmented_read_std(struct x86_emulate_ctxt *ctxt, struct segmented_address addr, void *data, @@ -1509,8 +1522,7 @@ static int read_interrupt_descriptor(struct x86_emulate_ctxt *ctxt, return emulate_gp(ctxt, index << 3 | 0x2); addr = dt.address + index * 8; - return ctxt->ops->read_std(ctxt, addr, desc, sizeof *desc, - &ctxt->exception); + return linear_read_system(ctxt, addr, desc, sizeof *desc); } static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt, @@ -1573,8 +1585,7 @@ static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt, if (rc != X86EMUL_CONTINUE) return rc; - return ctxt->ops->read_std(ctxt, *desc_addr_p, desc, sizeof(*desc), - &ctxt->exception); + return linear_read_system(ctxt, *desc_addr_p, desc, sizeof(*desc)); } /* allowed just for 8 bytes segments */ @@ -1588,8 +1599,7 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt, if (rc != X86EMUL_CONTINUE) return rc; - return ctxt->ops->write_std(ctxt, addr, desc, sizeof *desc, - &ctxt->exception); + return linear_write_system(ctxt, addr, desc, sizeof *desc); } static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, @@ -1750,8 +1760,7 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, return ret; } } else if (ctxt->mode == X86EMUL_MODE_PROT64) { - ret = ctxt->ops->read_std(ctxt, desc_addr+8, &base3, - sizeof(base3), &ctxt->exception); + ret = linear_read_system(ctxt, desc_addr+8, &base3, sizeof(base3)); if (ret != X86EMUL_CONTINUE) return ret; if (emul_is_noncanonical_address(get_desc_base(&seg_desc) | @@ -2064,11 +2073,11 @@ static int __emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq) eip_addr = dt.address + (irq << 2); cs_addr = dt.address + (irq << 2) + 2; - rc = ops->read_std(ctxt, cs_addr, &cs, 2, &ctxt->exception); + rc = linear_read_system(ctxt, cs_addr, &cs, 2); if (rc != X86EMUL_CONTINUE) return rc; - rc = ops->read_std(ctxt, eip_addr, &eip, 2, &ctxt->exception); + rc = linear_read_system(ctxt, eip_addr, &eip, 2); if (rc != X86EMUL_CONTINUE) return rc; @@ -3046,35 +3055,30 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt, u16 tss_selector, u16 old_tss_sel, ulong old_tss_base, struct desc_struct *new_desc) { - const struct x86_emulate_ops *ops = ctxt->ops; struct tss_segment_16 tss_seg; int ret; u32 new_tss_base = get_desc_base(new_desc); - ret = ops->read_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg, - &ctxt->exception); + ret = linear_read_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg); if (ret != X86EMUL_CONTINUE) return ret; save_state_to_tss16(ctxt, &tss_seg); - ret = ops->write_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg, - &ctxt->exception); + ret = linear_write_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg); if (ret != X86EMUL_CONTINUE) return ret; - ret = ops->read_std(ctxt, new_tss_base, &tss_seg, sizeof tss_seg, - &ctxt->exception); + ret = linear_read_system(ctxt, new_tss_base, &tss_seg, sizeof tss_seg); if (ret != X86EMUL_CONTINUE) return ret; if (old_tss_sel != 0xffff) { tss_seg.prev_task_link = old_tss_sel; - ret = ops->write_std(ctxt, new_tss_base, - &tss_seg.prev_task_link, - sizeof tss_seg.prev_task_link, - &ctxt->exception); + ret = linear_write_system(ctxt, new_tss_base, + &tss_seg.prev_task_link, + sizeof tss_seg.prev_task_link); if (ret != X86EMUL_CONTINUE) return ret; } @@ -3190,38 +3194,34 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt, u16 tss_selector, u16 old_tss_sel, ulong old_tss_base, struct desc_struct *new_desc) { - const struct x86_emulate_ops *ops = ctxt->ops; struct tss_segment_32 tss_seg; int ret; u32 new_tss_base = get_desc_base(new_desc); u32 eip_offset = offsetof(struct tss_segment_32, eip); u32 ldt_sel_offset = offsetof(struct tss_segment_32, ldt_selector); - ret = ops->read_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg, - &ctxt->exception); + ret = linear_read_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg); if (ret != X86EMUL_CONTINUE) return ret; save_state_to_tss32(ctxt, &tss_seg); /* Only GP registers and segment selectors are saved */ - ret = ops->write_std(ctxt, old_tss_base + eip_offset, &tss_seg.eip, - ldt_sel_offset - eip_offset, &ctxt->exception); + ret = linear_write_system(ctxt, old_tss_base + eip_offset, &tss_seg.eip, + ldt_sel_offset - eip_offset); if (ret != X86EMUL_CONTINUE) return ret; - ret = ops->read_std(ctxt, new_tss_base, &tss_seg, sizeof tss_seg, - &ctxt->exception); + ret = linear_read_system(ctxt, new_tss_base, &tss_seg, sizeof tss_seg); if (ret != X86EMUL_CONTINUE) return ret; if (old_tss_sel != 0xffff) { tss_seg.prev_task_link = old_tss_sel; - ret = ops->write_std(ctxt, new_tss_base, - &tss_seg.prev_task_link, - sizeof tss_seg.prev_task_link, - &ctxt->exception); + ret = linear_write_system(ctxt, new_tss_base, + &tss_seg.prev_task_link, + sizeof tss_seg.prev_task_link); if (ret != X86EMUL_CONTINUE) return ret; } -- GitLab From b1bd9caf5e98d8111361f53367fece3444b0a7c2 Mon Sep 17 00:00:00 2001 From: Felix Wilhelm Date: Mon, 11 Jun 2018 09:43:44 +0200 Subject: [PATCH 0335/1299] kvm: nVMX: Enforce cpl=0 for VMX instructions commit 727ba748e110b4de50d142edca9d6a9b7e6111d8 upstream. VMX instructions executed inside a L1 VM will always trigger a VM exit even when executed with cpl 3. This means we must perform the privilege check in software. Fixes: 70f3aac964ae("kvm: nVMX: Remove superfluous VMX instruction fault checks") Cc: stable@vger.kernel.org Signed-off-by: Felix Wilhelm Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/vmx.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 4c88572d2b81..947106933d0d 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -7399,6 +7399,12 @@ static int handle_vmon(struct kvm_vcpu *vcpu) return 1; } + /* CPL=0 must be checked manually. */ + if (vmx_get_cpl(vcpu)) { + kvm_queue_exception(vcpu, UD_VECTOR); + return 1; + } + if (vmx->nested.vmxon) { nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION); return kvm_skip_emulated_instruction(vcpu); @@ -7458,6 +7464,11 @@ static int handle_vmon(struct kvm_vcpu *vcpu) */ static int nested_vmx_check_permission(struct kvm_vcpu *vcpu) { + if (vmx_get_cpl(vcpu)) { + kvm_queue_exception(vcpu, UD_VECTOR); + return 0; + } + if (!to_vmx(vcpu)->nested.vmxon) { kvm_queue_exception(vcpu, UD_VECTOR); return 0; @@ -7790,7 +7801,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) if (get_vmx_mem_address(vcpu, exit_qualification, vmx_instruction_info, true, &gva)) return 1; - /* _system ok, as hardware has verified cpl=0 */ + /* _system ok, nested_vmx_check_permission has verified cpl=0 */ kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva, &field_value, (is_long_mode(vcpu) ? 8 : 4), NULL); } @@ -7933,7 +7944,7 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu) if (get_vmx_mem_address(vcpu, exit_qualification, vmx_instruction_info, true, &vmcs_gva)) return 1; - /* ok to use *_system, as hardware has verified cpl=0 */ + /* *_system ok, nested_vmx_check_permission has verified cpl=0 */ if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva, (void *)&to_vmx(vcpu)->nested.current_vmptr, sizeof(u64), &e)) { -- GitLab From bd2742e8366057f621b873f14a3abb936d55a640 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 6 Jun 2018 17:37:49 +0200 Subject: [PATCH 0336/1299] KVM: x86: pass kvm_vcpu to kvm_read_guest_virt and kvm_write_guest_virt_system commit ce14e868a54edeb2e30cb7a7b104a2fc4b9d76ca upstream. Int the next patch the emulator's .read_std and .write_std callbacks will grow another argument, which is not needed in kvm_read_guest_virt and kvm_write_guest_virt_system's callers. Since we have to make separate functions, let's give the currently existing names a nicer interface, too. Fixes: 129a72a0d3c8 ("KVM: x86: Introduce segmented_write_std", 2017-01-12) Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/vmx.c | 23 ++++++++++------------- arch/x86/kvm/x86.c | 39 ++++++++++++++++++++++++++------------- arch/x86/kvm/x86.h | 4 ++-- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 947106933d0d..b1556166a06d 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -7317,8 +7317,7 @@ static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer) vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva)) return 1; - if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, vmpointer, - sizeof(*vmpointer), &e)) { + if (kvm_read_guest_virt(vcpu, gva, vmpointer, sizeof(*vmpointer), &e)) { kvm_inject_page_fault(vcpu, &e); return 1; } @@ -7802,8 +7801,8 @@ static int handle_vmread(struct kvm_vcpu *vcpu) vmx_instruction_info, true, &gva)) return 1; /* _system ok, nested_vmx_check_permission has verified cpl=0 */ - kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva, - &field_value, (is_long_mode(vcpu) ? 8 : 4), NULL); + kvm_write_guest_virt_system(vcpu, gva, &field_value, + (is_long_mode(vcpu) ? 8 : 4), NULL); } nested_vmx_succeed(vcpu); @@ -7839,8 +7838,8 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) if (get_vmx_mem_address(vcpu, exit_qualification, vmx_instruction_info, false, &gva)) return 1; - if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, - &field_value, (is_64_bit_mode(vcpu) ? 8 : 4), &e)) { + if (kvm_read_guest_virt(vcpu, gva, &field_value, + (is_64_bit_mode(vcpu) ? 8 : 4), &e)) { kvm_inject_page_fault(vcpu, &e); return 1; } @@ -7945,9 +7944,9 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu) vmx_instruction_info, true, &vmcs_gva)) return 1; /* *_system ok, nested_vmx_check_permission has verified cpl=0 */ - if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva, - (void *)&to_vmx(vcpu)->nested.current_vmptr, - sizeof(u64), &e)) { + if (kvm_write_guest_virt_system(vcpu, vmcs_gva, + (void *)&to_vmx(vcpu)->nested.current_vmptr, + sizeof(u64), &e)) { kvm_inject_page_fault(vcpu, &e); return 1; } @@ -7994,8 +7993,7 @@ static int handle_invept(struct kvm_vcpu *vcpu) if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION), vmx_instruction_info, false, &gva)) return 1; - if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &operand, - sizeof(operand), &e)) { + if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) { kvm_inject_page_fault(vcpu, &e); return 1; } @@ -8059,8 +8057,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION), vmx_instruction_info, false, &gva)) return 1; - if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &operand, - sizeof(operand), &e)) { + if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) { kvm_inject_page_fault(vcpu, &e); return 1; } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f46e4c5cdbb6..ade1d165ada6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4492,11 +4492,10 @@ static int kvm_fetch_guest_virt(struct x86_emulate_ctxt *ctxt, return X86EMUL_CONTINUE; } -int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt, +int kvm_read_guest_virt(struct kvm_vcpu *vcpu, gva_t addr, void *val, unsigned int bytes, struct x86_exception *exception) { - struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0; return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access, @@ -4504,9 +4503,9 @@ int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt, } EXPORT_SYMBOL_GPL(kvm_read_guest_virt); -static int kvm_read_guest_virt_system(struct x86_emulate_ctxt *ctxt, - gva_t addr, void *val, unsigned int bytes, - struct x86_exception *exception) +static int emulator_read_std(struct x86_emulate_ctxt *ctxt, + gva_t addr, void *val, unsigned int bytes, + struct x86_exception *exception) { struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, exception); @@ -4521,18 +4520,16 @@ static int kvm_read_guest_phys_system(struct x86_emulate_ctxt *ctxt, return r < 0 ? X86EMUL_IO_NEEDED : X86EMUL_CONTINUE; } -int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt, - gva_t addr, void *val, - unsigned int bytes, - struct x86_exception *exception) +static int kvm_write_guest_virt_helper(gva_t addr, void *val, unsigned int bytes, + struct kvm_vcpu *vcpu, u32 access, + struct x86_exception *exception) { - struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); void *data = val; int r = X86EMUL_CONTINUE; while (bytes) { gpa_t gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, addr, - PFERR_WRITE_MASK, + access, exception); unsigned offset = addr & (PAGE_SIZE-1); unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset); @@ -4553,6 +4550,22 @@ int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt, out: return r; } + +static int emulator_write_std(struct x86_emulate_ctxt *ctxt, gva_t addr, void *val, + unsigned int bytes, struct x86_exception *exception) +{ + struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); + + return kvm_write_guest_virt_helper(addr, val, bytes, vcpu, + PFERR_WRITE_MASK, exception); +} + +int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val, + unsigned int bytes, struct x86_exception *exception) +{ + return kvm_write_guest_virt_helper(addr, val, bytes, vcpu, + PFERR_WRITE_MASK, exception); +} EXPORT_SYMBOL_GPL(kvm_write_guest_virt_system); static int vcpu_is_mmio_gpa(struct kvm_vcpu *vcpu, unsigned long gva, @@ -5287,8 +5300,8 @@ static void emulator_set_hflags(struct x86_emulate_ctxt *ctxt, unsigned emul_fla static const struct x86_emulate_ops emulate_ops = { .read_gpr = emulator_read_gpr, .write_gpr = emulator_write_gpr, - .read_std = kvm_read_guest_virt_system, - .write_std = kvm_write_guest_virt_system, + .read_std = emulator_read_std, + .write_std = emulator_write_std, .read_phys = kvm_read_guest_phys_system, .fetch = kvm_fetch_guest_virt, .read_emulated = emulator_read_emulated, diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 6d112d8f799c..d4b59cf0dc51 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -213,11 +213,11 @@ int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip); void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr); u64 get_kvmclock_ns(struct kvm *kvm); -int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt, +int kvm_read_guest_virt(struct kvm_vcpu *vcpu, gva_t addr, void *val, unsigned int bytes, struct x86_exception *exception); -int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt, +int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val, unsigned int bytes, struct x86_exception *exception); -- GitLab From f1769a9ba4bffec62a3025b7afa4c7b94081aa7b Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 14 May 2018 14:35:09 -0700 Subject: [PATCH 0337/1299] staging: android: ion: Switch to pr_warn_once in ion_buffer_destroy commit 45ad559a29629cb1c64ee636563c69b71524f077 upstream. Syzbot reported yet another warning with Ion: WARNING: CPU: 0 PID: 1467 at drivers/staging/android/ion/ion.c:122 ion_buffer_destroy+0xd4/0x190 drivers/staging/android/ion/ion.c:122 Kernel panic - not syncing: panic_on_warn set ... This is catching that a buffer was freed with an existing kernel mapping still present. This can be easily be triggered from userspace by calling DMA_BUF_SYNC_START without calling DMA_BUF_SYNC_END. Switch to a single pr_warn_once to indicate the error without being disruptive. Reported-by: syzbot+cd8bcd40cb049efa2770@syzkaller.appspotmail.com Reported-by: syzbot Signed-off-by: Laura Abbott Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 83dc3292e9ab..24cb666c9224 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -131,8 +131,11 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, void ion_buffer_destroy(struct ion_buffer *buffer) { - if (WARN_ON(buffer->kmap_cnt > 0)) + if (buffer->kmap_cnt > 0) { + pr_warn_once("%s: buffer still mapped in the kernel\n", + __func__); buffer->heap->ops->unmap_kernel(buffer->heap, buffer); + } buffer->heap->ops->free(buffer); kfree(buffer); } -- GitLab From 1caeb5022449ed7ef169b05bc9c5e7d884b72de2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 20 May 2018 15:19:46 +0200 Subject: [PATCH 0338/1299] NFC: pn533: don't send USB data off of the stack commit dbafc28955fa6779dc23d1607a0fee5e509a278b upstream. It's amazing that this driver ever worked, but now that x86 doesn't allow USB data to be sent off of the stack, it really does not work at all. Fix this up by properly allocating the data for the small "commands" that get sent to the device off of the stack. We do this for one command by having a whole urb just for ack messages, as they can be submitted in interrupt context, so we can not use usb_bulk_msg(). But the poweron command can sleep (and does), so use usb_bulk_msg() for that transfer. Reported-by: Carlos Manuel Santos Cc: Samuel Ortiz Cc: Stephen Hemminger Cc: stable Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/nfc/pn533/usb.c | 42 +++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c index e153e8b64bb8..d5553c47014f 100644 --- a/drivers/nfc/pn533/usb.c +++ b/drivers/nfc/pn533/usb.c @@ -62,6 +62,9 @@ struct pn533_usb_phy { struct urb *out_urb; struct urb *in_urb; + struct urb *ack_urb; + u8 *ack_buffer; + struct pn533 *priv; }; @@ -150,13 +153,16 @@ static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags) struct pn533_usb_phy *phy = dev->phy; static const u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ - int rc; - phy->out_urb->transfer_buffer = (u8 *)ack; - phy->out_urb->transfer_buffer_length = sizeof(ack); - rc = usb_submit_urb(phy->out_urb, flags); + if (!phy->ack_buffer) { + phy->ack_buffer = kmemdup(ack, sizeof(ack), flags); + if (!phy->ack_buffer) + return -ENOMEM; + } - return rc; + phy->ack_urb->transfer_buffer = phy->ack_buffer; + phy->ack_urb->transfer_buffer_length = sizeof(ack); + return usb_submit_urb(phy->ack_urb, flags); } static int pn533_usb_send_frame(struct pn533 *dev, @@ -375,26 +381,31 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) /* Power on th reader (CCID cmd) */ u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON, 0, 0, 0, 0, 0, 0, 3, 0, 0}; + char *buffer; + int transferred; int rc; void *cntx; struct pn533_acr122_poweron_rdr_arg arg; dev_dbg(&phy->udev->dev, "%s\n", __func__); + buffer = kmemdup(cmd, sizeof(cmd), GFP_KERNEL); + if (!buffer) + return -ENOMEM; + init_completion(&arg.done); cntx = phy->in_urb->context; /* backup context */ phy->in_urb->complete = pn533_acr122_poweron_rdr_resp; phy->in_urb->context = &arg; - phy->out_urb->transfer_buffer = cmd; - phy->out_urb->transfer_buffer_length = sizeof(cmd); - print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1, cmd, sizeof(cmd), false); - rc = usb_submit_urb(phy->out_urb, GFP_KERNEL); - if (rc) { + rc = usb_bulk_msg(phy->udev, phy->out_urb->pipe, buffer, sizeof(cmd), + &transferred, 0); + kfree(buffer); + if (rc || (transferred != sizeof(cmd))) { nfc_err(&phy->udev->dev, "Reader power on cmd error %d\n", rc); return rc; @@ -490,8 +501,9 @@ static int pn533_usb_probe(struct usb_interface *interface, phy->in_urb = usb_alloc_urb(0, GFP_KERNEL); phy->out_urb = usb_alloc_urb(0, GFP_KERNEL); + phy->ack_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!phy->in_urb || !phy->out_urb) + if (!phy->in_urb || !phy->out_urb || !phy->ack_urb) goto error; usb_fill_bulk_urb(phy->in_urb, phy->udev, @@ -501,7 +513,9 @@ static int pn533_usb_probe(struct usb_interface *interface, usb_fill_bulk_urb(phy->out_urb, phy->udev, usb_sndbulkpipe(phy->udev, out_endpoint), NULL, 0, pn533_send_complete, phy); - + usb_fill_bulk_urb(phy->ack_urb, phy->udev, + usb_sndbulkpipe(phy->udev, out_endpoint), + NULL, 0, pn533_send_complete, phy); switch (id->driver_info) { case PN533_DEVICE_STD: @@ -554,6 +568,7 @@ static int pn533_usb_probe(struct usb_interface *interface, error: usb_free_urb(phy->in_urb); usb_free_urb(phy->out_urb); + usb_free_urb(phy->ack_urb); usb_put_dev(phy->udev); kfree(in_buf); @@ -573,10 +588,13 @@ static void pn533_usb_disconnect(struct usb_interface *interface) usb_kill_urb(phy->in_urb); usb_kill_urb(phy->out_urb); + usb_kill_urb(phy->ack_urb); kfree(phy->in_urb->transfer_buffer); usb_free_urb(phy->in_urb); usb_free_urb(phy->out_urb); + usb_free_urb(phy->ack_urb); + kfree(phy->ack_buffer); nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n"); } -- GitLab From f31eb7298ba4fc6fb39119330367a44905da8c57 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 18 May 2018 20:13:42 -0500 Subject: [PATCH 0339/1299] usbip: vhci_sysfs: fix potential Spectre v1 commit a0d6ec88090d7b1b008429c44532a388e29bb1bd upstream. pdev_nr and rhport can be controlled by user-space, hence leading to a potential exploitation of the Spectre variant 1 vulnerability. This issue was detected with the help of Smatch: drivers/usb/usbip/vhci_sysfs.c:238 detach_store() warn: potential spectre issue 'vhcis' drivers/usb/usbip/vhci_sysfs.c:328 attach_store() warn: potential spectre issue 'vhcis' drivers/usb/usbip/vhci_sysfs.c:338 attach_store() warn: potential spectre issue 'vhci->vhci_hcd_ss->vdev' drivers/usb/usbip/vhci_sysfs.c:340 attach_store() warn: potential spectre issue 'vhci->vhci_hcd_hs->vdev' Fix this by sanitizing pdev_nr and rhport before using them to index vhcis and vhci->vhci_hcd_ss->vdev respectively. Notice that given that speculation windows are large, the policy is to kill the speculation on the first load and not worry if it can be completed with a dependent load/store [1]. [1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2 Cc: stable@vger.kernel.org Signed-off-by: Gustavo A. R. Silva Acked-by: Shuah Khan (Samsung OSG) Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vhci_sysfs.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index 84df63e3130d..4a22a9f06d96 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -24,6 +24,9 @@ #include #include +/* Hardening for Spectre-v1 */ +#include + #include "usbip_common.h" #include "vhci.h" @@ -219,16 +222,20 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport) return 0; } -static int valid_port(__u32 pdev_nr, __u32 rhport) +static int valid_port(__u32 *pdev_nr, __u32 *rhport) { - if (pdev_nr >= vhci_num_controllers) { - pr_err("pdev %u\n", pdev_nr); + if (*pdev_nr >= vhci_num_controllers) { + pr_err("pdev %u\n", *pdev_nr); return 0; } - if (rhport >= VHCI_HC_PORTS) { - pr_err("rhport %u\n", rhport); + *pdev_nr = array_index_nospec(*pdev_nr, vhci_num_controllers); + + if (*rhport >= VHCI_HC_PORTS) { + pr_err("rhport %u\n", *rhport); return 0; } + *rhport = array_index_nospec(*rhport, VHCI_HC_PORTS); + return 1; } @@ -246,7 +253,7 @@ static ssize_t store_detach(struct device *dev, struct device_attribute *attr, pdev_nr = port_to_pdev_nr(port); rhport = port_to_rhport(port); - if (!valid_port(pdev_nr, rhport)) + if (!valid_port(&pdev_nr, &rhport)) return -EINVAL; hcd = platform_get_drvdata(vhcis[pdev_nr].pdev); @@ -272,7 +279,8 @@ static ssize_t store_detach(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach); -static int valid_args(__u32 pdev_nr, __u32 rhport, enum usb_device_speed speed) +static int valid_args(__u32 *pdev_nr, __u32 *rhport, + enum usb_device_speed speed) { if (!valid_port(pdev_nr, rhport)) { return 0; @@ -336,7 +344,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, sockfd, devid, speed); /* check received parameters */ - if (!valid_args(pdev_nr, rhport, speed)) + if (!valid_args(&pdev_nr, &rhport, speed)) return -EINVAL; hcd = platform_get_drvdata(vhcis[pdev_nr].pdev); -- GitLab From c839680e8cbfb887ab7588aa1b4481aa1b85415b Mon Sep 17 00:00:00 2001 From: Alexander Kappner Date: Fri, 18 May 2018 21:50:15 -0700 Subject: [PATCH 0340/1299] usb-storage: Add support for FL_ALWAYS_SYNC flag in the UAS driver commit 8c4e97ddfe73a0958bb0abf7e6a3bc4cc3e04936 upstream. The ALWAYS_SYNC flag is currently honored by the usb-storage driver but not UAS and is required to work around devices that become unstable upon being queried for cache. This code is taken straight from: drivers/usb/storage/scsiglue.c:284 Signed-off-by: Alexander Kappner Acked-by: Alan Stern Cc: stable Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/uas.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 25a281f876b5..33a6d624c843 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -836,6 +836,12 @@ static int uas_slave_configure(struct scsi_device *sdev) if (devinfo->flags & US_FL_BROKEN_FUA) sdev->broken_fua = 1; + /* UAS also needs to support FL_ALWAYS_SYNC */ + if (devinfo->flags & US_FL_ALWAYS_SYNC) { + sdev->skip_ms_page_3f = 1; + sdev->skip_ms_page_8 = 1; + sdev->wce_default_on = 1; + } scsi_change_queue_depth(sdev, devinfo->qdepth - 2); return 0; } -- GitLab From 5c2e9e9bf44423ea43214a25e1ae1def34bff4ee Mon Sep 17 00:00:00 2001 From: Alexander Kappner Date: Fri, 18 May 2018 21:50:16 -0700 Subject: [PATCH 0341/1299] usb-storage: Add compatibility quirk flags for G-Technologies G-Drive commit ca7d9515d0e6825351ce106066cea1f60e40b1c8 upstream. The "G-Drive" (sold by G-Technology) external USB 3.0 drive hangs on write access under UAS and usb-storage: [ 136.079121] sd 15:0:0:0: [sdi] tag#0 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE [ 136.079144] sd 15:0:0:0: [sdi] tag#0 Sense Key : Illegal Request [current] [ 136.079152] sd 15:0:0:0: [sdi] tag#0 Add. Sense: Invalid field in cdb [ 136.079176] sd 15:0:0:0: [sdi] tag#0 CDB: Write(16) 8a 08 00 00 00 00 00 00 00 00 00 00 00 08 00 00 [ 136.079180] print_req_error: critical target error, dev sdi, sector 0 [ 136.079183] Buffer I/O error on dev sdi, logical block 0, lost sync page write [ 136.173148] EXT4-fs (sdi): mounted filesystem with ordered data mode. Opts: (null) [ 140.583998] sd 15:0:0:0: [sdi] tag#0 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE [ 140.584010] sd 15:0:0:0: [sdi] tag#0 Sense Key : Illegal Request [current] [ 140.584016] sd 15:0:0:0: [sdi] tag#0 Add. Sense: Invalid field in cdb [ 140.584022] sd 15:0:0:0: [sdi] tag#0 CDB: Write(16) 8a 08 00 00 00 00 e8 c4 00 18 00 00 00 08 00 00 [ 140.584025] print_req_error: critical target error, dev sdi, sector 3905159192 [ 140.584044] print_req_error: critical target error, dev sdi, sector 3905159192 [ 140.584052] Aborting journal on device sdi-8. The proposed patch adds compatibility quirks. Because the drive requires two quirks (one to work with UAS, and another to work with usb-storage), adding this under unusual_devs.h and not just unusual_uas.h so kernels compiled without UAS receive the quirk. With the patch, the drive works reliably on UAS and usb- storage. (tested on NEC Corporation uPD720200 USB 3.0 host controller). Signed-off-by: Alexander Kappner Acked-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 9 +++++++++ drivers/usb/storage/unusual_uas.h | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 52b3e6da0745..d100290628bd 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2340,6 +2340,15 @@ UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100, "Micro Mini 1GB", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), +/* "G-DRIVE" external HDD hangs on write without these. + * Patch submitted by Alexander Kappner + */ +UNUSUAL_DEV(0x4971, 0x8024, 0x0000, 0x9999, + "SimpleTech", + "External HDD", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_ALWAYS_SYNC), + /* * Nick Bowler * SCSI stack spams (otherwise harmless) error messages. diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index 719ec68ae309..f15aa47c54a9 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -183,3 +183,12 @@ UNUSUAL_DEV(0x4971, 0x8017, 0x0000, 0x9999, "External HDD", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_REPORT_OPCODES), + +/* "G-DRIVE" external HDD hangs on write without these. + * Patch submitted by Alexander Kappner + */ +UNUSUAL_DEV(0x4971, 0x8024, 0x0000, 0x9999, + "SimpleTech", + "External HDD", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_ALWAYS_SYNC), -- GitLab From cb6b5869658b7e1c3012e57aba17b3a74e5586cd Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Fri, 1 Jun 2018 11:46:08 -0700 Subject: [PATCH 0342/1299] Input: xpad - add GPD Win 2 Controller USB IDs commit c1ba08390a8bb13c927e699330896adc15b78205 upstream. GPD Win 2 Website: http://www.gpd.hk/gpdwin2.asp Tested on a unit from the first production run sent to Indiegogo backers Signed-off-by: Ethan Lee Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/joystick/xpad.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index d88d3e0f59fb..466cef930bf1 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -126,6 +126,7 @@ static const struct xpad_device { u8 mapping; u8 xtype; } xpad_device[] = { + { 0x0079, 0x18d4, "GPD Win 2 Controller", 0, XTYPE_XBOX360 }, { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, @@ -411,6 +412,7 @@ static const signed short xpad_abs_triggers[] = { static const struct usb_device_id xpad_table[] = { { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ + XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 Controller */ XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */ -- GitLab From 874cb201d511d867e6a97e43aacb674b46fd74f5 Mon Sep 17 00:00:00 2001 From: Manu Gautam Date: Thu, 3 May 2018 02:36:10 +0530 Subject: [PATCH 0343/1299] phy: qcom-qusb2: Fix crash if nvmem cell not specified commit 0b4555e776ba0712c6fafb98b226b21fd05d2427 upstream. Driver currently crashes due to NULL pointer deference while updating PHY tune register if nvmem cell is NULL. Since, fused value for Tune1/2 register is optional, we'd rather bail out. Fixes: ca04d9d3e1b1 ("phy: qcom-qusb2: New driver for QUSB2 PHY on Qcom chips") Reviewed-by: Vivek Gautam Reviewed-by: Evan Green Cc: stable # 4.14+ Signed-off-by: Manu Gautam Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman --- drivers/phy/qualcomm/phy-qcom-qusb2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 6c575244c0fb..af9b7005a2ba 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -178,6 +178,10 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) struct device *dev = &qphy->phy->dev; u8 *val; + /* efuse register is optional */ + if (!qphy->cell) + return; + /* * Read efuse register having TUNE2 parameter's high nibble. * If efuse register shows value as 0x0, or if we fail to find -- GitLab From 262af4fe6dff8ea742ab521e2d1cc39855b5e6c8 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 21 May 2018 20:18:07 +0900 Subject: [PATCH 0344/1299] usb: gadget: function: printer: avoid wrong list handling in printer_write() commit 4a014a7339f441b0851ce012f469c0fadac61c81 upstream. When printer_write() calls usb_ep_queue(), a udc driver (e.g. renesas_usbhs driver) may call usb_gadget_giveback_request() in the udc .queue ops immediately. Then, printer_write() calls list_add(&req->list, &dev->tx_reqs_active) wrongly. After that, if we do unbind the printer driver, WARN_ON() happens in printer_func_unbind() because the list entry is not removed. So, this patch moves list_add(&req->list, &dev->tx_reqs_active) calling before usb_ep_queue(). Signed-off-by: Yoshihiro Shimoda Acked-by: Felipe Balbi Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/f_printer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index ea0da35a44e2..e6d4fa5eeff1 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -635,19 +635,19 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) return -EAGAIN; } + list_add(&req->list, &dev->tx_reqs_active); + /* here, we unlock, and only unlock, to avoid deadlock. */ spin_unlock(&dev->lock); value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC); spin_lock(&dev->lock); if (value) { + list_del(&req->list); list_add(&req->list, &dev->tx_reqs); spin_unlock_irqrestore(&dev->lock, flags); mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } - - list_add(&req->list, &dev->tx_reqs_active); - } spin_unlock_irqrestore(&dev->lock, flags); -- GitLab From d6a9e699a3c2e07fa58865ab57a005c7afa2dd16 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 10 Apr 2018 14:38:54 +0900 Subject: [PATCH 0345/1299] usb: gadget: udc: renesas_usb3: disable the controller's irqs for reconnecting commit bd6bce004d78b867ba0c6d3712f1c5b50398af9a upstream. This patch fixes an issue that reconnection is possible to fail because unexpected state handling happens by the irqs. To fix the issue, the driver disables the controller's irqs when disconnected. Fixes: 746bfe63bba3 ("usb: gadget: renesas_usb3: add support for Renesas USB3.0 peripheral controller") Cc: # v4.5+ Reviewed-by: Simon Horman Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/renesas_usb3.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 6b3e8adb64e6..4cfa72cb0a91 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -623,6 +623,13 @@ static void usb3_disconnect(struct renesas_usb3 *usb3) usb3_usb2_pullup(usb3, 0); usb3_clear_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON); usb3_reset_epc(usb3); + usb3_disable_irq_1(usb3, USB_INT_1_B2_RSUM | USB_INT_1_B3_PLLWKUP | + USB_INT_1_B3_LUPSUCS | USB_INT_1_B3_DISABLE | + USB_INT_1_SPEED | USB_INT_1_B3_WRMRST | + USB_INT_1_B3_HOTRST | USB_INT_1_B2_SPND | + USB_INT_1_B2_L1SPND | USB_INT_1_B2_USBRST); + usb3_clear_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON); + usb3_init_epc_registers(usb3); if (usb3->driver) usb3->driver->disconnect(&usb3->gadget); -- GitLab From 95b8204b4491ae54c9024e695e6b327013e53fe0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Jun 2018 11:28:21 +0200 Subject: [PATCH 0346/1299] serial: sh-sci: Stop using printk format %pCr commit d63c16f8e1ab761775275adcf54f4bef7c330295 upstream. Printk format "%pCr" will be removed soon, as clk_get_rate() must not be called in atomic context. Replace it by open-coding the operation. This is safe here, as the code runs in task context. Link: http://lkml.kernel.org/r/1527845302-12159-4-git-send-email-geert+renesas@glider.be To: Jia-Ju Bai To: Jonathan Corbet To: Michael Turquette To: Stephen Boyd To: Zhang Rui To: Eduardo Valentin To: Eric Anholt To: Stefan Wahren To: Greg Kroah-Hartman Cc: Sergey Senozhatsky Cc: Petr Mladek Cc: Linus Torvalds Cc: Steven Rostedt Cc: linux-doc@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Geert Uytterhoeven Cc: stable@vger.kernel.org # 4.5+ Signed-off-by: Geert Uytterhoeven Signed-off-by: Petr Mladek Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 8a58ee32ff61..c6daa315ee4e 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2669,8 +2669,8 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i], PTR_ERR(clk)); else - dev_dbg(dev, "clk %s is %pC rate %pCr\n", clk_names[i], - clk, clk); + dev_dbg(dev, "clk %s is %pC rate %lu\n", clk_names[i], + clk, clk_get_rate(clk)); sci_port->clks[i] = IS_ERR(clk) ? NULL : clk; } return 0; -- GitLab From db30b8eb960a09fb8cd10c55e40cc09875d60eb1 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 7 May 2018 19:11:30 +0200 Subject: [PATCH 0347/1299] tty/serial: atmel: use port->name as name in request_irq() commit 9594b5be7ec110ed11acec58fa94f3f293668c85 upstream. I was puzzled while looking at /proc/interrupts and random things showed up between reboots. This occurred more often but I realised it later. The "correct" output should be: |38: 11861 atmel-aic5 2 Level ttyS0 but I saw sometimes |38: 6426 atmel-aic5 2 Level tty1 and accounted it wrongly as correct. This is use after free and the former example randomly got the "old" pointer which pointed to the same content. With SLAB_FREELIST_RANDOM and HARDENED I even got |38: 7067 atmel-aic5 2 Level E=Started User Manager for UID 0 or other nonsense. As it turns out the tty, pointer that is accessed in atmel_startup(), is freed() before atmel_shutdown(). It seems to happen quite often that the tty for ttyS0 is allocated and freed while ->shutdown is not invoked. I don't do anything special - just a systemd boot :) Use dev_name(&pdev->dev) as the IRQ name for request_irq(). This exists as long as the driver is loaded so no use-after-free here. Cc: stable@vger.kernel.org Fixes: 761ed4a94582 ("tty: serial_core: convert uart_close to use tty_port_close") Acked-by: Richard Genoud Acked-by: Rob Herring Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index a0b24bc09783..2286e9d73115 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1786,7 +1786,6 @@ static int atmel_startup(struct uart_port *port) { struct platform_device *pdev = to_platform_device(port->dev); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - struct tty_struct *tty = port->state->port.tty; int retval; /* @@ -1801,8 +1800,8 @@ static int atmel_startup(struct uart_port *port) * Allocate the IRQ */ retval = request_irq(port->irq, atmel_interrupt, - IRQF_SHARED | IRQF_COND_SUSPEND, - tty ? tty->name : "atmel_serial", port); + IRQF_SHARED | IRQF_COND_SUSPEND, + dev_name(&pdev->dev), port); if (retval) { dev_err(port->dev, "atmel_startup - Can't get irq\n"); return retval; -- GitLab From 804f090110695cd3e8cfa74cfec93ca54191e990 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 10 May 2018 08:41:13 +0200 Subject: [PATCH 0348/1299] serial: samsung: fix maxburst parameter for DMA transactions commit aa2f80e752c75e593b3820f42c416ed9458fa73e upstream. The best granularity of residue that DMA engine can report is in the BURST units, so the serial driver must use MAXBURST = 1 and DMA_SLAVE_BUSWIDTH_1_BYTE if it relies on exact number of bytes transferred by DMA engine. Fixes: 62c37eedb74c ("serial: samsung: add dma reqest/release functions") Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index bedd4bdec4ab..57baa84ccf86 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -865,15 +865,12 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) dma->rx_conf.direction = DMA_DEV_TO_MEM; dma->rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dma->rx_conf.src_addr = p->port.mapbase + S3C2410_URXH; - dma->rx_conf.src_maxburst = 16; + dma->rx_conf.src_maxburst = 1; dma->tx_conf.direction = DMA_MEM_TO_DEV; dma->tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dma->tx_conf.dst_addr = p->port.mapbase + S3C2410_UTXH; - if (dma_get_cache_alignment() >= 16) - dma->tx_conf.dst_maxburst = 16; - else - dma->tx_conf.dst_maxburst = 1; + dma->tx_conf.dst_maxburst = 1; dma->rx_chan = dma_request_chan(p->port.dev, "rx"); -- GitLab From a64ff0bea05115c611d95eec4bc5731381063b4d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 4 May 2018 10:44:09 -0700 Subject: [PATCH 0349/1299] serial: 8250: omap: Fix idling of clocks for unused uarts commit 13dc04d0e5fdc25c8f713ad23fdce51cf2bf96ba upstream. I noticed that unused UARTs won't necessarily idle properly always unless at least one byte tx transfer is done first. After some debugging I narrowed down the problem to the scr register dma configuration bits that need to be set before softreset for the clocks to idle. Unless we do this, the module clkctrl idlest bits may be set to 1 instead of 3 meaning the clock will never idle and is blocking deeper idle states for the whole domain. This might be related to the configuration done by the bootloader or kexec booting where certain configurations cause the 8250 or the clkctrl clock to jam in a way where setting of the scr bits and reset is needed to clear it. I've tried diffing the 8250 registers for the various modes, but did not see anything specific. So far I've only seen this on omap4 but I'm suspecting this might also happen on the other clkctrl using SoCs considering they already have a quirk enabled for UART_ERRATA_CLOCK_DISABLE. Let's fix the issue by configuring scr before reset for basic dma even if we don't use it. The scr register will be reset when we do softreset few lines after, and we restore scr on resume. We should do this for all the SoCs with UART_ERRATA_CLOCK_DISABLE quirk flag set since the ones with UART_ERRATA_CLOCK_DISABLE are all based using clkctrl similar to omap4. Looks like both OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL bits are needed for the clkctrl to idle after a softreset. And we need to add omap4 to also use the UART_ERRATA_CLOCK_DISABLE for the related workaround to be enabled. This same compatible value will also be used for omap5. Fixes: cdb929e4452a ("serial: 8250_omap: workaround errata around idling UART after using DMA") Cc: Keerthy Cc: Matthijs van Duin Cc: Sekhar Nori Cc: Tero Kristo Signed-off-by: Tony Lindgren Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 833771bca0a5..da04ba1ecf68 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1100,13 +1100,14 @@ static int omap8250_no_handle_irq(struct uart_port *port) return 0; } +static const u8 omap4_habit = UART_ERRATA_CLOCK_DISABLE; static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE; static const u8 dra742_habit = UART_ERRATA_CLOCK_DISABLE; static const struct of_device_id omap8250_dt_ids[] = { { .compatible = "ti,omap2-uart" }, { .compatible = "ti,omap3-uart" }, - { .compatible = "ti,omap4-uart" }, + { .compatible = "ti,omap4-uart", .data = &omap4_habit, }, { .compatible = "ti,am3352-uart", .data = &am3352_habit, }, { .compatible = "ti,am4372-uart", .data = &am3352_habit, }, { .compatible = "ti,dra742-uart", .data = &dra742_habit, }, @@ -1343,6 +1344,19 @@ static int omap8250_soft_reset(struct device *dev) int sysc; int syss; + /* + * At least on omap4, unused uarts may not idle after reset without + * a basic scr dma configuration even with no dma in use. The + * module clkctrl status bits will be 1 instead of 3 blocking idle + * for the whole clockdomain. The softreset below will clear scr, + * and we restore it on resume so this is safe to do on all SoCs + * needing omap8250_soft_reset() quirk. Do it in two writes as + * recommended in the comment for omap8250_update_scr(). + */ + serial_out(up, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1); + serial_out(up, UART_OMAP_SCR, + OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL); + sysc = serial_in(up, UART_OMAP_SYSC); /* softreset the UART */ -- GitLab From 5ee296fde55e0f357b10d547d593cede0f168642 Mon Sep 17 00:00:00 2001 From: Gil Kupfer Date: Fri, 1 Jun 2018 00:47:47 -0700 Subject: [PATCH 0350/1299] vmw_balloon: fixing double free when batching mode is off commit b23220fe054e92f616b82450fae8cd3ab176cc60 upstream. The balloon.page field is used for two different purposes if batching is on or off. If batching is on, the field point to the page which is used to communicate with with the hypervisor. If it is off, balloon.page points to the page that is about to be (un)locked. Unfortunately, this dual-purpose of the field introduced a bug: when the balloon is popped (e.g., when the machine is reset or the balloon driver is explicitly removed), the balloon driver frees, unconditionally, the page that is held in balloon.page. As a result, if batching is disabled, this leads to double freeing the last page that is sent to the hypervisor. The following error occurs during rmmod when kernel checkers are on, and the balloon is not empty: [ 42.307653] ------------[ cut here ]------------ [ 42.307657] Kernel BUG at ffffffffba1e4b28 [verbose debug info unavailable] [ 42.307720] invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC [ 42.312512] Modules linked in: vmw_vsock_vmci_transport vsock ppdev joydev vmw_balloon(-) input_leds serio_raw vmw_vmci parport_pc shpchp parport i2c_piix4 nfit mac_hid autofs4 vmwgfx drm_kms_helper hid_generic syscopyarea sysfillrect usbhid sysimgblt fb_sys_fops hid ttm mptspi scsi_transport_spi ahci mptscsih drm psmouse vmxnet3 libahci mptbase pata_acpi [ 42.312766] CPU: 10 PID: 1527 Comm: rmmod Not tainted 4.12.0+ #5 [ 42.312803] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 09/30/2016 [ 42.313042] task: ffff9bf9680f8000 task.stack: ffffbfefc1638000 [ 42.313290] RIP: 0010:__free_pages+0x38/0x40 [ 42.313510] RSP: 0018:ffffbfefc163be98 EFLAGS: 00010246 [ 42.313731] RAX: 000000000000003e RBX: ffffffffc02b9720 RCX: 0000000000000006 [ 42.313972] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff9bf97e08e0a0 [ 42.314201] RBP: ffffbfefc163be98 R08: 0000000000000000 R09: 0000000000000000 [ 42.314435] R10: 0000000000000000 R11: 0000000000000000 R12: ffffffffc02b97e4 [ 42.314505] R13: ffffffffc02b9748 R14: ffffffffc02b9728 R15: 0000000000000200 [ 42.314550] FS: 00007f3af5fec700(0000) GS:ffff9bf97e080000(0000) knlGS:0000000000000000 [ 42.314599] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 42.314635] CR2: 00007f44f6f4ab24 CR3: 00000003a7d12000 CR4: 00000000000006e0 [ 42.314864] Call Trace: [ 42.315774] vmballoon_pop+0x102/0x130 [vmw_balloon] [ 42.315816] vmballoon_exit+0x42/0xd64 [vmw_balloon] [ 42.315853] SyS_delete_module+0x1e2/0x250 [ 42.315891] entry_SYSCALL_64_fastpath+0x23/0xc2 [ 42.315924] RIP: 0033:0x7f3af5b0e8e7 [ 42.315949] RSP: 002b:00007fffe6ce0148 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0 [ 42.315996] RAX: ffffffffffffffda RBX: 000055be676401e0 RCX: 00007f3af5b0e8e7 [ 42.316951] RDX: 000000000000000a RSI: 0000000000000800 RDI: 000055be67640248 [ 42.317887] RBP: 0000000000000003 R08: 0000000000000000 R09: 1999999999999999 [ 42.318845] R10: 0000000000000883 R11: 0000000000000206 R12: 00007fffe6cdf130 [ 42.319755] R13: 0000000000000000 R14: 0000000000000000 R15: 000055be676401e0 [ 42.320606] Code: c0 74 1c f0 ff 4f 1c 74 02 5d c3 85 f6 74 07 e8 0f d8 ff ff 5d c3 31 f6 e8 c6 fb ff ff 5d c3 48 c7 c6 c8 0f c5 ba e8 58 be 02 00 <0f> 0b 66 0f 1f 44 00 00 66 66 66 66 90 48 85 ff 75 01 c3 55 48 [ 42.323462] RIP: __free_pages+0x38/0x40 RSP: ffffbfefc163be98 [ 42.325735] ---[ end trace 872e008e33f81508 ]--- To solve the bug, we eliminate the dual purpose of balloon.page. Fixes: f220a80f0c2e ("VMware balloon: add batching to the vmw_balloon.") Cc: stable@vger.kernel.org Reported-by: Oleksandr Natalenko Signed-off-by: Gil Kupfer Signed-off-by: Nadav Amit Reviewed-by: Xavier Deguillard Tested-by: Oleksandr Natalenko Signed-off-by: Greg Kroah-Hartman --- drivers/misc/vmw_balloon.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c index 9047c0a529b2..efd733472a35 100644 --- a/drivers/misc/vmw_balloon.c +++ b/drivers/misc/vmw_balloon.c @@ -576,15 +576,9 @@ static void vmballoon_pop(struct vmballoon *b) } } - if (b->batch_page) { - vunmap(b->batch_page); - b->batch_page = NULL; - } - - if (b->page) { - __free_page(b->page); - b->page = NULL; - } + /* Clearing the batch_page unconditionally has no adverse effect */ + free_page((unsigned long)b->batch_page); + b->batch_page = NULL; } /* @@ -991,16 +985,13 @@ static const struct vmballoon_ops vmballoon_batched_ops = { static bool vmballoon_init_batching(struct vmballoon *b) { - b->page = alloc_page(VMW_PAGE_ALLOC_NOSLEEP); - if (!b->page) - return false; + struct page *page; - b->batch_page = vmap(&b->page, 1, VM_MAP, PAGE_KERNEL); - if (!b->batch_page) { - __free_page(b->page); + page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!page) return false; - } + b->batch_page = page_address(page); return true; } -- GitLab From 739ac8f4a516e62c26e1325bd59d3be03fae210e Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Thu, 10 May 2018 18:08:23 +0100 Subject: [PATCH 0351/1299] tty: pl011: Avoid spuriously stuck-off interrupts commit 4a7e625ce50412a7711efa0f2ef0b96ce3826759 upstream. Commit 9b96fbacda34 ("serial: PL011: clear pending interrupts") clears the RX and receive timeout interrupts on pl011 startup, to avoid a screaming-interrupt scenario that can occur when the firmware or bootloader leaves these interrupts asserted. This has been noted as an issue when running Linux on qemu [1]. Unfortunately, the above fix seems to lead to potential misbehaviour if the RX FIFO interrupt is asserted _non_ spuriously on driver startup, if the RX FIFO is also already full to the trigger level. Clearing the RX FIFO interrupt does not change the FIFO fill level. In this scenario, because the interrupt is now clear and because the FIFO is already full to the trigger level, no new assertion of the RX FIFO interrupt can occur unless the FIFO is drained back below the trigger level. This never occurs because the pl011 driver is waiting for an RX FIFO interrupt to tell it that there is something to read, and does not read the FIFO at all until that interrupt occurs. Thus, simply clearing "spurious" interrupts on startup may be misguided, since there is no way to be sure that the interrupts are truly spurious, and things can go wrong if they are not. This patch instead clears the interrupt condition by draining the RX FIFO during UART startup, after clearing any potentially spurious interrupt. This should ensure that an interrupt will definitely be asserted if the RX FIFO subsequently becomes sufficiently full. The drain is done at the point of enabling interrupts only. This means that it will occur any time the UART is newly opened through the tty layer. It will not apply to polled-mode use of the UART by kgdboc: since that scenario cannot use interrupts by design, this should not matter. kgdboc will interact badly with "normal" use of the UART in any case: this patch makes no attempt to paper over such issues. This patch does not attempt to address the case where the RX FIFO fills faster than it can be drained: that is a pathological hardware design problem that is beyond the scope of the driver to work around. As a failsafe, the number of poll iterations for draining the FIFO is limited to twice the FIFO size. This will ensure that the kernel at least boots even if it is impossible to drain the FIFO for some reason. [1] [Qemu-devel] [Qemu-arm] [PATCH] pl011: do not put into fifo before enabled the interruption https://lists.gnu.org/archive/html/qemu-devel/2018-01/msg06446.html Reported-by: Wei Xu Cc: Russell King Cc: Linus Walleij Cc: Peter Maydell Fixes: 9b96fbacda34 ("serial: PL011: clear pending interrupts") Signed-off-by: Dave Martin Cc: stable Tested-by: Wei Xu Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 111e6a950779..c9f701aca677 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1747,10 +1747,26 @@ static int pl011_allocate_irq(struct uart_amba_port *uap) */ static void pl011_enable_interrupts(struct uart_amba_port *uap) { + unsigned int i; + spin_lock_irq(&uap->port.lock); /* Clear out any spuriously appearing RX interrupts */ pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR); + + /* + * RXIS is asserted only when the RX FIFO transitions from below + * to above the trigger threshold. If the RX FIFO is already + * full to the threshold this can't happen and RXIS will now be + * stuck off. Drain the RX FIFO explicitly to fix this: + */ + for (i = 0; i < uap->fifosize * 2; ++i) { + if (pl011_read(uap, REG_FR) & UART01x_FR_RXFE) + break; + + pl011_read(uap, REG_DR); + } + uap->im = UART011_RTIM; if (!pl011_dma_rx_running(uap)) uap->im |= UART011_RXIM; -- GitLab From 53e4b19fcd0ce08933e0f7a7fe11654f6eac1f19 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 6 Jun 2018 17:38:09 +0200 Subject: [PATCH 0352/1299] kvm: x86: use correct privilege level for sgdt/sidt/fxsave/fxrstor access commit 3c9fa24ca7c9c47605672916491f79e8ccacb9e6 upstream. The functions that were used in the emulation of fxrstor, fxsave, sgdt and sidt were originally meant for task switching, and as such they did not check privilege levels. This is very bad when the same functions are used in the emulation of unprivileged instructions. This is CVE-2018-10853. The obvious fix is to add a new argument to ops->read_std and ops->write_std, which decides whether the access is a "system" access or should use the processor's CPL. Fixes: 129a72a0d3c8 ("KVM: x86: Introduce segmented_write_std", 2017-01-12) Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/kvm_emulate.h | 6 ++++-- arch/x86/kvm/emulate.c | 12 ++++++------ arch/x86/kvm/x86.c | 18 ++++++++++++++---- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index ee23a43386a2..8493303d8b2e 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -107,11 +107,12 @@ struct x86_emulate_ops { * @addr: [IN ] Linear address from which to read. * @val: [OUT] Value read from memory, zero-extended to 'u_long'. * @bytes: [IN ] Number of bytes to read from memory. + * @system:[IN ] Whether the access is forced to be at CPL0. */ int (*read_std)(struct x86_emulate_ctxt *ctxt, unsigned long addr, void *val, unsigned int bytes, - struct x86_exception *fault); + struct x86_exception *fault, bool system); /* * read_phys: Read bytes of standard (non-emulated/special) memory. @@ -129,10 +130,11 @@ struct x86_emulate_ops { * @addr: [IN ] Linear address to which to write. * @val: [OUT] Value write to memory, zero-extended to 'u_long'. * @bytes: [IN ] Number of bytes to write to memory. + * @system:[IN ] Whether the access is forced to be at CPL0. */ int (*write_std)(struct x86_emulate_ctxt *ctxt, unsigned long addr, void *val, unsigned int bytes, - struct x86_exception *fault); + struct x86_exception *fault, bool system); /* * fetch: Read bytes of standard (non-emulated/special) memory. * Used for instruction fetch. diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 713d8861e5eb..5f758568fc44 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -814,14 +814,14 @@ static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) static int linear_read_system(struct x86_emulate_ctxt *ctxt, ulong linear, void *data, unsigned size) { - return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception); + return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, true); } static int linear_write_system(struct x86_emulate_ctxt *ctxt, ulong linear, void *data, unsigned int size) { - return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception); + return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, true); } static int segmented_read_std(struct x86_emulate_ctxt *ctxt, @@ -835,7 +835,7 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt, rc = linearize(ctxt, addr, size, false, &linear); if (rc != X86EMUL_CONTINUE) return rc; - return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception); + return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, false); } static int segmented_write_std(struct x86_emulate_ctxt *ctxt, @@ -849,7 +849,7 @@ static int segmented_write_std(struct x86_emulate_ctxt *ctxt, rc = linearize(ctxt, addr, size, true, &linear); if (rc != X86EMUL_CONTINUE) return rc; - return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception); + return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, false); } /* @@ -2921,12 +2921,12 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt, #ifdef CONFIG_X86_64 base |= ((u64)base3) << 32; #endif - r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL); + r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL, true); if (r != X86EMUL_CONTINUE) return false; if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg)) return false; - r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL); + r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL, true); if (r != X86EMUL_CONTINUE) return false; if ((perm >> bit_idx) & mask) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ade1d165ada6..b62328cd4cb0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4505,10 +4505,15 @@ EXPORT_SYMBOL_GPL(kvm_read_guest_virt); static int emulator_read_std(struct x86_emulate_ctxt *ctxt, gva_t addr, void *val, unsigned int bytes, - struct x86_exception *exception) + struct x86_exception *exception, bool system) { struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); - return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, exception); + u32 access = 0; + + if (!system && kvm_x86_ops->get_cpl(vcpu) == 3) + access |= PFERR_USER_MASK; + + return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access, exception); } static int kvm_read_guest_phys_system(struct x86_emulate_ctxt *ctxt, @@ -4552,12 +4557,17 @@ static int kvm_write_guest_virt_helper(gva_t addr, void *val, unsigned int bytes } static int emulator_write_std(struct x86_emulate_ctxt *ctxt, gva_t addr, void *val, - unsigned int bytes, struct x86_exception *exception) + unsigned int bytes, struct x86_exception *exception, + bool system) { struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); + u32 access = PFERR_WRITE_MASK; + + if (!system && kvm_x86_ops->get_cpl(vcpu) == 3) + access |= PFERR_USER_MASK; return kvm_write_guest_virt_helper(addr, val, bytes, vcpu, - PFERR_WRITE_MASK, exception); + access, exception); } int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val, -- GitLab From c4168f1920570a6a1ba7c6743ff0a29860d304ed Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Thu, 31 May 2018 16:13:17 -0700 Subject: [PATCH 0353/1299] Input: goodix - add new ACPI id for GPD Win 2 touch screen commit 5ca4d1ae9bad0f59bd6f851c39b19f5366953666 upstream. GPD Win 2 Website: http://www.gpd.hk/gpdwin2.asp Tested on a unit from the first production run sent to Indiegogo backers Signed-off-by: Ethan Lee Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/touchscreen/goodix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 5dafafad6351..2bfa89ec552c 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -888,6 +888,7 @@ MODULE_DEVICE_TABLE(i2c, goodix_ts_id); #ifdef CONFIG_ACPI static const struct acpi_device_id goodix_acpi_match[] = { { "GDIX1001", 0 }, + { "GDIX1002", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); -- GitLab From 3c42aa03cd6a9da88414d013589bf2d9d518fe63 Mon Sep 17 00:00:00 2001 From: Johannes Wienke Date: Mon, 4 Jun 2018 13:37:26 -0700 Subject: [PATCH 0354/1299] Input: elan_i2c - add ELAN0612 (Lenovo v330 14IKB) ACPI ID commit e6e7e9cd8eed0e18217c899843bffbe8c7dae564 upstream. Add ELAN0612 to the list of supported touchpads; this ID is used in Lenovo v330 14IKB devices. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199253 Signed-off-by: Johannes Wienke Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/elan_i2c_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index d6135900da64..c4926645c779 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1260,6 +1260,7 @@ static const struct acpi_device_id elan_acpi_id[] = { { "ELAN060B", 0 }, { "ELAN060C", 0 }, { "ELAN0611", 0 }, + { "ELAN0612", 0 }, { "ELAN1000", 0 }, { } }; -- GitLab From ed0a79561189487506ef7fe0a6709b4810378a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Mon, 16 Apr 2018 08:07:05 -0500 Subject: [PATCH 0355/1299] crypto: caam - strip input zeros from RSA input buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8a2a0dd35f2e54c023d9041a5428b6c5639af86c upstream. Sometimes the provided RSA input buffer provided is not stripped of leading zeros. This could cause its size to be bigger than that of the modulus, making the HW complain: caam_jr 2142000.jr1: 40000789: DECO: desc idx 7: Protocol Size Error - A protocol has seen an error in size. When running RSA, pdb size N < (size of F) when no formatting is used; or pdb size N < (F + 11) when formatting is used. Fix the problem by stripping off the leading zero from input data before feeding it to the CAAM accelerator. Fixes: 8c419778ab57e ("crypto: caam - add support for RSA algorithm") Cc: # 4.8+ Reported-by: Martin Townsend Link: https://lkml.kernel.org/r/CABatt_ytYORYKtApcB4izhNanEKkGFi9XAQMjHi_n-8YWoCRiw@mail.gmail.com Signed-off-by: Horia Geantă Tested-by: Fabio Estevam Reviewed-by: Tudor Ambarus Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/caam/caampkc.c | 54 +++++++++++++++++++++++++++++++++++ drivers/crypto/caam/caampkc.h | 8 ++++++ 2 files changed, 62 insertions(+) diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index 7a897209f181..979072b25eaa 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -166,18 +166,71 @@ static void rsa_priv_f3_done(struct device *dev, u32 *desc, u32 err, akcipher_request_complete(req, err); } +static int caam_rsa_count_leading_zeros(struct scatterlist *sgl, + unsigned int nbytes, + unsigned int flags) +{ + struct sg_mapping_iter miter; + int lzeros, ents; + unsigned int len; + unsigned int tbytes = nbytes; + const u8 *buff; + + ents = sg_nents_for_len(sgl, nbytes); + if (ents < 0) + return ents; + + sg_miter_start(&miter, sgl, ents, SG_MITER_FROM_SG | flags); + + lzeros = 0; + len = 0; + while (nbytes > 0) { + while (len && !*buff) { + lzeros++; + len--; + buff++; + } + + if (len && *buff) + break; + + sg_miter_next(&miter); + buff = miter.addr; + len = miter.length; + + nbytes -= lzeros; + lzeros = 0; + } + + miter.consumed = lzeros; + sg_miter_stop(&miter); + nbytes -= lzeros; + + return tbytes - nbytes; +} + static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req, size_t desclen) { struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); struct device *dev = ctx->dev; + struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req); struct rsa_edesc *edesc; gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC; + int sg_flags = (flags == GFP_ATOMIC) ? SG_MITER_ATOMIC : 0; int sgc; int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes; int src_nents, dst_nents; + int lzeros; + + lzeros = caam_rsa_count_leading_zeros(req->src, req->src_len, sg_flags); + if (lzeros < 0) + return ERR_PTR(lzeros); + + req->src_len -= lzeros; + req->src = scatterwalk_ffwd(req_ctx->src, req->src, lzeros); src_nents = sg_nents_for_len(req->src, req->src_len); dst_nents = sg_nents_for_len(req->dst, req->dst_len); @@ -953,6 +1006,7 @@ static struct akcipher_alg caam_rsa = { .max_size = caam_rsa_max_size, .init = caam_rsa_init_tfm, .exit = caam_rsa_exit_tfm, + .reqsize = sizeof(struct caam_rsa_req_ctx), .base = { .cra_name = "rsa", .cra_driver_name = "rsa-caam", diff --git a/drivers/crypto/caam/caampkc.h b/drivers/crypto/caam/caampkc.h index fd145c46eae1..82645bcf8b27 100644 --- a/drivers/crypto/caam/caampkc.h +++ b/drivers/crypto/caam/caampkc.h @@ -95,6 +95,14 @@ struct caam_rsa_ctx { struct device *dev; }; +/** + * caam_rsa_req_ctx - per request context. + * @src: input scatterlist (stripped of leading zeros) + */ +struct caam_rsa_req_ctx { + struct scatterlist src[2]; +}; + /** * rsa_edesc - s/w-extended rsa descriptor * @src_nents : number of segments in input scatterlist -- GitLab From 635ac89ea764dcb6a465e706107644f8baa96811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Wed, 28 Mar 2018 15:39:17 +0300 Subject: [PATCH 0356/1299] crypto: caam - fix DMA mapping dir for generated IV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a38acd236cac914aafffd80af79b9556fc2c3934 upstream. In case of GIVCIPHER, IV is generated by the device. Fix the DMA mapping direction. Cc: # 3.19+ Fixes: 7222d1a34103 ("crypto: caam - add support for givencrypt cbc(aes) and rfc3686(ctr(aes))") Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/caam/caamalg.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 54f3b375a453..e6f0501e9728 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -735,6 +735,7 @@ struct aead_edesc { * @src_nents: number of segments in input s/w scatterlist * @dst_nents: number of segments in output s/w scatterlist * @iv_dma: dma address of iv for checking continuity and link table + * @iv_dir: DMA mapping direction for IV * @sec4_sg_bytes: length of dma mapped sec4_sg space * @sec4_sg_dma: bus physical mapped address of h/w link table * @sec4_sg: pointer to h/w link table @@ -744,6 +745,7 @@ struct ablkcipher_edesc { int src_nents; int dst_nents; dma_addr_t iv_dma; + enum dma_data_direction iv_dir; int sec4_sg_bytes; dma_addr_t sec4_sg_dma; struct sec4_sg_entry *sec4_sg; @@ -753,7 +755,8 @@ struct ablkcipher_edesc { static void caam_unmap(struct device *dev, struct scatterlist *src, struct scatterlist *dst, int src_nents, int dst_nents, - dma_addr_t iv_dma, int ivsize, dma_addr_t sec4_sg_dma, + dma_addr_t iv_dma, int ivsize, + enum dma_data_direction iv_dir, dma_addr_t sec4_sg_dma, int sec4_sg_bytes) { if (dst != src) { @@ -765,7 +768,7 @@ static void caam_unmap(struct device *dev, struct scatterlist *src, } if (iv_dma) - dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE); + dma_unmap_single(dev, iv_dma, ivsize, iv_dir); if (sec4_sg_bytes) dma_unmap_single(dev, sec4_sg_dma, sec4_sg_bytes, DMA_TO_DEVICE); @@ -776,7 +779,7 @@ static void aead_unmap(struct device *dev, struct aead_request *req) { caam_unmap(dev, req->src, req->dst, - edesc->src_nents, edesc->dst_nents, 0, 0, + edesc->src_nents, edesc->dst_nents, 0, 0, DMA_NONE, edesc->sec4_sg_dma, edesc->sec4_sg_bytes); } @@ -789,7 +792,7 @@ static void ablkcipher_unmap(struct device *dev, caam_unmap(dev, req->src, req->dst, edesc->src_nents, edesc->dst_nents, - edesc->iv_dma, ivsize, + edesc->iv_dma, ivsize, edesc->iv_dir, edesc->sec4_sg_dma, edesc->sec4_sg_bytes); } @@ -1245,7 +1248,7 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, GFP_DMA | flags); if (!edesc) { caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0, - 0, 0, 0); + 0, DMA_NONE, 0, 0); return ERR_PTR(-ENOMEM); } @@ -1508,7 +1511,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request if (dma_mapping_error(jrdev, iv_dma)) { dev_err(jrdev, "unable to map IV\n"); caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0, - 0, 0, 0); + 0, DMA_NONE, 0, 0); return ERR_PTR(-ENOMEM); } @@ -1530,7 +1533,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request if (!edesc) { dev_err(jrdev, "could not allocate extended descriptor\n"); caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, 0, 0); + iv_dma, ivsize, DMA_TO_DEVICE, 0, 0); return ERR_PTR(-ENOMEM); } @@ -1539,6 +1542,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request edesc->sec4_sg_bytes = sec4_sg_bytes; edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) + desc_bytes; + edesc->iv_dir = DMA_TO_DEVICE; if (!in_contig) { dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0); @@ -1556,7 +1560,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) { dev_err(jrdev, "unable to map S/G table\n"); caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, 0, 0); + iv_dma, ivsize, DMA_TO_DEVICE, 0, 0); kfree(edesc); return ERR_PTR(-ENOMEM); } @@ -1714,11 +1718,11 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( * Check if iv can be contiguous with source and destination. * If so, include it. If not, create scatterlist. */ - iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_TO_DEVICE); + iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_FROM_DEVICE); if (dma_mapping_error(jrdev, iv_dma)) { dev_err(jrdev, "unable to map IV\n"); caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0, - 0, 0, 0); + 0, DMA_NONE, 0, 0); return ERR_PTR(-ENOMEM); } @@ -1739,7 +1743,7 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( if (!edesc) { dev_err(jrdev, "could not allocate extended descriptor\n"); caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, 0, 0); + iv_dma, ivsize, DMA_FROM_DEVICE, 0, 0); return ERR_PTR(-ENOMEM); } @@ -1748,6 +1752,7 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( edesc->sec4_sg_bytes = sec4_sg_bytes; edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) + desc_bytes; + edesc->iv_dir = DMA_FROM_DEVICE; if (mapped_src_nents > 1) sg_to_sec4_sg_last(req->src, mapped_src_nents, edesc->sec4_sg, @@ -1765,7 +1770,7 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) { dev_err(jrdev, "unable to map S/G table\n"); caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, 0, 0); + iv_dma, ivsize, DMA_FROM_DEVICE, 0, 0); kfree(edesc); return ERR_PTR(-ENOMEM); } -- GitLab From 9ed3135cab14c6ea372cb33b8865acbec0d04d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Wed, 28 Mar 2018 15:39:18 +0300 Subject: [PATCH 0357/1299] crypto: caam - fix IV DMA mapping and updating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 115957bb3e59fcb226ce76b97af14533f239e0ac upstream. There are two IV-related issues: (1) crypto API does not guarantee to provide an IV buffer that is DMAable, thus it's incorrect to DMA map it (2) for in-place decryption, since ciphertext is overwritten with plaintext, updated req->info will contain the last block of plaintext (instead of the last block of ciphertext) While these two issues could be fixed separately, it's straightforward to fix both in the same time - by allocating extra space in the ablkcipher_edesc for the IV that will be fed to the crypto engine; this allows for fixing (2) by saving req->src[last_block] in req->info directly, i.e. without allocating another temporary buffer. A side effect of the fix is that it's no longer possible to have the IV and req->src contiguous. Code checking for this case is removed. Cc: # 4.13+ Fixes: 854b06f76879 ("crypto: caam - properly set IV after {en,de}crypt") Link: http://lkml.kernel.org/r/20170113084620.GF22022@gondor.apana.org.au Reported-by: Gilad Ben-Yossef Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/caam/caamalg.c | 212 +++++++++++++++------------------- 1 file changed, 91 insertions(+), 121 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index e6f0501e9728..a8a2a271b63d 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -740,6 +740,7 @@ struct aead_edesc { * @sec4_sg_dma: bus physical mapped address of h/w link table * @sec4_sg: pointer to h/w link table * @hw_desc: the h/w job descriptor followed by any referenced link tables + * and IV */ struct ablkcipher_edesc { int src_nents; @@ -881,6 +882,18 @@ static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err, scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - ivsize, ivsize, 0); + /* In case initial IV was generated, copy it in GIVCIPHER request */ + if (edesc->iv_dir == DMA_FROM_DEVICE) { + u8 *iv; + struct skcipher_givcrypt_request *greq; + + greq = container_of(req, struct skcipher_givcrypt_request, + creq); + iv = (u8 *)edesc->hw_desc + desc_bytes(edesc->hw_desc) + + edesc->sec4_sg_bytes; + memcpy(greq->giv, iv, ivsize); + } + kfree(edesc); ablkcipher_request_complete(req, err); @@ -891,10 +904,10 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err, { struct ablkcipher_request *req = context; struct ablkcipher_edesc *edesc; +#ifdef DEBUG struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); int ivsize = crypto_ablkcipher_ivsize(ablkcipher); -#ifdef DEBUG dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); #endif @@ -912,14 +925,6 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err, edesc->dst_nents > 1 ? 100 : req->nbytes, 1); ablkcipher_unmap(jrdev, edesc, req); - - /* - * The crypto API expects us to set the IV (req->info) to the last - * ciphertext block. - */ - scatterwalk_map_and_copy(req->info, req->src, req->nbytes - ivsize, - ivsize, 0); - kfree(edesc); ablkcipher_request_complete(req, err); @@ -1060,15 +1065,14 @@ static void init_authenc_job(struct aead_request *req, */ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr, struct ablkcipher_edesc *edesc, - struct ablkcipher_request *req, - bool iv_contig) + struct ablkcipher_request *req) { struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); int ivsize = crypto_ablkcipher_ivsize(ablkcipher); u32 *desc = edesc->hw_desc; - u32 out_options = 0, in_options; - dma_addr_t dst_dma, src_dma; - int len, sec4_sg_index = 0; + u32 out_options = 0; + dma_addr_t dst_dma; + int len; #ifdef DEBUG print_hex_dump(KERN_ERR, "presciv@"__stringify(__LINE__)": ", @@ -1084,30 +1088,18 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr, len = desc_len(sh_desc); init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE); - if (iv_contig) { - src_dma = edesc->iv_dma; - in_options = 0; - } else { - src_dma = edesc->sec4_sg_dma; - sec4_sg_index += edesc->src_nents + 1; - in_options = LDST_SGF; - } - append_seq_in_ptr(desc, src_dma, req->nbytes + ivsize, in_options); + append_seq_in_ptr(desc, edesc->sec4_sg_dma, req->nbytes + ivsize, + LDST_SGF); if (likely(req->src == req->dst)) { - if (edesc->src_nents == 1 && iv_contig) { - dst_dma = sg_dma_address(req->src); - } else { - dst_dma = edesc->sec4_sg_dma + - sizeof(struct sec4_sg_entry); - out_options = LDST_SGF; - } + dst_dma = edesc->sec4_sg_dma + sizeof(struct sec4_sg_entry); + out_options = LDST_SGF; } else { if (edesc->dst_nents == 1) { dst_dma = sg_dma_address(req->dst); } else { - dst_dma = edesc->sec4_sg_dma + - sec4_sg_index * sizeof(struct sec4_sg_entry); + dst_dma = edesc->sec4_sg_dma + (edesc->src_nents + 1) * + sizeof(struct sec4_sg_entry); out_options = LDST_SGF; } } @@ -1119,13 +1111,12 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr, */ static void init_ablkcipher_giv_job(u32 *sh_desc, dma_addr_t ptr, struct ablkcipher_edesc *edesc, - struct ablkcipher_request *req, - bool iv_contig) + struct ablkcipher_request *req) { struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); int ivsize = crypto_ablkcipher_ivsize(ablkcipher); u32 *desc = edesc->hw_desc; - u32 out_options, in_options; + u32 in_options; dma_addr_t dst_dma, src_dma; int len, sec4_sg_index = 0; @@ -1151,15 +1142,9 @@ static void init_ablkcipher_giv_job(u32 *sh_desc, dma_addr_t ptr, } append_seq_in_ptr(desc, src_dma, req->nbytes, in_options); - if (iv_contig) { - dst_dma = edesc->iv_dma; - out_options = 0; - } else { - dst_dma = edesc->sec4_sg_dma + - sec4_sg_index * sizeof(struct sec4_sg_entry); - out_options = LDST_SGF; - } - append_seq_out_ptr(desc, dst_dma, req->nbytes + ivsize, out_options); + dst_dma = edesc->sec4_sg_dma + sec4_sg_index * + sizeof(struct sec4_sg_entry); + append_seq_out_ptr(desc, dst_dma, req->nbytes + ivsize, LDST_SGF); } /* @@ -1452,8 +1437,7 @@ static int aead_decrypt(struct aead_request *req) * allocate and map the ablkcipher extended descriptor for ablkcipher */ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request - *req, int desc_bytes, - bool *iv_contig_out) + *req, int desc_bytes) { struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); @@ -1462,8 +1446,8 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request GFP_KERNEL : GFP_ATOMIC; int src_nents, mapped_src_nents, dst_nents = 0, mapped_dst_nents = 0; struct ablkcipher_edesc *edesc; - dma_addr_t iv_dma = 0; - bool in_contig; + dma_addr_t iv_dma; + u8 *iv; int ivsize = crypto_ablkcipher_ivsize(ablkcipher); int dst_sg_idx, sec4_sg_ents, sec4_sg_bytes; @@ -1507,33 +1491,20 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request } } - iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE); - if (dma_mapping_error(jrdev, iv_dma)) { - dev_err(jrdev, "unable to map IV\n"); - caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0, - 0, DMA_NONE, 0, 0); - return ERR_PTR(-ENOMEM); - } - - if (mapped_src_nents == 1 && - iv_dma + ivsize == sg_dma_address(req->src)) { - in_contig = true; - sec4_sg_ents = 0; - } else { - in_contig = false; - sec4_sg_ents = 1 + mapped_src_nents; - } + sec4_sg_ents = 1 + mapped_src_nents; dst_sg_idx = sec4_sg_ents; sec4_sg_ents += mapped_dst_nents > 1 ? mapped_dst_nents : 0; sec4_sg_bytes = sec4_sg_ents * sizeof(struct sec4_sg_entry); - /* allocate space for base edesc and hw desc commands, link tables */ - edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes, + /* + * allocate space for base edesc and hw desc commands, link tables, IV + */ + edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes + ivsize, GFP_DMA | flags); if (!edesc) { dev_err(jrdev, "could not allocate extended descriptor\n"); - caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, DMA_TO_DEVICE, 0, 0); + caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0, + 0, DMA_NONE, 0, 0); return ERR_PTR(-ENOMEM); } @@ -1544,12 +1515,22 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request desc_bytes; edesc->iv_dir = DMA_TO_DEVICE; - if (!in_contig) { - dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0); - sg_to_sec4_sg_last(req->src, mapped_src_nents, - edesc->sec4_sg + 1, 0); + /* Make sure IV is located in a DMAable area */ + iv = (u8 *)edesc->hw_desc + desc_bytes + sec4_sg_bytes; + memcpy(iv, req->info, ivsize); + + iv_dma = dma_map_single(jrdev, iv, ivsize, DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, iv_dma)) { + dev_err(jrdev, "unable to map IV\n"); + caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0, + 0, DMA_NONE, 0, 0); + kfree(edesc); + return ERR_PTR(-ENOMEM); } + dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0); + sg_to_sec4_sg_last(req->src, mapped_src_nents, edesc->sec4_sg + 1, 0); + if (mapped_dst_nents > 1) { sg_to_sec4_sg_last(req->dst, mapped_dst_nents, edesc->sec4_sg + dst_sg_idx, 0); @@ -1573,7 +1554,6 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request sec4_sg_bytes, 1); #endif - *iv_contig_out = in_contig; return edesc; } @@ -1583,19 +1563,16 @@ static int ablkcipher_encrypt(struct ablkcipher_request *req) struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); struct device *jrdev = ctx->jrdev; - bool iv_contig; u32 *desc; int ret = 0; /* allocate extended descriptor */ - edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN * - CAAM_CMD_SZ, &iv_contig); + edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN * CAAM_CMD_SZ); if (IS_ERR(edesc)) return PTR_ERR(edesc); /* Create and submit job descriptor*/ - init_ablkcipher_job(ctx->sh_desc_enc, - ctx->sh_desc_enc_dma, edesc, req, iv_contig); + init_ablkcipher_job(ctx->sh_desc_enc, ctx->sh_desc_enc_dma, edesc, req); #ifdef DEBUG print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc, @@ -1619,20 +1596,25 @@ static int ablkcipher_decrypt(struct ablkcipher_request *req) struct ablkcipher_edesc *edesc; struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); struct device *jrdev = ctx->jrdev; - bool iv_contig; u32 *desc; int ret = 0; /* allocate extended descriptor */ - edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN * - CAAM_CMD_SZ, &iv_contig); + edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN * CAAM_CMD_SZ); if (IS_ERR(edesc)) return PTR_ERR(edesc); + /* + * The crypto API expects us to set the IV (req->info) to the last + * ciphertext block. + */ + scatterwalk_map_and_copy(req->info, req->src, req->nbytes - ivsize, + ivsize, 0); + /* Create and submit job descriptor*/ - init_ablkcipher_job(ctx->sh_desc_dec, - ctx->sh_desc_dec_dma, edesc, req, iv_contig); + init_ablkcipher_job(ctx->sh_desc_dec, ctx->sh_desc_dec_dma, edesc, req); desc = edesc->hw_desc; #ifdef DEBUG print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"__stringify(__LINE__)": ", @@ -1657,8 +1639,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *req) */ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( struct skcipher_givcrypt_request *greq, - int desc_bytes, - bool *iv_contig_out) + int desc_bytes) { struct ablkcipher_request *req = &greq->creq; struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); @@ -1668,8 +1649,8 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( GFP_KERNEL : GFP_ATOMIC; int src_nents, mapped_src_nents, dst_nents, mapped_dst_nents; struct ablkcipher_edesc *edesc; - dma_addr_t iv_dma = 0; - bool out_contig; + dma_addr_t iv_dma; + u8 *iv; int ivsize = crypto_ablkcipher_ivsize(ablkcipher); int dst_sg_idx, sec4_sg_ents, sec4_sg_bytes; @@ -1714,36 +1695,20 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( } } - /* - * Check if iv can be contiguous with source and destination. - * If so, include it. If not, create scatterlist. - */ - iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_FROM_DEVICE); - if (dma_mapping_error(jrdev, iv_dma)) { - dev_err(jrdev, "unable to map IV\n"); - caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0, - 0, DMA_NONE, 0, 0); - return ERR_PTR(-ENOMEM); - } - sec4_sg_ents = mapped_src_nents > 1 ? mapped_src_nents : 0; dst_sg_idx = sec4_sg_ents; - if (mapped_dst_nents == 1 && - iv_dma + ivsize == sg_dma_address(req->dst)) { - out_contig = true; - } else { - out_contig = false; - sec4_sg_ents += 1 + mapped_dst_nents; - } + sec4_sg_ents += 1 + mapped_dst_nents; - /* allocate space for base edesc and hw desc commands, link tables */ + /* + * allocate space for base edesc and hw desc commands, link tables, IV + */ sec4_sg_bytes = sec4_sg_ents * sizeof(struct sec4_sg_entry); - edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes, + edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes + ivsize, GFP_DMA | flags); if (!edesc) { dev_err(jrdev, "could not allocate extended descriptor\n"); - caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, DMA_FROM_DEVICE, 0, 0); + caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0, + 0, DMA_NONE, 0, 0); return ERR_PTR(-ENOMEM); } @@ -1754,16 +1719,24 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( desc_bytes; edesc->iv_dir = DMA_FROM_DEVICE; + /* Make sure IV is located in a DMAable area */ + iv = (u8 *)edesc->hw_desc + desc_bytes + sec4_sg_bytes; + iv_dma = dma_map_single(jrdev, iv, ivsize, DMA_FROM_DEVICE); + if (dma_mapping_error(jrdev, iv_dma)) { + dev_err(jrdev, "unable to map IV\n"); + caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0, + 0, DMA_NONE, 0, 0); + kfree(edesc); + return ERR_PTR(-ENOMEM); + } + if (mapped_src_nents > 1) sg_to_sec4_sg_last(req->src, mapped_src_nents, edesc->sec4_sg, 0); - if (!out_contig) { - dma_to_sec4_sg_one(edesc->sec4_sg + dst_sg_idx, - iv_dma, ivsize, 0); - sg_to_sec4_sg_last(req->dst, mapped_dst_nents, - edesc->sec4_sg + dst_sg_idx + 1, 0); - } + dma_to_sec4_sg_one(edesc->sec4_sg + dst_sg_idx, iv_dma, ivsize, 0); + sg_to_sec4_sg_last(req->dst, mapped_dst_nents, edesc->sec4_sg + + dst_sg_idx + 1, 0); edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, sec4_sg_bytes, DMA_TO_DEVICE); @@ -1783,7 +1756,6 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( sec4_sg_bytes, 1); #endif - *iv_contig_out = out_contig; return edesc; } @@ -1794,19 +1766,17 @@ static int ablkcipher_givencrypt(struct skcipher_givcrypt_request *creq) struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); struct device *jrdev = ctx->jrdev; - bool iv_contig = false; u32 *desc; int ret = 0; /* allocate extended descriptor */ - edesc = ablkcipher_giv_edesc_alloc(creq, DESC_JOB_IO_LEN * - CAAM_CMD_SZ, &iv_contig); + edesc = ablkcipher_giv_edesc_alloc(creq, DESC_JOB_IO_LEN * CAAM_CMD_SZ); if (IS_ERR(edesc)) return PTR_ERR(edesc); /* Create and submit job descriptor*/ init_ablkcipher_giv_job(ctx->sh_desc_givenc, ctx->sh_desc_givenc_dma, - edesc, req, iv_contig); + edesc, req); #ifdef DEBUG print_hex_dump(KERN_ERR, "ablkcipher jobdesc@" __stringify(__LINE__) ": ", -- GitLab From f535e1c3b3949c287432b9c047ec2cf7a05264f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Wed, 28 Mar 2018 15:39:19 +0300 Subject: [PATCH 0358/1299] crypto: caam/qi - fix IV DMA mapping and updating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 3a488aaec6f343b5dc6d94529847a840bbeaf009 upstream. There are two IV-related issues: (1) crypto API does not guarantee to provide an IV buffer that is DMAable, thus it's incorrect to DMA map it (2) for in-place decryption, since ciphertext is overwritten with plaintext, updated IV (req->info) will contain the last block of plaintext (instead of the last block of ciphertext) While these two issues could be fixed separately, it's straightforward to fix both in the same time - by using the {ablkcipher,aead}_edesc extended descriptor to store the IV that will be fed to the crypto engine; this allows for fixing (2) by saving req->src[last_block] in req->info directly, i.e. without allocating yet another temporary buffer. A side effect of the fix is that it's no longer possible to have the IV contiguous with req->src or req->dst. Code checking for this case is removed. Cc: # 4.14+ Fixes: a68a19380522 ("crypto: caam/qi - properly set IV after {en,de}crypt") Link: http://lkml.kernel.org/r/20170113084620.GF22022@gondor.apana.org.au Reported-by: Gilad Ben-Yossef Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/caam/caamalg_qi.c | 227 ++++++++++++++++--------------- 1 file changed, 116 insertions(+), 111 deletions(-) diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index b648e31673f9..e7966e37a5aa 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -401,7 +401,7 @@ static int xts_ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, * @assoclen: associated data length, in CAAM endianness * @assoclen_dma: bus physical mapped address of req->assoclen * @drv_req: driver-specific request structure - * @sgt: the h/w link table + * @sgt: the h/w link table, followed by IV */ struct aead_edesc { int src_nents; @@ -412,9 +412,6 @@ struct aead_edesc { unsigned int assoclen; dma_addr_t assoclen_dma; struct caam_drv_req drv_req; -#define CAAM_QI_MAX_AEAD_SG \ - ((CAAM_QI_MEMCACHE_SIZE - offsetof(struct aead_edesc, sgt)) / \ - sizeof(struct qm_sg_entry)) struct qm_sg_entry sgt[0]; }; @@ -426,7 +423,7 @@ struct aead_edesc { * @qm_sg_bytes: length of dma mapped h/w link table * @qm_sg_dma: bus physical mapped address of h/w link table * @drv_req: driver-specific request structure - * @sgt: the h/w link table + * @sgt: the h/w link table, followed by IV */ struct ablkcipher_edesc { int src_nents; @@ -435,9 +432,6 @@ struct ablkcipher_edesc { int qm_sg_bytes; dma_addr_t qm_sg_dma; struct caam_drv_req drv_req; -#define CAAM_QI_MAX_ABLKCIPHER_SG \ - ((CAAM_QI_MEMCACHE_SIZE - offsetof(struct ablkcipher_edesc, sgt)) / \ - sizeof(struct qm_sg_entry)) struct qm_sg_entry sgt[0]; }; @@ -649,17 +643,8 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, } } - if ((alg->caam.rfc3686 && encrypt) || !alg->caam.geniv) { + if ((alg->caam.rfc3686 && encrypt) || !alg->caam.geniv) ivsize = crypto_aead_ivsize(aead); - iv_dma = dma_map_single(qidev, req->iv, ivsize, DMA_TO_DEVICE); - if (dma_mapping_error(qidev, iv_dma)) { - dev_err(qidev, "unable to map IV\n"); - caam_unmap(qidev, req->src, req->dst, src_nents, - dst_nents, 0, 0, op_type, 0, 0); - qi_cache_free(edesc); - return ERR_PTR(-ENOMEM); - } - } /* * Create S/G table: req->assoclen, [IV,] req->src [, req->dst]. @@ -667,16 +652,33 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, */ qm_sg_ents = 1 + !!ivsize + mapped_src_nents + (mapped_dst_nents > 1 ? mapped_dst_nents : 0); - if (unlikely(qm_sg_ents > CAAM_QI_MAX_AEAD_SG)) { - dev_err(qidev, "Insufficient S/G entries: %d > %zu\n", - qm_sg_ents, CAAM_QI_MAX_AEAD_SG); - caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, op_type, 0, 0); + sg_table = &edesc->sgt[0]; + qm_sg_bytes = qm_sg_ents * sizeof(*sg_table); + if (unlikely(offsetof(struct aead_edesc, sgt) + qm_sg_bytes + ivsize > + CAAM_QI_MEMCACHE_SIZE)) { + dev_err(qidev, "No space for %d S/G entries and/or %dB IV\n", + qm_sg_ents, ivsize); + caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0, + 0, 0, 0, 0); qi_cache_free(edesc); return ERR_PTR(-ENOMEM); } - sg_table = &edesc->sgt[0]; - qm_sg_bytes = qm_sg_ents * sizeof(*sg_table); + + if (ivsize) { + u8 *iv = (u8 *)(sg_table + qm_sg_ents); + + /* Make sure IV is located in a DMAable area */ + memcpy(iv, req->iv, ivsize); + + iv_dma = dma_map_single(qidev, iv, ivsize, DMA_TO_DEVICE); + if (dma_mapping_error(qidev, iv_dma)) { + dev_err(qidev, "unable to map IV\n"); + caam_unmap(qidev, req->src, req->dst, src_nents, + dst_nents, 0, 0, 0, 0, 0); + qi_cache_free(edesc); + return ERR_PTR(-ENOMEM); + } + } edesc->src_nents = src_nents; edesc->dst_nents = dst_nents; @@ -813,15 +815,27 @@ static void ablkcipher_done(struct caam_drv_req *drv_req, u32 status) #endif ablkcipher_unmap(qidev, edesc, req); - qi_cache_free(edesc); + + /* In case initial IV was generated, copy it in GIVCIPHER request */ + if (edesc->drv_req.drv_ctx->op_type == GIVENCRYPT) { + u8 *iv; + struct skcipher_givcrypt_request *greq; + + greq = container_of(req, struct skcipher_givcrypt_request, + creq); + iv = (u8 *)edesc->sgt + edesc->qm_sg_bytes; + memcpy(greq->giv, iv, ivsize); + } /* * The crypto API expects us to set the IV (req->info) to the last * ciphertext block. This is used e.g. by the CTS mode. */ - scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - ivsize, - ivsize, 0); + if (edesc->drv_req.drv_ctx->op_type != DECRYPT) + scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - + ivsize, ivsize, 0); + qi_cache_free(edesc); ablkcipher_request_complete(req, status); } @@ -836,9 +850,9 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request int src_nents, mapped_src_nents, dst_nents = 0, mapped_dst_nents = 0; struct ablkcipher_edesc *edesc; dma_addr_t iv_dma; - bool in_contig; + u8 *iv; int ivsize = crypto_ablkcipher_ivsize(ablkcipher); - int dst_sg_idx, qm_sg_ents; + int dst_sg_idx, qm_sg_ents, qm_sg_bytes; struct qm_sg_entry *sg_table, *fd_sgt; struct caam_drv_ctx *drv_ctx; enum optype op_type = encrypt ? ENCRYPT : DECRYPT; @@ -885,55 +899,53 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request } } - iv_dma = dma_map_single(qidev, req->info, ivsize, DMA_TO_DEVICE); - if (dma_mapping_error(qidev, iv_dma)) { - dev_err(qidev, "unable to map IV\n"); - caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0, - 0, 0, 0, 0); - return ERR_PTR(-ENOMEM); - } - - if (mapped_src_nents == 1 && - iv_dma + ivsize == sg_dma_address(req->src)) { - in_contig = true; - qm_sg_ents = 0; - } else { - in_contig = false; - qm_sg_ents = 1 + mapped_src_nents; - } + qm_sg_ents = 1 + mapped_src_nents; dst_sg_idx = qm_sg_ents; qm_sg_ents += mapped_dst_nents > 1 ? mapped_dst_nents : 0; - if (unlikely(qm_sg_ents > CAAM_QI_MAX_ABLKCIPHER_SG)) { - dev_err(qidev, "Insufficient S/G entries: %d > %zu\n", - qm_sg_ents, CAAM_QI_MAX_ABLKCIPHER_SG); - caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, op_type, 0, 0); + qm_sg_bytes = qm_sg_ents * sizeof(struct qm_sg_entry); + if (unlikely(offsetof(struct ablkcipher_edesc, sgt) + qm_sg_bytes + + ivsize > CAAM_QI_MEMCACHE_SIZE)) { + dev_err(qidev, "No space for %d S/G entries and/or %dB IV\n", + qm_sg_ents, ivsize); + caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0, + 0, 0, 0, 0); return ERR_PTR(-ENOMEM); } - /* allocate space for base edesc and link tables */ + /* allocate space for base edesc, link tables and IV */ edesc = qi_cache_alloc(GFP_DMA | flags); if (unlikely(!edesc)) { dev_err(qidev, "could not allocate extended descriptor\n"); - caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, op_type, 0, 0); + caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0, + 0, 0, 0, 0); + return ERR_PTR(-ENOMEM); + } + + /* Make sure IV is located in a DMAable area */ + sg_table = &edesc->sgt[0]; + iv = (u8 *)(sg_table + qm_sg_ents); + memcpy(iv, req->info, ivsize); + + iv_dma = dma_map_single(qidev, iv, ivsize, DMA_TO_DEVICE); + if (dma_mapping_error(qidev, iv_dma)) { + dev_err(qidev, "unable to map IV\n"); + caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0, + 0, 0, 0, 0); + qi_cache_free(edesc); return ERR_PTR(-ENOMEM); } edesc->src_nents = src_nents; edesc->dst_nents = dst_nents; edesc->iv_dma = iv_dma; - sg_table = &edesc->sgt[0]; - edesc->qm_sg_bytes = qm_sg_ents * sizeof(*sg_table); + edesc->qm_sg_bytes = qm_sg_bytes; edesc->drv_req.app_ctx = req; edesc->drv_req.cbk = ablkcipher_done; edesc->drv_req.drv_ctx = drv_ctx; - if (!in_contig) { - dma_to_qm_sg_one(sg_table, iv_dma, ivsize, 0); - sg_to_qm_sg_last(req->src, mapped_src_nents, sg_table + 1, 0); - } + dma_to_qm_sg_one(sg_table, iv_dma, ivsize, 0); + sg_to_qm_sg_last(req->src, mapped_src_nents, sg_table + 1, 0); if (mapped_dst_nents > 1) sg_to_qm_sg_last(req->dst, mapped_dst_nents, sg_table + @@ -951,20 +963,12 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request fd_sgt = &edesc->drv_req.fd_sgt[0]; - if (!in_contig) - dma_to_qm_sg_one_last_ext(&fd_sgt[1], edesc->qm_sg_dma, - ivsize + req->nbytes, 0); - else - dma_to_qm_sg_one_last(&fd_sgt[1], iv_dma, ivsize + req->nbytes, - 0); + dma_to_qm_sg_one_last_ext(&fd_sgt[1], edesc->qm_sg_dma, + ivsize + req->nbytes, 0); if (req->src == req->dst) { - if (!in_contig) - dma_to_qm_sg_one_ext(&fd_sgt[0], edesc->qm_sg_dma + - sizeof(*sg_table), req->nbytes, 0); - else - dma_to_qm_sg_one(&fd_sgt[0], sg_dma_address(req->src), - req->nbytes, 0); + dma_to_qm_sg_one_ext(&fd_sgt[0], edesc->qm_sg_dma + + sizeof(*sg_table), req->nbytes, 0); } else if (mapped_dst_nents > 1) { dma_to_qm_sg_one_ext(&fd_sgt[0], edesc->qm_sg_dma + dst_sg_idx * sizeof(*sg_table), req->nbytes, 0); @@ -988,10 +992,10 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( int src_nents, mapped_src_nents, dst_nents, mapped_dst_nents; struct ablkcipher_edesc *edesc; dma_addr_t iv_dma; - bool out_contig; + u8 *iv; int ivsize = crypto_ablkcipher_ivsize(ablkcipher); struct qm_sg_entry *sg_table, *fd_sgt; - int dst_sg_idx, qm_sg_ents; + int dst_sg_idx, qm_sg_ents, qm_sg_bytes; struct caam_drv_ctx *drv_ctx; drv_ctx = get_drv_ctx(ctx, GIVENCRYPT); @@ -1039,46 +1043,45 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( mapped_dst_nents = src_nents; } - iv_dma = dma_map_single(qidev, creq->giv, ivsize, DMA_FROM_DEVICE); - if (dma_mapping_error(qidev, iv_dma)) { - dev_err(qidev, "unable to map IV\n"); - caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0, - 0, 0, 0, 0); - return ERR_PTR(-ENOMEM); - } - qm_sg_ents = mapped_src_nents > 1 ? mapped_src_nents : 0; dst_sg_idx = qm_sg_ents; - if (mapped_dst_nents == 1 && - iv_dma + ivsize == sg_dma_address(req->dst)) { - out_contig = true; - } else { - out_contig = false; - qm_sg_ents += 1 + mapped_dst_nents; - } - if (unlikely(qm_sg_ents > CAAM_QI_MAX_ABLKCIPHER_SG)) { - dev_err(qidev, "Insufficient S/G entries: %d > %zu\n", - qm_sg_ents, CAAM_QI_MAX_ABLKCIPHER_SG); - caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, GIVENCRYPT, 0, 0); + qm_sg_ents += 1 + mapped_dst_nents; + qm_sg_bytes = qm_sg_ents * sizeof(struct qm_sg_entry); + if (unlikely(offsetof(struct ablkcipher_edesc, sgt) + qm_sg_bytes + + ivsize > CAAM_QI_MEMCACHE_SIZE)) { + dev_err(qidev, "No space for %d S/G entries and/or %dB IV\n", + qm_sg_ents, ivsize); + caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0, + 0, 0, 0, 0); return ERR_PTR(-ENOMEM); } - /* allocate space for base edesc and link tables */ + /* allocate space for base edesc, link tables and IV */ edesc = qi_cache_alloc(GFP_DMA | flags); if (!edesc) { dev_err(qidev, "could not allocate extended descriptor\n"); - caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, - iv_dma, ivsize, GIVENCRYPT, 0, 0); + caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0, + 0, 0, 0, 0); + return ERR_PTR(-ENOMEM); + } + + /* Make sure IV is located in a DMAable area */ + sg_table = &edesc->sgt[0]; + iv = (u8 *)(sg_table + qm_sg_ents); + iv_dma = dma_map_single(qidev, iv, ivsize, DMA_FROM_DEVICE); + if (dma_mapping_error(qidev, iv_dma)) { + dev_err(qidev, "unable to map IV\n"); + caam_unmap(qidev, req->src, req->dst, src_nents, dst_nents, 0, + 0, 0, 0, 0); + qi_cache_free(edesc); return ERR_PTR(-ENOMEM); } edesc->src_nents = src_nents; edesc->dst_nents = dst_nents; edesc->iv_dma = iv_dma; - sg_table = &edesc->sgt[0]; - edesc->qm_sg_bytes = qm_sg_ents * sizeof(*sg_table); + edesc->qm_sg_bytes = qm_sg_bytes; edesc->drv_req.app_ctx = req; edesc->drv_req.cbk = ablkcipher_done; edesc->drv_req.drv_ctx = drv_ctx; @@ -1086,11 +1089,9 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( if (mapped_src_nents > 1) sg_to_qm_sg_last(req->src, mapped_src_nents, sg_table, 0); - if (!out_contig) { - dma_to_qm_sg_one(sg_table + dst_sg_idx, iv_dma, ivsize, 0); - sg_to_qm_sg_last(req->dst, mapped_dst_nents, sg_table + - dst_sg_idx + 1, 0); - } + dma_to_qm_sg_one(sg_table + dst_sg_idx, iv_dma, ivsize, 0); + sg_to_qm_sg_last(req->dst, mapped_dst_nents, sg_table + dst_sg_idx + 1, + 0); edesc->qm_sg_dma = dma_map_single(qidev, sg_table, edesc->qm_sg_bytes, DMA_TO_DEVICE); @@ -1111,13 +1112,8 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc( dma_to_qm_sg_one(&fd_sgt[1], sg_dma_address(req->src), req->nbytes, 0); - if (!out_contig) - dma_to_qm_sg_one_ext(&fd_sgt[0], edesc->qm_sg_dma + dst_sg_idx * - sizeof(*sg_table), ivsize + req->nbytes, - 0); - else - dma_to_qm_sg_one(&fd_sgt[0], sg_dma_address(req->dst), - ivsize + req->nbytes, 0); + dma_to_qm_sg_one_ext(&fd_sgt[0], edesc->qm_sg_dma + dst_sg_idx * + sizeof(*sg_table), ivsize + req->nbytes, 0); return edesc; } @@ -1127,6 +1123,7 @@ static inline int ablkcipher_crypt(struct ablkcipher_request *req, bool encrypt) struct ablkcipher_edesc *edesc; struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); int ret; if (unlikely(caam_congested)) @@ -1137,6 +1134,14 @@ static inline int ablkcipher_crypt(struct ablkcipher_request *req, bool encrypt) if (IS_ERR(edesc)) return PTR_ERR(edesc); + /* + * The crypto API expects us to set the IV (req->info) to the last + * ciphertext block. + */ + if (!encrypt) + scatterwalk_map_and_copy(req->info, req->src, req->nbytes - + ivsize, ivsize, 0); + ret = caam_qi_enqueue(ctx->qidev, &edesc->drv_req); if (!ret) { ret = -EINPROGRESS; -- GitLab From 4854c879107cdc38beeb1da7df4279f2c486a985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Fri, 27 Apr 2018 11:40:11 +0300 Subject: [PATCH 0359/1299] crypto: caam - fix size of RSA prime factor q MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4bffaab373d9afaf862f3924442c33340bd26736 upstream. Fix a typo where size of RSA prime factor q is using the size of prime factor p. Cc: # 4.13+ Fixes: 52e26d77b8b3 ("crypto: caam - add support for RSA key form 2") Fixes: 4a651b122adb ("crypto: caam - add support for RSA key form 3") Reported-by: David Binderman Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/caam/caampkc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index 979072b25eaa..7ff4a25440ac 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -66,7 +66,7 @@ static void rsa_priv_f2_unmap(struct device *dev, struct rsa_edesc *edesc, struct caam_rsa_key *key = &ctx->key; struct rsa_priv_f2_pdb *pdb = &edesc->pdb.priv_f2; size_t p_sz = key->p_sz; - size_t q_sz = key->p_sz; + size_t q_sz = key->q_sz; dma_unmap_single(dev, pdb->d_dma, key->d_sz, DMA_TO_DEVICE); dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE); @@ -83,7 +83,7 @@ static void rsa_priv_f3_unmap(struct device *dev, struct rsa_edesc *edesc, struct caam_rsa_key *key = &ctx->key; struct rsa_priv_f3_pdb *pdb = &edesc->pdb.priv_f3; size_t p_sz = key->p_sz; - size_t q_sz = key->p_sz; + size_t q_sz = key->q_sz; dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE); dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE); @@ -397,7 +397,7 @@ static int set_rsa_priv_f2_pdb(struct akcipher_request *req, struct rsa_priv_f2_pdb *pdb = &edesc->pdb.priv_f2; int sec4_sg_index = 0; size_t p_sz = key->p_sz; - size_t q_sz = key->p_sz; + size_t q_sz = key->q_sz; pdb->d_dma = dma_map_single(dev, key->d, key->d_sz, DMA_TO_DEVICE); if (dma_mapping_error(dev, pdb->d_dma)) { @@ -472,7 +472,7 @@ static int set_rsa_priv_f3_pdb(struct akcipher_request *req, struct rsa_priv_f3_pdb *pdb = &edesc->pdb.priv_f3; int sec4_sg_index = 0; size_t p_sz = key->p_sz; - size_t q_sz = key->p_sz; + size_t q_sz = key->q_sz; pdb->p_dma = dma_map_single(dev, key->p, p_sz, DMA_TO_DEVICE); if (dma_mapping_error(dev, pdb->p_dma)) { -- GitLab From 072e8b1f58d5e4cfdd80dfb36fce06628f9f4068 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 9 Apr 2018 17:45:50 +0200 Subject: [PATCH 0360/1299] crypto: cavium - Fix fallout from CONFIG_VMAP_STACK commit 37ff02acaa3d7be87ecb89f198a549ffd3ae2403 upstream. Enabling virtual mapped kernel stacks breaks the thunderx_zip driver. On compression or decompression the executing CPU hangs in an endless loop. The reason for this is the usage of __pa by the driver which does no longer work for an address that is not part of the 1:1 mapping. The zip driver allocates a result struct on the stack and needs to tell the hardware the physical address within this struct that is used to signal the completion of the request. As the hardware gets the wrong address after the broken __pa conversion it writes to an arbitrary address. The zip driver then waits forever for the completion byte to contain a non-zero value. Allocating the result struct from 1:1 mapped memory resolves this bug. Signed-off-by: Jan Glauber Reviewed-by: Robert Richter Cc: stable # 4.14 Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/cavium/zip/zip_crypto.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/crypto/cavium/zip/zip_crypto.c b/drivers/crypto/cavium/zip/zip_crypto.c index 8df4d26cf9d4..b92b6e7e100f 100644 --- a/drivers/crypto/cavium/zip/zip_crypto.c +++ b/drivers/crypto/cavium/zip/zip_crypto.c @@ -124,7 +124,7 @@ int zip_compress(const u8 *src, unsigned int slen, struct zip_kernel_ctx *zip_ctx) { struct zip_operation *zip_ops = NULL; - struct zip_state zip_state; + struct zip_state *zip_state; struct zip_device *zip = NULL; int ret; @@ -135,20 +135,23 @@ int zip_compress(const u8 *src, unsigned int slen, if (!zip) return -ENODEV; - memset(&zip_state, 0, sizeof(struct zip_state)); + zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC); + if (!zip_state) + return -ENOMEM; + zip_ops = &zip_ctx->zip_comp; zip_ops->input_len = slen; zip_ops->output_len = *dlen; memcpy(zip_ops->input, src, slen); - ret = zip_deflate(zip_ops, &zip_state, zip); + ret = zip_deflate(zip_ops, zip_state, zip); if (!ret) { *dlen = zip_ops->output_len; memcpy(dst, zip_ops->output, *dlen); } - + kfree(zip_state); return ret; } @@ -157,7 +160,7 @@ int zip_decompress(const u8 *src, unsigned int slen, struct zip_kernel_ctx *zip_ctx) { struct zip_operation *zip_ops = NULL; - struct zip_state zip_state; + struct zip_state *zip_state; struct zip_device *zip = NULL; int ret; @@ -168,7 +171,10 @@ int zip_decompress(const u8 *src, unsigned int slen, if (!zip) return -ENODEV; - memset(&zip_state, 0, sizeof(struct zip_state)); + zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC); + if (!zip_state) + return -ENOMEM; + zip_ops = &zip_ctx->zip_decomp; memcpy(zip_ops->input, src, slen); @@ -179,13 +185,13 @@ int zip_decompress(const u8 *src, unsigned int slen, zip_ops->input_len = slen; zip_ops->output_len = *dlen; - ret = zip_inflate(zip_ops, &zip_state, zip); + ret = zip_inflate(zip_ops, zip_state, zip); if (!ret) { *dlen = zip_ops->output_len; memcpy(dst, zip_ops->output, *dlen); } - + kfree(zip_state); return ret; } -- GitLab From b9705796e44b4af5b4cbfd299d4c52e4318ff52c Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 9 Apr 2018 17:45:51 +0200 Subject: [PATCH 0361/1299] crypto: cavium - Limit result reading attempts commit c782a8c43e94ba6c09e9de2d69b5e3a5840ce61c upstream. After issuing a request an endless loop was used to read the completion state from memory which is asynchronously updated by the ZIP coprocessor. Add an upper bound to the retry attempts to prevent a CPU getting stuck forever in case of an error. Additionally, add a read memory barrier and a small delay between the reading attempts. Signed-off-by: Jan Glauber Reviewed-by: Robert Richter Cc: stable # 4.14 Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/cavium/zip/common.h | 21 +++++++++++++++++++++ drivers/crypto/cavium/zip/zip_deflate.c | 4 ++-- drivers/crypto/cavium/zip/zip_inflate.c | 4 ++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/cavium/zip/common.h b/drivers/crypto/cavium/zip/common.h index dc451e0a43c5..58fb3ed6e644 100644 --- a/drivers/crypto/cavium/zip/common.h +++ b/drivers/crypto/cavium/zip/common.h @@ -46,8 +46,10 @@ #ifndef __COMMON_H__ #define __COMMON_H__ +#include #include #include +#include #include #include #include @@ -149,6 +151,25 @@ struct zip_operation { u32 sizeofzops; }; +static inline int zip_poll_result(union zip_zres_s *result) +{ + int retries = 1000; + + while (!result->s.compcode) { + if (!--retries) { + pr_err("ZIP ERR: request timed out"); + return -ETIMEDOUT; + } + udelay(10); + /* + * Force re-reading of compcode which is updated + * by the ZIP coprocessor. + */ + rmb(); + } + return 0; +} + /* error messages */ #define zip_err(fmt, args...) pr_err("ZIP ERR:%s():%d: " \ fmt "\n", __func__, __LINE__, ## args) diff --git a/drivers/crypto/cavium/zip/zip_deflate.c b/drivers/crypto/cavium/zip/zip_deflate.c index 9a944b8c1e29..d7133f857d67 100644 --- a/drivers/crypto/cavium/zip/zip_deflate.c +++ b/drivers/crypto/cavium/zip/zip_deflate.c @@ -129,8 +129,8 @@ int zip_deflate(struct zip_operation *zip_ops, struct zip_state *s, /* Stats update for compression requests submitted */ atomic64_inc(&zip_dev->stats.comp_req_submit); - while (!result_ptr->s.compcode) - continue; + /* Wait for completion or error */ + zip_poll_result(result_ptr); /* Stats update for compression requests completed */ atomic64_inc(&zip_dev->stats.comp_req_complete); diff --git a/drivers/crypto/cavium/zip/zip_inflate.c b/drivers/crypto/cavium/zip/zip_inflate.c index 50cbdd83dbf2..7e0d73e2f89e 100644 --- a/drivers/crypto/cavium/zip/zip_inflate.c +++ b/drivers/crypto/cavium/zip/zip_inflate.c @@ -143,8 +143,8 @@ int zip_inflate(struct zip_operation *zip_ops, struct zip_state *s, /* Decompression requests submitted stats update */ atomic64_inc(&zip_dev->stats.decomp_req_submit); - while (!result_ptr->s.compcode) - continue; + /* Wait for completion or error */ + zip_poll_result(result_ptr); /* Decompression requests completed stats update */ atomic64_inc(&zip_dev->stats.decomp_req_complete); -- GitLab From 1bc36d12a6edbdb42199fc0c4573d2ddd8bb7440 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 3 May 2018 22:29:29 +1000 Subject: [PATCH 0362/1299] crypto: vmx - Remove overly verbose printk from AES init routines commit 1411b5218adbcf1d45ddb260db5553c52e8d917c upstream. In the vmx AES init routines we do a printk(KERN_INFO ...) to report the fallback implementation we're using. However with a slow console this can significantly affect the speed of crypto operations. Using 'cryptsetup benchmark' the removal of the printk() leads to a ~5x speedup for aes-cbc decryption. So remove them. Fixes: 8676590a1593 ("crypto: vmx - Adding AES routines for VMX module") Fixes: 8c755ace357c ("crypto: vmx - Adding CBC routines for VMX module") Fixes: 4f7f60d312b3 ("crypto: vmx - Adding CTR routines for VMX module") Fixes: cc333cd68dfa ("crypto: vmx - Adding GHASH routines for VMX module") Cc: stable@vger.kernel.org # v4.1+ Signed-off-by: Michael Ellerman Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/vmx/aes.c | 2 -- drivers/crypto/vmx/aes_cbc.c | 3 --- drivers/crypto/vmx/aes_ctr.c | 2 -- drivers/crypto/vmx/ghash.c | 2 -- 4 files changed, 9 deletions(-) diff --git a/drivers/crypto/vmx/aes.c b/drivers/crypto/vmx/aes.c index 96072b9b55c4..d7316f7a3a69 100644 --- a/drivers/crypto/vmx/aes.c +++ b/drivers/crypto/vmx/aes.c @@ -48,8 +48,6 @@ static int p8_aes_init(struct crypto_tfm *tfm) alg, PTR_ERR(fallback)); return PTR_ERR(fallback); } - printk(KERN_INFO "Using '%s' as fallback implementation.\n", - crypto_tfm_alg_driver_name((struct crypto_tfm *) fallback)); crypto_cipher_set_flags(fallback, crypto_cipher_get_flags((struct diff --git a/drivers/crypto/vmx/aes_cbc.c b/drivers/crypto/vmx/aes_cbc.c index 7394d35d5936..5285ece4f33a 100644 --- a/drivers/crypto/vmx/aes_cbc.c +++ b/drivers/crypto/vmx/aes_cbc.c @@ -52,9 +52,6 @@ static int p8_aes_cbc_init(struct crypto_tfm *tfm) alg, PTR_ERR(fallback)); return PTR_ERR(fallback); } - printk(KERN_INFO "Using '%s' as fallback implementation.\n", - crypto_skcipher_driver_name(fallback)); - crypto_skcipher_set_flags( fallback, diff --git a/drivers/crypto/vmx/aes_ctr.c b/drivers/crypto/vmx/aes_ctr.c index 17d84217dd76..02ba5f2aa0e6 100644 --- a/drivers/crypto/vmx/aes_ctr.c +++ b/drivers/crypto/vmx/aes_ctr.c @@ -48,8 +48,6 @@ static int p8_aes_ctr_init(struct crypto_tfm *tfm) alg, PTR_ERR(fallback)); return PTR_ERR(fallback); } - printk(KERN_INFO "Using '%s' as fallback implementation.\n", - crypto_tfm_alg_driver_name((struct crypto_tfm *) fallback)); crypto_blkcipher_set_flags( fallback, diff --git a/drivers/crypto/vmx/ghash.c b/drivers/crypto/vmx/ghash.c index 27a94a119009..1c4b5b889fba 100644 --- a/drivers/crypto/vmx/ghash.c +++ b/drivers/crypto/vmx/ghash.c @@ -64,8 +64,6 @@ static int p8_ghash_init_tfm(struct crypto_tfm *tfm) alg, PTR_ERR(fallback)); return PTR_ERR(fallback); } - printk(KERN_INFO "Using '%s' as fallback implementation.\n", - crypto_tfm_alg_driver_name(crypto_shash_tfm(fallback))); crypto_shash_set_flags(fallback, crypto_shash_get_flags((struct crypto_shash -- GitLab From efc67e746b2705a42540510a6434be51b57e8da5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 3 May 2018 22:29:30 +1000 Subject: [PATCH 0363/1299] crypto: vmx - Remove overly verbose printk from AES XTS init commit 730f23b66095a700e2f0786abda6bca011b31558 upstream. In p8_aes_xts_init() we do a printk(KERN_INFO ...) to report the fallback implementation we're using. However with a slow console this can significantly affect the speed of crypto operations. So remove it. Fixes: c07f5d3da643 ("crypto: vmx - Adding support for XTS") Cc: stable@vger.kernel.org # v4.8+ Signed-off-by: Michael Ellerman Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/vmx/aes_xts.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/crypto/vmx/aes_xts.c b/drivers/crypto/vmx/aes_xts.c index 8cd6e62e4c90..8bd9aff0f55f 100644 --- a/drivers/crypto/vmx/aes_xts.c +++ b/drivers/crypto/vmx/aes_xts.c @@ -53,8 +53,6 @@ static int p8_aes_xts_init(struct crypto_tfm *tfm) alg, PTR_ERR(fallback)); return PTR_ERR(fallback); } - printk(KERN_INFO "Using '%s' as fallback implementation.\n", - crypto_skcipher_driver_name(fallback)); crypto_skcipher_set_flags( fallback, -- GitLab From 87883c89b4052b8a289fac271d200d69f8d662a9 Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Tue, 17 Apr 2018 14:53:13 -0500 Subject: [PATCH 0364/1299] crypto: omap-sham - fix memleak commit 9dbc8a0328efa485a6f5b68b867f9f523a3fbeff upstream. Fixes: 8043bb1ae03cb ("crypto: omap-sham - convert driver logic to use sgs for data xmit") The memory pages freed in omap_sham_finish_req() were less than those allocated in omap_sham_copy_sgs(). Cc: stable@vger.kernel.org Signed-off-by: Bin Liu Acked-by: Tero Kristo Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/omap-sham.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index c40ac30ec002..c1f8da958c78 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -1082,7 +1082,7 @@ static void omap_sham_finish_req(struct ahash_request *req, int err) if (test_bit(FLAGS_SGS_COPIED, &dd->flags)) free_pages((unsigned long)sg_virt(ctx->sg), - get_order(ctx->sg->length)); + get_order(ctx->sg->length + ctx->bufcnt)); if (test_bit(FLAGS_SGS_ALLOCED, &dd->flags)) kfree(ctx->sg); -- GitLab From cda6fd4d9382205bb792255cd56a91062d404bc0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 16 Jun 2018 09:45:18 +0200 Subject: [PATCH 0365/1299] Linux 4.14.50 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 480ae7ef755c..84374c5ba60e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 49 +SUBLEVEL = 50 EXTRAVERSION = NAME = Petit Gorille -- GitLab From 6abddb286883f9221bb737fa2630a1300773aca9 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Fri, 1 Jun 2018 01:23:06 +0530 Subject: [PATCH 0366/1299] ARM: dts: msm: Add USB configuration for QCS405 Add support for primary and secondary port USB controllers and corresponding PHYs. Change-Id: Ibe152160185e468c4d02ee234cc64cadf9527975 Signed-off-by: Sriharsha Allenki --- arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi | 9 + arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi | 6 +- arch/arm64/boot/dts/qcom/qcs405-usb.dtsi | 202 +++++++++++++++++++ arch/arm64/boot/dts/qcom/qcs405.dtsi | 78 +++---- 4 files changed, 252 insertions(+), 43 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/qcs405-usb.dtsi diff --git a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi index 990142fb205b..9b51a14b26b2 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi @@ -797,5 +797,14 @@ input-enable; }; }; + + usb3_id_det_default: usb2_id_det_default { + config { + pins = "gpio116"; + drive-strength = <2>; + bias-pull-up; + input-enable; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi b/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi index 6e855d4284c0..724b8d57430c 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi @@ -33,10 +33,6 @@ 0x0 0x4>; }; - usb_nop_phy: usb_nop_phy { - compatible = "usb-nop-xceiv"; - }; - timer { clock-frequency = <0x100000>; }; @@ -46,7 +42,7 @@ }; }; -&usb0 { +&usb2s { dwc3@78c0000 { usb-phy = <&usb_emu_phy>, <&usb_nop_phy>; maximum-speed = "high-speed"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi new file mode 100644 index 000000000000..b4a547bb7702 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi @@ -0,0 +1,202 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +&soc { + /* Secondary USB port related controller */ + usb3: ssusb@7580000 { + compatible = "qcom,dwc-usb3-msm"; + reg = <0x7580000 0x100000>; + reg-names = "core_base"; + + interrupts = <0 25 0>, <0 24 0>; + interrupt-names = "pwr_event_irq", "hs_phy_irq"; + + clocks = <&clock_gcc GCC_USB30_MASTER_CLK>, + <&clock_gcc GCC_SYS_NOC_USB3_CLK>, + <&clock_gcc GCC_USB30_SLEEP_CLK>, + <&clock_gcc GCC_USB30_MOCK_UTMI_CLK>, + <&clock_rpmcc CXO_SMD_OTG_CLK>; + clock-names = "core_clk", "iface_clk", "sleep_clk", + "utmi_clk", "xo"; + + qcom,core-clk-rate = <200000000>; + qcom,core-clk-rate-hs = <10000000>; + + qcom,pm-qos-latency = <181>; + qcom,msm-bus,name = "usb3"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + ; + + resets = <&clock_gcc GCC_USB_30_BCR>; + reset-names = "core_reset"; + + dwc3@7580000 { + compatible = "snps,dwc3"; + reg = <0x7580000 0xcd00>; + interrupts = <0 26 0>; + usb-phy = <&usb2_phy1>, <&usb_ss_phy>; + linux,sysdev_is_parent; + snps,disable-clk-gating; + snps,has-lpm-erratum; + snps,hird-threshold = /bits/ 8 <0x10>; + snps,usb3-u1u2-disable; + usb-core-id = <1>; + maximum-speed = "high-speed"; + dr_mode = "host"; + }; + }; + + /* Secondary USB port related High Speed PHY */ + usb2_phy1: hsphy@7a000 { + compatible = "qcom,usb-snps-hsphy"; + reg = <0x7a000 0x200>; + reg-names = "phy_csr"; + + vdd-supply = <&pms405_l4>; + vdda18-supply = <&pms405_l5>; + vdda33-supply = <&pms405_l12>; + qcom,vdd-voltage-level = <0 1144000 1144000>; + + clocks = <&clock_rpmcc RPM_SMD_LN_BB_CLK>, + <&clock_gcc GCC_USB_HS_PHY_CFG_AHB_CLK>; + clock-names = "ref_clk", "phy_csr_clk"; + + resets = <&clock_gcc GCC_USB_HS_PHY_CFG_AHB_BCR>, + <&clock_gcc GCC_USB2A_PHY_BCR>; + reset-names = "phy_reset", "phy_por_reset"; + + qcom,snps-hs-phy-init-seq = + <0xe8 0x0d 0>, + <0x74 0x12 0>, + <0x98 0x63 0>, + <0x9c 0x03 0>, + <0xa0 0x1d 0>, + <0xa4 0x03 0>, + <0x8c 0x23 0>, + <0x78 0x08 0>, + <0x7c 0xdc 0>, + <0x90 0xe0 20>, + <0x74 0x10 0>, + <0x90 0x60 0>, + <0xffffffff 0xffffffff 0>; + }; + + /* Secondary USB port related Super Speed PHY */ + usb_ss_phy: ssphy@7678800 { + compatible = "qcom,usb-ssphy"; + reg = <0x7678800 0x400>; + vdd-supply = <&pms405_l3>; + vdda18-supply = <&pms405_l5>; + qcom,vdd-voltage-level = <0 1050000 1050000>; + + clocks = <&clock_rpmcc RPM_SMD_LN_BB_CLK>; + clock-names = "ref_clk"; + + resets = <&clock_gcc GCC_USB3_PHY_BCR>, + <&clock_gcc GCC_USB3PHY_PHY_BCR>; + reset-names = "phy_reset", "phy_com_reset"; + }; + + usb_nop_phy: usb_nop_phy { + compatible = "usb-nop-xceiv"; + }; + + /* Primary USB port related controller */ + usb2s: hsusb@78c0000 { + compatible = "qcom,dwc-usb3-msm"; + reg = <0x78c0000 0x100000>; + reg-names = "core_base"; + + interrupts = <0 32 0>, <0 31 0>; + interrupt-names = "pwr_event_irq", "hs_phy_irq"; + + clocks = <&clock_gcc GCC_USB_HS_SYSTEM_CLK>, + <&clock_gcc GCC_PCNOC_USB2_CLK>, + <&clock_gcc GCC_USB_HS_INACTIVITY_TIMERS_CLK>, + <&clock_gcc GCC_USB20_MOCK_UTMI_CLK>, + <&clock_rpmcc CXO_SMD_OTG_CLK>; + clock-names = "core_clk", "iface_clk", "sleep_clk", + "utmi_clk", "xo"; + + qcom,core-clk-rate = <133333333>; + qcom,msm-bus,name = "usb2s"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + ; + + resets = <&clock_gcc GCC_USB_HS_BCR>; + reset-names = "core_reset"; + + dwc3@78c0000 { + compatible = "snps,dwc3"; + reg = <0x78c0000 0xcd00>; + interrupts = <0 44 0>; + usb-phy = <&usb2_phy0>, <&usb_nop_phy>; + linux,sysdev_is_parent; + snps,disable-clk-gating; + snps,has-lpm-erratum; + snps,hird-threshold = /bits/ 8 <0x10>; + snps,usb3_lpm_capable; + usb-core-id = <0>; + maximum-speed = "high-speed"; + dr_mode = "otg"; + }; + }; + + /* Primary USB port related High Speed PHY */ + usb2_phy0: hsphy@7c000 { + compatible = "qcom,usb-snps-hsphy"; + reg = <0x7c000 0x200>; + reg-names = "phy_csr"; + + vdd-supply = <&pms405_l4>; + vdda18-supply = <&pms405_l5>; + vdda33-supply = <&pms405_l12>; + qcom,vdd-voltage-level = <0 1144000 1144000>; + + clocks = <&clock_rpmcc RPM_SMD_LN_BB_CLK>, + <&clock_gcc GCC_USB_HS_PHY_CFG_AHB_CLK>; + clock-names = "ref_clk", "phy_csr_clk"; + + resets = <&clock_gcc GCC_QUSB2_PHY_BCR>, + <&clock_gcc GCC_USB2_HS_PHY_ONLY_BCR>; + reset-names = "phy_reset", "phy_por_reset"; + + qcom,snps-hs-phy-init-seq = + <0xe8 0x0d 0>, + <0x74 0x12 0>, + <0x98 0x63 0>, + <0x9c 0x03 0>, + <0xa0 0x1d 0>, + <0xa4 0x03 0>, + <0x8c 0x23 0>, + <0x78 0x08 0>, + <0x7c 0xdc 0>, + <0x90 0xe0 20>, + <0x74 0x10 0>, + <0x90 0x60 0>, + <0xffffffff 0xffffffff 0>; + }; + +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 275710a6cdf4..0fd1b5c578cb 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -859,44 +859,6 @@ thermal_zones: thermal-zones {}; - usb0: hsusb@78c0000 { - compatible = "qcom,dwc-usb3-msm"; - reg = <0x78c0000 0x100000>; - reg-names = "core_base"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - interrupts = <0 32 0>; - interrupt-names = "pwr_event_irq"; - /* Using dummy Xo clock, need to check the proper mapping */ - clocks = <&clock_gcc GCC_USB_HS_SYSTEM_CLK>, - <&clock_gcc GCC_PCNOC_USB2_CLK>, - <&clock_gcc GCC_USB30_SLEEP_CLK>, - <&clock_gcc GCC_USB_HS_INACTIVITY_TIMERS_CLK>, - <&clock_gcc GCC_USB20_MOCK_UTMI_CLK>; - clock-names = "core_clk", "iface_clk", "xo", - "sleep_clk", "utmi_clk"; - - qcom,core-clk-rate = <200000000>; - qcom,core-clk-rate-hs = <66666667>; - qcom,dwc-usb3-msm-tx-fifo-size = <27696>; - resets = <&clock_gcc GCC_USB_HS_BCR>; - reset-names = "core_reset"; - - dwc3@78c0000 { - compatible = "snps,dwc3"; - reg = <0x78c0000 0xcd00>; - interrupt-parent = <&intc>; - interrupts = <0 44 0>; - tx-fifo-resize; - linux,sysdev_is_parent; - snps,disable-clk-gating; - snps,has-lpm-erratum; - snps,hird-threshold = /bits/ 8 <0x10>; - }; - }; - sdhc_1: sdhci@7804000 { compatible = "qcom,sdhci-msm-v5"; reg = <0x7804000 0x1000>, <0x7805000 0x1000>; @@ -979,6 +941,7 @@ }; #include "qcs405-coresight.dtsi" +#include "qcs405-usb.dtsi" &i2c_5 { status = "ok"; @@ -997,3 +960,42 @@ qcom,switch-freq = <2>; }; }; + +&pms405_gpios { + usb3_vbus_boost { + usb3_vbus_boost_default: usb3_vbus_boost_default { + pins = "gpio3"; + function = "normal"; + output-low; + power-source = <1>; + }; + }; + + usb3_vbus_det { + usb3_vbus_det_default: usb3_vbus_det_default { + pins = "gpio12"; + function = "normal"; + input-enable; + bias-pull-down; + power-source = <1>; + }; + }; +}; + +&soc { + usb3_extcon: usb3_extcon { + compatible = "linux,extcon-usb-gpio"; + id-gpio = <&tlmm 116 GPIO_ACTIVE_HIGH>; + vbus-gpio = <&pms405_gpios 12 GPIO_ACTIVE_HIGH>; + vbus-out-gpio = <&pms405_gpios 3 GPIO_ACTIVE_HIGH>; + + pinctrl-names = "default"; + pinctrl-0 = <&usb3_vbus_det_default + &usb3_id_det_default + &usb3_vbus_boost_default>; + }; +}; + +&usb2s { + extcon = <&smb1351_otg_supply>; +}; -- GitLab From 1a070795aea442d6f5b80ff6e91768b321240416 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Sun, 17 Jun 2018 02:57:53 +0300 Subject: [PATCH 0367/1299] msm: ipa: Fix IPA driver compilation issues on sdxprairie 1. Add missing inline to static empty function. Issue hasn't been seen so far as msmnile uses different relevant defconfig configuration (CONFIG_IPA3_MHI_PROXY). 2. 64bit integer divide on 32bit CPU. Issue hasn't been seen so far as msmnile is 64bit CPU. CRs-Fixed: 2260620 Change-Id: I119a1f81182ca53cb0b52fa74a60b63a788da7d9 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/gsi/gsi.c | 7 +++++-- drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 5c6ef29b4b1f..4fd53ebab300 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -369,6 +369,8 @@ uint16_t gsi_find_idx_from_addr(struct gsi_ring_ctx *ctx, uint64_t addr) static uint16_t gsi_get_complete_num(struct gsi_ring_ctx *ctx, uint64_t addr1, uint64_t addr2) { + uint32_t addr_diff; + WARN(addr1 < ctx->base || addr1 >= ctx->end, "address not in range. base 0x%llx end 0x%llx addr 0x%llx\n", ctx->base, ctx->end, addr1); @@ -376,10 +378,11 @@ static uint16_t gsi_get_complete_num(struct gsi_ring_ctx *ctx, uint64_t addr1, "address not in range. base 0x%llx end 0x%llx addr 0x%llx\n", ctx->base, ctx->end, addr2); + addr_diff = (uint32_t)(addr2 - addr1); if (addr1 < addr2) - return (addr2 - addr1) / ctx->elem_sz; + return addr_diff / ctx->elem_sz; else - return (addr2 - addr1 + ctx->len) / ctx->elem_sz; + return (addr_diff + ctx->len) / ctx->elem_sz; } static void gsi_process_chan(struct gsi_xfer_compl_evt *evt, diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h index ce2e34a683ba..5fb9ebcda4ac 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h @@ -421,13 +421,13 @@ static inline int ipa3_qmi_stop_data_qouta(void) static inline void ipa3_q6_handshake_complete(bool ssr_bootup) { } -static int ipa3_qmi_send_mhi_ready_indication( +static inline int ipa3_qmi_send_mhi_ready_indication( struct ipa_mhi_ready_indication_msg_v01 *req) { return -EPERM; } -static int ipa3_qmi_send_mhi_cleanup_request( +static inline int ipa3_qmi_send_mhi_cleanup_request( struct ipa_mhi_cleanup_req_msg_v01 *req) { return -EPERM; -- GitLab From afbc89d208bfe6bc0cf70dd444648eca3c358343 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Sun, 17 Jun 2018 12:39:40 +0300 Subject: [PATCH 0368/1299] msm: gsi: Update Channel 0 context structure Channel 0 context structure reused bit 13 for protocol number MSB. This is to accommodate new added protocols. This change adds support for this bit. CRs-Fixed: 2262057 Change-Id: If8b828ce6c78b758ec5d57542d4d5f2ca4611ba6 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/gsi/gsi.c | 28 +++++++++++++++++++++++++--- drivers/platform/msm/gsi/gsi_reg.h | 2 ++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 5c6ef29b4b1f..d1e20f1a2c56 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -1677,10 +1677,32 @@ static void gsi_program_chan_ctx(struct gsi_chan_props *props, unsigned int ee, uint8_t erindex) { uint32_t val; + uint32_t prot; + uint32_t prot_msb; + + switch (props->prot) { + case GSI_CHAN_PROT_MHI: + case GSI_CHAN_PROT_XHCI: + case GSI_CHAN_PROT_GPI: + case GSI_CHAN_PROT_XDCI: + prot = props->prot; + prot_msb = 0; + break; + default: + GSIERR("Unsupported protocol %d\n", props->prot); + WARN_ON(1); + return; + } + val = ((prot << + GSI_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_SHFT) & + GSI_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_BMSK); + if (gsi_ctx->per.ver >= GSI_VER_2_5) { + val |= ((prot_msb << + GSI_V2_5_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_MSB_SHFT) & + GSI_V2_5_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_MSB_BMSK); + } - val = (((props->prot << GSI_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_SHFT) - & GSI_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_BMSK) | - ((props->dir << GSI_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_DIR_SHFT) & + val |= (((props->dir << GSI_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_DIR_SHFT) & GSI_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_DIR_BMSK) | ((erindex << GSI_EE_n_GSI_CH_k_CNTXT_0_ERINDEX_SHFT) & GSI_EE_n_GSI_CH_k_CNTXT_0_ERINDEX_BMSK) | diff --git a/drivers/platform/msm/gsi/gsi_reg.h b/drivers/platform/msm/gsi/gsi_reg.h index a9adbb1cde78..d32f8009ecbb 100644 --- a/drivers/platform/msm/gsi/gsi_reg.h +++ b/drivers/platform/msm/gsi/gsi_reg.h @@ -1049,6 +1049,8 @@ #define GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT 0x14 #define GSI_EE_n_GSI_CH_k_CNTXT_0_ERINDEX_BMSK 0x7c000 #define GSI_EE_n_GSI_CH_k_CNTXT_0_ERINDEX_SHFT 0xe +#define GSI_V2_5_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_MSB_BMSK 0x2000 +#define GSI_V2_5_EE_n_GSI_CH_k_CNTXT_0_CHTYPE_PROTOCOL_MSB_SHFT 0xd #define GSI_EE_n_GSI_CH_k_CNTXT_0_CHID_BMSK 0x1f00 #define GSI_EE_n_GSI_CH_k_CNTXT_0_CHID_SHFT 0x8 #define GSI_EE_n_GSI_CH_k_CNTXT_0_EE_BMSK 0xf0 -- GitLab From 9d8ff62099d2312cc035f0efd570852178ba206b Mon Sep 17 00:00:00 2001 From: Konstantin Dorfman Date: Sun, 17 Jun 2018 16:38:37 +0300 Subject: [PATCH 0369/1299] soc: qcom: spcom: fix rx path to support power collapse (cxpc) This change replaces wait_for_completion() with wait_for_completion_interruptible() variant for rx path. This make possible for user process context to remain TASK_INTERRUPTIBLE and receive signal during system suspend. read() syscall returns -ERESTART to trigger repeat of the call. Change-Id: Id469d606aaa900dc8f69a509d35dd6094723b031 Signed-off-by: Konstantin Dorfman --- drivers/soc/qcom/spcom.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index dd7a9ad2eaf6..b48e214d63dd 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -362,7 +362,7 @@ static int spcom_rx(struct spcom_channel *ch, { unsigned long jiffies = msecs_to_jiffies(timeout_msec); long timeleft = 1; - int ret; + int ret = 0; mutex_lock(&ch->lock); @@ -374,10 +374,10 @@ static int spcom_rx(struct spcom_channel *ch, /* wait for rx response */ pr_debug("wait for rx done, timeout_msec=%d\n", timeout_msec); if (timeout_msec) - timeleft = wait_for_completion_timeout(&ch->rx_done, - jiffies); + timeleft = wait_for_completion_interruptible_timeout( + &ch->rx_done, jiffies); else - wait_for_completion(&ch->rx_done); + ret = wait_for_completion_interruptible(&ch->rx_done); mutex_lock(&ch->lock); if (timeout_msec && timeleft == 0) { @@ -388,6 +388,12 @@ static int spcom_rx(struct spcom_channel *ch, pr_warn("rpmsg channel is closing\n"); ret = -ERESTART; goto exit_err; + } else if (ret < 0 || timeleft == -ERESTARTSYS) { + pr_debug("wait interrupted: ret=%d, timeleft=%ld\n", + ret, timeleft); + if (timeleft == -ERESTARTSYS) + ret = -ERESTARTSYS; + goto exit_err; } else if (ch->actual_rx_size) { pr_debug("actual_rx_size is [%zu]\n", ch->actual_rx_size); @@ -439,6 +445,7 @@ static int spcom_rx(struct spcom_channel *ch, static int spcom_get_next_request_size(struct spcom_channel *ch) { int size = -1; + int ret = 0; /* NOTE: Remote clients might not be connected yet.*/ mutex_lock(&ch->lock); @@ -448,18 +455,26 @@ static int spcom_get_next_request_size(struct spcom_channel *ch) if (ch->actual_rx_size) { pr_debug("next-req-size already ready ch [%s] size [%zu]\n", ch->name, ch->actual_rx_size); + ret = -EFAULT; goto exit_ready; } mutex_unlock(&ch->lock); /* unlock while waiting */ pr_debug("Wait for Rx Done, ch [%s].\n", ch->name); - wait_for_completion(&ch->rx_done); + ret = wait_for_completion_interruptible(&ch->rx_done); + if (ret < 0) { + pr_debug("ch [%s]:interrupted wait ret=%d\n", + ret, ch->name); + goto exit_error; + } mutex_lock(&ch->lock); /* re-lock after waiting */ if (ch->actual_rx_size == 0) { pr_err("invalid rx size [%zu] ch [%s]\n", ch->actual_rx_size, ch->name); + mutex_unlock(&ch->lock); + ret = -EFAULT; goto exit_error; } @@ -470,6 +485,8 @@ static int spcom_get_next_request_size(struct spcom_channel *ch) size -= sizeof(struct spcom_msg_hdr); } else { pr_err("rx size [%d] too small.\n", size); + ret = -EFAULT; + mutex_unlock(&ch->lock); goto exit_error; } @@ -477,10 +494,7 @@ static int spcom_get_next_request_size(struct spcom_channel *ch) return size; exit_error: - mutex_unlock(&ch->lock); - return -EFAULT; - - + return ret; } /*======================================================================*/ @@ -1465,7 +1479,8 @@ static ssize_t spcom_device_read(struct file *filp, char __user *user_buff, ret = spcom_handle_read(ch, buf, buf_size); if (ret < 0) { - pr_err("read error [%d].\n", ret); + if (ret != -ERESTARTSYS) + pr_err("read error [%d].\n", ret); kfree(buf); return ret; } -- GitLab From 846317e28fc2fa9d144d29cfd580f87c4bbeb4d0 Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Thu, 14 Jun 2018 11:55:29 +0530 Subject: [PATCH 0370/1299] defconfig: sm6150: Enable clock controller drivers for SM6150 Enable Global, GPU and Video clock controller drivers for SM6150. Change-Id: I3460bf542e013e15d87861824c1e48ec457648ac Signed-off-by: Odelu Kukatla --- arch/arm64/configs/vendor/sdmsteppe-perf_defconfig | 3 +++ arch/arm64/configs/vendor/sdmsteppe_defconfig | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index e4e007d601ba..3f0db6e9863c 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -464,6 +464,9 @@ CONFIG_MSM_DISPCC_SM8150=y CONFIG_MSM_DEBUGCC_SM8150=y CONFIG_MSM_CLK_RPMH=y CONFIG_MSM_GPUCC_SM8150=y +CONFIG_MSM_GCC_SM6150=y +CONFIG_MSM_GPUCC_SM6150=y +CONFIG_MSM_VIDEOCC_SM6150=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_QCOM_APCS_IPC=y diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index 696fde9ce5c8..e17283dfcc77 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -480,6 +480,9 @@ CONFIG_MSM_DISPCC_SM8150=y CONFIG_MSM_DEBUGCC_SM8150=y CONFIG_MSM_CLK_RPMH=y CONFIG_MSM_GPUCC_SM8150=y +CONFIG_MSM_GCC_SM6150=y +CONFIG_MSM_GPUCC_SM6150=y +CONFIG_MSM_VIDEOCC_SM6150=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_QCOM_APCS_IPC=y -- GitLab From b8fa72481bea3e8dc9cba530a257297d7b3a380d Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Mon, 18 Jun 2018 11:09:46 +0530 Subject: [PATCH 0371/1299] defconfig: msm: enable remote debugger driver on sm8150 Add remote debugger device configuration. The Remote Debugger driver allows a debugger running on a host PC to communicate with a remote stub running on peripheral subsystems. Change-Id: Id9859252f5e64b006b90c3a8e61ce1b1c59a15c0 Acked-by: Chenna Kesava Raju Signed-off-by: Tharun Kumar Merugu --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index c3adfafea314..06d9f7e526ac 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -314,6 +314,7 @@ CONFIG_HW_RANDOM_MSM_LEGACY=y CONFIG_DIAG_CHAR=y CONFIG_MSM_FASTCVPD=y CONFIG_MSM_ADSPRPC=y +CONFIG_MSM_RDBG=m CONFIG_I2C_CHARDEV=y CONFIG_I2C_QCOM_GENI=y CONFIG_SPI=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 162c9a7ab110..e68b70b953ca 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -328,6 +328,7 @@ CONFIG_HW_RANDOM_MSM_LEGACY=y CONFIG_DIAG_CHAR=y CONFIG_MSM_FASTCVPD=y CONFIG_MSM_ADSPRPC=y +CONFIG_MSM_RDBG=m CONFIG_I2C_CHARDEV=y CONFIG_I2C_QCOM_GENI=y CONFIG_SPI=y -- GitLab From d3463b6a3c1f728f8089f1e84157e6540df9b7d3 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Wed, 7 Mar 2018 19:34:36 +0530 Subject: [PATCH 0372/1299] cfg80211/nl80211: Optional authentication offload to userspace This interface allows the host driver to offload the authentication to user space. This is exclusively defined for host drivers that do not define separate commands for authentication and association, but rely on userspace SME (e.g., in wpa_supplicant for the ~WPA_DRIVER_FLAGS_SME case) for the authentication to happen. This can be used to implement SAE without full implementation in the kernel/firmware while still being able to use NL80211_CMD_CONNECT with driver-based BSS selection. Host driver sends NL80211_CMD_EXTERNAL_AUTH event to start/abort authentication to the port on which connect is triggered and status of authentication is further indicated by user space to host driver through the same command response interface. User space entities advertise this capability through the NL80211_ATTR_EXTERNAL_AUTH_SUPP flag in the NL80211_CMD_CONNECT request. Host drivers shall look at this capability to offload the authentication. Signed-off-by: Srinivas Dasari Signed-off-by: Jouni Malinen [add socket connection ownership check] Signed-off-by: Johannes Berg Git-commit: 40cbfa90218bc570a7959b436b9d48a18c361041 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git CRs-Fixed: 2262200 Change-Id: Id925dd82d9a9c719b32aac2de75b6ad001f1a958 [dasaris@codeaurora.org: merging with msm-specific changes] Signed-off-by: Srinivas Dasari --- include/net/cfg80211.h | 54 +++++++++++++++++++-- include/uapi/linux/nl80211.h | 47 ++++++++++++++++++ net/wireless/nl80211.c | 92 ++++++++++++++++++++++++++++++++++++ net/wireless/rdev-ops.h | 15 ++++++ net/wireless/trace.h | 23 +++++++++ 5 files changed, 228 insertions(+), 3 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index dd97d8b7e852..7bb33a4a6f91 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1900,11 +1900,16 @@ struct cfg80211_auth_request { * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n) * @ASSOC_REQ_DISABLE_VHT: Disable VHT * @ASSOC_REQ_USE_RRM: Declare RRM capability in this association + * @CONNECT_REQ_EXTERNAL_AUTH_SUPPORT: User space indicates external + * authentication capability. Drivers can offload authentication to + * userspace if this flag is set. Only applicable for cfg80211_connect() + * request (connect callback). */ enum cfg80211_assoc_req_flags { - ASSOC_REQ_DISABLE_HT = BIT(0), - ASSOC_REQ_DISABLE_VHT = BIT(1), - ASSOC_REQ_USE_RRM = BIT(2), + ASSOC_REQ_DISABLE_HT = BIT(0), + ASSOC_REQ_DISABLE_VHT = BIT(1), + ASSOC_REQ_USE_RRM = BIT(2), + CONNECT_REQ_EXTERNAL_AUTH_SUPPORT = BIT(3), }; /** @@ -2590,6 +2595,33 @@ struct cfg80211_pmk_conf { const u8 *pmk_r0_name; }; +/** + * struct cfg80211_external_auth_params - Trigger External authentication. + * + * Commonly used across the external auth request and event interfaces. + * + * @action: action type / trigger for external authentication. Only significant + * for the authentication request event interface (driver to user space). + * @bssid: BSSID of the peer with which the authentication has + * to happen. Used by both the authentication request event and + * authentication response command interface. + * @ssid: SSID of the AP. Used by both the authentication request event and + * authentication response command interface. + * @key_mgmt_suite: AKM suite of the respective authentication. Used by the + * authentication request event interface. + * @status: status code, %WLAN_STATUS_SUCCESS for successful authentication, + * use %WLAN_STATUS_UNSPECIFIED_FAILURE if user space cannot give you + * the real status code for failures. Used only for the authentication + * response command interface (user space to driver). + */ +struct cfg80211_external_auth_params { + enum nl80211_external_auth_action action; + u8 bssid[ETH_ALEN] __aligned(2); + struct cfg80211_ssid ssid; + unsigned int key_mgmt_suite; + u16 status; +}; + /** * struct cfg80211_ops - backend description for wireless configuration * @@ -2913,6 +2945,9 @@ struct cfg80211_pmk_conf { * (invoked with the wireless_dev mutex held) * @del_pmk: delete the previously configured PMK for the given authenticator. * (invoked with the wireless_dev mutex held) + * + * @external_auth: indicates result of offloaded authentication processing from + * user space */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -3206,6 +3241,8 @@ struct cfg80211_ops { const struct cfg80211_pmk_conf *conf); int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev, const u8 *aa); + int (*external_auth)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_external_auth_params *params); }; /* @@ -6236,6 +6273,17 @@ void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info); */ bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb); +/** + * cfg80211_external_auth_request - userspace request for authentication + * @netdev: network device + * @params: External authentication parameters + * @gfp: allocation flags + * Returns: 0 on success, < 0 on error + */ +int cfg80211_external_auth_request(struct net_device *netdev, + struct cfg80211_external_auth_params *params, + gfp_t gfp); + /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 7e8de4bcb231..25426e9c4f41 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -992,6 +992,27 @@ * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. * * + * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host + * drivers that do not define separate commands for authentication and + * association, but rely on user space for the authentication to happen. + * This interface acts both as the event request (driver to user space) + * to trigger the authentication and command response (userspace to + * driver) to indicate the authentication status. + * + * User space uses the %NL80211_CMD_CONNECT command to the host driver to + * trigger a connection. The host driver selects a BSS and further uses + * this interface to offload only the authentication part to the user + * space. Authentication frames are passed between the driver and user + * space through the %NL80211_CMD_FRAME interface. Host driver proceeds + * further with the association after getting successful authentication + * status. User space indicates the authentication status through + * %NL80211_ATTR_STATUS_CODE attribute in %NL80211_CMD_EXTERNAL_AUTH + * command interface. + * + * Host driver reports this status on an authentication failure to the + * user space through the connect result as the user space would have + * initiated the connection through the connect request. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1198,6 +1219,8 @@ enum nl80211_commands { NL80211_CMD_RELOAD_REGDB, + NL80211_CMD_EXTERNAL_AUTH, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -2156,6 +2179,16 @@ enum nl80211_commands { * the driver or is not needed (because roaming used the Fast Transition * protocol). * + * @NL80211_ATTR_EXTERNAL_AUTH_ACTION: Identify the requested external + * authentication operation (u32 attribute with an + * &enum nl80211_external_auth_action value). This is used with the + * &NL80211_CMD_EXTERNAL_AUTH request event. + * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user + * space supports external authentication. This attribute shall be used + * only with %NL80211_CMD_CONNECT request. The driver may offload + * authentication processing to user space if this capability is indicated + * in NL80211_CMD_CONNECT requests from the user space. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2582,6 +2615,9 @@ enum nl80211_attrs { NL80211_ATTR_PMKR0_NAME, NL80211_ATTR_PORT_AUTHORIZED, + NL80211_ATTR_EXTERNAL_AUTH_ACTION, + NL80211_ATTR_EXTERNAL_AUTH_SUPPORT, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -5503,4 +5539,15 @@ enum nl80211_nan_match_attributes { NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1 }; +/** + * nl80211_external_auth_action - Action to perform with external + * authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION. + * @NL80211_EXTERNAL_AUTH_START: Start the authentication. + * @NL80211_EXTERNAL_AUTH_ABORT: Abort the ongoing authentication. + */ +enum nl80211_external_auth_action { + NL80211_EXTERNAL_AUTH_START, + NL80211_EXTERNAL_AUTH_ABORT, +}; + #endif /* __LINUX_NL80211_H */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7ae58969a651..d7222bd96a1f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -421,6 +421,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 }, [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN }, [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG }, + [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG }, }; /* policy for the key attributes */ @@ -9101,6 +9102,13 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) return -EINVAL; } + if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) { + if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) { + return -EINVAL; + } + connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT; + } + wdev_lock(dev->ieee80211_ptr); err = cfg80211_connect(rdev, dev, &connect, connkeys, @@ -12409,6 +12417,41 @@ static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info) return ret; } +static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct cfg80211_external_auth_params params; + + if (rdev->ops->external_auth) + return -EOPNOTSUPP; + + if (!info->attrs[NL80211_ATTR_SSID]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_BSSID]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_STATUS_CODE]) + return -EINVAL; + + memset(¶ms, 0, sizeof(params)); + + params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); + if (params.ssid.ssid_len == 0 || + params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN) + return -EINVAL; + memcpy(params.ssid.ssid, nla_data(info->attrs[NL80211_ATTR_SSID]), + params.ssid.ssid_len); + + memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]), + ETH_ALEN); + + params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]); + + return rdev_external_auth(rdev, dev, ¶ms); +} + #define NL80211_FLAG_NEED_WIPHY 0x01 #define NL80211_FLAG_NEED_NETDEV 0x02 #define NL80211_FLAG_NEED_RTNL 0x04 @@ -13298,6 +13341,14 @@ static const struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, + { + .cmd = NL80211_CMD_EXTERNAL_AUTH, + .doit = nl80211_external_auth, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, }; @@ -15292,6 +15343,47 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev) nlmsg_free(msg); } +int cfg80211_external_auth_request(struct net_device *dev, + struct cfg80211_external_auth_params *params, + gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + struct sk_buff *msg; + void *hdr; + + if (!wdev->conn_owner_nlportid) + return -EINVAL; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return -ENOMEM; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH); + if (!hdr) + goto nla_put_failure; + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) || + nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION, + params->action) || + nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) || + nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len, + params->ssid.ssid)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, + wdev->conn_owner_nlportid); + return 0; + + nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; +} +EXPORT_SYMBOL(cfg80211_external_auth_request); + /* initialisation/exit functions */ int __init nl80211_init(void) diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 0c06240d25af..84f23ae015fc 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -1190,4 +1190,19 @@ static inline int rdev_del_pmk(struct cfg80211_registered_device *rdev, trace_rdev_return_int(&rdev->wiphy, ret); return ret; } + +static inline int +rdev_external_auth(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct cfg80211_external_auth_params *params) +{ + int ret = -EOPNOTSUPP; + + trace_rdev_external_auth(&rdev->wiphy, dev, params); + if (rdev->ops->external_auth) + ret = rdev->ops->external_auth(&rdev->wiphy, dev, params); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; +} + #endif /* __CFG80211_RDEV_OPS */ diff --git a/net/wireless/trace.h b/net/wireless/trace.h index f3353fe5b35b..c8c463bab79d 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2319,6 +2319,29 @@ TRACE_EVENT(rdev_del_pmk, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(aa)) ); +TRACE_EVENT(rdev_external_auth, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_external_auth_params *params), + TP_ARGS(wiphy, netdev, params), + TP_STRUCT__entry(WIPHY_ENTRY + NETDEV_ENTRY + MAC_ENTRY(bssid) + __array(u8, ssid, IEEE80211_MAX_SSID_LEN + 1) + __field(u16, status) + ), + TP_fast_assign(WIPHY_ASSIGN; + NETDEV_ASSIGN; + MAC_ASSIGN(bssid, params->bssid); + memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); + memcpy(__entry->ssid, params->ssid.ssid, + params->ssid.ssid_len); + __entry->status = params->status; + ), + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT + ", ssid: %s, status: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, + __entry->bssid, __entry->ssid, __entry->status) +); + /************************************************************* * cfg80211 exported functions traces * *************************************************************/ -- GitLab From bc3bb8a2874642d298c446a7b2fcc36faf6a9525 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Thu, 25 Jan 2018 17:13:39 +0200 Subject: [PATCH 0373/1299] nl80211: Allow SAE Authentication for NL80211_CMD_CONNECT This commit allows SAE Authentication for NL80211_CMD_CONNECT interface, provided host driver advertises the support. Host drivers may offload the SAE authentication to user space through NL80211_CMD_EXTERNAL_AUTH interface and thus expect the user space to advertise support to handle offload through NL80211_ATTR_EXTERNAL_AUTH_SUPPORT in NL80211_CMD_CONNECT request. Such drivers should reject the connect request on no offload support from user space. Signed-off-by: Srinivas Dasari Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Git-commit: 10773a7c09b327d02144c7d181e6544b7015ffc7 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git CRs-Fixed: 2262200 Change-Id: I41b49228e88b32a35323c4dc8fa98e507a8a971d Signed-off-by: Srinivas Dasari --- net/wireless/nl80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d7222bd96a1f..a789d68e96d3 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3864,9 +3864,10 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev, return false; return true; case NL80211_CMD_CONNECT: - /* SAE not supported yet */ - if (auth_type == NL80211_AUTHTYPE_SAE) + if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) && + auth_type == NL80211_AUTHTYPE_SAE) return false; + /* FILS with SK PFS or PK not supported yet */ if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS || auth_type == NL80211_AUTHTYPE_FILS_PK) -- GitLab From f7f44d41171d45d00e84c5b516391dba55a13978 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Wed, 7 Mar 2018 19:55:52 +0530 Subject: [PATCH 0374/1299] cfg80211: indicate support for external authentication Define macro to indicate backport support for external authentication where authentication can be offloaded to userspace in specific cases such as SAE. Change-Id: Ib253b303e82f583f61bc13d14c8d491d5ea2af15 CRs-Fixed: 2262200 Signed-off-by: Srinivas Dasari --- include/net/cfg80211.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 7bb33a4a6f91..df5da42eaa4d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -27,6 +27,9 @@ /* Indicate backport support for processing user cell base hint */ #define CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED 1 +/* Indicate backport support for external authentication*/ +#define CFG80211_EXTERNAL_AUTH_SUPPORT 1 + /** * DOC: Introduction * -- GitLab From 622fdc1dbb4001020a8363ac17e1b0909adc9f50 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Fri, 2 Feb 2018 11:15:27 +0200 Subject: [PATCH 0375/1299] nl80211: Fix external_auth check for offloaded authentication Unfortunately removal of the ext_feature flag in the last revision of the patch ended up negating the comparison and prevented the command from being processed (either nl80211_external_auth() or rdev_external_auth() returns -EOPNOTSUPP). Fix this by adding back the lost '!'. Fixes: 40cbfa90218b ("cfg80211/nl80211: Optional authentication offload to userspace") Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Git-commit: db8d93a7a355121d49777c059afbca23c53c8628 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git CRs-Fixed: 2210017 Change-Id: I41f7c25d68a5060d7b5e24fb5bd164e063311ed0 Signed-off-by: Srinivas Dasari --- net/wireless/nl80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a789d68e96d3..310cfe13c909 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -12424,7 +12424,7 @@ static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info) struct net_device *dev = info->user_ptr[1]; struct cfg80211_external_auth_params params; - if (rdev->ops->external_auth) + if (!rdev->ops->external_auth) return -EOPNOTSUPP; if (!info->attrs[NL80211_ATTR_SSID]) -- GitLab From db6241b33712cc2fc5cc8e7fea161b25497c01c1 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Mon, 18 Jun 2018 10:42:25 +0530 Subject: [PATCH 0376/1299] defconfig: sm8150: Enable GCM crypto library compilation GCM crypto library is needed for GMAC support. Define flag CONFIG_CRYPTO_GCM and set to 'y'(yes) to enable compilation of the same. Change-Id: I710fc81b3624bf484c6ba6f3cdd1bdb370e5bb33 CRs-Fixed: 2194089 Signed-off-by: Srinivas Dasari --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index c3adfafea314..7649eb0e413c 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -623,6 +623,7 @@ CONFIG_HARDENED_USERCOPY=y CONFIG_FORTIFY_SOURCE=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y +CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 162c9a7ab110..24031c0a6522 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -704,6 +704,7 @@ CONFIG_HARDENED_USERCOPY_PAGESPAN=y CONFIG_FORTIFY_SOURCE=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y +CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y -- GitLab From 0381b1b444b432a06b135bdf514be61891eab908 Mon Sep 17 00:00:00 2001 From: Jitendra Sharma Date: Wed, 6 Jun 2018 15:14:04 +0530 Subject: [PATCH 0377/1299] ARM: dts: msm: Add CDSP pil node for SM6150 Add CDSP pil node to facilitate CDSP firmware loading in SM6150. Change-Id: I485dec3146a7c3b0cea8a97f769c8692611fd9c5 Signed-off-by: Jitendra Sharma --- arch/arm64/boot/dts/qcom/sm6150.dtsi | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index 81a0f35c2b79..c744416563c3 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -1574,6 +1574,46 @@ mbox-names = "mss-pil"; }; + qcom,turing@8300000 { + compatible = "qcom,pil-tz-generic"; + reg = <0x8300000 0x100000>; + + vdd_cx-supply = <&VDD_CX_LEVEL>; + qcom,proxy-reg-names = "vdd_cx"; + qcom,vdd_cx-uV-uA = ; + + clocks = <&clock_rpmh RPMH_CXO_CLK>; + clock-names = "xo"; + qcom,proxy-clock-names = "xo"; + + qcom,pas-id = <18>; + qcom,proxy-timeout-ms = <10000>; + qcom,smem-id = <601>; + qcom,sysmon-id = <7>; + qcom,ssctl-instance-id = <0x17>; + qcom,firmware-name = "cdsp"; + memory-region = <&pil_cdsp_mem>; + + /* Inputs from turing */ + interrupts-extended = <&pdc 0 578 1>, + <&cdsp_smp2p_in 0 0>, + <&cdsp_smp2p_in 2 0>, + <&cdsp_smp2p_in 1 0>, + <&cdsp_smp2p_in 3 0>; + + interrupt-names = "qcom,wdog", + "qcom,err-fatal", + "qcom,proxy-unvote", + "qcom,err-ready", + "qcom,stop-ack"; + + /* Outputs to turing */ + qcom,smem-states = <&cdsp_smp2p_out 0>; + qcom,smem-state-names = "qcom,force-stop"; + + mboxes = <&qmp_aop 0>; + mbox-names = "cdsp-pil"; + }; }; #include "pm6150.dtsi" -- GitLab From c6e140b2292ca50a93cf68b50df2253a8f966a4b Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Fri, 15 Jun 2018 14:39:12 +0530 Subject: [PATCH 0378/1299] clk: qcom: gcc: Update order of clock registration Update the clock registration of PLL before the branch and rcgs so as to avoid failure in clock parent during OPP table population. Thus update the clock references for the same. Change-Id: Ib629469969b3df15f734eaeee3dfa25727f3dd05 Signed-off-by: Shefali Jain --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 9 + include/dt-bindings/clock/qcom,gcc-qcs405.h | 254 ++++++++++---------- 2 files changed, 136 insertions(+), 127 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 4d07feade11a..55ecc7d0e8ea 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -221,6 +221,15 @@ }; }; + clocks { + xo_board { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <19200000>; + clock-output-names = "xo_board"; + }; + }; + restart@4ab000 { compatible = "qcom,pshold"; reg = <0x4ab000 0x4>, diff --git a/include/dt-bindings/clock/qcom,gcc-qcs405.h b/include/dt-bindings/clock/qcom,gcc-qcs405.h index 6c2bed052f04..6a122d262c04 100644 --- a/include/dt-bindings/clock/qcom,gcc-qcs405.h +++ b/include/dt-bindings/clock/qcom,gcc-qcs405.h @@ -14,133 +14,133 @@ #ifndef _DT_BINDINGS_CLK_QCOM_GCC_QCS405_H #define _DT_BINDINGS_CLK_QCOM_GCC_QCS405_H -#define APSS_AHB_CLK_SRC 0 -#define BLSP1_QUP0_I2C_APPS_CLK_SRC 1 -#define BLSP1_QUP0_SPI_APPS_CLK_SRC 2 -#define BLSP1_QUP1_I2C_APPS_CLK_SRC 3 -#define BLSP1_QUP1_SPI_APPS_CLK_SRC 4 -#define BLSP1_QUP2_I2C_APPS_CLK_SRC 5 -#define BLSP1_QUP2_SPI_APPS_CLK_SRC 6 -#define BLSP1_QUP3_I2C_APPS_CLK_SRC 7 -#define BLSP1_QUP3_SPI_APPS_CLK_SRC 8 -#define BLSP1_QUP4_I2C_APPS_CLK_SRC 9 -#define BLSP1_QUP4_SPI_APPS_CLK_SRC 10 -#define BLSP1_UART0_APPS_CLK_SRC 11 -#define BLSP1_UART1_APPS_CLK_SRC 12 -#define BLSP1_UART2_APPS_CLK_SRC 13 -#define BLSP1_UART3_APPS_CLK_SRC 14 -#define BLSP2_QUP0_I2C_APPS_CLK_SRC 15 -#define BLSP2_QUP0_SPI_APPS_CLK_SRC 16 -#define BLSP2_UART0_APPS_CLK_SRC 17 -#define BYTE0_CLK_SRC 18 -#define EMAC_CLK_SRC 19 -#define EMAC_PTP_CLK_SRC 20 -#define ESC0_CLK_SRC 21 -#define GCC_APSS_AHB_CLK 22 -#define GCC_APSS_AXI_CLK 23 -#define GCC_BIMC_APSS_AXI_CLK 24 -#define GCC_BIMC_GFX_CLK 25 -#define GCC_BIMC_MDSS_CLK 26 -#define GCC_BLSP1_AHB_CLK 27 -#define GCC_BLSP1_QUP0_I2C_APPS_CLK 28 -#define GCC_BLSP1_QUP0_SPI_APPS_CLK 29 -#define GCC_BLSP1_QUP1_I2C_APPS_CLK 30 -#define GCC_BLSP1_QUP1_SPI_APPS_CLK 31 -#define GCC_BLSP1_QUP2_I2C_APPS_CLK 32 -#define GCC_BLSP1_QUP2_SPI_APPS_CLK 33 -#define GCC_BLSP1_QUP3_I2C_APPS_CLK 34 -#define GCC_BLSP1_QUP3_SPI_APPS_CLK 35 -#define GCC_BLSP1_QUP4_I2C_APPS_CLK 36 -#define GCC_BLSP1_QUP4_SPI_APPS_CLK 37 -#define GCC_BLSP1_UART0_APPS_CLK 38 -#define GCC_BLSP1_UART1_APPS_CLK 39 -#define GCC_BLSP1_UART2_APPS_CLK 40 -#define GCC_BLSP1_UART3_APPS_CLK 41 -#define GCC_BLSP2_AHB_CLK 42 -#define GCC_BLSP2_QUP0_I2C_APPS_CLK 43 -#define GCC_BLSP2_QUP0_SPI_APPS_CLK 44 -#define GCC_BLSP2_UART0_APPS_CLK 45 -#define GCC_BOOT_ROM_AHB_CLK 46 -#define GCC_DCC_CLK 47 -#define GCC_GENI_IR_H_CLK 48 -#define GCC_ETH_AXI_CLK 49 -#define GCC_ETH_PTP_CLK 50 -#define GCC_ETH_RGMII_CLK 51 -#define GCC_ETH_SLAVE_AHB_CLK 52 -#define GCC_GENI_IR_S_CLK 53 -#define GCC_GP1_CLK 54 -#define GCC_GP2_CLK 55 -#define GCC_GP3_CLK 56 -#define GCC_MDSS_AHB_CLK 57 -#define GCC_MDSS_AXI_CLK 58 -#define GCC_MDSS_BYTE0_CLK 59 -#define GCC_MDSS_ESC0_CLK 60 -#define GCC_MDSS_HDMI_APP_CLK 61 -#define GCC_MDSS_HDMI_PCLK_CLK 62 -#define GCC_MDSS_MDP_CLK 63 -#define GCC_MDSS_PCLK0_CLK 64 -#define GCC_MDSS_VSYNC_CLK 65 -#define GCC_OXILI_AHB_CLK 66 -#define GCC_OXILI_GFX3D_CLK 67 -#define GCC_PCIE_0_AUX_CLK 68 -#define GCC_PCIE_0_CFG_AHB_CLK 69 -#define GCC_PCIE_0_MSTR_AXI_CLK 70 -#define GCC_PCIE_0_PIPE_CLK 71 -#define GCC_PCIE_0_SLV_AXI_CLK 72 -#define GCC_PCNOC_USB2_CLK 73 -#define GCC_PCNOC_USB3_CLK 74 -#define GCC_PDM2_CLK 75 -#define GCC_PDM_AHB_CLK 76 -#define VSYNC_CLK_SRC 77 -#define GCC_PRNG_AHB_CLK 78 -#define GCC_PWM0_XO512_CLK 79 -#define GCC_PWM1_XO512_CLK 80 -#define GCC_PWM2_XO512_CLK 81 -#define GCC_SDCC1_AHB_CLK 82 -#define GCC_SDCC1_APPS_CLK 83 -#define GCC_SDCC1_ICE_CORE_CLK 84 -#define GCC_SDCC2_AHB_CLK 85 -#define GCC_SDCC2_APPS_CLK 86 -#define GCC_SYS_NOC_USB3_CLK 87 -#define GCC_USB20_MOCK_UTMI_CLK 88 -#define GCC_USB2A_PHY_SLEEP_CLK 89 -#define GCC_USB30_MASTER_CLK 90 -#define GCC_USB30_MOCK_UTMI_CLK 91 -#define GCC_USB30_SLEEP_CLK 92 -#define GCC_USB3_PHY_AUX_CLK 93 -#define GCC_USB3_PHY_PIPE_CLK 94 -#define GCC_USB_HS_PHY_CFG_AHB_CLK 95 -#define GCC_USB_HS_SYSTEM_CLK 96 -#define GFX3D_CLK_SRC 97 -#define GP1_CLK_SRC 98 -#define GP2_CLK_SRC 99 -#define GP3_CLK_SRC 100 -#define GPLL0_OUT_MAIN 101 -#define GPLL1_OUT_MAIN 102 -#define GPLL3_OUT_MAIN 103 -#define GPLL4_OUT_MAIN 104 -#define HDMI_APP_CLK_SRC 105 -#define HDMI_PCLK_CLK_SRC 106 -#define MDP_CLK_SRC 107 -#define PCIE_0_AUX_CLK_SRC 108 -#define PCIE_0_PIPE_CLK_SRC 109 -#define PCLK0_CLK_SRC 110 -#define PDM2_CLK_SRC 111 -#define SDCC1_APPS_CLK_SRC 112 -#define SDCC1_ICE_CORE_CLK_SRC 113 -#define SDCC2_APPS_CLK_SRC 114 -#define USB20_MOCK_UTMI_CLK_SRC 115 -#define USB30_MASTER_CLK_SRC 116 -#define USB30_MOCK_UTMI_CLK_SRC 117 -#define USB3_PHY_AUX_CLK_SRC 118 -#define USB_HS_SYSTEM_CLK_SRC 119 -#define GPLL0_AO_CLK_SRC 120 -#define WCNSS_M_CLK 121 -#define GCC_USB_HS_INACTIVITY_TIMERS_CLK 122 -#define GPLL0_AO_OUT_MAIN 123 -#define GPLL0_SLEEP_CLK_SRC 124 -#define GPLL6 125 -#define GPLL6_OUT_AUX 126 +#define GPLL0_OUT_MAIN 0 +#define GPLL0_AO_CLK_SRC 1 +#define GPLL1_OUT_MAIN 2 +#define GPLL3_OUT_MAIN 3 +#define GPLL4_OUT_MAIN 4 +#define GPLL0_AO_OUT_MAIN 5 +#define GPLL0_SLEEP_CLK_SRC 6 +#define GPLL6 7 +#define GPLL6_OUT_AUX 8 +#define APSS_AHB_CLK_SRC 9 +#define BLSP1_QUP0_I2C_APPS_CLK_SRC 10 +#define BLSP1_QUP0_SPI_APPS_CLK_SRC 11 +#define BLSP1_QUP1_I2C_APPS_CLK_SRC 12 +#define BLSP1_QUP1_SPI_APPS_CLK_SRC 13 +#define BLSP1_QUP2_I2C_APPS_CLK_SRC 14 +#define BLSP1_QUP2_SPI_APPS_CLK_SRC 15 +#define BLSP1_QUP3_I2C_APPS_CLK_SRC 16 +#define BLSP1_QUP3_SPI_APPS_CLK_SRC 17 +#define BLSP1_QUP4_I2C_APPS_CLK_SRC 18 +#define BLSP1_QUP4_SPI_APPS_CLK_SRC 19 +#define BLSP1_UART0_APPS_CLK_SRC 20 +#define BLSP1_UART1_APPS_CLK_SRC 21 +#define BLSP1_UART2_APPS_CLK_SRC 22 +#define BLSP1_UART3_APPS_CLK_SRC 23 +#define BLSP2_QUP0_I2C_APPS_CLK_SRC 24 +#define BLSP2_QUP0_SPI_APPS_CLK_SRC 25 +#define BLSP2_UART0_APPS_CLK_SRC 26 +#define BYTE0_CLK_SRC 27 +#define EMAC_CLK_SRC 28 +#define EMAC_PTP_CLK_SRC 29 +#define ESC0_CLK_SRC 30 +#define GCC_APSS_AHB_CLK 31 +#define GCC_APSS_AXI_CLK 32 +#define GCC_BIMC_APSS_AXI_CLK 33 +#define GCC_BIMC_GFX_CLK 34 +#define GCC_BIMC_MDSS_CLK 35 +#define GCC_BLSP1_AHB_CLK 36 +#define GCC_BLSP1_QUP0_I2C_APPS_CLK 37 +#define GCC_BLSP1_QUP0_SPI_APPS_CLK 38 +#define GCC_BLSP1_QUP1_I2C_APPS_CLK 39 +#define GCC_BLSP1_QUP1_SPI_APPS_CLK 40 +#define GCC_BLSP1_QUP2_I2C_APPS_CLK 41 +#define GCC_BLSP1_QUP2_SPI_APPS_CLK 42 +#define GCC_BLSP1_QUP3_I2C_APPS_CLK 43 +#define GCC_BLSP1_QUP3_SPI_APPS_CLK 44 +#define GCC_BLSP1_QUP4_I2C_APPS_CLK 45 +#define GCC_BLSP1_QUP4_SPI_APPS_CLK 46 +#define GCC_BLSP1_UART0_APPS_CLK 47 +#define GCC_BLSP1_UART1_APPS_CLK 48 +#define GCC_BLSP1_UART2_APPS_CLK 49 +#define GCC_BLSP1_UART3_APPS_CLK 50 +#define GCC_BLSP2_AHB_CLK 51 +#define GCC_BLSP2_QUP0_I2C_APPS_CLK 52 +#define GCC_BLSP2_QUP0_SPI_APPS_CLK 53 +#define GCC_BLSP2_UART0_APPS_CLK 54 +#define GCC_BOOT_ROM_AHB_CLK 55 +#define GCC_DCC_CLK 56 +#define GCC_GENI_IR_H_CLK 57 +#define GCC_ETH_AXI_CLK 58 +#define GCC_ETH_PTP_CLK 59 +#define GCC_ETH_RGMII_CLK 60 +#define GCC_ETH_SLAVE_AHB_CLK 61 +#define GCC_GENI_IR_S_CLK 62 +#define GCC_GP1_CLK 63 +#define GCC_GP2_CLK 64 +#define GCC_GP3_CLK 65 +#define GCC_MDSS_AHB_CLK 66 +#define GCC_MDSS_AXI_CLK 67 +#define GCC_MDSS_BYTE0_CLK 68 +#define GCC_MDSS_ESC0_CLK 69 +#define GCC_MDSS_HDMI_APP_CLK 70 +#define GCC_MDSS_HDMI_PCLK_CLK 71 +#define GCC_MDSS_MDP_CLK 72 +#define GCC_MDSS_PCLK0_CLK 73 +#define GCC_MDSS_VSYNC_CLK 74 +#define GCC_OXILI_AHB_CLK 75 +#define GCC_OXILI_GFX3D_CLK 76 +#define GCC_PCIE_0_AUX_CLK 77 +#define GCC_PCIE_0_CFG_AHB_CLK 78 +#define GCC_PCIE_0_MSTR_AXI_CLK 79 +#define GCC_PCIE_0_PIPE_CLK 80 +#define GCC_PCIE_0_SLV_AXI_CLK 81 +#define GCC_PCNOC_USB2_CLK 82 +#define GCC_PCNOC_USB3_CLK 83 +#define GCC_PDM2_CLK 84 +#define GCC_PDM_AHB_CLK 85 +#define VSYNC_CLK_SRC 86 +#define GCC_PRNG_AHB_CLK 87 +#define GCC_PWM0_XO512_CLK 88 +#define GCC_PWM1_XO512_CLK 89 +#define GCC_PWM2_XO512_CLK 90 +#define GCC_SDCC1_AHB_CLK 91 +#define GCC_SDCC1_APPS_CLK 92 +#define GCC_SDCC1_ICE_CORE_CLK 93 +#define GCC_SDCC2_AHB_CLK 94 +#define GCC_SDCC2_APPS_CLK 95 +#define GCC_SYS_NOC_USB3_CLK 96 +#define GCC_USB20_MOCK_UTMI_CLK 97 +#define GCC_USB2A_PHY_SLEEP_CLK 98 +#define GCC_USB30_MASTER_CLK 99 +#define GCC_USB30_MOCK_UTMI_CLK 100 +#define GCC_USB30_SLEEP_CLK 101 +#define GCC_USB3_PHY_AUX_CLK 102 +#define GCC_USB3_PHY_PIPE_CLK 103 +#define GCC_USB_HS_PHY_CFG_AHB_CLK 104 +#define GCC_USB_HS_SYSTEM_CLK 105 +#define GFX3D_CLK_SRC 106 +#define GP1_CLK_SRC 107 +#define GP2_CLK_SRC 108 +#define GP3_CLK_SRC 109 +#define HDMI_APP_CLK_SRC 110 +#define HDMI_PCLK_CLK_SRC 111 +#define MDP_CLK_SRC 112 +#define PCIE_0_AUX_CLK_SRC 113 +#define PCIE_0_PIPE_CLK_SRC 114 +#define PCLK0_CLK_SRC 115 +#define PDM2_CLK_SRC 116 +#define SDCC1_APPS_CLK_SRC 117 +#define SDCC1_ICE_CORE_CLK_SRC 118 +#define SDCC2_APPS_CLK_SRC 119 +#define USB20_MOCK_UTMI_CLK_SRC 120 +#define USB30_MASTER_CLK_SRC 121 +#define USB30_MOCK_UTMI_CLK_SRC 122 +#define USB3_PHY_AUX_CLK_SRC 123 +#define USB_HS_SYSTEM_CLK_SRC 124 +#define WCNSS_M_CLK 125 +#define GCC_USB_HS_INACTIVITY_TIMERS_CLK 126 #define MDSS_MDP_VOTE_CLK 127 #define MDSS_ROTATOR_VOTE_CLK 128 #define GCC_BIMC_GPU_CLK 129 -- GitLab From b89646bfdec65283223becaba531b81fe81bcb44 Mon Sep 17 00:00:00 2001 From: Maria Yu Date: Fri, 10 Nov 2017 11:05:58 +0800 Subject: [PATCH 0379/1299] cpufreq: schedutil: fix undefined reference to '__aeabi_uldivmod' Division of 64 bit variable isn't supported by the "/" operator in 32-bit architecture. So, use do_div() instead. Change-Id: Id07ce36166ee1ee88ff6519dc26724c4e847890b Signed-off-by: Maria Yu --- kernel/sched/cpufreq_schedutil.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index c53f5a3f2159..98739c5f55c4 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -153,7 +153,9 @@ static void sugov_track_cycles(struct sugov_policy *sg_policy, /* Track cycles in current window */ delta_ns = upto - sg_policy->last_cyc_update_time; - cycles = (prev_freq * delta_ns) / (NSEC_PER_SEC / KHZ); + delta_ns *= prev_freq; + do_div(delta_ns, (NSEC_PER_SEC / KHZ)); + cycles = delta_ns; sg_policy->curr_cycles += cycles; sg_policy->last_cyc_update_time = upto; } -- GitLab From d34dc1028dbe35f1d77839d4e7e6b0e7165d4756 Mon Sep 17 00:00:00 2001 From: Ramprasad Katkam Date: Fri, 15 Jun 2018 13:14:07 +0530 Subject: [PATCH 0380/1299] ARM: dts: msm: Add new file of audio port types for soundwire Add audio codec port types in new header required by soundwire interface to parse from soundwire device nodes. Change-Id: I2325b3a8d04aaa5e204ab7e51041329700156154 Signed-off-by: Ramprasad Katkam --- .../sound/audio-codec-port-types.h | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 include/dt-bindings/sound/audio-codec-port-types.h diff --git a/include/dt-bindings/sound/audio-codec-port-types.h b/include/dt-bindings/sound/audio-codec-port-types.h new file mode 100644 index 000000000000..aba5aa0ca7be --- /dev/null +++ b/include/dt-bindings/sound/audio-codec-port-types.h @@ -0,0 +1,33 @@ +#ifndef __AUDIO_CODEC_PORT_TYPES_H +#define __AUDIO_CODEC_PORT_TYPES_H + +enum codec_port_type { + SPKR_L = 1, + SPKR_L_BOOST, + SPKR_L_COMP, + SPKR_L_VI, + SPKR_R, + SPKR_R_BOOST, + SPKR_R_COMP, + SPKR_R_VI, + HPH, + COMPANDER, + CLSH, + LO, + DSD, + MBHC, + ADC1, + ADC2, + ADC3, + DMIC1, + DMIC2, + DMIC3, + DMIC4, + DMIC5, + DMIC6, + DMIC7, + DMIC8, + DMIC9, + DMIC10, +}; +#endif /* __AUDIO_CODEC_PORT_TYPES_H */ -- GitLab From 11ce89f0fb7052e25dd5a4a8d23017ff4abd934e Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Tue, 5 Jun 2018 18:14:47 +0530 Subject: [PATCH 0381/1299] ARM: dts: msm: Add device tree support for variants of qcs405 Add device tree files for various SKU versions of qcs405 and qcs403 SoCs. Also removing qcs405 mdp and cdp device tree files as they are not applicable. Change-Id: Ia2fd439a0fc80886b0135f7b36723560bdbda056 Signed-off-by: Avaneesh Kumar Dwivedi --- .../devicetree/bindings/arm/msm/msm.txt | 9 ++- arch/arm64/boot/dts/qcom/Makefile | 12 ++- arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts | 78 +++++++++++++++++++ arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts | 78 +++++++++++++++++++ .../dts/qcom/{qcs405-mtp.dtsi => qcs403.dtsi} | 7 ++ .../{qcs405-cdp.dtsi => qcs405-iot-sku1.dts} | 10 ++- .../{qcs405-cdp.dts => qcs405-iot-sku2.dts} | 11 +-- arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts | 22 ++++++ .../{qcs405-mtp.dts => qcs405-iot-sku4.dts} | 11 +-- arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts | 22 ++++++ arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts | 22 ++++++ arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts | 22 ++++++ arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts | 22 ++++++ 13 files changed, 304 insertions(+), 22 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts create mode 100644 arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts rename arch/arm64/boot/dts/qcom/{qcs405-mtp.dtsi => qcs403.dtsi} (83%) rename arch/arm64/boot/dts/qcom/{qcs405-cdp.dtsi => qcs405-iot-sku1.dts} (73%) rename arch/arm64/boot/dts/qcom/{qcs405-cdp.dts => qcs405-iot-sku2.dts} (74%) create mode 100644 arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts rename arch/arm64/boot/dts/qcom/{qcs405-mtp.dts => qcs405-iot-sku4.dts} (74%) create mode 100644 arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts create mode 100644 arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts create mode 100644 arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts create mode 100644 arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index 58c94abd503d..cf28eb84fe8a 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -53,6 +53,9 @@ SoCs: - QCS405 compatible = "qcom,qcs405" +- QCS403 + compatible = "qcom,qcs403" + - SDXPRAIRIE compatible = "qcom,sdxprairie" @@ -100,6 +103,8 @@ Generic board variants: - RUMI device: compatible = "qcom,rumi" +- IOT device: + compatible = "qcom,iot" Boards (SoC type + board variant): @@ -156,8 +161,8 @@ compatible = "qcom,sm6150-cdp" compatible = "qcom,sm6150-qrd" compatible = "qcom,sm6150-idp" compatible = "qcom,qcs405-rumi" -compatible = "qcom,qcs405-mtp" -compatible = "qcom,qcs405-cdp" +compatible = "qcom,qcs405-iot" +compatible = "qcom,qcs403-iot" compatible = "qcom,sm8150-auto-adp-star" compatible = "qcom,auto-adp-star" compatible = "qcom,sdxprairie-rumi" diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index bc3a97c3b241..d6e44ecc2ee1 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -7,8 +7,16 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8994-angler-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb dtb-$(CONFIG_ARCH_QCS405) += qcs405-rumi.dtb \ - qcs405-mtp.dtb \ - qcs405-cdp.dtb + qcs405-iot-sku1.dtb \ + qcs405-iot-sku2.dtb \ + qcs405-iot-sku3.dtb \ + qcs405-iot-sku4.dtb \ + qcs405-iot-sku5.dtb \ + qcs405-iot-sku6.dtb \ + qcs405-iot-sku7.dtb \ + qcs405-iot-sku8.dtb \ + qcs403-iot-sku1.dtb \ + qcs403-iot-sku2.dtb ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y) dtbo-$(CONFIG_ARCH_SM8150) += \ diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts new file mode 100644 index 000000000000..2bad4d66d940 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "qcs403.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCS403 EVB2 1000 IOT"; + compatible = "qcom,qcs403-iot", "qcom,qcs403", "qcom,iot"; + qcom,board-id = <0x010020 0x3>; + + cpus { + /delete-node/ cpu@102; + /delete-node/ cpu@103; + + cpu-map { + cluster1 { + /delete-node/ core2; + /delete-node/ core3; + }; + }; + }; +}; + +&soc { + cpuss_dump { + /delete-node/ qcom,l1_i_cache102; + /delete-node/ qcom,l1_i_cache103; + /delete-node/ qcom,l1_d_cache102; + /delete-node/ qcom,l1_d_cache103; + }; + + qcom,spm@b012000 { + qcom,cpu-vctl-list = <&CPU0 &CPU1>; + }; + + qcom,lpm-levels { + qcom,pm-cluster@0{ + qcom,pm-cpu { + qcom,cpu = <&CPU0 &CPU1>; + }; + }; + }; + + /delete-node/ cti@61ba000; + /delete-node/ cti@61bb000; + /delete-node/ etm@61be000; + /delete-node/ etm@61bf000; + funnel@61a1000 { + ports { + /delete-node/ port@3; + /delete-node/ port@4; + }; + }; +}; + +&thermal_zones { + cpuss-max-step { + cooling-maps { + /delete-node/ cpu2_cdev; + /delete-node/ cpu3_cdev; + }; + }; + + /delete-node/ cpuss-2-step; + /delete-node/ cpuss-3-step; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts new file mode 100644 index 000000000000..c97646be3e34 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "qcs403.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCS403 RCM IOT"; + compatible = "qcom,qcs403-iot", "qcom,qcs403", "qcom,iot"; + qcom,board-id = <0x010015 0x0>; + + cpus { + /delete-node/ cpu@102; + /delete-node/ cpu@103; + + cpu-map { + cluster1 { + /delete-node/ core2; + /delete-node/ core3; + }; + }; + }; +}; + +&soc { + cpuss_dump { + /delete-node/ qcom,l1_i_cache102; + /delete-node/ qcom,l1_i_cache103; + /delete-node/ qcom,l1_d_cache102; + /delete-node/ qcom,l1_d_cache103; + }; + + qcom,spm@b012000 { + qcom,cpu-vctl-list = <&CPU0 &CPU1>; + }; + + qcom,lpm-levels { + qcom,pm-cluster@0{ + qcom,pm-cpu { + qcom,cpu = <&CPU0 &CPU1>; + }; + }; + }; + + /delete-node/ cti@61ba000; + /delete-node/ cti@61bb000; + /delete-node/ etm@61be000; + /delete-node/ etm@61bf000; + funnel@61a1000 { + ports { + /delete-node/ port@3; + /delete-node/ port@4; + }; + }; +}; + +&thermal_zones { + cpuss-max-step { + cooling-maps { + /delete-node/ cpu2_cdev; + /delete-node/ cpu3_cdev; + }; + }; + + /delete-node/ cpuss-2-step; + /delete-node/ cpuss-3-step; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-mtp.dtsi b/arch/arm64/boot/dts/qcom/qcs403.dtsi similarity index 83% rename from arch/arm64/boot/dts/qcom/qcs405-mtp.dtsi rename to arch/arm64/boot/dts/qcom/qcs403.dtsi index 406c57cfa407..3cdbb7a533b2 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs403.dtsi @@ -10,4 +10,11 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ + #include "qcs405.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCS403"; + qcom,msm-name = "QCS403"; + qcom,msm-id = <373 0x0>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-cdp.dtsi b/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts similarity index 73% rename from arch/arm64/boot/dts/qcom/qcs405-cdp.dtsi rename to arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts index 2922b606d35a..ced1ff96533c 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-cdp.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts @@ -11,6 +11,12 @@ * GNU General Public License for more details. */ -&smb1351_otg_supply { - qcom,charging-disabled; +/dts-v1/; + +#include "qcs405.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCS405 EVB1 1000 IOT"; + compatible = "qcom,qcs405-iot", "qcom,qcs405", "qcom,iot"; + qcom,board-id = <0x010020 0>; }; diff --git a/arch/arm64/boot/dts/qcom/qcs405-cdp.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts similarity index 74% rename from arch/arm64/boot/dts/qcom/qcs405-cdp.dts rename to arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts index 3d36f2b018a1..43737c832578 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-cdp.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts @@ -14,14 +14,9 @@ /dts-v1/; #include "qcs405.dtsi" -#include "qcs405-cdp.dtsi" / { - model = "Qualcomm Technologies, Inc. QCS405 CDP"; - compatible = "qcom,qcs405-cdp", "qcom,qcs405", "qcom,cdp"; - qcom,board-id = <1 0>; -}; - -&qnand_1 { - status = "ok"; + model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 SPI IOT"; + compatible = "qcom,qcs405-iot", "qcom,qcs405", "qcom,iot"; + qcom,board-id = <0x010020 0x1>; }; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts new file mode 100644 index 000000000000..ba6c9c151a09 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "qcs405.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCS405 sEVB/SLT IOT"; + compatible = "qcom,qcs405-iot", "qcom,qcs405", "qcom,iot"; + qcom,board-id = <0x010020 0x2>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-mtp.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts similarity index 74% rename from arch/arm64/boot/dts/qcom/qcs405-mtp.dts rename to arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts index 7e7872d997aa..66393d820b73 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-mtp.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts @@ -14,14 +14,9 @@ /dts-v1/; #include "qcs405.dtsi" -#include "qcs405-mtp.dtsi" / { - model = "Qualcomm Technologies, Inc. QCS405 MTP"; - compatible = "qcom,qcs405-mtp", "qcom,qcs405", "qcom,mtp"; - qcom,board-id = <8 0>; -}; - -&qnand_1 { - status = "ok"; + model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 DSI IOT"; + compatible = "qcom,qcs405-iot", "qcom,qcs405", "qcom,iot"; + qcom,board-id = <0x020020 0x1>; }; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts new file mode 100644 index 000000000000..52144522045f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "qcs405.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 RGB IOT"; + compatible = "qcom,qcs405-iot", "qcom,qcs405", "qcom,iot"; + qcom,board-id = <0x030020 0x1>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts new file mode 100644 index 000000000000..9b5779b74132 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "qcs405.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 CSRA1 IOT"; + compatible = "qcom,qcs405-iot", "qcom,qcs405", "qcom,iot"; + qcom,board-id = <0x040020 0x1>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts new file mode 100644 index 000000000000..3be37a281726 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "qcs405.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 CSRA6 IOT"; + compatible = "qcom,qcs405-iot", "qcom,qcs405", "qcom,iot"; + qcom,board-id = <0x050020 0x1>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts new file mode 100644 index 000000000000..261cd8bc7051 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "qcs405.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 AMIC IOT"; + compatible = "qcom,qcs405-iot", "qcom,qcs405", "qcom,iot"; + qcom,board-id = <0x060020 0x1>; +}; -- GitLab From 63ec4410d808f1d08347ce74326dc3a809431e19 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Mon, 18 Jun 2018 17:26:09 +0530 Subject: [PATCH 0382/1299] defconfig: enable HAVE_LOW_MEMORY_KILLER on all s[d]m configs Enable HAVE_LOW_MEMORY_KILLER to avoid premature OOM kills on all configs for targets that can have a userspace or kernel lowmemorykiller. Change-Id: I2ba0148e0fa94ab5903a14c18005f7d550a593fc Signed-off-by: Vinayak Menon --- arch/arm64/configs/vendor/sdmshrike-perf_defconfig | 1 + arch/arm64/configs/vendor/sdmshrike_defconfig | 1 + arch/arm64/configs/vendor/sdmsteppe-perf_defconfig | 1 + arch/arm64/configs/vendor/sdmsteppe_defconfig | 1 + arch/arm64/configs/vendor/sm8150-auto-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150-auto_defconfig | 1 + arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + 8 files changed, 8 insertions(+) diff --git a/arch/arm64/configs/vendor/sdmshrike-perf_defconfig b/arch/arm64/configs/vendor/sdmshrike-perf_defconfig index 75a748c2e54b..23b8c69dfa56 100644 --- a/arch/arm64/configs/vendor/sdmshrike-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmshrike-perf_defconfig @@ -48,6 +48,7 @@ CONFIG_PREEMPT=y CONFIG_HZ_100=y CONFIG_CMA=y CONFIG_ZSMALLOC=y +CONFIG_HAVE_LOW_MEMORY_KILLER=y CONFIG_SECCOMP=y # CONFIG_HARDEN_BRANCH_PREDICTOR is not set CONFIG_ARMV8_DEPRECATED=y diff --git a/arch/arm64/configs/vendor/sdmshrike_defconfig b/arch/arm64/configs/vendor/sdmshrike_defconfig index 830f06dc204a..405f65c178c9 100644 --- a/arch/arm64/configs/vendor/sdmshrike_defconfig +++ b/arch/arm64/configs/vendor/sdmshrike_defconfig @@ -51,6 +51,7 @@ CONFIG_HZ_100=y CONFIG_CLEANCACHE=y CONFIG_CMA=y CONFIG_ZSMALLOC=y +CONFIG_HAVE_LOW_MEMORY_KILLER=y CONFIG_SECCOMP=y # CONFIG_HARDEN_BRANCH_PREDICTOR is not set CONFIG_ARMV8_DEPRECATED=y diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index e4e007d601ba..848991a01fff 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -62,6 +62,7 @@ CONFIG_PREEMPT=y CONFIG_HZ_100=y CONFIG_CMA=y CONFIG_ZSMALLOC=y +CONFIG_HAVE_LOW_MEMORY_KILLER=y CONFIG_SECCOMP=y # CONFIG_UNMAP_KERNEL_AT_EL0 is not set # CONFIG_HARDEN_BRANCH_PREDICTOR is not set diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index 696fde9ce5c8..fe9771ba4d28 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -65,6 +65,7 @@ CONFIG_HZ_100=y CONFIG_CLEANCACHE=y CONFIG_CMA=y CONFIG_ZSMALLOC=y +CONFIG_HAVE_LOW_MEMORY_KILLER=y CONFIG_SECCOMP=y # CONFIG_UNMAP_KERNEL_AT_EL0 is not set # CONFIG_HARDEN_BRANCH_PREDICTOR is not set diff --git a/arch/arm64/configs/vendor/sm8150-auto-perf_defconfig b/arch/arm64/configs/vendor/sm8150-auto-perf_defconfig index 1e5d70ac5ccc..7badb45b9a6f 100644 --- a/arch/arm64/configs/vendor/sm8150-auto-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-auto-perf_defconfig @@ -64,6 +64,7 @@ CONFIG_PREEMPT=y CONFIG_HZ_100=y CONFIG_CMA=y CONFIG_ZSMALLOC=y +CONFIG_HAVE_LOW_MEMORY_KILLER=y CONFIG_SECCOMP=y # CONFIG_UNMAP_KERNEL_AT_EL0 is not set # CONFIG_HARDEN_BRANCH_PREDICTOR is not set diff --git a/arch/arm64/configs/vendor/sm8150-auto_defconfig b/arch/arm64/configs/vendor/sm8150-auto_defconfig index 9077f3d381f7..d104e6c4a745 100644 --- a/arch/arm64/configs/vendor/sm8150-auto_defconfig +++ b/arch/arm64/configs/vendor/sm8150-auto_defconfig @@ -70,6 +70,7 @@ CONFIG_CLEANCACHE=y CONFIG_CMA=y CONFIG_CMA_DEBUGFS=y CONFIG_ZSMALLOC=y +CONFIG_HAVE_LOW_MEMORY_KILLER=y CONFIG_SECCOMP=y # CONFIG_UNMAP_KERNEL_AT_EL0 is not set # CONFIG_HARDEN_BRANCH_PREDICTOR is not set diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index f3de46c2cffb..23d0bfd8c6c0 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -64,6 +64,7 @@ CONFIG_PREEMPT=y CONFIG_HZ_100=y CONFIG_CMA=y CONFIG_ZSMALLOC=y +CONFIG_HAVE_LOW_MEMORY_KILLER=y CONFIG_SECCOMP=y # CONFIG_UNMAP_KERNEL_AT_EL0 is not set # CONFIG_HARDEN_BRANCH_PREDICTOR is not set diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index bf66033211a0..50894f35940c 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -70,6 +70,7 @@ CONFIG_CLEANCACHE=y CONFIG_CMA=y CONFIG_CMA_DEBUGFS=y CONFIG_ZSMALLOC=y +CONFIG_HAVE_LOW_MEMORY_KILLER=y CONFIG_SECCOMP=y # CONFIG_UNMAP_KERNEL_AT_EL0 is not set # CONFIG_HARDEN_BRANCH_PREDICTOR is not set -- GitLab From c28e8913f5a4dc9b9fe8915eaddb61022a68b6b8 Mon Sep 17 00:00:00 2001 From: Amit Nischal Date: Mon, 18 Jun 2018 16:03:02 +0530 Subject: [PATCH 0383/1299] clk: qcom: Update order of clocks registration Update the clock registration of PLLs before the branch and rcg clocks so as to avoid failure in getting parent rate during OPP table population. Thus update the clock references for the same. Change-Id: I4b1a92f54da8ee59a1012da0e2687355084eec7b Signed-off-by: Amit Nischal --- include/dt-bindings/clock/qcom,gcc-sm6150.h | 326 +++++++++--------- include/dt-bindings/clock/qcom,gpucc-sm6150.h | 22 +- .../dt-bindings/clock/qcom,videocc-sm6150.h | 25 +- 3 files changed, 186 insertions(+), 187 deletions(-) diff --git a/include/dt-bindings/clock/qcom,gcc-sm6150.h b/include/dt-bindings/clock/qcom,gcc-sm6150.h index cf08a333002d..ed98f1450084 100644 --- a/include/dt-bindings/clock/qcom,gcc-sm6150.h +++ b/include/dt-bindings/clock/qcom,gcc-sm6150.h @@ -22,171 +22,171 @@ #define MEASURE_ONLY_IPA_2X_CLK 4 /* GCC clock registers */ -#define GCC_AGGRE_UFS_PHY_AXI_CLK 5 -#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK 6 -#define GCC_AGGRE_USB2_SEC_AXI_CLK 7 -#define GCC_AGGRE_USB3_PRIM_AXI_CLK 8 -#define GCC_AHB2PHY_EAST_CLK 9 -#define GCC_AHB2PHY_WEST_CLK 10 -#define GCC_APC_VS_CLK 11 -#define GCC_BOOT_ROM_AHB_CLK 12 -#define GCC_CAMERA_AHB_CLK 13 -#define GCC_CAMERA_HF_AXI_CLK 14 -#define GCC_CE1_AHB_CLK 15 -#define GCC_CE1_AXI_CLK 16 -#define GCC_CE1_CLK 17 -#define GCC_CFG_NOC_USB2_SEC_AXI_CLK 18 -#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 19 -#define GCC_CPUSS_AHB_CLK 20 -#define GCC_CPUSS_AHB_CLK_SRC 21 -#define GCC_DDRSS_GPU_AXI_CLK 22 -#define GCC_DISP_AHB_CLK 23 -#define GCC_DISP_GPLL0_DIV_CLK_SRC 24 -#define GCC_DISP_HF_AXI_CLK 25 -#define GCC_EMAC_AXI_CLK 26 -#define GCC_EMAC_PTP_CLK 27 -#define GCC_EMAC_PTP_CLK_SRC 28 -#define GCC_EMAC_RGMII_CLK 29 -#define GCC_EMAC_RGMII_CLK_SRC 30 -#define GCC_EMAC_SLV_AHB_CLK 31 -#define GCC_GP1_CLK 32 -#define GCC_GP1_CLK_SRC 33 -#define GCC_GP2_CLK 34 -#define GCC_GP2_CLK_SRC 35 -#define GCC_GP3_CLK 36 -#define GCC_GP3_CLK_SRC 37 -#define GCC_GPU_CFG_AHB_CLK 38 -#define GCC_GPU_GPLL0_CLK_SRC 39 -#define GCC_GPU_GPLL0_DIV_CLK_SRC 40 -#define GCC_GPU_IREF_CLK 41 -#define GCC_GPU_MEMNOC_GFX_CLK 42 -#define GCC_GPU_SNOC_DVM_GFX_CLK 43 -#define GCC_MSS_AXIS2_CLK 44 -#define GCC_MSS_CFG_AHB_CLK 45 -#define GCC_MSS_GPLL0_DIV_CLK_SRC 46 -#define GCC_MSS_MFAB_AXIS_CLK 47 -#define GCC_MSS_Q6_MEMNOC_AXI_CLK 48 -#define GCC_MSS_SNOC_AXI_CLK 49 -#define GCC_MSS_VS_CLK 50 -#define GCC_PCIE0_PHY_REFGEN_CLK 51 -#define GCC_PCIE_0_AUX_CLK 52 -#define GCC_PCIE_0_AUX_CLK_SRC 53 -#define GCC_PCIE_0_CFG_AHB_CLK 54 -#define GCC_PCIE_0_CLKREF_CLK 55 -#define GCC_PCIE_0_MSTR_AXI_CLK 56 -#define GCC_PCIE_0_PIPE_CLK 57 -#define GCC_PCIE_0_SLV_AXI_CLK 58 -#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 59 -#define GCC_PCIE_PHY_AUX_CLK 60 -#define GCC_PCIE_PHY_REFGEN_CLK_SRC 61 -#define GCC_PDM2_CLK 62 -#define GCC_PDM2_CLK_SRC 63 -#define GCC_PDM_AHB_CLK 64 -#define GCC_PDM_XO4_CLK 65 -#define GCC_PRNG_AHB_CLK 66 -#define GCC_QMIP_CAMERA_NRT_AHB_CLK 67 -#define GCC_QMIP_DISP_AHB_CLK 68 -#define GCC_QMIP_PCIE_AHB_CLK 69 -#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 70 -#define GCC_QSPI_CNOC_PERIPH_AHB_CLK 71 -#define GCC_QSPI_CORE_CLK 72 -#define GCC_QSPI_CORE_CLK_SRC 73 -#define GCC_QUPV3_WRAP0_CORE_2X_CLK 74 -#define GCC_QUPV3_WRAP0_CORE_CLK 75 -#define GCC_QUPV3_WRAP0_S0_CLK 76 -#define GCC_QUPV3_WRAP0_S0_CLK_SRC 77 -#define GCC_QUPV3_WRAP0_S1_CLK 78 -#define GCC_QUPV3_WRAP0_S1_CLK_SRC 79 -#define GCC_QUPV3_WRAP0_S2_CLK 80 -#define GCC_QUPV3_WRAP0_S2_CLK_SRC 81 -#define GCC_QUPV3_WRAP0_S3_CLK 82 -#define GCC_QUPV3_WRAP0_S3_CLK_SRC 83 -#define GCC_QUPV3_WRAP0_S4_CLK 84 -#define GCC_QUPV3_WRAP0_S4_CLK_SRC 85 -#define GCC_QUPV3_WRAP0_S5_CLK 86 -#define GCC_QUPV3_WRAP0_S5_CLK_SRC 87 -#define GCC_QUPV3_WRAP1_CORE_2X_CLK 88 -#define GCC_QUPV3_WRAP1_CORE_CLK 89 -#define GCC_QUPV3_WRAP1_S0_CLK 90 -#define GCC_QUPV3_WRAP1_S0_CLK_SRC 91 -#define GCC_QUPV3_WRAP1_S1_CLK 92 -#define GCC_QUPV3_WRAP1_S1_CLK_SRC 93 -#define GCC_QUPV3_WRAP1_S2_CLK 94 -#define GCC_QUPV3_WRAP1_S2_CLK_SRC 95 -#define GCC_QUPV3_WRAP1_S3_CLK 96 -#define GCC_QUPV3_WRAP1_S3_CLK_SRC 97 -#define GCC_QUPV3_WRAP1_S4_CLK 98 -#define GCC_QUPV3_WRAP1_S4_CLK_SRC 99 -#define GCC_QUPV3_WRAP1_S5_CLK 100 -#define GCC_QUPV3_WRAP1_S5_CLK_SRC 101 -#define GCC_QUPV3_WRAP_0_M_AHB_CLK 102 -#define GCC_QUPV3_WRAP_0_S_AHB_CLK 103 -#define GCC_QUPV3_WRAP_1_M_AHB_CLK 104 -#define GCC_QUPV3_WRAP_1_S_AHB_CLK 105 -#define GCC_SDCC1_AHB_CLK 106 -#define GCC_SDCC1_APPS_CLK 107 -#define GCC_SDCC1_APPS_CLK_SRC 108 -#define GCC_SDCC1_ICE_CORE_CLK 109 -#define GCC_SDCC1_ICE_CORE_CLK_SRC 110 -#define GCC_SDCC2_AHB_CLK 111 -#define GCC_SDCC2_APPS_CLK 112 -#define GCC_SDCC2_APPS_CLK_SRC 113 -#define GCC_SYS_NOC_CPUSS_AHB_CLK 114 -#define GCC_UFS_CARD_CLKREF_CLK 115 -#define GCC_UFS_MEM_CLKREF_CLK 116 -#define GCC_UFS_PHY_AHB_CLK 117 -#define GCC_UFS_PHY_AXI_CLK 118 -#define GCC_UFS_PHY_AXI_CLK_SRC 119 -#define GCC_UFS_PHY_AXI_HW_CTL_CLK 120 -#define GCC_UFS_PHY_ICE_CORE_CLK 121 -#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 122 -#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK 123 -#define GCC_UFS_PHY_PHY_AUX_CLK 124 -#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 125 -#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK 126 -#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 127 -#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 128 -#define GCC_UFS_PHY_UNIPRO_CORE_CLK 129 -#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 130 -#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK 131 -#define GCC_USB20_SEC_MASTER_CLK 132 -#define GCC_USB20_SEC_MASTER_CLK_SRC 133 -#define GCC_USB20_SEC_MOCK_UTMI_CLK 134 -#define GCC_USB20_SEC_MOCK_UTMI_CLK_SRC 135 -#define GCC_USB20_SEC_SLEEP_CLK 136 -#define GCC_USB2_SEC_PHY_AUX_CLK 137 -#define GCC_USB2_SEC_PHY_AUX_CLK_SRC 138 -#define GCC_USB2_SEC_PHY_COM_AUX_CLK 139 -#define GCC_USB2_SEC_PHY_PIPE_CLK 140 -#define GCC_USB30_PRIM_MASTER_CLK 141 -#define GCC_USB30_PRIM_MASTER_CLK_SRC 142 -#define GCC_USB30_PRIM_MOCK_UTMI_CLK 143 -#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 144 -#define GCC_USB30_PRIM_SLEEP_CLK 145 -#define GCC_USB3_PRIM_CLKREF_CLK 146 -#define GCC_USB3_PRIM_PHY_AUX_CLK 147 -#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 148 -#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 149 -#define GCC_USB3_PRIM_PHY_PIPE_CLK 150 -#define GCC_USB3_SEC_CLKREF_CLK 151 -#define GCC_VDDA_VS_CLK 152 -#define GCC_VDDCX_VS_CLK 153 -#define GCC_VDDMX_VS_CLK 154 -#define GCC_VIDEO_AHB_CLK 155 -#define GCC_VIDEO_AXI0_CLK 156 -#define GCC_VS_CTRL_AHB_CLK 157 -#define GCC_VS_CTRL_CLK 158 -#define GCC_VS_CTRL_CLK_SRC 159 -#define GCC_VSENSOR_CLK_SRC 160 -#define GCC_WCSS_VS_CLK 161 -#define GPLL0_OUT_MAIN 162 -#define GPLL6_OUT_MAIN 163 -#define GPLL7_OUT_MAIN 164 -#define GPLL8_OUT_MAIN 165 +#define GPLL0_OUT_MAIN 5 +#define GPLL6_OUT_MAIN 6 +#define GPLL7_OUT_MAIN 7 +#define GPLL8_OUT_MAIN 8 +#define GCC_AGGRE_UFS_PHY_AXI_CLK 9 +#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK 10 +#define GCC_AGGRE_USB2_SEC_AXI_CLK 11 +#define GCC_AGGRE_USB3_PRIM_AXI_CLK 12 +#define GCC_AHB2PHY_EAST_CLK 13 +#define GCC_AHB2PHY_WEST_CLK 14 +#define GCC_APC_VS_CLK 15 +#define GCC_BOOT_ROM_AHB_CLK 16 +#define GCC_CAMERA_AHB_CLK 17 +#define GCC_CAMERA_HF_AXI_CLK 18 +#define GCC_CE1_AHB_CLK 19 +#define GCC_CE1_AXI_CLK 20 +#define GCC_CE1_CLK 21 +#define GCC_CFG_NOC_USB2_SEC_AXI_CLK 22 +#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 23 +#define GCC_CPUSS_AHB_CLK 24 +#define GCC_CPUSS_AHB_CLK_SRC 25 +#define GCC_DDRSS_GPU_AXI_CLK 26 +#define GCC_DISP_AHB_CLK 27 +#define GCC_DISP_GPLL0_DIV_CLK_SRC 28 +#define GCC_DISP_HF_AXI_CLK 29 +#define GCC_EMAC_AXI_CLK 30 +#define GCC_EMAC_PTP_CLK 31 +#define GCC_EMAC_PTP_CLK_SRC 32 +#define GCC_EMAC_RGMII_CLK 33 +#define GCC_EMAC_RGMII_CLK_SRC 34 +#define GCC_EMAC_SLV_AHB_CLK 35 +#define GCC_GP1_CLK 36 +#define GCC_GP1_CLK_SRC 37 +#define GCC_GP2_CLK 38 +#define GCC_GP2_CLK_SRC 39 +#define GCC_GP3_CLK 40 +#define GCC_GP3_CLK_SRC 41 +#define GCC_GPU_CFG_AHB_CLK 42 +#define GCC_GPU_GPLL0_CLK_SRC 43 +#define GCC_GPU_GPLL0_DIV_CLK_SRC 44 +#define GCC_GPU_IREF_CLK 45 +#define GCC_GPU_MEMNOC_GFX_CLK 46 +#define GCC_GPU_SNOC_DVM_GFX_CLK 47 +#define GCC_MSS_AXIS2_CLK 48 +#define GCC_MSS_CFG_AHB_CLK 49 +#define GCC_MSS_GPLL0_DIV_CLK_SRC 50 +#define GCC_MSS_MFAB_AXIS_CLK 51 +#define GCC_MSS_Q6_MEMNOC_AXI_CLK 52 +#define GCC_MSS_SNOC_AXI_CLK 53 +#define GCC_MSS_VS_CLK 54 +#define GCC_PCIE0_PHY_REFGEN_CLK 55 +#define GCC_PCIE_0_AUX_CLK 56 +#define GCC_PCIE_0_AUX_CLK_SRC 57 +#define GCC_PCIE_0_CFG_AHB_CLK 58 +#define GCC_PCIE_0_CLKREF_CLK 59 +#define GCC_PCIE_0_MSTR_AXI_CLK 60 +#define GCC_PCIE_0_PIPE_CLK 61 +#define GCC_PCIE_0_SLV_AXI_CLK 62 +#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 63 +#define GCC_PCIE_PHY_AUX_CLK 64 +#define GCC_PCIE_PHY_REFGEN_CLK_SRC 65 +#define GCC_PDM2_CLK 66 +#define GCC_PDM2_CLK_SRC 67 +#define GCC_PDM_AHB_CLK 68 +#define GCC_PDM_XO4_CLK 69 +#define GCC_PRNG_AHB_CLK 70 +#define GCC_QMIP_CAMERA_NRT_AHB_CLK 71 +#define GCC_QMIP_DISP_AHB_CLK 72 +#define GCC_QMIP_PCIE_AHB_CLK 73 +#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 74 +#define GCC_QSPI_CNOC_PERIPH_AHB_CLK 75 +#define GCC_QSPI_CORE_CLK 76 +#define GCC_QSPI_CORE_CLK_SRC 77 +#define GCC_QUPV3_WRAP0_CORE_2X_CLK 78 +#define GCC_QUPV3_WRAP0_CORE_CLK 79 +#define GCC_QUPV3_WRAP0_S0_CLK 80 +#define GCC_QUPV3_WRAP0_S0_CLK_SRC 81 +#define GCC_QUPV3_WRAP0_S1_CLK 82 +#define GCC_QUPV3_WRAP0_S1_CLK_SRC 83 +#define GCC_QUPV3_WRAP0_S2_CLK 84 +#define GCC_QUPV3_WRAP0_S2_CLK_SRC 85 +#define GCC_QUPV3_WRAP0_S3_CLK 86 +#define GCC_QUPV3_WRAP0_S3_CLK_SRC 87 +#define GCC_QUPV3_WRAP0_S4_CLK 88 +#define GCC_QUPV3_WRAP0_S4_CLK_SRC 89 +#define GCC_QUPV3_WRAP0_S5_CLK 90 +#define GCC_QUPV3_WRAP0_S5_CLK_SRC 91 +#define GCC_QUPV3_WRAP1_CORE_2X_CLK 92 +#define GCC_QUPV3_WRAP1_CORE_CLK 93 +#define GCC_QUPV3_WRAP1_S0_CLK 94 +#define GCC_QUPV3_WRAP1_S0_CLK_SRC 95 +#define GCC_QUPV3_WRAP1_S1_CLK 96 +#define GCC_QUPV3_WRAP1_S1_CLK_SRC 97 +#define GCC_QUPV3_WRAP1_S2_CLK 98 +#define GCC_QUPV3_WRAP1_S2_CLK_SRC 99 +#define GCC_QUPV3_WRAP1_S3_CLK 100 +#define GCC_QUPV3_WRAP1_S3_CLK_SRC 101 +#define GCC_QUPV3_WRAP1_S4_CLK 102 +#define GCC_QUPV3_WRAP1_S4_CLK_SRC 103 +#define GCC_QUPV3_WRAP1_S5_CLK 104 +#define GCC_QUPV3_WRAP1_S5_CLK_SRC 105 +#define GCC_QUPV3_WRAP_0_M_AHB_CLK 106 +#define GCC_QUPV3_WRAP_0_S_AHB_CLK 107 +#define GCC_QUPV3_WRAP_1_M_AHB_CLK 108 +#define GCC_QUPV3_WRAP_1_S_AHB_CLK 109 +#define GCC_SDCC1_AHB_CLK 110 +#define GCC_SDCC1_APPS_CLK 111 +#define GCC_SDCC1_APPS_CLK_SRC 112 +#define GCC_SDCC1_ICE_CORE_CLK 113 +#define GCC_SDCC1_ICE_CORE_CLK_SRC 114 +#define GCC_SDCC2_AHB_CLK 115 +#define GCC_SDCC2_APPS_CLK 116 +#define GCC_SDCC2_APPS_CLK_SRC 117 +#define GCC_SYS_NOC_CPUSS_AHB_CLK 118 +#define GCC_UFS_CARD_CLKREF_CLK 119 +#define GCC_UFS_MEM_CLKREF_CLK 120 +#define GCC_UFS_PHY_AHB_CLK 121 +#define GCC_UFS_PHY_AXI_CLK 122 +#define GCC_UFS_PHY_AXI_CLK_SRC 123 +#define GCC_UFS_PHY_AXI_HW_CTL_CLK 124 +#define GCC_UFS_PHY_ICE_CORE_CLK 125 +#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 126 +#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK 127 +#define GCC_UFS_PHY_PHY_AUX_CLK 128 +#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 129 +#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK 130 +#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 131 +#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 132 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK 133 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 134 +#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK 135 +#define GCC_USB20_SEC_MASTER_CLK 136 +#define GCC_USB20_SEC_MASTER_CLK_SRC 137 +#define GCC_USB20_SEC_MOCK_UTMI_CLK 138 +#define GCC_USB20_SEC_MOCK_UTMI_CLK_SRC 139 +#define GCC_USB20_SEC_SLEEP_CLK 140 +#define GCC_USB2_SEC_PHY_AUX_CLK 141 +#define GCC_USB2_SEC_PHY_AUX_CLK_SRC 142 +#define GCC_USB2_SEC_PHY_COM_AUX_CLK 143 +#define GCC_USB2_SEC_PHY_PIPE_CLK 144 +#define GCC_USB30_PRIM_MASTER_CLK 145 +#define GCC_USB30_PRIM_MASTER_CLK_SRC 146 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK 147 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 148 +#define GCC_USB30_PRIM_SLEEP_CLK 149 +#define GCC_USB3_PRIM_CLKREF_CLK 150 +#define GCC_USB3_PRIM_PHY_AUX_CLK 151 +#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 152 +#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 153 +#define GCC_USB3_PRIM_PHY_PIPE_CLK 154 +#define GCC_USB3_SEC_CLKREF_CLK 155 +#define GCC_VDDA_VS_CLK 156 +#define GCC_VDDCX_VS_CLK 157 +#define GCC_VDDMX_VS_CLK 158 +#define GCC_VIDEO_AHB_CLK 159 +#define GCC_VIDEO_AXI0_CLK 160 +#define GCC_VS_CTRL_AHB_CLK 161 +#define GCC_VS_CTRL_CLK 162 +#define GCC_VS_CTRL_CLK_SRC 163 +#define GCC_VSENSOR_CLK_SRC 164 +#define GCC_WCSS_VS_CLK 165 #define GCC_CAMERA_XO_CLK 166 #define GCC_CPUSS_GNOC_CLK 167 -#define GCC_DISP_XO_CLK 166 -#define GCC_VIDEO_XO_CLK 166 +#define GCC_DISP_XO_CLK 168 +#define GCC_VIDEO_XO_CLK 169 /* GCC Resets */ #define GCC_QUSB2PHY_PRIM_BCR 0 diff --git a/include/dt-bindings/clock/qcom,gpucc-sm6150.h b/include/dt-bindings/clock/qcom,gpucc-sm6150.h index 33c9975f6838..405f6dd09e69 100644 --- a/include/dt-bindings/clock/qcom,gpucc-sm6150.h +++ b/include/dt-bindings/clock/qcom,gpucc-sm6150.h @@ -15,17 +15,17 @@ #define _DT_BINDINGS_CLK_QCOM_GPU_CC_SM6150_H /* GPUCC clock registers */ -#define GPU_CC_CRC_AHB_CLK 0 -#define GPU_CC_CX_APB_CLK 1 -#define GPU_CC_CX_GFX3D_CLK 2 -#define GPU_CC_CX_GFX3D_SLV_CLK 3 -#define GPU_CC_CX_GMU_CLK 4 -#define GPU_CC_CX_SNOC_DVM_CLK 5 -#define GPU_CC_CXO_AON_CLK 6 -#define GPU_CC_CXO_CLK 7 -#define GPU_CC_GMU_CLK_SRC 8 -#define GPU_CC_PLL0_OUT_AUX2 9 -#define GPU_CC_PLL1_OUT_AUX2 10 +#define GPU_CC_PLL0_OUT_AUX2 0 +#define GPU_CC_PLL1_OUT_AUX2 1 +#define GPU_CC_CRC_AHB_CLK 2 +#define GPU_CC_CX_APB_CLK 3 +#define GPU_CC_CX_GFX3D_CLK 4 +#define GPU_CC_CX_GFX3D_SLV_CLK 5 +#define GPU_CC_CX_GMU_CLK 6 +#define GPU_CC_CX_SNOC_DVM_CLK 7 +#define GPU_CC_CXO_AON_CLK 8 +#define GPU_CC_CXO_CLK 9 +#define GPU_CC_GMU_CLK_SRC 10 #define GPU_CC_SLEEP_CLK 11 #define GPU_CC_GX_GMU_CLK 12 #define GPU_CC_GX_CXO_CLK 13 diff --git a/include/dt-bindings/clock/qcom,videocc-sm6150.h b/include/dt-bindings/clock/qcom,videocc-sm6150.h index 0d911e44f2f8..c7fff1475c18 100644 --- a/include/dt-bindings/clock/qcom,videocc-sm6150.h +++ b/include/dt-bindings/clock/qcom,videocc-sm6150.h @@ -18,18 +18,17 @@ #define CHIP_SLEEP_CLK 0 /* VIDEOCC clock registers */ -#define VIDEO_CC_APB_CLK 1 -#define VIDEO_CC_SLEEP_CLK 2 -#define VIDEO_CC_SLEEP_CLK_SRC 3 -#define VIDEO_CC_VCODEC0_AXI_CLK 4 -#define VIDEO_CC_VCODEC0_CORE_CLK 5 -#define VIDEO_CC_VENUS_AHB_CLK 6 -#define VIDEO_CC_VENUS_CLK_SRC 7 -#define VIDEO_CC_VENUS_CTL_AXI_CLK 8 -#define VIDEO_CC_VENUS_CTL_CORE_CLK 9 -#define VIDEO_CC_XO_CLK 10 -#define VIDEO_CC_XO_CLK_SRC 11 -#define VIDEO_PLL0 12 -#define VIDEO_PLL0_OUT_MAIN 13 +#define VIDEO_PLL0_OUT_MAIN 1 +#define VIDEO_CC_APB_CLK 2 +#define VIDEO_CC_SLEEP_CLK 3 +#define VIDEO_CC_SLEEP_CLK_SRC 4 +#define VIDEO_CC_VCODEC0_AXI_CLK 5 +#define VIDEO_CC_VCODEC0_CORE_CLK 6 +#define VIDEO_CC_VENUS_AHB_CLK 7 +#define VIDEO_CC_VENUS_CLK_SRC 8 +#define VIDEO_CC_VENUS_CTL_AXI_CLK 9 +#define VIDEO_CC_VENUS_CTL_CORE_CLK 10 +#define VIDEO_CC_XO_CLK 11 +#define VIDEO_CC_XO_CLK_SRC 12 #endif -- GitLab From acc14a6de04a849c8fbc51ffa0abdd8cdd62746a Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Thu, 14 Jun 2018 19:40:18 -0700 Subject: [PATCH 0384/1299] sched/boost: provide helper api for boost on big Currently the two callsites check if a task has sched boost enabled and if the boost policy is "boost on big". Provide a helper api to do the needful checks. This will further help with improving colocation boost in the upcoming patch. Change-Id: Ia55e4fe6cae66d7c7883f8a3c0a5d851a7917fc8 Signed-off-by: Abhijeet Dharmapurikar --- kernel/sched/fair.c | 4 +--- kernel/sched/sched.h | 13 +++++++++++++ kernel/sched/walt.c | 4 +--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 3ace54a93c45..858db66cc719 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6999,9 +6999,7 @@ static inline bool task_fits_max(struct task_struct *p, int cpu) if (capacity == max_capacity) return true; - if (sched_boost_policy() == SCHED_BOOST_ON_BIG && - task_sched_boost(p) && - is_min_capacity_cpu(cpu)) + if (task_boost_on_big_eligible(p) && is_min_capacity_cpu(cpu)) return false; return task_fits_capacity(p, capacity, cpu); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 9a537b5fea80..e425ccba8d6e 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2899,6 +2899,14 @@ static inline bool task_placement_boost_enabled(struct task_struct *p) return false; } +static inline bool task_boost_on_big_eligible(struct task_struct *p) +{ + bool boost_on_big = task_sched_boost(p) && + sched_boost_policy() == SCHED_BOOST_ON_BIG; + + return boost_on_big; +} + #else /* CONFIG_SCHED_WALT */ struct walt_sched_stats; @@ -2915,6 +2923,11 @@ static inline bool task_placement_boost_enabled(struct task_struct *p) return false; } +static inline bool task_boost_on_big_eligible(struct task_struct *p) +{ + return false; +} + static inline void check_for_migration(struct rq *rq, struct task_struct *p) { } static inline int sched_boost(void) diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c index 22b0419eae05..3efbef67e0b8 100644 --- a/kernel/sched/walt.c +++ b/kernel/sched/walt.c @@ -2529,7 +2529,6 @@ static void _set_preferred_cluster(struct related_thread_group *grp) { struct task_struct *p; u64 combined_demand = 0; - bool boost_on_big = sched_boost_policy() == SCHED_BOOST_ON_BIG; bool group_boost = false; u64 wallclock; @@ -2548,7 +2547,7 @@ static void _set_preferred_cluster(struct related_thread_group *grp) return; list_for_each_entry(p, &grp->tasks, grp_list) { - if (boost_on_big && task_sched_boost(p)) { + if (task_boost_on_big_eligible(p)) { group_boost = true; break; } @@ -2558,7 +2557,6 @@ static void _set_preferred_cluster(struct related_thread_group *grp) continue; combined_demand += p->ravg.coloc_demand; - } grp->preferred_cluster = best_cluster(grp, -- GitLab From 2ca21c7039fdb53ad9710c2a87f6c02922526c88 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Fri, 15 Jun 2018 10:39:10 -0700 Subject: [PATCH 0385/1299] msm: ipa: disable status for WAN_PROD on SSR Disable status for WAN_PROD pipe as part of SSR cleanup to make sure all status packets to modem are dropped. Change-Id: I2bfee024fc7ca664ea2aa1b1cb7a7491cb6e00e8 Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 6dc9075b18a9..404bb355e661 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -2582,9 +2582,12 @@ static int ipa3_q6_set_ex_path_to_apps(void) /* disable statuses for all modem controlled prod pipes */ if (IPA_CLIENT_IS_Q6_PROD(client_idx) || (ipa3_ctx->ep[ep_idx].valid && - ipa3_ctx->ep[ep_idx].skip_ep_cfg)) { + ipa3_ctx->ep[ep_idx].skip_ep_cfg) || + (ipa3_ctx->ep[ep_idx].client == IPA_CLIENT_APPS_WAN_PROD + && ipa3_ctx->modem_cfg_emb_pipe_flt)) { ipa_assert_on(num_descs >= ipa3_ctx->ipa_num_pipes); + ipa3_ctx->ep[ep_idx].status.status_en = false; reg_write.skip_pipeline_clear = false; reg_write.pipeline_clear_options = IPAHAL_HPS_CLEAR; -- GitLab From ac643925381ed205fa21387ebfeab22bbcf71871 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Mon, 11 Jun 2018 13:21:20 +0530 Subject: [PATCH 0386/1299] msm: ADSPRPC: Unmap remote heap buffer only for ADSP SSR Unmap remote heap buffer only for ADSP SSR, as remote heap feature is available only on ADSP. Change-Id: I9abff20cfdcc4588a3a377e73d38d3ea91316d25 Acked-by: Himateja Reddy Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index f0c6fc1fe1c1..4d1f43bcef9c 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2673,7 +2673,7 @@ static int fastrpc_channel_open(struct fastrpc_file *fl) pr_info("'opened /dev/%s c %d %d'\n", gcinfo[cid].name, MAJOR(me->dev_no), cid); - if (me->channel[cid].ssrcount != + if (cid == ADSP_DOMAIN_ID && me->channel[cid].ssrcount != me->channel[cid].prevssrcount) { mutex_lock(&fl->map_mutex); if (fastrpc_mmap_remove_ssr(fl)) -- GitLab From bb1aeff9d4f3a5be915852fdd7882899b51e1de8 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 14 Jun 2018 17:58:58 -0700 Subject: [PATCH 0387/1299] xhci: Fix use-after-free in xhci_free_virt_device KASAN found a use-after-free in xhci_free_virt_device+0x33b/0x38e where xhci_free_virt_device() sets slot id to 0 if udev exists: if (dev->udev && dev->udev->slot_id) dev->udev->slot_id = 0; dev->udev will be true even if udev is freed because dev->udev is not set to NULL. set dev->udev pointer to NULL in xhci_free_dev() The original patch went to stable so this fix needs to be applied there as well. Fixes: a400efe455f7 ("xhci: zero usb device slot_id member when disabling and freeing a xhci slot") Cc: Reported-by: Guenter Roeck Reviewed-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman Git-commit: 44a182b9d17765514fa2b1cc911e4e65134eef93 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [hemantk@codeaurora.org: resolved merge conflict] Signed-off-by: Hemant Kumar Change-Id: I507d8439de007b3df6728f77407a4aee51463913 --- drivers/usb/host/xhci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7dbc66fb514f..83d54232ebc7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3559,6 +3559,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); } + virt_dev->udev = NULL; xhci_disable_slot(xhci, udev->slot_id); /* * Event command completion handler will free any data structures -- GitLab From 4fd836ae966b73a50fe97b8c829c61dea6c61459 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Mon, 18 Jun 2018 11:55:52 -0700 Subject: [PATCH 0388/1299] Revert "msm: ipa4: fix client register and deregister for usb" This reverts commit 5dd14bdd2079f594a17083c3e30d6e1f5dafe275. Change-Id: I7e1d9da350ffd9cbb688153e019c322d6a53a2b0 Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa_pm.c | 9 ++++----- drivers/platform/msm/ipa/ipa_v3/ipa_pm.h | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c index 34065cf8c2ed..bffadfb7147e 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c @@ -242,7 +242,7 @@ static int calculate_throughput(void) struct ipa_pm_client *client; /* Create a basic array to hold throughputs*/ - for (i = 1, n = 0; i < IPA_PM_MAX_CLIENTS; i++) { + for (i = 0, n = 0; i < IPA_PM_MAX_CLIENTS; i++) { client = ipa_pm_ctx->clients[i]; if (client != NULL && IPA_PM_STATE_ACTIVE(client->state)) { /* default case */ @@ -498,8 +498,7 @@ static int find_next_open_array_element(const char *name) n = -ENOBUFS; - /* 0 is not a valid handle */ - for (i = IPA_PM_MAX_CLIENTS - 1; i >= 1; i--) { + for (i = IPA_PM_MAX_CLIENTS - 1; i >= 0; i--) { if (ipa_pm_ctx->clients[i] == NULL) { n = i; continue; @@ -1064,7 +1063,7 @@ int ipa_pm_deactivate_all_deferred(void) return -EINVAL; } - for (i = 1; i < IPA_PM_MAX_CLIENTS; i++) { + for (i = 0; i < IPA_PM_MAX_CLIENTS; i++) { client = ipa_pm_ctx->clients[i]; if (client == NULL) @@ -1305,7 +1304,7 @@ int ipa_pm_stat(char *buf, int size) cnt += result; - for (i = 1; i < IPA_PM_MAX_CLIENTS; i++) { + for (i = 0; i < IPA_PM_MAX_CLIENTS; i++) { client = ipa_pm_ctx->clients[i]; if (client == NULL) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h index 47a03f938243..38e082f35e6f 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,7 +16,7 @@ #include /* internal to ipa */ -#define IPA_PM_MAX_CLIENTS 32 /* actual max is value -1 since we start from 1*/ +#define IPA_PM_MAX_CLIENTS 12 /* actual max is value -1 since we start from 1*/ #define IPA_PM_MAX_EX_CL 64 #define IPA_PM_THRESHOLD_MAX 5 #define IPA_PM_EXCEPTION_MAX 2 -- GitLab From 3737f09ac66f7efa8d1858fb8a4b32fb4d3d3ccd Mon Sep 17 00:00:00 2001 From: Yuan Zhao Date: Thu, 31 May 2018 14:36:10 +0800 Subject: [PATCH 0389/1299] ARM: dts: msm: Add FHD panel support for QRD SM8150 This panel DDIC also support FHD+ scaler to WQHD, so add the support configurate for QRD device. Change-Id: Ie139cc0ee193c941a4043d4ae676f7f363d4333f Signed-off-by: Yuan Zhao --- ...panel-sw43404-amoled-dsc-fhd-plus-cmd.dtsi | 106 ++++++++++++++++++ arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi | 12 ++ .../boot/dts/qcom/sm8150-sde-display.dtsi | 26 ++++- 3 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-fhd-plus-cmd.dtsi diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-fhd-plus-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-fhd-plus-cmd.dtsi new file mode 100644 index 000000000000..553ba0bac78a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-fhd-plus-cmd.dtsi @@ -0,0 +1,106 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_sw43404_amoled_fhd_plus_cmd: qcom,mdss_dsi_sw43404_fhd_plus_cmd { + qcom,mdss-dsi-panel-name = + "sw43404 amoled boe fhd+ panel with DSC"; + qcom,mdss-dsi-panel-type = "dsi_cmd_mode"; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-color-order = "rgb_swap_rgb"; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + + qcom,mdss-dsi-traffic-mode = "non_burst_sync_event"; + qcom,mdss-dsi-lane-map = "lane_map_0123"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,mdss-dsi-bl-max-level = <1023>; + qcom,mdss-dsi-te-pin-select = <1>; + qcom,mdss-dsi-wr-mem-start = <0x2c>; + qcom,mdss-dsi-wr-mem-continue = <0x3c>; + qcom,mdss-dsi-te-dcs-command = <1>; + qcom,mdss-dsi-te-check-enable; + qcom,mdss-dsi-te-using-te-pin; + qcom,mdss-pan-physical-width-dimension = <68>; + qcom,mdss-pan-physical-height-dimension = <138>; + + qcom,mdss-dsi-display-timings { + timing@0{ + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <2160>; + qcom,mdss-dsi-h-front-porch = <160>; + qcom,mdss-dsi-h-back-porch = <72>; + qcom,mdss-dsi-h-pulse-width = <16>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-h-sync-pulse = <0>; + qcom,mdss-dsi-v-back-porch = <8>; + qcom,mdss-dsi-v-front-porch = <8>; + qcom,mdss-dsi-v-pulse-width = <1>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-panel-jitter = <0x1 0x1>; + qcom,mdss-dsi-on-command = [ + 39 01 00 00 00 00 03 b0 a5 00 + 07 01 00 00 00 00 02 01 00 + 0a 01 00 00 00 00 80 11 00 00 89 30 80 + 08 70 04 38 02 1c 02 1c 02 1c 02 00 + 02 0e 00 20 34 29 00 07 00 0C 00 2e + 00 31 18 00 10 F0 03 0C 20 00 06 0B + 0B 33 0E 1C 2A 38 46 54 62 69 70 77 + 79 7B 7D 7E 01 02 01 00 09 40 09 BE + 19 FC 19 FA 19 F8 1A 38 1A 78 1A B6 + 2A F6 2B 34 2B 74 3B 74 6B F4 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 + 39 01 00 00 00 00 03 b0 a5 00 + 15 01 00 00 00 00 02 5e 10 + 39 01 00 00 00 00 06 b9 bf 11 40 00 30 + 39 01 00 00 00 00 09 F8 00 08 10 08 2D + 00 00 2D + 15 01 00 00 00 00 02 55 0c + 05 01 00 00 1e 00 02 11 00 + 15 01 00 00 78 00 02 3d 01 + 39 01 00 00 00 00 03 b0 a5 00 + 05 01 00 00 78 00 02 35 00 + 05 01 00 00 3c 00 02 29 00 + ]; + qcom,mdss-dsi-off-command = [ + 05 01 00 00 14 00 02 28 00 + 05 01 00 00 78 00 02 10 00]; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + qcom,compression-mode = "dsc"; + qcom,mdss-dsc-slice-height = <540>; + qcom,mdss-dsc-slice-width = <540>; + qcom,mdss-dsc-slice-per-pkt = <1>; + qcom,mdss-dsc-bit-per-component = <8>; + qcom,mdss-dsc-bit-per-pixel = <8>; + qcom,mdss-dsc-block-prediction-enable; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi index fb880952c6e2..24a779335c17 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi @@ -191,6 +191,18 @@ qcom,platform-reset-gpio = <&tlmm 6 0>; }; +&dsi_sw43404_amoled_fhd_plus_cmd { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply_vdd_no_labibb>; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-brightness-max-level = <1023>; + qcom,mdss-dsi-mode-sel-gpio-state = "single_port"; + qcom,panel-mode-gpio = <&tlmm 7 0>; + qcom,platform-te-gpio = <&tlmm 8 0>; + qcom,platform-reset-gpio = <&tlmm 6 0>; +}; + &dsi_sw43404_amoled_cmd_display { qcom,dsi-display-active; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi index 8f04799b24d9..38a805f27487 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi @@ -29,6 +29,7 @@ #include "dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi" #include "dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi" #include "dsi-panel-sw43404-amoled-dsc-wqhd-video.dtsi" +#include "dsi-panel-sw43404-amoled-dsc-fhd-plus-cmd.dtsi" #include &tlmm { @@ -333,6 +334,17 @@ qcom,dsi-panel = <&dsi_sw43404_amoled_video>; }; + dsi_sw43404_amoled_fhd_plus_cmd_display: qcom,dsi-display@18 { + label = "dsi_sw43404_amoled_fhd_plus_cmd_display"; + qcom,display-type = "primary"; + + qcom,dsi-ctrl-num = <0>; + qcom,dsi-phy-num = <0>; + qcom,dsi-select-clocks = "src_byte_clk0", "src_pixel_clk0"; + + qcom,dsi-panel = <&dsi_sw43404_amoled_fhd_plus_cmd>; + }; + sde_dsi: qcom,dsi-display { compatible = "qcom,dsi-display"; @@ -375,7 +387,8 @@ &dsi_sw43404_amoled_cmd_display &dsi_nt35695b_truly_fhd_cmd_display &dsi_nt35695b_truly_fhd_video_display - &dsi_sw43404_amoled_video_display>; + &dsi_sw43404_amoled_video_display + &dsi_sw43404_amoled_fhd_plus_cmd_display>; }; sde_wb: qcom,wb-display@0 { @@ -676,6 +689,17 @@ }; }; +&dsi_sw43404_amoled_fhd_plus_cmd { + qcom,mdss-dsi-display-timings { + timing@0 { + qcom,mdss-dsi-panel-phy-timings = [00 12 04 04 1e 1e 04 + 05 02 03 04 00 11 14]; + qcom,display-topology = <2 2 1>; + qcom,default-topology-index = <0>; + }; + }; +}; + &dsi_sw43404_amoled_video { qcom,mdss-dsi-display-timings { timing@0 { -- GitLab From 7eec0871e04f40773d0ed71b45638d70012b1202 Mon Sep 17 00:00:00 2001 From: Raghavendra Rao Ananta Date: Mon, 18 Jun 2018 14:20:19 -0700 Subject: [PATCH 0390/1299] ARM: dts: msm: Fix incorrect device-tree pickup for SM8150+SDX50 Due to the addition of a recent change (9fcd7689), the target platform always picks up the sm8150+sdx50 2.5k display device tree, even for a 4k display panel. Hence, with this fix, the platform picks up the correct corresponding device tree for the platform. Change-Id: If2538b48e8046d61727e7a138a896bc245993133 Signed-off-by: Raghavendra Rao Ananta --- .../boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts | 2 +- arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-overlay.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts index 4e590ea853d3..aa14b2923e77 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-2.5k-panel-overlay.dts @@ -26,5 +26,5 @@ / { model = "SDX50M 2.5k panel MTP"; compatible = "qcom,sm8150-mtp", "qcom,sm8150", "qcom,mtp"; - qcom,board-id = <0x01010008 0x1>; + qcom,board-id = <0x01010108 0x1>; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-overlay.dts index 84ae64fe701f..834f7c095d97 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-mtp-overlay.dts @@ -26,5 +26,5 @@ / { model = "SDX50M MTP"; compatible = "qcom,sm8150-mtp", "qcom,sm8150", "qcom,mtp"; - qcom,board-id = <8 1>; + qcom,board-id = <0x01010008 0x1>; }; -- GitLab From dca6f43af1ab4585f6b4ed33da441044edf9ff24 Mon Sep 17 00:00:00 2001 From: Jayant Shekhar Date: Fri, 4 May 2018 10:55:15 +0530 Subject: [PATCH 0391/1299] drm/msm/sde: Correct vblank ref count in case of failures If register IRQ fails, correct vblank ref counts so that IRQ registration can be tried again. Change-Id: I4bc0864f182da6ef1a8f1ab5e36892d8201b1195 Signed-off-by: Jayant Shekhar --- drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index ea0fb886776f..c97e4f1e1bdd 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -667,11 +667,17 @@ static int sde_encoder_phys_vid_control_vblank_irq( SDE_EVT32(DRMID(phys_enc->parent), enable, atomic_read(&phys_enc->vblank_refcount)); - if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) + if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) { ret = sde_encoder_helper_register_irq(phys_enc, INTR_IDX_VSYNC); - else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0) + if (ret) + atomic_dec_return(&phys_enc->vblank_refcount); + } else if (!enable && + atomic_dec_return(&phys_enc->vblank_refcount) == 0) { ret = sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_VSYNC); + if (ret) + atomic_inc_return(&phys_enc->vblank_refcount); + } end: if (ret) { -- GitLab From 93b3dc3d4041ffdc63bf70bd8a73ce2e88aca245 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Wed, 2 Aug 2017 17:55:23 -0700 Subject: [PATCH 0392/1299] msm: gsi: check channel state on timeout In some cases of stopping a channel, the CH CTRL interrupt arrives late even though the channel is already stopped. This change will check the channel state after timeout occurs. CRs-Fixed: 2090459 Change-Id: I4b99e8fb6710dca16047025a614fb734995934a1 Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/gsi/gsi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 9906e19c9db3..d5cc4ece49cf 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -2216,6 +2216,20 @@ int gsi_stop_channel(unsigned long chan_hdl) res = wait_for_completion_timeout(&ctx->compl, msecs_to_jiffies(GSI_STOP_CMD_TIMEOUT_MS)); if (res == 0) { + /* + * check channel state here in case the channel is stopped but + * the interrupt was not handled yet. + */ + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(chan_hdl, + gsi_ctx->per.ee)); + ctx->state = (val & + GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_BMSK) >> + GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT; + if (ctx->state == GSI_CHAN_STATE_STOPPED) { + res = GSI_STATUS_SUCCESS; + goto free_lock; + } GSIDBG("chan_hdl=%lu timed out\n", chan_hdl); res = -GSI_STATUS_TIMED_OUT; goto free_lock; -- GitLab From 1657f2b2d9fcf0d614aafb718b62f9fb2684b789 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Fri, 15 Jun 2018 10:33:26 -0700 Subject: [PATCH 0393/1299] msm: ipa3: fix the fast_map issue Currently ipa AP-CB always enables fast_map flag when calling smmu API. Make fix to enable it when IPA dtsi specifies fast_map flag. CRs-Fixed: 2261733 Change-Id: I325ead58b6873f798af14ffe2182aa48a008141d Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index d5633a179a1b..fa2edff56ede 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -6266,15 +6266,17 @@ static int ipa_smmu_ap_cb_probe(struct device *dev) } IPADBG("AP/USB SMMU atomic set\n"); - if (iommu_domain_set_attr(cb->mapping->domain, + if (smmu_info.fast_map) { + if (iommu_domain_set_attr(cb->mapping->domain, DOMAIN_ATTR_FAST, &fast)) { - IPAERR("couldn't set fast map\n"); - arm_iommu_release_mapping(cb->mapping); - cb->valid = false; - return -EIO; + IPAERR("couldn't set fast map\n"); + arm_iommu_release_mapping(cb->mapping); + cb->valid = false; + return -EIO; + } + IPADBG("SMMU fast map set\n"); } - IPADBG("SMMU fast map set\n"); } pr_info("IPA smmu_info.s1_bypass_arr[AP]=%d smmu_info.fast_map=%d\n", -- GitLab From 672987410e46c729ff57db9af6c8def0114fcc15 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Fri, 15 Jun 2018 07:49:23 +0800 Subject: [PATCH 0394/1299] input: qti-haptics: Add a timer to stop playing when the time expired Currently, when VMAX waveform source is chosen, the haptics would not stop playing when playing timer is expired, it requires an explicit calling with playback(0) to stop it. Add a timer to stop it when the playing time is expired. This is not required when playing BUFFER waveform source because haptics would stop playing after the pattern is played. Change-Id: I64659ea95478319cc39148443a229bcf56ad168c Signed-off-by: Fenglin Wu --- drivers/input/misc/qti-haptics.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/input/misc/qti-haptics.c b/drivers/input/misc/qti-haptics.c index ad9dd51f66ba..d63ced793719 100644 --- a/drivers/input/misc/qti-haptics.c +++ b/drivers/input/misc/qti-haptics.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -213,6 +214,7 @@ struct qti_hap_chip { struct qti_hap_effect *predefined; struct qti_hap_effect constant; struct regulator *vdd_supply; + struct hrtimer stop_timer; spinlock_t bus_lock; ktime_t last_sc_time; int play_irq; @@ -901,6 +903,8 @@ static int qti_haptics_playback(struct input_dev *dev, int effect_id, int val) { struct qti_hap_chip *chip = input_get_drvdata(dev); struct qti_hap_play_info *play = &chip->play; + s64 secs; + unsigned long nsecs; int rc = 0; dev_dbg(chip->dev, "playback, val = %d\n", val); @@ -919,6 +923,11 @@ static int qti_haptics_playback(struct input_dev *dev, int effect_id, int val) disable_irq_nosync(chip->play_irq); chip->play_irq_en = false; } + secs = play->length_us / USEC_PER_SEC; + nsecs = (play->length_us % USEC_PER_SEC) * + NSEC_PER_USEC; + hrtimer_start(&chip->stop_timer, ktime_set(secs, nsecs), + HRTIMER_MODE_REL); } } else { play->length_us = 0; @@ -1056,6 +1065,26 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) return 0; } +static enum hrtimer_restart qti_hap_stop_timer(struct hrtimer *timer) +{ + struct qti_hap_chip *chip = container_of(timer, struct qti_hap_chip, + stop_timer); + int rc; + + chip->play.length_us = 0; + rc = qti_haptics_play(chip, false); + if (rc < 0) { + dev_err(chip->dev, "Stop playing failed, rc=%d\n", rc); + goto err_out; + } + + rc = qti_haptics_module_en(chip, false); + if (rc < 0) + dev_err(chip->dev, "Disable module failed, rc=%d\n", rc); +err_out: + return HRTIMER_NORESTART; +} + static int qti_haptics_parse_dt(struct qti_hap_chip *chip) { struct qti_hap_config *config = &chip->config; @@ -1367,6 +1396,9 @@ static int qti_haptics_probe(struct platform_device *pdev) return rc; } + hrtimer_init(&chip->stop_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + chip->stop_timer.function = qti_hap_stop_timer; + input_dev->name = "vibrator"; input_set_drvdata(input_dev, chip); chip->input_dev = input_dev; -- GitLab From 4aeaa891c7e8d3e68183f546e43b02c31b4be79d Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Mon, 18 Jun 2018 11:32:56 -0700 Subject: [PATCH 0395/1299] defconfig: sm8150: Enable QPNP_QNOVO driver Enable QPNP_QNOVO driver for pulse charging control. Change-Id: If2528733af56f1b74fbda0567fe4c91b979da183 Signed-off-by: Fenglin Wu --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index aea5edec49f8..37ac7c017233 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -334,6 +334,7 @@ CONFIG_POWER_RESET_SYSCON=y CONFIG_QPNP_FG_GEN4=y CONFIG_SMB1355_SLAVE_CHARGER=y CONFIG_QPNP_SMB5=y +CONFIG_QPNP_QNOVO5=y CONFIG_SMB1390_CHARGE_PUMP=y CONFIG_THERMAL=y CONFIG_THERMAL_WRITABLE_TRIPS=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index f199eb6e964c..9582ca688786 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -348,6 +348,7 @@ CONFIG_POWER_RESET_SYSCON=y CONFIG_QPNP_FG_GEN4=y CONFIG_SMB1355_SLAVE_CHARGER=y CONFIG_QPNP_SMB5=y +CONFIG_QPNP_QNOVO5=y CONFIG_SMB1390_CHARGE_PUMP=y CONFIG_THERMAL=y CONFIG_THERMAL_WRITABLE_TRIPS=y -- GitLab From 22448dfb6c02cf474a3534cb1a14539aaf8cd136 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Wed, 4 Apr 2018 11:22:34 +0800 Subject: [PATCH 0396/1299] ARM: dts: msm: Add Qnovo device node for PM8150B Add Qnovo device node in PM8150B to enable it for pulse charging control. Change-Id: Idfe632c8058382481cf551faf7ec51e1dadbef54 Signed-off-by: Fenglin Wu --- arch/arm64/boot/dts/qcom/pm8150b.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi b/arch/arm64/boot/dts/qcom/pm8150b.dtsi index 4219369b4f0f..6f5667ec64ff 100644 --- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi @@ -50,6 +50,13 @@ clock-names = "xo"; }; + pm8150b_qnovo: qcom,sdam-qnovo@b000 { + compatible = "qcom,qpnp-qnovo5"; + reg = <0xb000 0x100>; + interrupts = <0x2 0xb0 0 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "ptrain-done"; + }; + pm8150b_gpios: pinctrl@c000 { compatible = "qcom,spmi-gpio"; reg = <0xc000 0xc00>; -- GitLab From cebe9a6aead5922d4ceb7dfcd07c7c60f624f341 Mon Sep 17 00:00:00 2001 From: Bojun Pan Date: Thu, 14 Jun 2018 17:57:04 -0700 Subject: [PATCH 0397/1299] msm: gsi: gsi channel mode switch spinlock fix Fix the spin lock issue which will cause the race condition that gsi_isr will still happen even we are in polling mode. Change-Id: I616eba7734dd54646d2ca45c297caee4b2026334 Signed-off-by: Bojun Pan --- drivers/platform/msm/gsi/gsi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 9906e19c9db3..060215daf2e1 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -2892,21 +2892,27 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode) return -GSI_STATUS_UNSUPPORTED_OP; } - spin_lock_irqsave(&gsi_ctx->slock, flags); if (curr == GSI_CHAN_MODE_CALLBACK && mode == GSI_CHAN_MODE_POLL) { + spin_lock_irqsave(&gsi_ctx->slock, flags); __gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, 0); + spin_unlock_irqrestore(&gsi_ctx->slock, flags); + spin_lock_irqsave(&ctx->ring.slock, flags); atomic_set(&ctx->poll_mode, mode); + spin_unlock_irqrestore(&ctx->ring.slock, flags); ctx->stats.callback_to_poll++; } if (curr == GSI_CHAN_MODE_POLL && mode == GSI_CHAN_MODE_CALLBACK) { + spin_lock_irqsave(&ctx->ring.slock, flags); atomic_set(&ctx->poll_mode, mode); + spin_unlock_irqrestore(&ctx->ring.slock, flags); + spin_lock_irqsave(&gsi_ctx->slock, flags); __gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, ~0); + spin_unlock_irqrestore(&gsi_ctx->slock, flags); ctx->stats.poll_to_callback++; } - spin_unlock_irqrestore(&gsi_ctx->slock, flags); return GSI_STATUS_SUCCESS; } -- GitLab From ad8ec648a801821accc7ea4dace2ec12e2b8bb92 Mon Sep 17 00:00:00 2001 From: Mulu He Date: Wed, 11 Apr 2018 10:45:56 +0800 Subject: [PATCH 0398/1299] ARM: dts: msm: Add NPU TPDM node for sm8150 Add NPU TPDM node for sm8150, TPDM is used to config HW event for NPU. Change-Id: I14f93c2d9d9d68923e356da0ae8a2c9417e5bbd4 Signed-off-by: Mulu He --- .../arm64/boot/dts/qcom/sm8150-coresight.dtsi | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi b/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi index 5da67a724097..d5f3c1315583 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi @@ -1730,18 +1730,42 @@ coresight-name = "coresight-tpdm-npu"; - clocks = <&clock_npucc NPU_CC_NPU_CORE_APB_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_ATB_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_CTI_CLK>; - - com,tpdm-clks = "npu_cc_npu_core_apb_clk", - "npu_cc_npu_core_atb_clk", - "npu_cc_npu_core_cti_clk"; - com,tpdm-regs = <&npu_core_gdsc>; + clocks = <&clock_aop QDSS_CLK>, + <&clock_gcc GCC_NPU_TRIG_CLK>, + <&clock_gcc GCC_NPU_AT_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_APB_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_ATB_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_CLK_SRC>, + <&clock_npucc NPU_CC_NPU_CORE_CTI_CLK>; + + clock-names = "apb_pclk", + "gcc_npu_trig_clk", + "gcc_npu_at_clk", + "npu_core_apb_clk", + "npu_core_atb_clk", + "npu_core_clk", + "npu_core_clk_src", + "npu_core_cti_clk"; + + qcom,tpdm-clks = "apb_pclk", + "gcc_npu_trig_clk", + "gcc_npu_at_clk", + "npu_core_apb_clk", + "npu_core_atb_clk", + "npu_core_clk", + "npu_core_clk_src", + "npu_core_cti_clk"; + + vdd-supply = <&npu_core_gdsc>; + vdd_cx-supply = <&VDD_CX_LEVEL>; + qcom,proxy-reg-names ="vdd", "vdd_cx"; + qcom,vdd_cx-uV-uA = ; + qcom,tpdm-regs = "vdd", "vdd_cx"; port{ tpdm_npu_out_tpda: endpoint { - remote-endpoint = <&tpda_in_tpdm_npu>; + remote-endpoint = <&tpda_in_tpdm_npu>; }; }; }; -- GitLab From 16fb3e8043903673bc03b78a2cbad0844ebd1146 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Fri, 15 Jun 2018 19:12:52 -0700 Subject: [PATCH 0399/1299] mhi: core: use debugfs lookup method to find parent directory Instead of storing debug_fs directory inode in a global data structure, use a look up method to get the directory inode. CRs-Fixed: 2258358 Change-Id: I2df480d7ea29b1cc90dff3a7fa19bb9c46132552 Signed-off-by: Sujeev Dias --- drivers/bus/mhi/core/mhi_init.c | 9 ++++----- drivers/bus/mhi/core/mhi_internal.h | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 2febfd0d5718..0b8403277bdc 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -1158,7 +1158,7 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl) mhi_cntrl->mhi_dev = mhi_dev; - mhi_cntrl->parent = mhi_bus.dentry; + mhi_cntrl->parent = debugfs_lookup(mhi_bus_type.name, NULL); mhi_cntrl->klog_lvl = MHI_MSG_LVL_ERROR; /* adding it to this list only for debug purpose */ @@ -1493,14 +1493,13 @@ struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl) static int __init mhi_init(void) { - struct dentry *dentry; int ret; mutex_init(&mhi_bus.lock); INIT_LIST_HEAD(&mhi_bus.controller_list); - dentry = debugfs_create_dir("mhi", NULL); - if (!IS_ERR_OR_NULL(dentry)) - mhi_bus.dentry = dentry; + + /* parent directory */ + debugfs_create_dir(mhi_bus_type.name, NULL); ret = bus_register(&mhi_bus_type); diff --git a/drivers/bus/mhi/core/mhi_internal.h b/drivers/bus/mhi/core/mhi_internal.h index 01f77382d0d3..9d39040c5590 100644 --- a/drivers/bus/mhi/core/mhi_internal.h +++ b/drivers/bus/mhi/core/mhi_internal.h @@ -626,7 +626,6 @@ struct mhi_timesync { struct mhi_bus { struct list_head controller_list; struct mutex lock; - struct dentry *dentry; }; /* default MHI timeout */ -- GitLab From 75e9ef809c6ef2452b1ac46c477b4e01c5ad07e4 Mon Sep 17 00:00:00 2001 From: Surajit Podder Date: Tue, 1 May 2018 11:05:04 +0530 Subject: [PATCH 0400/1299] msm: vidc: Add support for ar50 bus bw governor Add support for ar50 bus governors msm-vidc-ar50-ddr and msm-vidc-ar50-llcc for sm6150 target. Change-Id: I785e9ffc88da4ef6276cf23cc020d7c3cb32b755 Signed-off-by: Surajit Podder --- .../platform/msm/vidc/governors/Makefile | 4 +- .../vidc/governors/msm_vidc_ar50_dyn_gov.c | 982 ++++++++++++++++++ .../msm/vidc/governors/msm_vidc_dyn_gov.c | 2 +- 3 files changed, 986 insertions(+), 2 deletions(-) create mode 100644 drivers/media/platform/msm/vidc/governors/msm_vidc_ar50_dyn_gov.c diff --git a/drivers/media/platform/msm/vidc/governors/Makefile b/drivers/media/platform/msm/vidc/governors/Makefile index 695a3ae4053a..ee4b29298a68 100644 --- a/drivers/media/platform/msm/vidc/governors/Makefile +++ b/drivers/media/platform/msm/vidc/governors/Makefile @@ -4,4 +4,6 @@ ccflags-y := -I$(srctree)/drivers/devfreq/ \ msm-vidc-dyn-gov-objs := msm_vidc_dyn_gov.o -obj-$(CONFIG_MSM_VIDC_GOVERNORS) := msm-vidc-dyn-gov.o +msm-vidc-ar50-dyn-gov-objs := msm_vidc_ar50_dyn_gov.o + +obj-$(CONFIG_MSM_VIDC_GOVERNORS) := msm-vidc-dyn-gov.o msm-vidc-ar50-dyn-gov.o diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_ar50_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_ar50_dyn_gov.c new file mode 100644 index 000000000000..7fd073a140bf --- /dev/null +++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_ar50_dyn_gov.c @@ -0,0 +1,982 @@ +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include "governor.h" +#include "fixedpoint.h" +#include "msm_vidc_internal.h" +#include "msm_vidc_debug.h" +#include "vidc_hfi_api.h" +#define COMPRESSION_RATIO_MAX 5 + +static bool debug; +module_param(debug, bool, 0644); + +enum governor_mode { + GOVERNOR_DDR, + GOVERNOR_LLCC, +}; + +struct governor { + enum governor_mode mode; + struct devfreq_governor devfreq_gov; +}; + +/* + * Minimum dimensions that the governor is willing to calculate + * bandwidth for. This means that anything bandwidth(0, 0) == + * bandwidth(BASELINE_DIMENSIONS.width, BASELINE_DIMENSIONS.height) + */ +static const struct { + int height, width; +} BASELINE_DIMENSIONS = { + .width = 1280, + .height = 720, +}; + +/* + * These are hardcoded AB values that the governor votes for in certain + * situations, where a certain bus frequency is desired. It isn't exactly + * scalable since different platforms have different bus widths, but we'll + * deal with that in the future. + */ +static const unsigned long NOMINAL_BW_MBPS = 6000 /* ideally 320 Mhz */, + SVS_BW_MBPS = 2000 /* ideally 100 Mhz */; + +/* converts Mbps to bps (the "b" part can be bits or bytes based on context) */ +#define kbps(__mbps) ((__mbps) * 1000) +#define bps(__mbps) (kbps(__mbps) * 1000) + +#define GENERATE_COMPRESSION_PROFILE(__bpp, __worst) { \ + .bpp = __bpp, \ + .ratio = __worst, \ +} + +/* + * The below table is a structural representation of the following table: + * Resolution | Bitrate | Compression Ratio | + * ............|............|.........................................| + * Width Height|Average High|Avg_8bpc Worst_8bpc Avg_10bpc Worst_10bpc| + * 1280 720| 7 14| 1.69 1.28 1.49 1.23| + * 1920 1080| 20 40| 1.69 1.28 1.49 1.23| + * 2560 1440| 32 64| 2.2 1.26 1.97 1.22| + * 3840 2160| 42 84| 2.2 1.26 1.97 1.22| + * 4096 2160| 44 88| 2.2 1.26 1.97 1.22| + * 4096 2304| 48 96| 2.2 1.26 1.97 1.22| + */ +static struct lut { + int frame_size; /* width x height */ + int frame_rate; + unsigned long bitrate; + struct { + int bpp; + fp_t ratio; + } compression_ratio[COMPRESSION_RATIO_MAX]; +} const LUT[] = { + { + .frame_size = 1280 * 720, + .frame_rate = 30, + .bitrate = 14, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 28, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 23, 100)), + } + }, + { + .frame_size = 1280 * 720, + .frame_rate = 60, + .bitrate = 22, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 28, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 23, 100)), + } + }, + { + .frame_size = 1920 * 1088, + .frame_rate = 30, + .bitrate = 40, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 28, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 23, 100)), + } + }, + { + .frame_size = 1920 * 1088, + .frame_rate = 60, + .bitrate = 64, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 28, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 23, 100)), + } + }, + { + .frame_size = 2560 * 1440, + .frame_rate = 30, + .bitrate = 64, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 26, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 22, 100)), + } + }, + { + .frame_size = 2560 * 1440, + .frame_rate = 60, + .bitrate = 102, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 26, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 22, 100)), + } + }, + { + .frame_size = 3840 * 2160, + .frame_rate = 30, + .bitrate = 84, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 26, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 22, 100)), + } + }, + { + .frame_size = 3840 * 2160, + .frame_rate = 60, + .bitrate = 134, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 26, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 22, 100)), + } + }, + { + .frame_size = 4096 * 2160, + .frame_rate = 30, + .bitrate = 88, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 26, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 22, 100)), + } + }, + { + .frame_size = 4096 * 2160, + .frame_rate = 60, + .bitrate = 141, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 26, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 22, 100)), + } + }, + { + .frame_size = 4096 * 2304, + .frame_rate = 30, + .bitrate = 96, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 26, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 22, 100)), + } + }, + { + .frame_size = 4096 * 2304, + .frame_rate = 60, + .bitrate = 154, + .compression_ratio = { + GENERATE_COMPRESSION_PROFILE(8, + FP(1, 26, 100)), + GENERATE_COMPRESSION_PROFILE(10, + FP(1, 22, 100)), + } + }, +}; + +static struct lut const *__lut(int width, int height, int fps) +{ + int frame_size = height * width, c = 0; + + do { + if (LUT[c].frame_size >= frame_size && LUT[c].frame_rate >= fps) + return &LUT[c]; + } while (++c < ARRAY_SIZE(LUT)); + + return &LUT[ARRAY_SIZE(LUT) - 1]; +} + +static fp_t __compression_ratio(struct lut const *entry, int bpp) +{ + int c = 0; + + for (c = 0; c < COMPRESSION_RATIO_MAX; ++c) { + if (entry->compression_ratio[c].bpp == bpp) + return entry->compression_ratio[c].ratio; + } + + WARN(true, "Shouldn't be here, LUT possibly corrupted?\n"); + return FP_ZERO; /* impossible */ +} + +#define DUMP_HEADER_MAGIC 0xdeadbeef +#define DUMP_FP_FMT "%FP" /* special format for fp_t */ +struct dump { + char *key; + char *format; + size_t val; +}; + +static void __dump(struct dump dump[], int len) +{ + int c = 0; + + for (c = 0; c < len; ++c) { + char format_line[128] = "", formatted_line[128] = ""; + + if (dump[c].val == DUMP_HEADER_MAGIC) { + snprintf(formatted_line, sizeof(formatted_line), "%s\n", + dump[c].key); + } else { + bool fp_format = !strcmp(dump[c].format, DUMP_FP_FMT); + + if (!fp_format) { + snprintf(format_line, sizeof(format_line), + " %-35s: %s\n", dump[c].key, + dump[c].format); + snprintf(formatted_line, sizeof(formatted_line), + format_line, dump[c].val); + } else { + size_t integer_part, fractional_part; + + integer_part = fp_int(dump[c].val); + fractional_part = fp_frac(dump[c].val); + snprintf(formatted_line, sizeof(formatted_line), + " %-35s: %zd + %zd/%zd\n", + dump[c].key, integer_part, + fractional_part, + fp_frac_base()); + + + } + } + + dprintk(VIDC_DBG, "%s", formatted_line); + } +} + +static unsigned long __calculate_vpe(struct vidc_bus_vote_data *d, + enum governor_mode gm) +{ + return 0; +} + +static bool __ubwc(enum hal_uncompressed_format f) +{ + switch (f) { + case HAL_COLOR_FORMAT_NV12_UBWC: + case HAL_COLOR_FORMAT_NV12_TP10_UBWC: + return true; + default: + return false; + } +} + +static int __bpp(enum hal_uncompressed_format f) +{ + switch (f) { + case HAL_COLOR_FORMAT_NV12: + case HAL_COLOR_FORMAT_NV21: + case HAL_COLOR_FORMAT_NV12_UBWC: + return 8; + case HAL_COLOR_FORMAT_NV12_TP10_UBWC: + case HAL_COLOR_FORMAT_P010: + return 10; + default: + dprintk(VIDC_ERR, + "What's this? We don't support this colorformat (%x)", + f); + return INT_MAX; + } +} + +static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d, + enum governor_mode gm) +{ + /* + * XXX: Don't fool around with any of the hardcoded numbers unless you + * know /exactly/ what you're doing. Many of these numbers are + * measured heuristics and hardcoded numbers taken from the firmware. + */ + /* Decoder parameters */ + int width, height, lcu_size, dpb_bpp, opb_bpp, fps, opb_factor; + bool unified_dpb_opb, dpb_compression_enabled, opb_compression_enabled, + llc_ref_read_l2_cache_enabled = false, + llc_vpss_ds_line_buf_enabled = false; + fp_t dpb_opb_scaling_ratio, dpb_read_compression_factor, + dpb_write_compression_factor, opb_compression_factor, + qsmmu_bw_overhead_factor, height_ratio; + + /* Derived parameters */ + int lcu_per_frame, tnbr_per_lcu, colocated_bytes_per_lcu; + unsigned long bitrate; + + fp_t bins_to_bit_factor, dpb_write_factor, ten_bpc_packing_factor, + ten_bpc_bpp_factor, vsp_read_factor, vsp_write_factor, + bw_for_1x_8bpc, dpb_bw_for_1x, + motion_vector_complexity = 0, row_cache_penalty = 0, opb_bw = 0, + dpb_total = 0; + + /* Output parameters */ + struct { + fp_t vsp_read, vsp_write, collocated_read, collocated_write, + line_buffer_read, line_buffer_write, recon_read, + recon_write, opb_read, opb_write, dpb_read, dpb_write, + total; + } ddr = {0}; + + struct { + fp_t dpb_read, opb_read, total; + } llc = {0}; + + unsigned long ret = 0; + unsigned int integer_part, frac_part; + + width = max(d->input_width, BASELINE_DIMENSIONS.width); + height = max(d->input_height, BASELINE_DIMENSIONS.height); + + lcu_size = d->lcu_size; + + dpb_bpp = d->num_formats >= 1 ? __bpp(d->color_formats[0]) : INT_MAX; + opb_bpp = d->num_formats >= 2 ? __bpp(d->color_formats[1]) : dpb_bpp; + + fps = d->fps; + + unified_dpb_opb = d->num_formats == 1; + + dpb_opb_scaling_ratio = fp_div(FP_INT( + (int)(d->input_width * d->input_height)), + FP_INT((int)(d->output_width * d->output_height))); + height_ratio = fp_div(d->input_height, d->output_height); + + dpb_compression_enabled = d->num_formats >= 1 && + __ubwc(d->color_formats[0]); + opb_compression_enabled = d->num_formats >= 2 && + __ubwc(d->color_formats[1]); + + /* + * Convert Q16 number into Integer and Fractional part upto 2 places. + * Ex : 105752 / 65536 = 1.61; 1.61 in Q16 = 105752; + * Integer part = 105752 / 65536 = 1; + * Reminder = 105752 - 1 * 65536 = 40216; + * Fractional part = 40216 * 100 / 65536 = 61; + * Now converto to FP(1, 61, 100) for below code. + */ + + integer_part = d->compression_ratio >> 16; + frac_part = + ((d->compression_ratio - (integer_part << 16)) * 100) >> 16; + + dpb_read_compression_factor = FP(integer_part, frac_part, 100); + + integer_part = d->complexity_factor >> 16; + frac_part = + ((d->complexity_factor - (integer_part << 16)) * 100) >> 16; + + motion_vector_complexity = FP(integer_part, frac_part, 100); + + dpb_write_compression_factor = !dpb_compression_enabled ? FP_ONE : + __compression_ratio(__lut(width, height, fps), opb_bpp); + + dpb_write_compression_factor = d->use_dpb_read ? + dpb_read_compression_factor : + dpb_write_compression_factor; + + opb_compression_factor = !opb_compression_enabled ? FP_ONE : + __compression_ratio(__lut(width, height, fps), opb_bpp); + + llc_ref_read_l2_cache_enabled = llc_vpss_ds_line_buf_enabled = false; + if (d->use_sys_cache) { + llc_ref_read_l2_cache_enabled = true; + llc_vpss_ds_line_buf_enabled = true; + } + + /* Derived parameters setup */ + lcu_per_frame = DIV_ROUND_UP(width, lcu_size) * + DIV_ROUND_UP(height, lcu_size); + + bitrate = __lut(width, height, fps)->bitrate; + + bins_to_bit_factor = d->work_mode == VIDC_WORK_MODE_1 ? + FP_INT(0) : FP_INT(4); + + vsp_read_factor = bins_to_bit_factor + FP_INT(2); + + dpb_write_factor = FP(1, 5, 100); + + ten_bpc_packing_factor = FP(1, 67, 1000); + ten_bpc_bpp_factor = FP(1, 1, 4); + + vsp_write_factor = bins_to_bit_factor; + + tnbr_per_lcu = lcu_size == 16 ? 128 : + lcu_size == 32 ? 64 : 128; + + colocated_bytes_per_lcu = lcu_size == 16 ? 16 : + lcu_size == 32 ? 64 : 256; + + /* ........................................ for DDR */ + ddr.vsp_read = fp_div(fp_mult(FP_INT(bitrate), + vsp_read_factor), FP_INT(8)); + ddr.vsp_write = fp_div(fp_mult(FP_INT(bitrate), + vsp_write_factor), FP_INT(8)); + + ddr.collocated_read = FP_INT(lcu_per_frame * + colocated_bytes_per_lcu * fps / bps(1)); + ddr.collocated_write = FP_INT(lcu_per_frame * + colocated_bytes_per_lcu * fps / bps(1)); + + ddr.line_buffer_read = FP_INT(tnbr_per_lcu * + lcu_per_frame * fps / bps(1)); + ddr.line_buffer_write = ddr.line_buffer_read; + + bw_for_1x_8bpc = fp_div(FP_INT((int)(width * height)), FP_INT(32 * 8)); + + bw_for_1x_8bpc = fp_mult(bw_for_1x_8bpc, + fp_div(FP_INT(((int)(256 * fps))), FP_INT(1000 * 1000))); + + dpb_bw_for_1x = dpb_bpp == 8 ? bw_for_1x_8bpc : + fp_mult(bw_for_1x_8bpc, fp_mult(ten_bpc_packing_factor, + ten_bpc_bpp_factor)); + + ddr.dpb_read = fp_div(fp_mult(fp_mult(dpb_bw_for_1x, + motion_vector_complexity), dpb_write_factor), + dpb_read_compression_factor); + + ddr.dpb_write = fp_div(fp_mult(dpb_bw_for_1x, dpb_write_factor), + dpb_write_compression_factor); + dpb_total = ddr.dpb_read + ddr.dpb_write; + if (llc_ref_read_l2_cache_enabled) { + row_cache_penalty = FP(1, 30, 100); + ddr.dpb_read = fp_div(ddr.dpb_read, row_cache_penalty); + llc.dpb_read = dpb_total - ddr.dpb_read; + } + + opb_factor = dpb_bpp == 8 ? 8 : 4; + + ddr.opb_read = unified_dpb_opb ? 0 : opb_compression_enabled ? + fp_div(fp_mult(fp_div(dpb_bw_for_1x, dpb_opb_scaling_ratio), + FP_INT(opb_factor)), height_ratio) : 0; + ddr.opb_write = unified_dpb_opb ? 0 : opb_compression_enabled ? + ddr.dpb_read : fp_div(fp_div(fp_mult(dpb_bw_for_1x, + FP(1, 50, 100)), dpb_opb_scaling_ratio), + opb_compression_factor); + + if (llc_vpss_ds_line_buf_enabled) { + llc.opb_read = ddr.opb_read; + ddr.opb_write -= ddr.opb_read; + ddr.opb_read = 0; + } + ddr.total = ddr.vsp_read + ddr.vsp_write + + ddr.collocated_read + ddr.collocated_write + + ddr.opb_read + ddr.opb_write + + ddr.dpb_read + ddr.dpb_write; + + qsmmu_bw_overhead_factor = FP(1, 3, 100); + + ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor); + llc.total = llc.dpb_read + llc.opb_read; + + /* Dump all the variables for easier debugging */ + if (debug) { + struct dump dump[] = { + {"DECODER PARAMETERS", "", DUMP_HEADER_MAGIC}, + {"LCU size", "%d", lcu_size}, + {"DPB bitdepth", "%d", dpb_bpp}, + {"frame rate", "%d", fps}, + {"DPB/OPB unified", "%d", unified_dpb_opb}, + {"DPB/OPB downscaling ratio", DUMP_FP_FMT, + dpb_opb_scaling_ratio}, + {"DPB compression", "%d", dpb_compression_enabled}, + {"OPB compression", "%d", opb_compression_enabled}, + {"DPB Read compression factor", DUMP_FP_FMT, + dpb_read_compression_factor}, + {"DPB Write compression factor", DUMP_FP_FMT, + dpb_write_compression_factor}, + {"OPB compression factor", DUMP_FP_FMT, + opb_compression_factor}, + {"frame width", "%d", width}, + {"frame height", "%d", height}, + + {"DERIVED PARAMETERS (1)", "", DUMP_HEADER_MAGIC}, + {"LCUs/frame", "%d", lcu_per_frame}, + {"bitrate (Mbit/sec)", "%d", bitrate}, + {"bins to bit factor", DUMP_FP_FMT, bins_to_bit_factor}, + {"DPB write factor", DUMP_FP_FMT, dpb_write_factor}, + {"10bpc packing factor", DUMP_FP_FMT, + ten_bpc_packing_factor}, + {"10bpc,BPP factor", DUMP_FP_FMT, ten_bpc_bpp_factor}, + {"VSP read factor", DUMP_FP_FMT, vsp_read_factor}, + {"VSP write factor", DUMP_FP_FMT, vsp_write_factor}, + {"TNBR/LCU", "%d", tnbr_per_lcu}, + {"colocated bytes/LCU", "%d", colocated_bytes_per_lcu}, + {"B/W for 1x (NV12 8bpc)", DUMP_FP_FMT, bw_for_1x_8bpc}, + {"DPB B/W For 1x (NV12)", DUMP_FP_FMT, dpb_bw_for_1x}, + + {"DERIVED PARAMETERS (2)", "", DUMP_HEADER_MAGIC}, + {"MV complexity", DUMP_FP_FMT, motion_vector_complexity}, + {"row cache penalty", DUMP_FP_FMT, row_cache_penalty}, + {"qsmmu_bw_overhead_factor", DUMP_FP_FMT, + qsmmu_bw_overhead_factor}, + {"OPB B/W (single instance)", DUMP_FP_FMT, opb_bw}, + + {"INTERMEDIATE DDR B/W", "", DUMP_HEADER_MAGIC}, + {"VSP read", DUMP_FP_FMT, ddr.vsp_read}, + {"VSP write", DUMP_FP_FMT, ddr.vsp_write}, + {"collocated read", DUMP_FP_FMT, ddr.collocated_read}, + {"collocated write", DUMP_FP_FMT, ddr.collocated_write}, + {"line buffer read", DUMP_FP_FMT, ddr.line_buffer_read}, + {"line buffer write", DUMP_FP_FMT, ddr.line_buffer_write}, + {"recon read", DUMP_FP_FMT, ddr.recon_read}, + {"recon write", DUMP_FP_FMT, ddr.recon_write}, + {"OPB read", DUMP_FP_FMT, ddr.opb_read}, + {"OPB write", DUMP_FP_FMT, ddr.opb_write}, + {"DPB read", DUMP_FP_FMT, ddr.dpb_read}, + {"DPB write", DUMP_FP_FMT, ddr.dpb_write}, + {"LLC DPB read", DUMP_FP_FMT, llc.dpb_read}, + {"LLC OPB read", DUMP_FP_FMT, llc.opb_read}, + + }; + __dump(dump, ARRAY_SIZE(dump)); + } + + switch (gm) { + case GOVERNOR_DDR: + ret = kbps(fp_round(ddr.total)); + break; + case GOVERNOR_LLCC: + ret = kbps(fp_round(llc.total)); + break; + default: + dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__); + } + + return ret; +} + +static unsigned long __calculate_encoder(struct vidc_bus_vote_data *d, + enum governor_mode gm) +{ + /* + * XXX: Don't fool around with any of the hardcoded numbers unless you + * know /exactly/ what you're doing. Many of these numbers are + * measured heuristics and hardcoded numbers taken from the firmware. + */ + /* Encoder Parameters */ + + int width, height, fps, dpb_bpp, lcu_per_frame, lcu_size, + vertical_tile_width, colocated_bytes_per_lcu, bitrate, + ref_overlap_bw_factor; + enum hal_uncompressed_format dpb_color_format, original_color_format; + bool dpb_compression_enabled, original_compression_enabled, + work_mode_1, low_power, rotation, cropping_or_scaling, + b_frames_enabled = false, + llc_dual_core_ref_read_buf_enabled = false, + llc_top_line_buf_enabled = false, + llc_ref_chroma_cache_enabled = false; + fp_t dpb_compression_factor, original_compression_factor, + input_compression_factor, qsmmu_bw_overhead_factor, + ref_y_bw_factor, ref_cb_cr_bw_factor, ten_bpc_bpp_factor, + bw_for_1x_8bpc, dpb_bw_for_1x, ref_cb_cr_read, + bins_to_bit_factor, ref_y_read, ten_bpc_packing_factor, + dpb_write_factor, ref_overlap_bw, llc_ref_y_read, + llc_ref_cb_cr_read; + fp_t integer_part, frac_part; + unsigned long ret = 0; + + /* Output parameters */ + struct { + fp_t vsp_read, vsp_write, collocated_read, collocated_write, + line_buffer_read, line_buffer_write, original_read, + original_write, dpb_read, dpb_write, total; + } ddr = {0}; + + struct { + fp_t dpb_read, line_buffer, total; + } llc = {0}; + + /* Encoder Parameters setup */ + ten_bpc_packing_factor = FP(1, 67, 1000); + ten_bpc_bpp_factor = FP(1, 1, 4); + rotation = false; + cropping_or_scaling = false; + vertical_tile_width = 960; + ref_y_bw_factor = FP(1, 30, 100); + ref_cb_cr_bw_factor = FP(1, 50, 100); + dpb_write_factor = FP(1, 8, 100); + + + /* Derived Parameters */ + lcu_size = d->lcu_size; + fps = d->fps; + b_frames_enabled = d->b_frames_enabled; + width = max(d->input_width, BASELINE_DIMENSIONS.width); + height = max(d->input_height, BASELINE_DIMENSIONS.height); + bitrate = __lut(width, height, fps)->bitrate; + lcu_per_frame = DIV_ROUND_UP(width, lcu_size) * + DIV_ROUND_UP(height, lcu_size); + + dpb_color_format = HAL_COLOR_FORMAT_NV12_UBWC; + original_color_format = d->num_formats >= 1 ? + d->color_formats[0] : HAL_UNUSED_COLOR; + + dpb_bpp = d->num_formats >= 1 ? __bpp(d->color_formats[0]) : INT_MAX; + + dpb_compression_enabled = __ubwc(dpb_color_format); + original_compression_enabled = __ubwc(original_color_format); + + work_mode_1 = d->work_mode == VIDC_WORK_MODE_1; + low_power = d->power_mode == VIDC_POWER_LOW; + bins_to_bit_factor = work_mode_1 ? + FP_INT(0) : FP_INT(4); + + if (d->use_sys_cache) { + llc_dual_core_ref_read_buf_enabled = true; + llc_ref_chroma_cache_enabled = true; + } + + /* + * Convert Q16 number into Integer and Fractional part upto 2 places. + * Ex : 105752 / 65536 = 1.61; 1.61 in Q16 = 105752; + * Integer part = 105752 / 65536 = 1; + * Reminder = 105752 - 1 * 65536 = 40216; + * Fractional part = 40216 * 100 / 65536 = 61; + * Now converto to FP(1, 61, 100) for below code. + */ + + integer_part = d->compression_ratio >> 16; + frac_part = + ((d->compression_ratio - (integer_part * 65536)) * 100) >> 16; + + dpb_compression_factor = FP(integer_part, frac_part, 100); + + integer_part = d->input_cr >> 16; + frac_part = + ((d->input_cr - (integer_part * 65536)) * 100) >> 16; + + input_compression_factor = FP(integer_part, frac_part, 100); + + original_compression_factor = + original_compression_enabled ? d->use_dpb_read ? + dpb_compression_factor : input_compression_factor : + FP_ONE; + + ddr.vsp_read = fp_mult(fp_div(FP_INT(bitrate), FP_INT(8)), + bins_to_bit_factor); + ddr.vsp_write = ddr.vsp_read + fp_div(FP_INT(bitrate), FP_INT(8)); + + colocated_bytes_per_lcu = lcu_size == 16 ? 16 : + lcu_size == 32 ? 64 : 256; + + ddr.collocated_read = FP_INT(lcu_per_frame * + colocated_bytes_per_lcu * fps / bps(1)); + + ddr.collocated_write = ddr.collocated_read; + + ddr.line_buffer_read = FP_INT(16 * lcu_per_frame * fps / bps(1)); + + ddr.line_buffer_write = ddr.line_buffer_read; + + llc.line_buffer = ddr.line_buffer_read + ddr.line_buffer_write; + if (llc_top_line_buf_enabled) + ddr.line_buffer_read = ddr.line_buffer_write = FP_INT(0); + + llc.line_buffer -= (ddr.line_buffer_read + ddr.line_buffer_write); + + bw_for_1x_8bpc = fp_div(FP_INT((int)(width * height)), FP_INT(32 * 8)); + + bw_for_1x_8bpc = fp_mult(bw_for_1x_8bpc, + fp_div(FP_INT(((int)(256 * fps))), FP_INT(1000 * 1000))); + + dpb_bw_for_1x = dpb_bpp == 8 ? bw_for_1x_8bpc : + fp_mult(bw_for_1x_8bpc, fp_mult(ten_bpc_packing_factor, + ten_bpc_bpp_factor)); + + ddr.original_read = fp_div(fp_mult(FP(1, 50, 100), dpb_bw_for_1x), + input_compression_factor); + + ddr.original_write = FP_ZERO; + + ref_y_bw_factor = + width == vertical_tile_width ? FP_INT(1) : ref_y_bw_factor; + + ref_y_read = fp_mult(ref_y_bw_factor, dpb_bw_for_1x); + + ref_y_read = fp_div(ref_y_read, dpb_compression_factor); + + ref_y_read = + b_frames_enabled ? fp_mult(ref_y_read, FP_INT(2)) : ref_y_read; + + llc_ref_y_read = ref_y_read; + if (llc_dual_core_ref_read_buf_enabled) + ref_y_read = fp_div(ref_y_read, FP_INT(2)); + + llc_ref_y_read -= ref_y_read; + + ref_cb_cr_read = fp_mult(ref_cb_cr_bw_factor, dpb_bw_for_1x); + + ref_cb_cr_read = fp_div(ref_cb_cr_read, dpb_compression_factor); + + ref_cb_cr_read = + b_frames_enabled ? fp_mult(ref_cb_cr_read, FP_INT(2)) : + ref_cb_cr_read; + + llc_ref_cb_cr_read = ref_cb_cr_read; + + if (llc_ref_chroma_cache_enabled) + ref_cb_cr_read = fp_div(ref_cb_cr_read, ref_cb_cr_bw_factor); + + if (llc_dual_core_ref_read_buf_enabled) + ref_cb_cr_read = fp_div(ref_cb_cr_read, FP_INT(2)); + + llc_ref_cb_cr_read -= ref_cb_cr_read; + + ddr.dpb_write = fp_mult(dpb_write_factor, dpb_bw_for_1x); + + ddr.dpb_write = fp_mult(ddr.dpb_write, FP(1, 50, 100)); + + ddr.dpb_write = fp_div(ddr.dpb_write, input_compression_factor); + + ref_overlap_bw_factor = + width <= vertical_tile_width ? FP_INT(0) : FP_INT(1); + + ref_overlap_bw = fp_mult(ddr.dpb_write, ref_overlap_bw_factor); + + ref_overlap_bw = fp_div(ref_overlap_bw, dpb_write_factor); + + ref_overlap_bw = fp_mult(ref_overlap_bw, + (dpb_write_factor - FP_INT(1))); + + ddr.dpb_read = ref_y_read + ref_cb_cr_read + ref_overlap_bw; + + llc.dpb_read = llc_ref_y_read + llc_ref_cb_cr_read; + + ddr.total = ddr.vsp_read + ddr.vsp_write + + ddr.collocated_read + ddr.collocated_write + + ddr.line_buffer_read + ddr.line_buffer_write + + ddr.original_read + ddr.original_write + + ddr.dpb_read + ddr.dpb_write; + + llc.total = llc.dpb_read + llc.line_buffer; + + qsmmu_bw_overhead_factor = FP(1, 3, 100); + ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor); + + if (debug) { + struct dump dump[] = { + {"ENCODER PARAMETERS", "", DUMP_HEADER_MAGIC}, + {"width", "%d", width}, + {"height", "%d", height}, + {"DPB format", "%#x", dpb_color_format}, + {"original frame format", "%#x", original_color_format}, + {"fps", "%d", fps}, + {"DPB compression enable", "%d", dpb_compression_enabled}, + {"original compression enable", "%d", + original_compression_enabled}, + {"low power mode", "%d", low_power}, + {"Work Mode", "%d", work_mode_1}, + {"DPB compression factor", DUMP_FP_FMT, + dpb_compression_factor}, + {"original compression factor", DUMP_FP_FMT, + original_compression_factor}, + {"rotation", "%d", rotation}, + {"cropping or scaling", "%d", cropping_or_scaling}, + + {"DERIVED PARAMETERS", "", DUMP_HEADER_MAGIC}, + {"LCU size", "%d", lcu_size}, + {"bitrate (Mbit/sec)", "%lu", bitrate}, + {"bins to bit factor", DUMP_FP_FMT, bins_to_bit_factor}, + {"qsmmu_bw_overhead_factor", + DUMP_FP_FMT, qsmmu_bw_overhead_factor}, + + {"INTERMEDIATE B/W DDR", "", DUMP_HEADER_MAGIC}, + {"ref_y_read", DUMP_FP_FMT, ref_y_read}, + {"ref_cb_cr_read", DUMP_FP_FMT, ref_cb_cr_read}, + {"ref_overlap_bw", DUMP_FP_FMT, ref_overlap_bw}, + {"VSP read", DUMP_FP_FMT, ddr.vsp_read}, + {"VSP write", DUMP_FP_FMT, ddr.vsp_write}, + {"collocated read", DUMP_FP_FMT, ddr.collocated_read}, + {"collocated write", DUMP_FP_FMT, ddr.collocated_write}, + {"line buffer read", DUMP_FP_FMT, ddr.line_buffer_read}, + {"line buffer write", DUMP_FP_FMT, ddr.line_buffer_write}, + {"original read", DUMP_FP_FMT, ddr.original_read}, + {"original write", DUMP_FP_FMT, ddr.original_write}, + {"DPB read", DUMP_FP_FMT, ddr.dpb_read}, + {"DPB write", DUMP_FP_FMT, ddr.dpb_write}, + {"LLC DPB read", DUMP_FP_FMT, llc.dpb_read}, + {"LLC Line buffer", DUMP_FP_FMT, llc.line_buffer}, + }; + __dump(dump, ARRAY_SIZE(dump)); + } + + switch (gm) { + case GOVERNOR_DDR: + ret = kbps(fp_round(ddr.total)); + break; + case GOVERNOR_LLCC: + ret = kbps(fp_round(llc.total)); + break; + default: + dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__); + } + + return ret; +} + +static unsigned long __calculate(struct vidc_bus_vote_data *d, + enum governor_mode gm) +{ + unsigned long (*calc[])(struct vidc_bus_vote_data *, + enum governor_mode) = { + [HAL_VIDEO_DOMAIN_VPE] = __calculate_vpe, + [HAL_VIDEO_DOMAIN_ENCODER] = __calculate_encoder, + [HAL_VIDEO_DOMAIN_DECODER] = __calculate_decoder, + }; + + if (d->domain >= ARRAY_SIZE(calc)) { + dprintk(VIDC_ERR, "%s: invalid domain %d\n", + __func__, d->domain); + return 0; + } + return calc[d->domain](d, gm); +} + + +static int __get_target_freq(struct devfreq *dev, unsigned long *freq) +{ + unsigned long ab_kbps = 0, c = 0; + struct devfreq_dev_status stats = {0}; + struct msm_vidc_gov_data *vidc_data = NULL; + struct governor *gov = NULL; + + if (!dev || !freq) + return -EINVAL; + + gov = container_of(dev->governor, + struct governor, devfreq_gov); + dev->profile->get_dev_status(dev->dev.parent, &stats); + vidc_data = (struct msm_vidc_gov_data *)stats.private_data; + + if (!vidc_data || !vidc_data->data_count) + goto exit; + + for (c = 0; c < vidc_data->data_count; ++c) { + if (vidc_data->data->power_mode == VIDC_POWER_TURBO) { + ab_kbps = INT_MAX; + goto exit; + } + } + + for (c = 0; c < vidc_data->data_count; ++c) + ab_kbps += __calculate(&vidc_data->data[c], gov->mode); + +exit: + *freq = clamp(ab_kbps, dev->min_freq, dev->max_freq ?: UINT_MAX); + trace_msm_vidc_perf_bus_vote(gov->devfreq_gov.name, *freq); + return 0; +} + +static int __event_handler(struct devfreq *devfreq, unsigned int event, + void *data) +{ + int rc = 0; + + if (!devfreq) + return -EINVAL; + + switch (event) { + case DEVFREQ_GOV_START: + case DEVFREQ_GOV_RESUME: + case DEVFREQ_GOV_SUSPEND: + mutex_lock(&devfreq->lock); + rc = update_devfreq(devfreq); + mutex_unlock(&devfreq->lock); + break; + } + + return rc; +} + +static struct governor governors[] = { + { + .mode = GOVERNOR_DDR, + .devfreq_gov = { + .name = "vidc-ar50-ddr", + .get_target_freq = __get_target_freq, + .event_handler = __event_handler, + }, + }, + { + .mode = GOVERNOR_LLCC, + .devfreq_gov = { + .name = "vidc-ar50-llcc", + .get_target_freq = __get_target_freq, + .event_handler = __event_handler, + }, + }, +}; + +static int __init msm_vidc_ar50_bw_gov_init(void) +{ + int c = 0, rc = 0; + + for (c = 0; c < ARRAY_SIZE(governors); ++c) { + dprintk(VIDC_DBG, "Adding governor %s\n", + governors[c].devfreq_gov.name); + + rc = devfreq_add_governor(&governors[c].devfreq_gov); + if (rc) { + dprintk(VIDC_ERR, "Error adding governor %s: %d\n", + governors[c].devfreq_gov.name, rc); + break; + } + } + + return rc; +} +module_init(msm_vidc_ar50_bw_gov_init); + +static void __exit msm_vidc_ar50_bw_gov_exit(void) +{ + int c = 0; + + for (c = 0; c < ARRAY_SIZE(governors); ++c) { + dprintk(VIDC_DBG, "Removing governor %s\n", + governors[c].devfreq_gov.name); + devfreq_remove_governor(&governors[c].devfreq_gov); + } +} +module_exit(msm_vidc_ar50_bw_gov_exit); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c index 5dbed452206c..611c52cfe9d0 100644 --- a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c +++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c @@ -36,7 +36,7 @@ struct governor { * bandwidth for. This means that anything bandwidth(0, 0) == * bandwidth(BASELINE_DIMENSIONS.width, BASELINE_DIMENSIONS.height) */ -const struct { +static const struct { int height, width; } BASELINE_DIMENSIONS = { .width = 1280, -- GitLab From 16d46dc39cf3d1f876f2b7e7ecea1e1fadf7245d Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Tue, 19 Jun 2018 10:42:22 +0530 Subject: [PATCH 0401/1299] ARM: dts: msm: Fix DT compilation failure for QCS405 For QCS405 fix the DT compilation failure because of reference to non-existent label pms405_gpios on qcs405-rumi. Fix the same and other compilation failures. Change-Id: I548aa24df9263c31950172e144ff7c69076209ee Signed-off-by: Sriharsha Allenki --- arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi | 6 ++++++ arch/arm64/boot/dts/qcom/qcs405-usb.dtsi | 6 ++++++ arch/arm64/boot/dts/qcom/qcs405.dtsi | 1 + 3 files changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi b/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi index 724b8d57430c..c6a7675bcb4e 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi @@ -42,7 +42,12 @@ }; }; +&usb3 { + /delete-property/ extcon; +}; + &usb2s { + /delete-property/ extcon; dwc3@78c0000 { usb-phy = <&usb_emu_phy>, <&usb_nop_phy>; maximum-speed = "high-speed"; @@ -73,6 +78,7 @@ /delete-node/ qcom,spmi@200f000; /delete-node/ regulator@1942120; /delete-node/ regulator@b018000; + /delete-node/ usb3_extcon; }; &rpm_bus { diff --git a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi index b4a547bb7702..e6fb5e0620fc 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi @@ -19,6 +19,9 @@ compatible = "qcom,dwc-usb3-msm"; reg = <0x7580000 0x100000>; reg-names = "core_base"; + #address-cells = <1>; + #size-cells = <1>; + ranges; interrupts = <0 25 0>, <0 24 0>; interrupt-names = "pwr_event_irq", "hs_phy_irq"; @@ -123,6 +126,9 @@ compatible = "qcom,dwc-usb3-msm"; reg = <0x78c0000 0x100000>; reg-names = "core_base"; + #address-cells = <1>; + #size-cells = <1>; + ranges; interrupts = <0 32 0>, <0 31 0>; interrupt-names = "pwr_event_irq", "hs_phy_irq"; diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index dafcff4016b2..2732a939e71d 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include / { model = "Qualcomm Technologies, Inc. QCS405"; -- GitLab From eb4f12de356c68a0f79451c84d87822974ec45c1 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Tue, 19 Jun 2018 10:50:01 +0530 Subject: [PATCH 0402/1299] ARM: dts: msm: Remove 650MHz GPU clock for QCS405 Remove 650MHz GPU clock level as GPU Fmax is now 598MHz instead of 650MHz. Change-Id: Ibfdbed60e0de065c35836bba5156c3b7891ebe60 Signed-off-by: Deepak Kumar --- arch/arm64/boot/dts/qcom/qcs405-gpu.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-gpu.dtsi b/arch/arm64/boot/dts/qcom/qcs405-gpu.dtsi index ed8a630383b6..102533616403 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-gpu.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-gpu.dtsi @@ -110,9 +110,9 @@ /* TURBO */ qcom,gpu-pwrlevel@0 { reg = <0>; - qcom,gpu-freq = <650000000>; + qcom,gpu-freq = <598000000>; qcom,bus-freq = <8>; - qcom,bus-min = <8>; + qcom,bus-min = <7>; qcom,bus-max = <8>; }; -- GitLab From d3b1b3167d30a8364866748bd48095661ee39f7b Mon Sep 17 00:00:00 2001 From: Shaoqing Liu Date: Tue, 12 Jun 2018 14:01:42 +0800 Subject: [PATCH 0403/1299] Coresight: Modify reset channel for tmc-etf Modify reset channel for tmc-etf since previous reset channel configuration is wrong according cti config document for sm8150. CRs-Fixed: 2256917 Change-Id: I244ff8a18df3284ef582656278d37d33ec4b2db5 Signed-off-by: Shaoqing Liu --- drivers/hwtracing/coresight/coresight-tmc-etf.c | 4 ++-- drivers/hwtracing/coresight/coresight-tmc.c | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 8fb2d1d22030..9e12d3df16d2 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -184,7 +184,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) kfree(buf); if (!ret) { - coresight_cti_map_trigin(drvdata->cti_reset, 2, 0); + coresight_cti_map_trigin(drvdata->cti_reset, 0, 0); coresight_cti_map_trigout(drvdata->cti_flush, 1, 0); dev_info(drvdata->dev, "TMC-ETB/ETF enabled\n"); } @@ -266,7 +266,7 @@ static void tmc_disable_etf_sink(struct coresight_device *csdev) spin_unlock_irqrestore(&drvdata->spinlock, flags); - coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0); + coresight_cti_unmap_trigin(drvdata->cti_reset, 0, 0); coresight_cti_unmap_trigout(drvdata->cti_flush, 1, 0); dev_info(drvdata->dev, "TMC-ETB/ETF disabled\n"); diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 74b31597ec5a..b857b9c59fb4 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -719,12 +719,18 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) dev_err(dev, "invalid cti data\n"); } else if (ctidata && ctidata->nr_ctis == 2) { drvdata->cti_flush = coresight_cti_get(ctidata->names[0]); - if (IS_ERR(drvdata->cti_flush)) - dev_err(dev, "failed to get flush cti\n"); + if (IS_ERR(drvdata->cti_flush)) { + dev_err(dev, "failed to get flush cti, defer probe\n"); + tmc_iommu_deinit(drvdata); + return -EPROBE_DEFER; + } drvdata->cti_reset = coresight_cti_get(ctidata->names[1]); - if (IS_ERR(drvdata->cti_reset)) - dev_err(dev, "failed to get reset cti\n"); + if (IS_ERR(drvdata->cti_reset)) { + dev_err(dev, "failed to get reset cti, defer probe\n"); + tmc_iommu_deinit(drvdata); + return -EPROBE_DEFER; + } } ret = of_get_coresight_csr_name(adev->dev.of_node, &drvdata->csr_name); -- GitLab From 676815e35bb96a4fa72cac6e40d3aa9d23633853 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Tue, 19 Jun 2018 14:02:52 +0800 Subject: [PATCH 0404/1299] defconfig: sm8150: Enable QTI haptics input driver Enable QTI haptics input driver so that the QTI haptics device can be exported as a FF (Force-Feedback) type input device and controlled through ioctl/write API to input device. Change-Id: I076a134b700c504bcfc3fa355ff82b4b4f3bde2d Signed-off-by: Fenglin Wu --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index aea5edec49f8..3b3e839caa03 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -300,6 +300,7 @@ CONFIG_TOUCHSCREEN_ST=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y CONFIG_INPUT_QPNP_POWER_ON=y +CONFIG_INPUT_QTI_HAPTICS=y CONFIG_INPUT_UINPUT=y # CONFIG_SERIO_SERPORT is not set # CONFIG_VT is not set diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index f199eb6e964c..fe24e02a9088 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -312,6 +312,7 @@ CONFIG_TOUCHSCREEN_ST=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y CONFIG_INPUT_QPNP_POWER_ON=y +CONFIG_INPUT_QTI_HAPTICS=y CONFIG_INPUT_UINPUT=y # CONFIG_SERIO_SERPORT is not set # CONFIG_VT is not set -- GitLab From f131eeacd9057d37e638e41a5fafecdf36a15100 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Fri, 15 Jun 2018 09:51:03 +0800 Subject: [PATCH 0405/1299] ARM: dts: msm: Update haptics device node on pm8150b Change to use qti-haptics driver and update the device node configurations. It registers the haptics module as an input FF (force-feedback) device and it defines different vibration effects for userspace to control them via write/ioctl calls into the input device. Change-Id: I02e7dcdcb149847633ba389f756c83f5e5fb75ae Signed-off-by: Fenglin Wu --- arch/arm64/boot/dts/qcom/pm8150b.dtsi | 57 +++++++++++++++++++++------ 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi b/arch/arm64/boot/dts/qcom/pm8150b.dtsi index 4219369b4f0f..d79c5ae54279 100644 --- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi @@ -462,23 +462,54 @@ }; pm8150b_haptics: qcom,haptics@c000 { - compatible = "qcom,qpnp-haptics"; + compatible = "qcom,haptics"; reg = <0xc000 0x100>; interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>, <0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>; interrupt-names = "hap-sc-irq", "hap-play-irq"; - qcom,pmic-revid = <&pm8150b_revid>; - qcom,actuator-type = <0>; - qcom,play-mode = "direct"; - qcom,vmax-mv = <3200>; - qcom,ilim-ma = <800>; - qcom,sc-dbc-cycles = <8>; - qcom,wave-play-rate-us = <6667>; - qcom,en-brake; - qcom,lra-high-z = "opt0"; - qcom,lra-auto-res-mode = "qwd"; - qcom,lra-res-cal-period = <4>; - status = "ok"; + qcom,actuator-type = "lra"; + qcom,vmax-mv = <3600>; + qcom,play-rate-us = <6667>; + qcom,lra-resonance-sig-shape = "sine"; + qcom,lra-auto-resonance-mode = "qwd"; + qcom,lra-allow-variable-play-rate; + + wf_0 { + /* CLICK */ + qcom,effect-id = <0>; + qcom,wf-pattern = [3e 3e 3e]; + qcom,wf-play-rate-us = <6667>; + }; + wf_1 { + /* DOUBLE CLICK */ + qcom,effect-id = <1>; + qcom,wf-pattern = [7e 7e 02 02 02 02 7e 7e]; + qcom,wf-play-rate-us = <7143>; + }; + wf_2 { + /* TICK */ + qcom,effect-id = <2>; + qcom,wf-pattern = [7e 7e]; + qcom,wf-play-rate-us = <4000>; + }; + wf_3 { + /* THUD */ + qcom,effect-id = <3>; + qcom,wf-pattern = [7e 7e 7e]; + qcom,wf-play-rate-us = <5714>; + }; + wf_4 { + /* POP */ + qcom,effect-id = <4>; + qcom,wf-pattern = [7e 7e]; + qcom,wf-play-rate-us = <5000>; + }; + wf_5 { + /* HEAVY CLICK */ + qcom,effect-id = <5>; + qcom,wf-pattern = [7e 7e 7e]; + qcom,wf-play-rate-us = <6667>; + }; }; }; }; -- GitLab From c48373088eefa6bf8aa456256f9037e16a5276de Mon Sep 17 00:00:00 2001 From: Xu Yang Date: Mon, 26 Mar 2018 14:16:09 +0800 Subject: [PATCH 0406/1299] drm/msm/sde: fix deadlock between IRQ lock and node state lock Deadlock is found when histogram interrupt is being disabled and at the same time histogram callback function is being called. The histogram IRQ lock is hold by interrupt thread, and node state lock is hold by main thread. And each thread is waiting for the other lock. Change fixes the race condition and add one more state in node to avoid the interrupt be disabled twice. And the patch also fix another issue, when Driver receives the request from userspace to disable histogram irq, and the irq node has already been deleted from user event list, it will fail to disable the irq. The change fixes the issue by getting the irq node by container_of instead of user event list. Change-Id: If1158e1d916fce4d79248b082a15b7590b54bab6 Signed-off-by: Xu Yang --- .../gpu/drm/msm/sde/sde_color_processing.c | 108 +++++++----------- drivers/gpu/drm/msm/sde/sde_crtc.c | 4 +- drivers/gpu/drm/msm/sde/sde_crtc.h | 1 + 3 files changed, 42 insertions(+), 71 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c index 02050a695fa2..aaeed7a61814 100644 --- a/drivers/gpu/drm/msm/sde/sde_color_processing.c +++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c @@ -1721,25 +1721,21 @@ int sde_cp_ad_interrupt(struct drm_crtc *crtc_drm, bool en, goto exit; } - node = _sde_cp_get_intr_node(DRM_EVENT_AD_BACKLIGHT, crtc); + node = container_of(ad_irq, struct sde_crtc_irq_info, irq); if (!en) { - if (node) { - spin_lock_irqsave(&node->state_lock, flags); - if (node->state == IRQ_ENABLED) { - ret = sde_core_irq_disable(kms, &irq_idx, 1); - if (ret) - DRM_ERROR("disable irq %d error %d\n", - irq_idx, ret); - else - node->state = IRQ_NOINIT; - } else { + spin_lock_irqsave(&node->state_lock, flags); + if (node->state == IRQ_ENABLED) { + ret = sde_core_irq_disable(kms, &irq_idx, 1); + if (ret) + DRM_ERROR("disable irq %d error %d\n", + irq_idx, ret); + else node->state = IRQ_NOINIT; - } - spin_unlock_irqrestore(&node->state_lock, flags); } else { - DRM_ERROR("failed to get node from crtc event list\n"); + node->state = IRQ_NOINIT; } + spin_unlock_irqrestore(&node->state_lock, flags); sde_core_irq_unregister_callback(kms, irq_idx, ad_irq); ret = 0; goto exit; @@ -1753,32 +1749,18 @@ int sde_cp_ad_interrupt(struct drm_crtc *crtc_drm, bool en, goto exit; } - if (node) { - /* device resume or resume from IPC cases */ - spin_lock_irqsave(&node->state_lock, flags); - if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) { - ret = sde_core_irq_enable(kms, &irq_idx, 1); - if (ret) { - DRM_ERROR("enable irq %d error %d\n", - irq_idx, ret); - sde_core_irq_unregister_callback(kms, - irq_idx, ad_irq); - } else { - node->state = IRQ_ENABLED; - } - } - spin_unlock_irqrestore(&node->state_lock, flags); - } else { - /* request from userspace to register the event - * in this case, node has not been added into the event list - */ + spin_lock_irqsave(&node->state_lock, flags); + if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) { ret = sde_core_irq_enable(kms, &irq_idx, 1); if (ret) { - DRM_ERROR("failed to enable irq ret %d\n", ret); - sde_core_irq_unregister_callback(kms, - irq_idx, ad_irq); + DRM_ERROR("enable irq %d error %d\n", irq_idx, ret); + sde_core_irq_unregister_callback(kms, irq_idx, ad_irq); + } else { + node->state = IRQ_ENABLED; } } + spin_unlock_irqrestore(&node->state_lock, flags); + exit: return ret; } @@ -1859,7 +1841,7 @@ static void sde_cp_hist_interrupt_cb(void *arg, int irq_idx) spin_unlock_irqrestore(&crtc->spin_lock, flags); if (!node) { - DRM_ERROR("cannot find histogram event node in crtc\n"); + DRM_DEBUG_DRIVER("cannot find histogram event node in crtc\n"); return; } @@ -1983,26 +1965,29 @@ int sde_cp_hist_interrupt(struct drm_crtc *crtc_drm, bool en, goto exit; } - node = _sde_cp_get_intr_node(DRM_EVENT_HISTOGRAM, crtc); + node = container_of(hist_irq, struct sde_crtc_irq_info, irq); /* deregister histogram irq */ if (!en) { - if (node) { - /* device suspend case or suspend to IPC cases */ + spin_lock_irqsave(&node->state_lock, flags); + if (node->state == IRQ_ENABLED) { + node->state = IRQ_DISABLING; + spin_unlock_irqrestore(&node->state_lock, flags); + ret = sde_core_irq_disable(kms, &irq_idx, 1); spin_lock_irqsave(&node->state_lock, flags); - if (node->state == IRQ_ENABLED) { - ret = sde_core_irq_disable(kms, &irq_idx, 1); - if (ret) - DRM_ERROR("disable irq %d error %d\n", - irq_idx, ret); - else - node->state = IRQ_NOINIT; + if (ret) { + DRM_ERROR("disable irq %d error %d\n", + irq_idx, ret); + node->state = IRQ_ENABLED; } else { node->state = IRQ_NOINIT; } spin_unlock_irqrestore(&node->state_lock, flags); + } else if (node->state == IRQ_DISABLED) { + node->state = IRQ_NOINIT; + spin_unlock_irqrestore(&node->state_lock, flags); } else { - DRM_ERROR("failed to get node from crtc event list\n"); + spin_unlock_irqrestore(&node->state_lock, flags); } sde_core_irq_unregister_callback(kms, irq_idx, hist_irq); @@ -2018,32 +2003,19 @@ int sde_cp_hist_interrupt(struct drm_crtc *crtc_drm, bool en, goto exit; } - if (node) { - /* device resume or resume from IPC cases */ - spin_lock_irqsave(&node->state_lock, flags); - if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) { - ret = sde_core_irq_enable(kms, &irq_idx, 1); - if (ret) { - DRM_ERROR("enable irq %d error %d\n", - irq_idx, ret); - sde_core_irq_unregister_callback(kms, - irq_idx, hist_irq); - } else { - node->state = IRQ_ENABLED; - } - } - spin_unlock_irqrestore(&node->state_lock, flags); - } else { - /* request from userspace to register the event - * in this case, node has not been added into the event list - */ + spin_lock_irqsave(&node->state_lock, flags); + if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) { ret = sde_core_irq_enable(kms, &irq_idx, 1); if (ret) { - DRM_ERROR("failed to enable irq ret %d\n", ret); + DRM_ERROR("enable irq %d error %d\n", irq_idx, ret); sde_core_irq_unregister_callback(kms, irq_idx, hist_irq); + } else { + node->state = IRQ_ENABLED; } } + spin_unlock_irqrestore(&node->state_lock, flags); + exit: return ret; } diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 310d6498df61..ee263ff2c04f 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -6102,10 +6102,10 @@ static int _sde_crtc_event_enable(struct sde_kms *kms, node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) return -ENOMEM; - node->event = event; INIT_LIST_HEAD(&node->list); node->func = custom_events[i].func; node->event = event; + node->state = IRQ_NOINIT; spin_lock_init(&node->state_lock); break; } @@ -6136,8 +6136,6 @@ static int _sde_crtc_event_enable(struct sde_kms *kms, if (!ret) { spin_lock_irqsave(&crtc->spin_lock, flags); - /* irq is regiestered and enabled and set the state */ - node->state = IRQ_ENABLED; list_add_tail(&node->list, &crtc->user_event_list); spin_unlock_irqrestore(&crtc->spin_lock, flags); } else { diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h index 37e197e1e37a..2e0f735ab0af 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.h +++ b/drivers/gpu/drm/msm/sde/sde_crtc.h @@ -379,6 +379,7 @@ struct sde_crtc_state { enum sde_crtc_irq_state { IRQ_NOINIT, IRQ_ENABLED, + IRQ_DISABLING, IRQ_DISABLED, }; -- GitLab From 545f545f14f1361b211729868ca66a7b8b4d2fde Mon Sep 17 00:00:00 2001 From: Xu Yang Date: Mon, 29 Jan 2018 14:03:10 +0800 Subject: [PATCH 0407/1299] drm/msm/sde: move AD4 to idle state when device suspend Move AD4 to idle state when device suspend. Change enforces AD4 initial strength to be 0 after device resume. Change-Id: I5fc486900b7bb38604d482a3418ef3b90a460f2a Signed-off-by: Xu Yang --- drivers/gpu/drm/msm/sde/sde_color_processing.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c index 02050a695fa2..6d3a9d1a4df4 100644 --- a/drivers/gpu/drm/msm/sde/sde_color_processing.c +++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c @@ -1176,6 +1176,7 @@ void sde_cp_crtc_suspend(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc = NULL; struct sde_cp_node *prop_node = NULL, *n = NULL; + bool ad_suspend = false; if (!crtc) { DRM_ERROR("crtc %pK\n", crtc); @@ -1198,8 +1199,12 @@ void sde_cp_crtc_suspend(struct drm_crtc *crtc) active_list) { sde_cp_update_list(prop_node, sde_crtc, true); list_del_init(&prop_node->active_list); + ad_suspend = true; } mutex_unlock(&sde_crtc->crtc_cp_lock); + + if (ad_suspend) + sde_cp_ad_set_prop(sde_crtc, AD_SUSPEND); } void sde_cp_crtc_resume(struct drm_crtc *crtc) -- GitLab From 4460cd9b2cbe535d03b92edeb6f0a9a9812c56ba Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 25 May 2018 13:57:22 +0530 Subject: [PATCH 0408/1299] drivers: mailbox: rpmh: Enhance debug logs Enhance debug log to print IRQ pending status at GIC and tasklet schedule status for rpmh timeout case. Also print waiting device name when retry to send data. Change-Id: Ifd83ee87b29bfff682c9facf34c91d186b29e1fd Signed-off-by: Maulik Shah --- drivers/mailbox/qcom-rpmh-mailbox.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/mailbox/qcom-rpmh-mailbox.c b/drivers/mailbox/qcom-rpmh-mailbox.c index 22aad2a2736c..2677ed0c3b3e 100644 --- a/drivers/mailbox/qcom-rpmh-mailbox.c +++ b/drivers/mailbox/qcom-rpmh-mailbox.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -128,6 +128,7 @@ struct rsc_drv { const char *name; void __iomem *base; /* start address of the RSC's registers */ void __iomem *reg_base; /* start address for DRV specific register */ + int irq; int drv_id; struct platform_device *pdev; struct tcs_mbox tcs[TCS_TYPE_NR]; @@ -877,6 +878,8 @@ static void dump_tcs_stats(struct rsc_drv *drv) { int i; unsigned long long curr = arch_counter_get_cntvct(); + struct irq_data *rsc_irq_data = irq_get_irq_data(drv->irq); + bool irq_sts; for (i = 0; i < drv->num_tcs; i++) { if (!atomic_read(&drv->tcs_in_use[i])) @@ -890,6 +893,20 @@ static void dump_tcs_stats(struct rsc_drv *drv) print_tcs_regs(drv, i); print_response(drv, i); } + + if (rsc_irq_data) { + irq_get_irqchip_state(drv->irq, IRQCHIP_STATE_PENDING, + &irq_sts); + pr_warn("HW IRQ %lu is %s at GIC\n", rsc_irq_data->hwirq, + irq_sts ? "PENDING" : "NOT PENDING"); + } + + if (test_bit(TASKLET_STATE_SCHED, &drv->tasklet.state)) + pr_warn("Tasklet is scheduled for execution\n"); + else if (test_bit(TASKLET_STATE_RUN, &drv->tasklet.state)) + pr_warn("Tasklet is running\n"); + else + pr_warn("Tasklet is not active\n"); } static void chan_debug(struct mbox_chan *chan) @@ -979,7 +996,8 @@ static int chan_tcs_write(struct mbox_chan *chan, void *data) /* If we were just busy waiting for TCS, dump the state and return */ if (ret == -EBUSY) { - pr_info_ratelimited("TCS Busy, retrying RPMH message send\n"); + dev_err_ratelimited(chan->cl->dev, + "TCS Busy, retrying RPMH message send\n"); ret = -EAGAIN; } @@ -1258,6 +1276,8 @@ static int rsc_drv_probe(struct platform_device *pdev) if (ret) return ret; + drv->irq = irq; + /* Enable interrupts for AMC TCS */ write_tcs_reg(drv->reg_base, RSC_DRV_IRQ_ENABLE, 0, 0, drv->tcs[ACTIVE_TCS].tcs_mask); -- GitLab From d4807bd60dc166a6445c3b13684f1d1afb722bc5 Mon Sep 17 00:00:00 2001 From: Naresh Maradana Date: Tue, 19 Jun 2018 14:34:49 +0530 Subject: [PATCH 0409/1299] selinux: Relocate ss_initialized and selinux_enforcing to separate 4k We need to relocate ss_initialized and selinux_enforcing to a separate 4k page to enable EL2 Hypervisor to monitor changes to this variable using ARM stage 2 MMU. We will avoid getting page faults from un-related data as the MMU granularity is configured to 4k. Change-Id: I904176b6772feb27065bddd89613f6280ed99891 Signed-off-by: Naresh Maradana --- arch/arm64/kernel/vmlinux.lds.S | 10 ++++++++++ include/linux/init.h | 2 ++ security/selinux/hooks.c | 2 +- security/selinux/ss/services.c | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index cb3e4393b412..8bdfb7a00d95 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -68,6 +68,12 @@ jiffies = jiffies_64; #define TRAMP_TEXT #endif +#define RTIC_BSS \ + . = ALIGN(PAGE_SIZE); \ + VMLINUX_SYMBOL(__bss_rtic_start) = .; \ + KEEP(*(.bss.rtic)) \ + . = ALIGN(PAGE_SIZE); \ + VMLINUX_SYMBOL(__bss_rtic_end) = .; /* * The size of the PE/COFF section that covers the kernel image, which * runs from stext to _edata, must be a round multiple of the PE/COFF @@ -237,6 +243,10 @@ SECTIONS STABS_DEBUG HEAD_SYMBOLS + + .bss : { /* bss segment */ + RTIC_BSS + } } /* diff --git a/include/linux/init.h b/include/linux/init.h index f138e5b918c2..d66317911c1a 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -289,6 +289,8 @@ void __init parse_early_options(char *cmdline); /* Data marked not to be saved by software suspend */ #define __nosavedata __section(.data..nosave) +#define __rticdata __attribute__((section(".bss.rtic"))) + #ifdef MODULE #define __exit_p(x) x #else diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2e3a627fc0b1..dd9ca3b13547 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -102,7 +102,7 @@ static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); #ifdef CONFIG_SECURITY_SELINUX_DEVELOP -int selinux_enforcing; +int selinux_enforcing __rticdata; static int __init enforcing_setup(char *str) { diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b275743e23cc..56766f038fe9 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -91,7 +91,7 @@ static DEFINE_RWLOCK(policy_rwlock); static struct sidtab sidtab; struct policydb policydb; -int ss_initialized; +int ss_initialized __rticdata; /* * The largest sequence number that has been used when -- GitLab From 9d73b66796a06afbfbd08bd8c0604cf414187b5c Mon Sep 17 00:00:00 2001 From: Monika Singh Date: Tue, 24 Apr 2018 09:54:50 +0530 Subject: [PATCH 0410/1299] ARM: dts: msm: Untrusted pointer dereference To avoid access of variable after being freed, using list_first_entry_safe function to iterate over list of given type,safe against removal of list entry. Change-Id: I70611fddf3e9b80b1affa3e5235be24eac0d0a58 Signed-off-by: Monika Singh --- drivers/misc/qseecom.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 11ef17750881..34a86fefa520 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -8787,6 +8787,7 @@ static int qseecom_probe(struct platform_device *pdev) static int qseecom_remove(struct platform_device *pdev) { struct qseecom_registered_kclient_list *kclient = NULL; + struct qseecom_registered_kclient_list *kclient_tmp = NULL; unsigned long flags = 0; int ret = 0; int i; @@ -8796,10 +8797,8 @@ static int qseecom_remove(struct platform_device *pdev) atomic_set(&qseecom.qseecom_state, QSEECOM_STATE_NOT_READY); spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags); - list_for_each_entry(kclient, &qseecom.registered_kclient_list_head, - list) { - if (!kclient) - goto exit_irqrestore; + list_for_each_entry_safe(kclient, kclient_tmp, + &qseecom.registered_kclient_list_head, list) { /* Break the loop if client handle is NULL */ if (!kclient->handle) @@ -8823,7 +8822,7 @@ static int qseecom_remove(struct platform_device *pdev) kzfree(kclient->handle); exit_free_kclient: kzfree(kclient); -exit_irqrestore: + spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags); if (qseecom.qseos_version > QSEEE_VERSION_00) -- GitLab From f7227015a322de34d851dd8edb6a33e443f4e96a Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Mon, 18 Jun 2018 16:13:09 +0530 Subject: [PATCH 0411/1299] ARM: dts: msm: Disable dynamic-loading from HLOS_PHYSPOOL for qcs405 Hypervisor is not supported on qcs405 and XPU allocated for fastrpc is needed to lock remote heap memory, hence disable dynamic loading of shared objects from HLOS_PHYSPOOL. Change-Id: I39d4bdb98ab746aa8df8321a6d82d0c11943f663 Acked-by: Chenna Kesava Raju Signed-off-by: Tharun Kumar Merugu --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 275710a6cdf4..8bb84d8e4bb1 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -585,6 +585,7 @@ qcom,rpc-latency-us = <611>; qcom,fastrpc-adsp-audio-pdr; qcom,fastrpc-adsp-sensors-pdr; + qcom,fastrpc-legacy-remote-heap; qcom,msm_fastrpc_compute_cb1 { compatible = "qcom,msm-fastrpc-compute-cb"; -- GitLab From 2c65ebb18486b11f8e65c257330508e63bc7b4ba Mon Sep 17 00:00:00 2001 From: Srinivas Rao L Date: Thu, 24 May 2018 16:34:47 +0530 Subject: [PATCH 0412/1299] ARM: dts: msm: Add LPM nodes for sdmmagpie Add different low power mode nodes supported, rpm stats node and rpmh master stats node. Change-Id: I32d000d4c3177a534877d7d03c18709911d8ebc3 Signed-off-by: Srinivas Rao L --- arch/arm64/boot/dts/qcom/sdmmagpie-pm.dtsi | 172 +++++++++++++++++++++ arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 1 + 2 files changed, 173 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sdmmagpie-pm.dtsi diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-pm.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-pm.dtsi new file mode 100644 index 000000000000..d12395384a45 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-pm.dtsi @@ -0,0 +1,172 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + qcom,lpm-levels { + compatible = "qcom,lpm-levels"; + #address-cells = <1>; + #size-cells = <0>; + + qcom,pm-cluster@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + label = "L3"; + qcom,psci-mode-shift = <4>; + qcom,psci-mode-mask = <0xfff>; + + qcom,pm-cluster-level@0 { /* D1 */ + reg = <0>; + label = "l3-wfi"; + qcom,psci-mode = <0x1>; + qcom,latency-us = <600>; + qcom,ss-power = <420>; + qcom,energy-overhead = <4254140>; + qcom,time-overhead = <1260>; + }; + + qcom,pm-cluster-level@1 { /* D4 */ + reg = <1>; + label = "l3-pc"; + qcom,psci-mode = <0x4>; + qcom,latency-us = <3048>; + qcom,ss-power = <329>; + qcom,energy-overhead = <6189829>; + qcom,time-overhead = <5800>; + qcom,min-child-idx = <2>; + qcom,is-reset; + }; + + qcom,pm-cluster-level@2 { /* Cx Off */ + reg = <2>; + label = "cx-off"; + qcom,psci-mode = <0x224>; + qcom,latency-us = <4562>; + qcom,ss-power = <290>; + qcom,energy-overhead = <6989829>; + qcom,time-overhead = <8200>; + qcom,min-child-idx = <2>; + qcom,is-reset; + qcom,notify-rpm; + }; + + qcom,pm-cluster-level@3 { /* LLCC off, AOSS sleep */ + reg = <3>; + label = "llcc-off"; + qcom,psci-mode = <0xC24>; + qcom,latency-us = <6562>; + qcom,ss-power = <165>; + qcom,energy-overhead = <7000029>; + qcom,time-overhead = <9825>; + qcom,min-child-idx = <2>; + qcom,is-reset; + qcom,notify-rpm; + }; + + qcom,pm-cpu@0 { + #address-cells = <1>; + #size-cells = <0>; + qcom,psci-mode-shift = <0>; + qcom,psci-mode-mask = <0xf>; + qcom,cpu = <&CPU0 &CPU1 &CPU2 &CPU3 &CPU4 + &CPU5>; + + qcom,pm-cpu-level@0 { /* C1 */ + reg = <0>; + label = "wfi"; + qcom,psci-cpu-mode = <0x1>; + qcom,latency-us = <60>; + qcom,ss-power = <383>; + qcom,energy-overhead = <64140>; + qcom,time-overhead = <121>; + }; + + qcom,pm-cpu-level@1 { /* C3 */ + reg = <1>; + label = "pc"; + qcom,psci-cpu-mode = <0x3>; + qcom,latency-us = <901>; + qcom,ss-power = <364>; + qcom,energy-overhead = <579285>; + qcom,time-overhead = <1450>; + qcom,is-reset; + qcom,use-broadcast-timer; + }; + + qcom,pm-cpu-level@2 { /* C4 */ + reg = <2>; + label = "rail-pc"; + qcom,psci-cpu-mode = <0x4>; + qcom,latency-us = <915>; + qcom,ss-power = <353>; + qcom,energy-overhead = <666292>; + qcom,time-overhead = <1617>; + qcom,is-reset; + qcom,use-broadcast-timer; + }; + }; + + qcom,pm-cpu@1 { + #address-cells = <1>; + #size-cells = <0>; + qcom,psci-mode-shift = <0>; + qcom,psci-mode-mask = <0xf>; + qcom,cpu = <&CPU6 &CPU7>; + + qcom,pm-cpu-level@0 { /* C1 */ + reg = <0>; + label = "wfi"; + qcom,psci-cpu-mode = <0x1>; + qcom,latency-us = <66>; + qcom,ss-power = <427>; + qcom,energy-overhead = <68410>; + qcom,time-overhead = <121>; + }; + + qcom,pm-cpu-level@1 { /* C3 */ + reg = <1>; + label = "pc"; + qcom,psci-cpu-mode = <0x3>; + qcom,latency-us = <1244>; + qcom,ss-power = <373>; + qcom,energy-overhead = <795006>; + qcom,time-overhead = <1767>; + qcom,is-reset; + qcom,use-broadcast-timer; + }; + + qcom,pm-cpu-level@2 { /* C4 */ + reg = <2>; + label = "rail-pc"; + qcom,psci-cpu-mode = <0x4>; + qcom,latency-us = <1854>; + qcom,ss-power = <359>; + qcom,energy-overhead = <1068095>; + qcom,time-overhead = <2380>; + qcom,is-reset; + qcom,use-broadcast-timer; + }; + }; + }; + }; + + qcom,rpm-stats@c300000 { + compatible = "qcom,rpm-stats"; + reg = <0xc300000 0x1000>, <0xc3f0004 0x4>; + reg-names = "phys_addr_base", "offset_addr"; + }; + + qcom,rpmh-master-stats@b221200 { + compatible = "qcom,rpmh-master-stats-v1"; + reg = <0xb221200 0x60>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index 92d97ab53b5b..68510df7fcff 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -1006,3 +1006,4 @@ #include "sdmmagpie-ion.dtsi" #include "msm-arm-smmu-sdmmagpie.dtsi" +#include "sdmmagpie-pm.dtsi" -- GitLab From 3c07b3ad2b77e0409e7f4ea44451bb5a2e131960 Mon Sep 17 00:00:00 2001 From: Srinivas Rao L Date: Fri, 25 May 2018 12:56:45 +0530 Subject: [PATCH 0413/1299] drivers: irqchip: qcom: Add PDC pin data for sdmmagpie Add the pdc pin input mapping and config. Change-Id: Ie13a3d63df4573a306f08d5a2242e3fd23592181 Signed-off-by: Srinivas Rao L --- .../qti,pdc-sdmmagpie.txt | 63 +++++++ drivers/irqchip/qcom/Kconfig | 10 ++ drivers/irqchip/qcom/Makefile | 1 + drivers/irqchip/qcom/pdc-sdmmagpie.c | 154 ++++++++++++++++++ 4 files changed, 228 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sdmmagpie.txt create mode 100644 drivers/irqchip/qcom/pdc-sdmmagpie.c diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sdmmagpie.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sdmmagpie.txt new file mode 100644 index 000000000000..968019c5ad99 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc-sdmmagpie.txt @@ -0,0 +1,63 @@ +QTI PDC interrupt controller + +PDC is QTI's platform parent interrupt controller that serves as wakeup source. + +Newer QTI SOCs are replacing MPM (MSM sleep Power Manager) with PDC (Power +Domain Controller) to manage subsystem wakeups and resources during sleep. +This driver marks the wakeup interrupts in APSS PDC such that it monitors the +interrupts when the system is asleep, wakes up the APSS when one of these +interrupts occur and replays it to the subsystem interrupt controller after it +becomes operational. + +Earlier MPM architecture used arch-extension of GIC interrupt +controller to mark enabled wake-up interrupts and monitor these when the +system goes to sleep. Since the arch-extensions are no-longer available +on newer kernel versions, this driver is implemented as hierarchical irq +domain. GIC is parent interrupt controller at the highest level. +Platform interrupt controller PDC is next in hierarchy, followed by others. +This driver only configures the interrupts, does not handle them. + +PDC interrupt configuration involves programming of 2 set of registers: +IRQ_ENABLE_BANK - Enable the irq +IRQ_i_CFG - Configure the interrupt i + +Properties: + +- compatible: + Usage: required + Value type: + Definition: Should contain "qcom,pdc-" + +- reg: + Usage: required + Value type: + Definition: Specifies the base physical address for PDC hardware + block for DRV2. + +- interrupt-cells: + Usage: required + Value type: + Definition: Specifies the number of cells needed to encode an interrupt source. + Value must be 3. + The encoding of these cells are same as described in + Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt + +- interrupt-parent: + Usage: required + Value type: + Definition: Specifies the interrupt parent necessary for hierarchical domain to operate. + +- interrupt-controller: + Usage: required + Value type: + Definition: Identifies the node as an interrupt controller. + +Example: + +pdcgic: interrupt-controller@0xb220000{ + compatible = "qcom,pdc-sdmmagpie"; + reg = <0xb220000 0x30000>; + #interrupt-cells = <3>; + interrupt-parent = <&intc>; + interrupt-controller; +}; diff --git a/drivers/irqchip/qcom/Kconfig b/drivers/irqchip/qcom/Kconfig index 6f5dff0bda53..5d9a9b82544f 100644 --- a/drivers/irqchip/qcom/Kconfig +++ b/drivers/irqchip/qcom/Kconfig @@ -21,6 +21,16 @@ config QTI_PDC_SM6150 help QTI Power Domain Controller for SM6150 +config QTI_PDC_SDMMAGPIE + bool "QTI PDC SDMMAGPIE" + select QTI_PDC + default y if ARCH_SDMMAGPIE + help + QTI Power Domain Controller for SDMMAGPIE + This is used for managing and configuring + the wakeup interrupts. Enable it when + ARCH_SDMMAGPIE is selected. + config QTI_MPM bool "QTI MPM" depends on ARCH_QCOM diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile index 62582613438d..d879a5e0eb7a 100644 --- a/drivers/irqchip/qcom/Makefile +++ b/drivers/irqchip/qcom/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_QTI_PDC) += pdc.o obj-$(CONFIG_QTI_PDC_SM8150) += pdc-sm8150.o obj-$(CONFIG_QTI_PDC_SM6150) += pdc-sm6150.o +obj-$(CONFIG_QTI_PDC_SDMMAGPIE) += pdc-sdmmagpie.o obj-$(CONFIG_QTI_MPM) += mpm.o obj-$(CONFIG_QTI_MPM) += mpm.o mpm-8937.o diff --git a/drivers/irqchip/qcom/pdc-sdmmagpie.c b/drivers/irqchip/qcom/pdc-sdmmagpie.c new file mode 100644 index 000000000000..04c24d6b2745 --- /dev/null +++ b/drivers/irqchip/qcom/pdc-sdmmagpie.c @@ -0,0 +1,154 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include "pdc.h" + +static struct pdc_pin sdmmagpie_data[] = { + {0, 512},/*rpmh_wake*/ + {1, 513},/*ee0_apps_hlos_spmi_periph_irq*/ + {2, 514},/*ee1_apps_trustzone_spmi_periph_irq*/ + {3, 515},/*secure_wdog_expired*/ + {4, 516},/*secure_wdog_bark_irq*/ + {5, 517},/*aop_wdog_expired_irq*/ + {6, 518},/*qmp_usb3_lfps_rxterm_irq*/ + {6, 518},/*qmp_usb3_lfps_rxterm_irq*/ + {7, 519},/*not-connected*/ + {8, 520},/*eud_p0_dmse_int_mx*/ + {9, 521},/*eud_p0_dpse_int_mx*/ + {10, 522},/*not-connected*/ + {11, 523},/*not-connected*/ + {12, 524},/*eud_int_mx[1]*/ + {13, 525},/*ssc_xpu_irq_summary*/ + {14, 526},/*wd_bite_apps*/ + {15, 527},/*ssc_vmidmt_irq_summary*/ + {16, 528},/*sdc_gpo[0]*/ + {17, 529},/*not-connected*/ + {18, 530},/*aoss_pmic_arb_mpu_xpu_summary_irq*/ + {19, 531},/*rpmh_wake_2*/ + {20, 532},/*apps_pdc_irq_in_20*/ + {21, 533},/*apps_pdc_irq_in_21*/ + {22, 534},/*pdc_apps_epcb_timeout_summary_irq*/ + {23, 535},/*spmi_protocol_irq*/ + {24, 536},/*tsense0_tsense_max_min_int*/ + {25, 537},/*tsense1_tsense_max_min_int*/ + {26, 538},/*tsense0_upper_lower_intr*/ + {27, 539},/*tsense1_upper_lower_intr*/ + {28, 540},/*tsense0_critical_intr*/ + {29, 541},/*tsense1_critical_intr*/ + {30, 542},/*apps_pdc.gp_irq_mux[0]*/ + {31, 543},/*apps_pdc.gp_irq_mux[1]*/ + {32, 544},/*apps_pdc.gp_irq_mux[2]*/ + {33, 545},/*apps_pdc.gp_irq_mux[3]*/ + {34, 546},/*apps_pdc.gp_irq_mux[4]*/ + {35, 547},/*apps_pdc.gp_irq_mux[5]*/ + {36, 548},/*apps_pdc.gp_irq_mux[6]*/ + {37, 549},/*apps_pdc.gp_irq_mux[7]*/ + {38, 550},/*apps_pdc.gp_irq_mux[8]*/ + {39, 551},/*apps_pdc.gp_irq_mux[9]*/ + {40, 552},/*apps_pdc.gp_irq_mux[10]*/ + {41, 553},/*apps_pdc.gp_irq_mux[11]*/ + {42, 554},/*apps_pdc.gp_irq_mux[12]*/ + {43, 555},/*apps_pdc.gp_irq_mux[13]*/ + {44, 556},/*apps_pdc.gp_irq_mux[14]*/ + {45, 557},/*apps_pdc.gp_irq_mux[15]*/ + {46, 558},/*apps_pdc.gp_irq_mux[16]*/ + {47, 559},/*apps_pdc.gp_irq_mux[17]*/ + {48, 560},/*apps_pdc.gp_irq_mux[18]*/ + {49, 561},/*apps_pdc.gp_irq_mux[19]*/ + {50, 562},/*apps_pdc.gp_irq_mux[20]*/ + {51, 563},/*apps_pdc.gp_irq_mux[21]*/ + {52, 564},/*apps_pdc.gp_irq_mux[22]*/ + {53, 565},/*apps_pdc.gp_irq_mux[23]*/ + {54, 566},/*apps_pdc.gp_irq_mux[24]*/ + {55, 567},/*apps_pdc.gp_irq_mux[25]*/ + {56, 568},/*apps_pdc.gp_irq_mux[26]*/ + {57, 569},/*apps_pdc.gp_irq_mux[27]*/ + {58, 570},/*apps_pdc.gp_irq_mux[28]*/ + {59, 571},/*apps_pdc.gp_irq_mux[29]*/ + {60, 572},/*apps_pdc.gp_irq_mux[30]*/ + {61, 573},/*apps_pdc.gp_irq_mux[31]*/ + {62, 574},/*apps_pdc.gp_irq_mux[32]*/ + {63, 575},/*apps_pdc.gp_irq_mux[33]*/ + {64, 576},/*apps_pdc.gp_irq_mux[34]*/ + {65, 577},/*apps_pdc.gp_irq_mux[35]*/ + {66, 578},/*apps_pdc.gp_irq_mux[36]*/ + {67, 579},/*apps_pdc.gp_irq_mux[37]*/ + {68, 580},/*apps_pdc.gp_irq_mux[38]*/ + {69, 581},/*apps_pdc.gp_irq_mux[39]*/ + {70, 582},/*apps_pdc.gp_irq_mux[40]*/ + {71, 583},/*apps_pdc.gp_irq_mux[41]*/ + {72, 584},/*apps_pdc.gp_irq_mux[42]*/ + {73, 585},/*apps_pdc.gp_irq_mux[43]*/ + {74, 586},/*apps_pdc.gp_irq_mux[44]*/ + {75, 587},/*apps_pdc.gp_irq_mux[45]*/ + {76, 588},/*apps_pdc.gp_irq_mux[46]*/ + {77, 589},/*apps_pdc.gp_irq_mux[47]*/ + {78, 590},/*apps_pdc.gp_irq_mux[48]*/ + {79, 591},/*apps_pdc.gp_irq_mux[49]*/ + {80, 592},/*apps_pdc.gp_irq_mux[50]*/ + {81, 593},/*apps_pdc.gp_irq_mux[51]*/ + {82, 594},/*apps_pdc.gp_irq_mux[52]*/ + {83, 595},/*apps_pdc.gp_irq_mux[53]*/ + {84, 596},/*apps_pdc.gp_irq_mux[54]*/ + {85, 597},/*apps_pdc.gp_irq_mux[55]*/ + {86, 598},/*apps_pdc.gp_irq_mux[56]*/ + {87, 599},/*apps_pdc.gp_irq_mux[57]*/ + {88, 600},/*apps_pdc.gp_irq_mux[58]*/ + {89, 601},/*apps_pdc.gp_irq_mux[59]*/ + {90, 602},/*apps_pdc.gp_irq_mux[60]*/ + {91, 603},/*apps_pdc.gp_irq_mux[61]*/ + {92, 604},/*apps_pdc.gp_irq_mux[62]*/ + {93, 605},/*apps_pdc.gp_irq_mux[63]*/ + {94, 641},/*apps_pdc.gp_irq_mux[64]*/ + {95, 642},/*apps_pdc.gp_irq_mux[65]*/ + {96, 643},/*apps_pdc.gp_irq_mux[66]*/ + {97, 644},/*apps_pdc.gp_irq_mux[67]*/ + {98, 645},/*apps_pdc.gp_irq_mux[68]*/ + {99, 646},/*apps_pdc.gp_irq_mux[69]*/ + {100, 647},/*apps_pdc.gp_irq_mux[70]*/ + {101, 648},/*apps_pdc.gp_irq_mux[71]*/ + {102, 649},/*apps_pdc.gp_irq_mux[72]*/ + {103, 650},/*apps_pdc.gp_irq_mux[73]*/ + {104, 651},/*apps_pdc.gp_irq_mux[74]*/ + {105, 652},/*apps_pdc.gp_irq_mux[75]*/ + {106, 653},/*apps_pdc.gp_irq_mux[76]*/ + {107, 654},/*apps_pdc.gp_irq_mux[77]*/ + {108, 655},/*apps_pdc.gp_irq_mux[78]*/ + {109, 656},/*apps_pdc.gp_irq_mux[79]*/ + {110, 657},/*apps_pdc.gp_irq_mux[80]*/ + {111, 658},/*apps_pdc.gp_irq_mux[81]*/ + {112, 659},/*apps_pdc.gp_irq_mux[82]*/ + {113, 660},/*apps_pdc.gp_irq_mux[83]*/ + {114, 661},/*apps_pdc.gp_irq_mux[84]*/ + {115, 662},/*apps_pdc.gp_irq_mux[85]*/ + {116, 663},/*apps_pdc.gp_irq_mux[86]*/ + {117, 664},/*apps_pdc.gp_irq_mux[87]*/ + {118, 665},/*apps_pdc.gp_irq_mux[88]*/ + {119, 666},/*apps_pdc.gp_irq_mux[89]*/ + {120, 667},/*apps_pdc.gp_irq_mux[90]*/ + {121, 668},/*apps_pdc.gp_irq_mux[91]*/ + {122, 669},/*apps_pdc.gp_irq_mux[92]*/ + {123, 670},/*apps_pdc.gp_irq_mux[93]*/ + {124, 671},/*apps_pdc.gp_irq_mux[94]*/ + {125, 95},/*apps_pdc.gp_irq_mux[95]*/ + {-1} +}; + +static int __init qcom_pdc_gic_init(struct device_node *node, + struct device_node *parent) +{ + return qcom_pdc_init(node, parent, sdmmagpie_data); +} + +IRQCHIP_DECLARE(pdc_sdmmagpie, "qcom,pdc-sdmmagpie", qcom_pdc_gic_init); -- GitLab From 9cac8592d49bf9a947557d264bf3b9c0f8eafd7f Mon Sep 17 00:00:00 2001 From: Srinivas Rao L Date: Fri, 25 May 2018 17:15:24 +0530 Subject: [PATCH 0414/1299] ARM: dts: msm: Add PDC interrupt controller for sdmmagpie Add pdc interrupt controller as SOC interrupt parent and as a child domain under intc. Change-Id: I3c375c4fac2e5a227550fd1a0aab2c4c71ab2efe Signed-off-by: Srinivas Rao L --- arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index 68510df7fcff..1245487d5239 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -24,7 +24,7 @@ model = "Qualcomm Technologies, Inc. SDMMAGPIE"; compatible = "qcom,sdmmagpie"; qcom,msm-id = <365 0x0>; - interrupt-parent = <&intc>; + interrupt-parent = <&pdc>; cpus { #address-cells = <2>; @@ -511,6 +511,14 @@ interrupt-parent = <&intc>; }; + pdc: interrupt-controller@b220000 { + compatible = "qcom,pdc-sdmmagpie"; + reg = <0xb220000 0x400>; + #interrupt-cells = <3>; + interrupt-parent = <&intc>; + interrupt-controller; + }; + timer { compatible = "arm,armv8-timer"; interrupts = , -- GitLab From c57c9844305ac99e612cddd78d9eb25f584a882d Mon Sep 17 00:00:00 2001 From: Ahmad Masri Date: Tue, 19 Jun 2018 14:29:43 +0300 Subject: [PATCH 0415/1299] wil6210: align to latest auto generated wmi.h Align to latest version of the auto generated wmi file describing the interface with FW Change-Id: I64189702d629e5c6f2c84fed0dd59170896f4464 Signed-off-by: Ahmad Masri Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 8a4fa21438e38ed2db8c01a282de3995a6c0d75f Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git [merez@codeaurora.org: trivial conflict fixes] --- drivers/net/wireless/ath/wil6210/wmi.c | 6 +- drivers/net/wireless/ath/wil6210/wmi.h | 387 +++++++++++++++++++++++-- 2 files changed, 371 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 4d2aea70e35d..a3e20af59ea0 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1669,7 +1669,9 @@ int wmi_pcp_start(struct wil6210_vif *vif, .pcp_max_assoc_sta = max_assoc_sta, .hidden_ssid = hidden_ssid, .is_go = is_go, - .disable_ap_sme = disable_ap_sme, + .ap_sme_offload_mode = disable_ap_sme ? + WMI_AP_SME_OFFLOAD_PARTIAL : + WMI_AP_SME_OFFLOAD_FULL, .abft_len = wil->abft_len, }; struct { @@ -1689,7 +1691,7 @@ int wmi_pcp_start(struct wil6210_vif *vif, } if (disable_ap_sme && - !test_bit(WMI_FW_CAPABILITY_DISABLE_AP_SME, + !test_bit(WMI_FW_CAPABILITY_AP_SME_OFFLOAD_PARTIAL, wil->fw_capabilities)) { wil_err(wil, "disable_ap_sme not supported by FW\n"); return -EOPNOTSUPP; diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 329c5aea8b3d..b2de674ecce2 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * Copyright (c) 2006-2012 Wilocity * @@ -29,8 +30,6 @@ #ifndef __WILOCITY_WMI_H__ #define __WILOCITY_WMI_H__ -/* General */ -#define WMI_MAX_ASSOC_STA (8) #define WMI_DEFAULT_ASSOC_STA (1) #define WMI_MAC_LEN (6) #define WMI_PROX_RANGE_NUM (3) @@ -41,6 +40,19 @@ #define WMI_RF_ETYPE_LENGTH (3) #define WMI_RF_RX2TX_LENGTH (3) #define WMI_RF_ETYPE_VAL_PER_RANGE (5) +/* DTYPE configuration array size + * must always be kept equal to (WMI_RF_DTYPE_LENGTH+1) + */ +#define WMI_RF_DTYPE_CONF_LENGTH (4) +/* ETYPE configuration array size + * must always be kept equal to + * (WMI_RF_ETYPE_LENGTH+WMI_RF_ETYPE_VAL_PER_RANGE) + */ +#define WMI_RF_ETYPE_CONF_LENGTH (8) +/* RX2TX configuration array size + * must always be kept equal to (WMI_RF_RX2TX_LENGTH+1) + */ +#define WMI_RF_RX2TX_CONF_LENGTH (4) /* Mailbox interface * used for commands and events @@ -61,7 +73,7 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_PS_CONFIG = 1, WMI_FW_CAPABILITY_RF_SECTORS = 2, WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT = 3, - WMI_FW_CAPABILITY_DISABLE_AP_SME = 4, + WMI_FW_CAPABILITY_AP_SME_OFFLOAD_PARTIAL = 4, WMI_FW_CAPABILITY_WMI_ONLY = 5, WMI_FW_CAPABILITY_THERMAL_THROTTLING = 7, WMI_FW_CAPABILITY_D3_SUSPEND = 8, @@ -74,6 +86,7 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_PNO = 15, WMI_FW_CAPABILITY_CONNECT_SNR_THR = 16, WMI_FW_CAPABILITY_REF_CLOCK_CONTROL = 18, + WMI_FW_CAPABILITY_AP_SME_OFFLOAD_NONE = 19, WMI_FW_CAPABILITY_AMSDU = 23, WMI_FW_CAPABILITY_MAX, }; @@ -167,12 +180,14 @@ enum wmi_command_id { WMI_SET_ACTIVE_SILENT_RSSI_TABLE_CMDID = 0x85C, WMI_RF_PWR_ON_DELAY_CMDID = 0x85D, WMI_SET_HIGH_POWER_TABLE_PARAMS_CMDID = 0x85E, + WMI_FIXED_SCHEDULING_UL_CONFIG_CMDID = 0x85F, /* Performance monitoring commands */ WMI_BF_CTRL_CMDID = 0x862, WMI_NOTIFY_REQ_CMDID = 0x863, WMI_GET_STATUS_CMDID = 0x864, WMI_GET_RF_STATUS_CMDID = 0x866, WMI_GET_BASEBAND_TYPE_CMDID = 0x867, + WMI_VRING_SWITCH_TIMING_CONFIG_CMDID = 0x868, WMI_UNIT_TEST_CMDID = 0x900, WMI_FLASH_READ_CMDID = 0x902, WMI_FLASH_WRITE_CMDID = 0x903, @@ -205,6 +220,7 @@ enum wmi_command_id { WMI_GET_THERMAL_THROTTLING_CFG_CMDID = 0x941, /* Read Power Save profile type */ WMI_PS_DEV_PROFILE_CFG_READ_CMDID = 0x942, + WMI_TSF_SYNC_CMDID = 0x973, WMI_TOF_SESSION_START_CMDID = 0x991, WMI_TOF_GET_CAPABILITIES_CMDID = 0x992, WMI_TOF_SET_LCR_CMDID = 0x993, @@ -221,6 +237,7 @@ enum wmi_command_id { WMI_PRIO_TX_SECTORS_ORDER_CMDID = 0x9A5, WMI_PRIO_TX_SECTORS_NUMBER_CMDID = 0x9A6, WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_CMDID = 0x9A7, + WMI_BF_CONTROL_CMDID = 0x9AA, WMI_TX_STATUS_RING_ADD_CMDID = 0x9C0, WMI_RX_STATUS_RING_ADD_CMDID = 0x9C1, WMI_TX_DESC_RING_ADD_CMDID = 0x9C2, @@ -232,6 +249,10 @@ enum wmi_command_id { WMI_ENABLE_FIXED_SCHEDULING_CMDID = 0xA03, WMI_SET_MULTI_DIRECTED_OMNIS_CONFIG_CMDID = 0xA04, WMI_SET_LONG_RANGE_CONFIG_CMDID = 0xA05, + WMI_GET_ASSOC_LIST_CMDID = 0xA06, + WMI_GET_CCA_INDICATIONS_CMDID = 0xA07, + WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_CMDID = 0xA08, + WMI_INTERNAL_FW_IOCTL_CMDID = 0xA0B, WMI_SET_MAC_ADDRESS_CMDID = 0xF003, WMI_ABORT_SCAN_CMDID = 0xF007, WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041, @@ -493,6 +514,18 @@ enum wmi_rf_mgmt_type { WMI_RF_MGMT_GET_STATUS = 0x02, }; +/* WMI_BF_CONTROL_CMDID */ +enum wmi_bf_triggers { + WMI_BF_TRIGGER_RS_MCS1_TH_FAILURE = 0x01, + WMI_BF_TRIGGER_RS_MCS1_NO_BACK_FAILURE = 0x02, + WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_TXOP = 0x04, + WMI_BF_TRIGGER_MAX_BACK_FAILURE = 0x08, + WMI_BF_TRIGGER_FW = 0x10, + WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_KEEP_ALIVE = 0x20, + WMI_BF_TRIGGER_AOA = 0x40, + WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_UPM = 0x80, +}; + /* WMI_RF_MGMT_CMDID */ struct wmi_rf_mgmt_cmd { __le32 rf_mgmt_type; @@ -528,7 +561,9 @@ struct wmi_bcon_ctrl_cmd { u8 disable_sec; u8 hidden_ssid; u8 is_go; - u8 reserved[2]; + /* A-BFT length override if non-0 */ + u8 abft_len; + u8 reserved; } __packed; /* WMI_PORT_ALLOCATE_CMDID */ @@ -593,6 +628,16 @@ struct wmi_power_mgmt_cfg_cmd { u8 reserved[3]; } __packed; +/* WMI_PCP_START_CMDID */ +enum wmi_ap_sme_offload_mode { + /* Full AP SME in FW */ + WMI_AP_SME_OFFLOAD_FULL = 0x00, + /* Probe AP SME in FW */ + WMI_AP_SME_OFFLOAD_PARTIAL = 0x01, + /* AP SME in host */ + WMI_AP_SME_OFFLOAD_NONE = 0x02, +}; + /* WMI_PCP_START_CMDID */ struct wmi_pcp_start_cmd { __le16 bcon_interval; @@ -602,7 +647,8 @@ struct wmi_pcp_start_cmd { u8 reserved0[5]; /* A-BFT length override if non-0 */ u8 abft_len; - u8 disable_ap_sme; + /* enum wmi_ap_sme_offload_mode_e */ + u8 ap_sme_offload_mode; u8 network_type; u8 channel; u8 disable_sec_offload; @@ -616,6 +662,17 @@ struct wmi_sw_tx_req_cmd { u8 payload[0]; } __packed; +/* WMI_VRING_SWITCH_TIMING_CONFIG_CMDID */ +struct wmi_vring_switch_timing_config_cmd { + /* Set vring timing configuration: + * + * defined interval for vring switch + */ + __le32 interval_usec; + /* vring inactivity threshold */ + __le32 idle_th_usec; +} __packed; + struct wmi_sw_ring_cfg { __le64 ring_mem_base; __le16 ring_size; @@ -651,6 +708,7 @@ enum wmi_vring_cfg_schd_params_priority { WMI_SCH_PRIO_HIGH = 0x01, }; +#define CIDXTID_EXTENDED_CID_TID (0xFF) #define CIDXTID_CID_POS (0) #define CIDXTID_CID_LEN (4) #define CIDXTID_CID_MSK (0xF) @@ -671,6 +729,9 @@ struct wmi_vring_cfg { struct wmi_sw_ring_cfg tx_sw_ring; /* 0-23 vrings */ u8 ringid; + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 encap_trans_type; /* 802.3 DS cfg */ @@ -680,6 +741,11 @@ struct wmi_vring_cfg { u8 to_resolution; u8 agg_max_wsize; struct wmi_vring_cfg_schd schd_params; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved[2]; } __packed; enum wmi_vring_cfg_cmd_action { @@ -949,12 +1015,20 @@ struct wmi_cfg_rx_chain_cmd { /* WMI_RCP_ADDBA_RESP_CMDID */ struct wmi_rcp_addba_resp_cmd { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 dialog_token; __le16 status_code; /* ieee80211_ba_parameterset field to send */ __le16 ba_param_set; __le16 ba_timeout; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved[2]; } __packed; /* WMI_RCP_ADDBA_RESP_EDMA_CMDID */ @@ -974,13 +1048,24 @@ struct wmi_rcp_addba_resp_edma_cmd { /* WMI_RCP_DELBA_CMDID */ struct wmi_rcp_delba_cmd { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 reserved; __le16 reason; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved2[2]; } __packed; /* WMI_RCP_ADDBA_REQ_CMDID */ struct wmi_rcp_addba_req_cmd { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 dialog_token; /* ieee80211_ba_parameterset field as it received */ @@ -988,6 +1073,11 @@ struct wmi_rcp_addba_req_cmd { __le16 ba_timeout; /* ieee80211_ba_seqstrl field as it received */ __le16 ba_seq_ctrl; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved[2]; } __packed; /* WMI_SET_MAC_ADDRESS_CMDID */ @@ -998,15 +1088,20 @@ struct wmi_set_mac_address_cmd { /* WMI_ECHO_CMDID * Check FW is alive - * WMI_DEEP_ECHO_CMDID - * Check FW and ucode are alive * Returned event: WMI_ECHO_RSP_EVENTID - * same event for both commands */ struct wmi_echo_cmd { __le32 value; } __packed; +/* WMI_DEEP_ECHO_CMDID + * Check FW and ucode are alive + * Returned event: WMI_ECHO_RSP_EVENTID + */ +struct wmi_deep_echo_cmd { + __le32 value; +} __packed; + /* WMI_RF_PWR_ON_DELAY_CMDID * set FW time parameters used through RF resetting * RF reset consists of bringing its power down for a period of time, then @@ -1024,7 +1119,7 @@ struct wmi_rf_pwr_on_delay_cmd { __le16 up_delay_usec; } __packed; -/* \WMI_SET_HIGH_POWER_TABLE_PARAMS_CMDID +/* WMI_SET_HIGH_POWER_TABLE_PARAMS_CMDID * This API controls the Tx and Rx gain over temperature. * It controls the Tx D-type, Rx D-type and Rx E-type amplifiers. * It also controls the Tx gain index, by controlling the Rx to Tx gain index @@ -1038,25 +1133,46 @@ struct wmi_set_high_power_table_params_cmd { u8 tx_dtype_temp[WMI_RF_DTYPE_LENGTH]; u8 reserved0; /* Tx D-type values to be used for each temperature range */ - __le32 tx_dtype_conf[WMI_RF_DTYPE_LENGTH + 1]; + __le32 tx_dtype_conf[WMI_RF_DTYPE_CONF_LENGTH]; + /* Temperature range for Tx E-type parameters */ + u8 tx_etype_temp[WMI_RF_ETYPE_LENGTH]; + u8 reserved1; + /* Tx E-type values to be used for each temperature range. + * The last 4 values of any range are the first 4 values of the next + * range and so on + */ + __le32 tx_etype_conf[WMI_RF_ETYPE_CONF_LENGTH]; /* Temperature range for Rx D-type parameters */ u8 rx_dtype_temp[WMI_RF_DTYPE_LENGTH]; - u8 reserved1; + u8 reserved2; /* Rx D-type values to be used for each temperature range */ - __le32 rx_dtype_conf[WMI_RF_DTYPE_LENGTH + 1]; + __le32 rx_dtype_conf[WMI_RF_DTYPE_CONF_LENGTH]; /* Temperature range for Rx E-type parameters */ u8 rx_etype_temp[WMI_RF_ETYPE_LENGTH]; - u8 reserved2; + u8 reserved3; /* Rx E-type values to be used for each temperature range. * The last 4 values of any range are the first 4 values of the next * range and so on */ - __le32 rx_etype_conf[WMI_RF_ETYPE_VAL_PER_RANGE + WMI_RF_ETYPE_LENGTH]; + __le32 rx_etype_conf[WMI_RF_ETYPE_CONF_LENGTH]; /* Temperature range for rx_2_tx_offs parameters */ u8 rx_2_tx_temp[WMI_RF_RX2TX_LENGTH]; - u8 reserved3; + u8 reserved4; /* Rx to Tx gain index offset */ - s8 rx_2_tx_offs[WMI_RF_RX2TX_LENGTH + 1]; + s8 rx_2_tx_offs[WMI_RF_RX2TX_CONF_LENGTH]; +} __packed; + +/* WMI_FIXED_SCHEDULING_UL_CONFIG_CMDID + * This API sets rd parameter per mcs. + * Relevant only in Fixed Scheduling mode. + * Returned event: WMI_FIXED_SCHEDULING_UL_CONFIG_EVENTID + */ +struct wmi_fixed_scheduling_ul_config_cmd { + /* Use mcs -1 to set for every mcs */ + s8 mcs; + /* Number of frames with rd bit set in a single virtual slot */ + u8 rd_count_per_slot; + u8 reserved[2]; } __packed; /* CMD: WMI_RF_XPM_READ_CMDID */ @@ -1363,6 +1479,93 @@ struct wmi_set_long_range_config_complete_event { u8 reserved[3]; } __packed; +/* payload max size is 236 bytes: max event buffer size (256) - WMI headers + * (16) - prev struct field size (4) + */ +#define WMI_MAX_IOCTL_PAYLOAD_SIZE (236) +#define WMI_MAX_IOCTL_REPLY_PAYLOAD_SIZE (236) +#define WMI_MAX_INTERNAL_EVENT_PAYLOAD_SIZE (236) + +enum wmi_internal_fw_ioctl_code { + WMI_INTERNAL_FW_CODE_NONE = 0x0, + WMI_INTERNAL_FW_CODE_QCOM = 0x1, +}; + +/* WMI_INTERNAL_FW_IOCTL_CMDID */ +struct wmi_internal_fw_ioctl_cmd { + /* enum wmi_internal_fw_ioctl_code */ + __le16 code; + __le16 length; + /* payload max size is WMI_MAX_IOCTL_PAYLOAD_SIZE + * Must be the last member of the struct + */ + __le32 payload[0]; +} __packed; + +/* WMI_INTERNAL_FW_IOCTL_EVENTID */ +struct wmi_internal_fw_ioctl_event { + /* wmi_fw_status */ + u8 status; + u8 reserved; + __le16 length; + /* payload max size is WMI_MAX_IOCTL_REPLY_PAYLOAD_SIZE + * Must be the last member of the struct + */ + __le32 payload[0]; +} __packed; + +/* WMI_INTERNAL_FW_EVENT_EVENTID */ +struct wmi_internal_fw_event_event { + __le16 id; + __le16 length; + /* payload max size is WMI_MAX_INTERNAL_EVENT_PAYLOAD_SIZE + * Must be the last member of the struct + */ + __le32 payload[0]; +} __packed; + +/* WMI_BF_CONTROL_CMDID */ +struct wmi_bf_control_cmd { + /* wmi_bf_triggers */ + __le32 triggers; + u8 cid; + /* DISABLED = 0, ENABLED = 1 , DRY_RUN = 2 */ + u8 txss_mode; + /* DISABLED = 0, ENABLED = 1, DRY_RUN = 2 */ + u8 brp_mode; + /* Max cts threshold (correspond to + * WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_TXOP) + */ + u8 bf_trigger_max_cts_failure_thr; + /* Max cts threshold in dense (correspond to + * WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_TXOP) + */ + u8 bf_trigger_max_cts_failure_dense_thr; + /* Max b-ack threshold (correspond to + * WMI_BF_TRIGGER_MAX_BACK_FAILURE) + */ + u8 bf_trigger_max_back_failure_thr; + /* Max b-ack threshold in dense (correspond to + * WMI_BF_TRIGGER_MAX_BACK_FAILURE) + */ + u8 bf_trigger_max_back_failure_dense_thr; + u8 reserved0; + /* Wrong sectors threshold */ + __le32 wrong_sector_bis_thr; + /* BOOL to enable/disable long term trigger */ + u8 long_term_enable; + /* 1 = Update long term thresholds from the long_term_mbps_th_tbl and + * long_term_trig_timeout_per_mcs arrays, 0 = Ignore + */ + u8 long_term_update_thr; + /* Long term throughput threshold [Mbps] */ + u8 long_term_mbps_th_tbl[WMI_NUM_MCS]; + u8 reserved1; + /* Long term timeout threshold table [msec] */ + __le16 long_term_trig_timeout_per_mcs[WMI_NUM_MCS]; + u8 reserved2[2]; +} __packed; + /* WMI Events * List of Events (target to host) */ @@ -1421,6 +1624,7 @@ enum wmi_event_id { WMI_SET_SILENT_RSSI_TABLE_DONE_EVENTID = 0x185C, WMI_RF_PWR_ON_DELAY_RSP_EVENTID = 0x185D, WMI_SET_HIGH_POWER_TABLE_PARAMS_EVENTID = 0x185E, + WMI_FIXED_SCHEDULING_UL_CONFIG_EVENTID = 0x185F, /* Performance monitoring events */ WMI_DATA_PORT_OPEN_EVENTID = 0x1860, WMI_WBE_LINK_DOWN_EVENTID = 0x1861, @@ -1430,6 +1634,7 @@ enum wmi_event_id { WMI_RING_EN_EVENTID = 0x1865, WMI_GET_RF_STATUS_EVENTID = 0x1866, WMI_GET_BASEBAND_TYPE_EVENTID = 0x1867, + WMI_VRING_SWITCH_TIMING_CONFIG_EVENTID = 0x1868, WMI_UNIT_TEST_EVENTID = 0x1900, WMI_FLASH_READ_DONE_EVENTID = 0x1902, WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, @@ -1459,6 +1664,7 @@ enum wmi_event_id { WMI_GET_THERMAL_THROTTLING_CFG_EVENTID = 0x1941, /* return the Power Save profile */ WMI_PS_DEV_PROFILE_CFG_READ_EVENTID = 0x1942, + WMI_TSF_SYNC_STATUS_EVENTID = 0x1973, WMI_TOF_SESSION_END_EVENTID = 0x1991, WMI_TOF_GET_CAPABILITIES_EVENTID = 0x1992, WMI_TOF_SET_LCR_EVENTID = 0x1993, @@ -1476,6 +1682,7 @@ enum wmi_event_id { WMI_PRIO_TX_SECTORS_ORDER_EVENTID = 0x19A5, WMI_PRIO_TX_SECTORS_NUMBER_EVENTID = 0x19A6, WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID = 0x19A7, + WMI_BF_CONTROL_EVENTID = 0x19AA, WMI_TX_STATUS_RING_CFG_DONE_EVENTID = 0x19C0, WMI_RX_STATUS_RING_CFG_DONE_EVENTID = 0x19C1, WMI_TX_DESC_RING_CFG_DONE_EVENTID = 0x19C2, @@ -1486,12 +1693,18 @@ enum wmi_event_id { WMI_ENABLE_FIXED_SCHEDULING_COMPLETE_EVENTID = 0x1A03, WMI_SET_MULTI_DIRECTED_OMNIS_CONFIG_EVENTID = 0x1A04, WMI_SET_LONG_RANGE_CONFIG_COMPLETE_EVENTID = 0x1A05, + WMI_GET_ASSOC_LIST_RES_EVENTID = 0x1A06, + WMI_GET_CCA_INDICATIONS_EVENTID = 0x1A07, + WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_EVENTID = 0x1A08, + WMI_INTERNAL_FW_EVENT_EVENTID = 0x1A0A, + WMI_INTERNAL_FW_IOCTL_EVENTID = 0x1A0B, WMI_SET_CHANNEL_EVENTID = 0x9000, WMI_ASSOC_REQ_EVENTID = 0x9001, WMI_EAPOL_RX_EVENTID = 0x9002, WMI_MAC_ADDR_RESP_EVENTID = 0x9003, WMI_FW_VER_EVENTID = 0x9004, WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID = 0x9005, + WMI_INTERNAL_FW_SET_CHANNEL = 0x9006, WMI_COMMAND_NOT_SUPPORTED_EVENTID = 0xFFFF, }; @@ -1563,12 +1776,16 @@ enum rf_type { RF_UNKNOWN = 0x00, RF_MARLON = 0x01, RF_SPARROW = 0x02, + RF_TALYNA1 = 0x03, + RF_TALYNA2 = 0x04, }; /* WMI_GET_RF_STATUS_EVENTID */ enum board_file_rf_type { BF_RF_MARLON = 0x00, BF_RF_SPARROW = 0x01, + BF_RF_TALYNA1 = 0x02, + BF_RF_TALYNA2 = 0x03, }; /* WMI_GET_RF_STATUS_EVENTID */ @@ -1608,6 +1825,7 @@ enum baseband_type { BASEBAND_SPARROW_M_C0 = 0x06, BASEBAND_SPARROW_M_D0 = 0x07, BASEBAND_TALYN_M_A0 = 0x08, + BASEBAND_TALYN_M_B0 = 0x09, }; /* WMI_GET_BASEBAND_TYPE_EVENTID */ @@ -1652,7 +1870,11 @@ struct wmi_ready_event { u8 numof_additional_mids; /* rfc read calibration result. 5..15 */ u8 rfc_read_calib_result; - u8 reserved[3]; + /* Max associated STAs supported by FW in AP mode (default 0 means 8 + * STA) + */ + u8 max_assoc_sta; + u8 reserved[2]; } __packed; /* WMI_NOTIFY_REQ_DONE_EVENTID */ @@ -1767,13 +1989,13 @@ enum wmi_pno_result { }; struct wmi_start_sched_scan_event { - /* pno_result */ + /* wmi_pno_result */ u8 result; u8 reserved[3]; } __packed; struct wmi_stop_sched_scan_event { - /* pno_result */ + /* wmi_pno_result */ u8 result; u8 reserved[3]; } __packed; @@ -1840,9 +2062,17 @@ struct wmi_ba_status_event { /* WMI_DELBA_EVENTID */ struct wmi_delba_event { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 from_initiator; __le16 reason; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved[2]; } __packed; /* WMI_VRING_CFG_DONE_EVENTID */ @@ -1855,9 +2085,17 @@ struct wmi_vring_cfg_done_event { /* WMI_RCP_ADDBA_RESP_SENT_EVENTID */ struct wmi_rcp_addba_resp_sent_event { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 reserved; __le16 status; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved2[2]; } __packed; /* WMI_TX_STATUS_RING_CFG_DONE_EVENTID */ @@ -1905,6 +2143,9 @@ struct wmi_rx_desc_ring_cfg_done_event { /* WMI_RCP_ADDBA_REQ_EVENTID */ struct wmi_rcp_addba_req_event { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 dialog_token; /* ieee80211_ba_parameterset as it received */ @@ -1912,6 +2153,11 @@ struct wmi_rcp_addba_req_event { __le16 ba_timeout; /* ieee80211_ba_seqstrl field as it received */ __le16 ba_seq_ctrl; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved[2]; } __packed; /* WMI_CFG_RX_CHAIN_DONE_EVENTID */ @@ -2086,6 +2332,13 @@ struct wmi_set_high_power_table_params_event { u8 reserved[3]; } __packed; +/* WMI_FIXED_SCHEDULING_UL_CONFIG_EVENTID */ +struct wmi_fixed_scheduling_ul_config_event { + /* wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + /* WMI_TEMP_SENSE_DONE_EVENTID * * Measure MAC and radio temperatures @@ -2434,6 +2687,8 @@ struct wmi_link_maintain_cfg { __le32 bad_beacons_num_threshold; /* SNR limit for bad_beacons_detector */ __le32 bad_beacons_snr_threshold_db; + /* timeout for disassoc response frame in uSec */ + __le32 disconnect_timeout; } __packed; /* WMI_LINK_MAINTAIN_CFG_WRITE_CMDID */ @@ -2663,6 +2918,7 @@ enum wmi_tof_session_end_status { WMI_TOF_SESSION_END_FAIL = 0x01, WMI_TOF_SESSION_END_PARAMS_ERROR = 0x02, WMI_TOF_SESSION_END_ABORTED = 0x03, + WMI_TOF_SESSION_END_BUSY = 0x04, }; /* WMI_TOF_SESSION_END_EVENTID */ @@ -3069,7 +3325,40 @@ struct wmi_set_silent_rssi_table_done_event { __le32 table; } __packed; -/* \WMI_COMMAND_NOT_SUPPORTED_EVENTID */ +/* WMI_VRING_SWITCH_TIMING_CONFIG_EVENTID */ +struct wmi_vring_switch_timing_config_event { + /* enum wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + +/* WMI_GET_ASSOC_LIST_RES_EVENTID */ +struct wmi_assoc_sta_info { + u8 mac[WMI_MAC_LEN]; + u8 omni_index_address; + u8 reserved; +} __packed; + +#define WMI_GET_ASSOC_LIST_SIZE (8) + +/* WMI_GET_ASSOC_LIST_RES_EVENTID + * Returns up to MAX_ASSOC_STA_LIST_SIZE associated STAs + */ +struct wmi_get_assoc_list_res_event { + struct wmi_assoc_sta_info assoc_sta_list[WMI_GET_ASSOC_LIST_SIZE]; + /* STA count */ + u8 count; + u8 reserved[3]; +} __packed; + +/* WMI_BF_CONTROL_EVENTID */ +struct wmi_bf_control_event { + /* wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + +/* WMI_COMMAND_NOT_SUPPORTED_EVENTID */ struct wmi_command_not_supported_event { /* device id */ u8 mid; @@ -3080,4 +3369,62 @@ struct wmi_command_not_supported_event { __le16 reserved1; } __packed; +/* WMI_TSF_SYNC_CMDID */ +struct wmi_tsf_sync_cmd { + /* The time interval to send announce frame in one BI */ + u8 interval_ms; + /* The mcs to send announce frame */ + u8 mcs; + u8 reserved[6]; +} __packed; + +/* WMI_TSF_SYNC_STATUS_EVENTID */ +enum wmi_tsf_sync_status { + WMI_TSF_SYNC_SUCCESS = 0x00, + WMI_TSF_SYNC_FAILED = 0x01, + WMI_TSF_SYNC_REJECTED = 0x02, +}; + +/* WMI_TSF_SYNC_STATUS_EVENTID */ +struct wmi_tsf_sync_status_event { + /* enum wmi_tsf_sync_status */ + u8 status; + u8 reserved[3]; +} __packed; + +/* WMI_GET_CCA_INDICATIONS_EVENTID */ +struct wmi_get_cca_indications_event { + /* wmi_fw_status */ + u8 status; + /* CCA-Energy Detect in percentage over last BI (0..100) */ + u8 cca_ed_percent; + /* Averaged CCA-Energy Detect in percent over number of BIs (0..100) */ + u8 cca_ed_avg_percent; + /* NAV percent over last BI (0..100) */ + u8 nav_percent; + /* Averaged NAV percent over number of BIs (0..100) */ + u8 nav_avg_percent; + u8 reserved[3]; +} __packed; + +/* WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_CMDID */ +struct wmi_set_cca_indications_bi_avg_num_cmd { + /* set the number of bis to average cca_ed (0..255) */ + u8 bi_number; + u8 reserved[3]; +} __packed; + +/* WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_EVENTID */ +struct wmi_set_cca_indications_bi_avg_num_event { + /* wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + +/* WMI_INTERNAL_FW_SET_CHANNEL */ +struct wmi_internal_fw_set_channel_event { + u8 channel_num; + u8 reserved[3]; +} __packed; + #endif /* __WILOCITY_WMI_H__ */ -- GitLab From d95f61f6c3c47e277e2f18b2894b4dcc0ea99ddd Mon Sep 17 00:00:00 2001 From: Srinivas Rao L Date: Fri, 25 May 2018 17:29:19 +0530 Subject: [PATCH 0416/1299] ARM: dts: msm: Add RSC mailbox controller device nodes for sdmmagpie Add mailbox controller device nodes for application processor and display subsystem. Change-Id: Ifd58c41085cfa33cd75cfb726103b64ce2828cd4 Signed-off-by: Srinivas Rao L --- arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index 1245487d5239..a958b913ae01 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -19,6 +19,7 @@ #include #include #include +#include / { model = "Qualcomm Technologies, Inc. SDMMAGPIE"; @@ -911,6 +912,32 @@ compatible = "qcom,llcc-amon"; }; }; + + apps_rsc: mailbox@18220000 { + compatible = "qcom,tcs-drv"; + label = "apps_rsc"; + reg = <0x18220000 0x100>, <0x18220d00 0x3000>; + interrupts = <0 5 0>; + #mbox-cells = <1>; + qcom,drv-id = <2>; + qcom,tcs-config = , + , + , + ; + }; + + disp_rsc: mailbox@af20000 { + compatible = "qcom,tcs-drv"; + label = "display_rsc"; + reg = <0xaf20000 0x100>, <0xaf21c00 0x3000>; + interrupts = <0 129 0>; + #mbox-cells = <1>; + qcom,drv-id = <0>; + qcom,tcs-config = , + , + , + ; + }; }; #include "sdmmagpie-pinctrl.dtsi" -- GitLab From 893875f2dbc89b8ceb5311ef81287876190321dd Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 19 Jun 2018 14:31:03 +0300 Subject: [PATCH 0417/1299] wil6210: fix call to wil6210_disconnect during unload Move the call to wil6210_disconnect so it will be called before unregister_netdevice. This is because it calls netif_carrier_off which is forbidden to call on an unregistered net device. Calling netif_carrier_off can add a link watch event which might be handled after net device was freed, causing a kernel oops. Change-Id: I08295a779367eb6ac86e4b60735a331505e70b39 Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 9861bf3b818fbe810442b89230b80c0385ef9e04 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git --- drivers/net/wireless/ath/wil6210/netdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 0e0b8064fe01..eda79dd2739b 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -529,16 +529,16 @@ void wil_vif_remove(struct wil6210_priv *wil, u8 mid) return; } + mutex_lock(&wil->mutex); + wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); + mutex_unlock(&wil->mutex); + ndev = vif_to_ndev(vif); /* during unregister_netdevice cfg80211_leave may perform operations * such as stop AP, disconnect, so we only clear the VIF afterwards */ unregister_netdevice(ndev); - mutex_lock(&wil->mutex); - wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); - mutex_unlock(&wil->mutex); - if (any_active && vif->mid != 0) wmi_port_delete(wil, vif->mid); -- GitLab From 3440f98c2b3a98c95775e8c656f34169401b3b2a Mon Sep 17 00:00:00 2001 From: Lior David Date: Thu, 14 Jun 2018 18:50:36 +0300 Subject: [PATCH 0418/1299] wil6210: change reply_size arg to u16 in wmi_call Change the type of the argument reply_size from u8 to u16 in order to support reply sizes > 255 bytes. The driver already supports u16 reply size in all other places, this was the only missing change. Change-Id: I0e9baafdc50d845036e5f2b50c0b55935eb09082 Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 5f85c7e702d2185d3d553982f916b5ac96ae77a9 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git --- drivers/net/wireless/ath/wil6210/wil6210.h | 2 +- drivers/net/wireless/ath/wil6210/wmi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index f5ef47c2e755..6b4e443d0ea1 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -1174,7 +1174,7 @@ int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len); void wmi_recv_cmd(struct wil6210_priv *wil); int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len, - u16 reply_id, void *reply, u8 reply_size, int to_msec); + u16 reply_id, void *reply, u16 reply_size, int to_msec); void wmi_event_worker(struct work_struct *work); void wmi_event_flush(struct wil6210_priv *wil); int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index a3e20af59ea0..fe5cc85d69f4 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1531,7 +1531,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) } int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len, - u16 reply_id, void *reply, u8 reply_size, int to_msec) + u16 reply_id, void *reply, u16 reply_size, int to_msec) { int rc; unsigned long remain; -- GitLab From 0ea98930d5eaae5e9bd9b636906d3fdcd0a496bb Mon Sep 17 00:00:00 2001 From: Srinivas Rao L Date: Fri, 25 May 2018 17:32:57 +0530 Subject: [PATCH 0419/1299] ARM: dts: msm: add system PM device binding for sdmmagpie System PM device handles all activities supporting the SoC's capability to enter system sleep modes. Add device bindings for this. Change-Id: I8cbcdfdfd074d78fb64203afd0d47f9ffeb76469 Signed-off-by: Srinivas Rao L --- arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index a958b913ae01..6215a90adb4c 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -938,6 +938,11 @@ , ; }; + + system_pm { + compatible = "qcom,system-pm"; + mboxes = <&apps_rsc 0>; + }; }; #include "sdmmagpie-pinctrl.dtsi" -- GitLab From 3a9333b3ac5c2639c554cf7199754e05293e9dc9 Mon Sep 17 00:00:00 2001 From: Dedy Lansky Date: Fri, 15 Jun 2018 17:17:05 +0300 Subject: [PATCH 0420/1299] wil6210: move WMI functionality out of wil_cfg80211_mgmt_tx Rearrange the code by having new function wmi_mgmt_tx() to take care of the WMI part of wil_cfg80211_mgmt_tx(). Change-Id: Ia045999cdc9153c3403abda3ee023173cea70dad Signed-off-by: Dedy Lansky Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 1c21cc5fc4df4997eddc6e0b5c5bad225c3f1ecc Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git [merez@codeaurora.org: trivial conflict fixes] --- drivers/net/wireless/ath/wil6210/cfg80211.c | 39 ++--------------- drivers/net/wireless/ath/wil6210/wil6210.h | 1 + drivers/net/wireless/ath/wil6210/wmi.c | 47 +++++++++++++++++++++ 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index eb0895a55b74..244eab811ad8 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1158,17 +1158,11 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, u64 *cookie) { const u8 *buf = params->buf; - size_t len = params->len, total; + size_t len = params->len; struct wil6210_priv *wil = wiphy_to_wil(wiphy); struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc; - bool tx_status = false; - struct ieee80211_mgmt *mgmt_frame = (void *)buf; - struct wmi_sw_tx_req_cmd *cmd; - struct { - struct wmi_cmd_hdr wmi; - struct wmi_sw_tx_complete_event evt; - } __packed evt; + bool tx_status; /* Note, currently we do not support the "wait" parameter, user-space * must call remain_on_channel before mgmt_tx or listen on a channel @@ -1177,34 +1171,9 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, * different from currently "listened" channel and fail if it is. */ - wil_dbg_misc(wil, "mgmt_tx mid %d\n", vif->mid); - wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf, - len, true); - - if (len < sizeof(struct ieee80211_hdr_3addr)) - return -EINVAL; - - total = sizeof(*cmd) + len; - if (total < len) - return -EINVAL; - - cmd = kmalloc(total, GFP_KERNEL); - if (!cmd) { - rc = -ENOMEM; - goto out; - } - - memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN); - cmd->len = cpu_to_le16(len); - memcpy(cmd->payload, buf, len); - - rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, vif->mid, cmd, total, - WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); - if (rc == 0) - tx_status = !evt.evt.status; + rc = wmi_mgmt_tx(vif, buf, len); + tx_status = (rc == 0); - kfree(cmd); - out: cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len, tx_status, GFP_KERNEL); return rc; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 6b4e443d0ea1..bfff0b93a658 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -1362,6 +1362,7 @@ int wmi_set_snr_thresh(struct wil6210_priv *wil, short omni, short direct); int wmi_start_sched_scan(struct wil6210_priv *wil, struct cfg80211_sched_scan_request *request); int wmi_stop_sched_scan(struct wil6210_priv *wil); +int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len); int reverse_memcmp(const void *cs, const void *ct, size_t count); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index fe5cc85d69f4..be9ee2737c24 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -3095,6 +3095,53 @@ int wmi_stop_sched_scan(struct wil6210_priv *wil) return 0; } +int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len) +{ + size_t total; + struct wil6210_priv *wil = vif_to_wil(vif); + struct ieee80211_mgmt *mgmt_frame = (void *)buf; + struct wmi_sw_tx_req_cmd *cmd; + struct { + struct wmi_cmd_hdr wmi; + struct wmi_sw_tx_complete_event evt; + } __packed evt = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; + int rc; + + wil_dbg_misc(wil, "mgmt_tx mid %d\n", vif->mid); + wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf, + len, true); + + if (len < sizeof(struct ieee80211_hdr_3addr)) + return -EINVAL; + + total = sizeof(*cmd) + len; + if (total < len) { + wil_err(wil, "mgmt_tx invalid len %zu\n", len); + return -EINVAL; + } + + cmd = kmalloc(total, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN); + cmd->len = cpu_to_le16(len); + memcpy(cmd->payload, buf, len); + + rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, vif->mid, cmd, total, + WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); + if (!rc && evt.evt.status != WMI_FW_STATUS_SUCCESS) { + wil_err(wil, "mgmt_tx failed with status %d\n", evt.evt.status); + rc = -EINVAL; + } + + kfree(cmd); + + return rc; +} + int wil_wmi_tx_sring_cfg(struct wil6210_priv *wil, int ring_id) { int rc; -- GitLab From 11dd6e219dd208993f4a2cd1204fae23e3567b0f Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Fri, 15 Jun 2018 17:18:01 +0300 Subject: [PATCH 0421/1299] wil6210: Initialize reply struct of the WMI commands WMI command reply saved in uninitialized struct. In order to avoid accessing unset values from FW initialize the reply struct. Change-Id: I4c5b22da327cc7a8c1f64c940247acef518e2ebd Signed-off-by: Alexei Avshalom Lazar Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 807b086053df9bdbc9bf732130e9acda1c161aa5 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git [merez@codeaurora.org: trivial conflict fixes] --- drivers/net/wireless/ath/wil6210/cfg80211.c | 22 +++-- drivers/net/wireless/ath/wil6210/debugfs.c | 2 + drivers/net/wireless/ath/wil6210/main.c | 2 + drivers/net/wireless/ath/wil6210/txrx.c | 8 +- drivers/net/wireless/ath/wil6210/wmi.c | 97 +++++++++++++-------- 5 files changed, 85 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 244eab811ad8..0c98459f01d6 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -353,6 +353,8 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, struct wil_net_stats *stats = &wil->sta[cid].stats; int rc; + memset(&reply, 0, sizeof(reply)); + rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20); if (rc) @@ -2391,7 +2393,9 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, struct { struct wmi_cmd_hdr wmi; struct wmi_get_rf_sector_params_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, + }; struct sk_buff *msg; struct nlattr *nl_cfgs, *nl_cfg; u32 i; @@ -2437,7 +2441,6 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, cmd.sector_idx = cpu_to_le16(sector_index); cmd.sector_type = sector_type; cmd.rf_modules_vec = rf_modules_vec & 0xFF; - memset(&reply, 0, sizeof(reply)); rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID, &reply, sizeof(reply), @@ -2512,7 +2515,9 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, struct { struct wmi_cmd_hdr wmi; struct wmi_set_rf_sector_params_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, + }; struct nlattr *nl_cfg; struct wmi_rf_sector_info *si; @@ -2595,7 +2600,6 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, } cmd.rf_modules_vec = rf_modules_vec & 0xFF; - memset(&reply, 0, sizeof(reply)); rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID, &reply, sizeof(reply), @@ -2619,7 +2623,9 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, struct { struct wmi_cmd_hdr wmi; struct wmi_get_selected_rf_sector_index_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, + }; struct sk_buff *msg; if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) @@ -2659,7 +2665,6 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, memset(&cmd, 0, sizeof(cmd)); cmd.cid = (u8)cid; cmd.sector_type = sector_type; - memset(&reply, 0, sizeof(reply)); rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, @@ -2700,14 +2705,15 @@ static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil, struct { struct wmi_cmd_hdr wmi; struct wmi_set_selected_rf_sector_index_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, + }; int rc; memset(&cmd, 0, sizeof(cmd)); cmd.sector_idx = cpu_to_le16(sector_index); cmd.sector_type = sector_type; cmd.cid = (u8)cid; - memset(&reply, 0, sizeof(reply)); rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID, mid, &cmd, sizeof(cmd), WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 61fc8d06d710..c079ce07474d 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1335,6 +1335,8 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data) struct wmi_notify_req_done_event evt; } __packed reply; + memset(&reply, 0, sizeof(reply)); + for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { u32 status; diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 3c319bf1fd16..2453b3c6f7f5 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -397,6 +397,8 @@ void wil_disconnect_worker(struct work_struct *work) /* already disconnected */ return; + memset(&reply, 0, sizeof(reply)); + rc = wmi_call(wil, WMI_DISCONNECT_CMDID, vif->mid, NULL, 0, WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), WIL6210_DISCONNECT_TO_MS); diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 04c9a7261c36..277a162107b7 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -956,7 +956,9 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, struct { struct wmi_cmd_hdr wmi; struct wmi_vring_cfg_done_event cmd; - } __packed reply; + } __packed reply = { + .cmd = {.status = WMI_FW_STATUS_FAILURE}, + }; struct wil_ring *vring = &wil->ring_tx[id]; struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id]; @@ -1039,7 +1041,9 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) struct { struct wmi_cmd_hdr wmi; struct wmi_vring_cfg_done_event cmd; - } __packed reply; + } __packed reply = { + .cmd = {.status = WMI_FW_STATUS_FAILURE}, + }; struct wil_ring *vring = &wil->ring_tx[id]; struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id]; diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index be9ee2737c24..49f25ac3382b 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1624,7 +1624,9 @@ int wmi_led_cfg(struct wil6210_priv *wil, bool enable) struct { struct wmi_cmd_hdr wmi; struct wmi_led_cfg_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = cpu_to_le32(WMI_FW_STATUS_FAILURE)}, + }; if (led_id == WIL_LED_INVALID_ID) goto out; @@ -1677,7 +1679,9 @@ int wmi_pcp_start(struct wil6210_vif *vif, struct { struct wmi_cmd_hdr wmi; struct wmi_pcp_started_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; if (!vif->privacy) cmd.disable_sec = 1; @@ -1754,6 +1758,8 @@ int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid) } __packed reply; int len; /* reply.cmd.ssid_len in CPU order */ + memset(&reply, 0, sizeof(reply)); + rc = wmi_call(wil, WMI_GET_SSID_CMDID, vif->mid, NULL, 0, WMI_GET_SSID_EVENTID, &reply, sizeof(reply), 20); if (rc) @@ -1789,6 +1795,8 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel) struct wmi_set_pcp_channel_cmd cmd; } __packed reply; + memset(&reply, 0, sizeof(reply)); + rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, vif->mid, NULL, 0, WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); if (rc) @@ -1814,7 +1822,9 @@ int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi) struct { struct wmi_cmd_hdr wmi; struct wmi_p2p_cfg_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n"); @@ -1835,7 +1845,9 @@ int wmi_start_listen(struct wil6210_vif *vif) struct { struct wmi_cmd_hdr wmi; struct wmi_listen_started_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n"); @@ -1857,7 +1869,9 @@ int wmi_start_search(struct wil6210_vif *vif) struct { struct wmi_cmd_hdr wmi; struct wmi_search_started_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n"); @@ -1983,7 +1997,9 @@ int wmi_rxon(struct wil6210_priv *wil, bool on) struct { struct wmi_cmd_hdr wmi; struct wmi_listen_started_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_info(wil, "(%s)\n", on ? "on" : "off"); @@ -2025,6 +2041,8 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring) } __packed evt; int rc; + memset(&evt, 0, sizeof(evt)); + if (wdev->iftype == NL80211_IFTYPE_MONITOR) { struct ieee80211_channel *ch = wil->monitor_chandef.chan; @@ -2054,14 +2072,14 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring) if (rc) return rc; + if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS) + rc = -EINVAL; + vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr); wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n", le32_to_cpu(evt.evt.status), vring->hwtail); - if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS) - rc = -EINVAL; - return rc; } @@ -2079,6 +2097,8 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) struct wmi_temp_sense_done_event evt; } __packed reply; + memset(&reply, 0, sizeof(reply)); + rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100); if (rc) @@ -2111,6 +2131,7 @@ int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason); + memset(&reply, 0, sizeof(reply)); vif->locally_generated_disc = true; if (del_sta) { ether_addr_copy(del_sta_cmd.dst_mac, mac); @@ -2212,7 +2233,9 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, struct { struct wmi_cmd_hdr wmi; struct wmi_rcp_addba_resp_sent_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)}, + }; wil_dbg_wmi(wil, "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n", @@ -2293,13 +2316,13 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, struct { struct wmi_cmd_hdr wmi; struct wmi_ps_dev_profile_cfg_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR)}, + }; u32 status; wil_dbg_wmi(wil, "Setting ps dev profile %d\n", ps_profile); - reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR); - rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply), @@ -2328,15 +2351,15 @@ int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short) struct { struct wmi_cmd_hdr wmi; struct wmi_set_mgmt_retry_limit_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_wmi(wil, "Setting mgmt retry short %d\n", retry_short); if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities)) return -ENOTSUPP; - reply.evt.status = WMI_FW_STATUS_FAILURE; - rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), @@ -2367,7 +2390,7 @@ int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short) if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities)) return -ENOTSUPP; - reply.evt.mgmt_retry_limit = 0; + memset(&reply, 0, sizeof(reply)); rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, vif->mid, NULL, 0, WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), 100); @@ -2515,14 +2538,15 @@ int wmi_suspend(struct wil6210_priv *wil) struct { struct wmi_cmd_hdr wmi; struct wmi_traffic_suspend_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE}, + }; + u32 suspend_to = WIL_WAIT_FOR_SUSPEND_RESUME_COMP; wil->suspend_resp_rcvd = false; wil->suspend_resp_comp = false; - reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE; - rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply), @@ -2598,10 +2622,11 @@ int wmi_resume(struct wil6210_priv *wil) struct { struct wmi_cmd_hdr wmi; struct wmi_traffic_resume_event evt; - } __packed reply; - - reply.evt.status = WMI_TRAFFIC_RESUME_FAILED; - reply.evt.resume_triggers = WMI_RESUME_TRIGGER_UNKNOWN; + } __packed reply = { + .evt = {.status = WMI_TRAFFIC_RESUME_FAILED, + .resume_triggers = + cpu_to_le32(WMI_RESUME_TRIGGER_UNKNOWN)}, + }; rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, vif->mid, NULL, 0, WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply), @@ -2686,7 +2711,9 @@ int wmi_port_allocate(struct wil6210_priv *wil, u8 mid, struct { struct wmi_cmd_hdr wmi; struct wmi_port_allocated_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_misc(wil, "port allocate, mid %d iftype %d, mac %pM\n", mid, iftype, mac); @@ -2711,8 +2738,6 @@ int wmi_port_allocate(struct wil6210_priv *wil, u8 mid, return -EINVAL; } - reply.evt.status = WMI_FW_STATUS_FAILURE; - rc = wmi_call(wil, WMI_PORT_ALLOCATE_CMDID, mid, &cmd, sizeof(cmd), WMI_PORT_ALLOCATED_EVENTID, &reply, @@ -2739,12 +2764,12 @@ int wmi_port_delete(struct wil6210_priv *wil, u8 mid) struct { struct wmi_cmd_hdr wmi; struct wmi_port_deleted_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_misc(wil, "port delete, mid %d\n", mid); - reply.evt.status = WMI_FW_STATUS_FAILURE; - rc = wmi_call(wil, WMI_PORT_DELETE_CMDID, mid, &cmd, sizeof(cmd), WMI_PORT_DELETED_EVENTID, &reply, @@ -3032,7 +3057,9 @@ int wmi_start_sched_scan(struct wil6210_priv *wil, struct { struct wmi_cmd_hdr wmi; struct wmi_start_sched_scan_event evt; - } __packed reply; + } __packed reply = { + .evt = {.result = WMI_PNO_REJECT}, + }; if (!test_bit(WMI_FW_CAPABILITY_PNO, wil->fw_capabilities)) return -ENOTSUPP; @@ -3048,8 +3075,6 @@ int wmi_start_sched_scan(struct wil6210_priv *wil, wmi_sched_scan_set_plans(wil, &cmd, request->scan_plans, request->n_scan_plans); - reply.evt.result = WMI_PNO_REJECT; - rc = wmi_call(wil, WMI_START_SCHED_SCAN_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_START_SCHED_SCAN_EVENTID, &reply, sizeof(reply), @@ -3073,13 +3098,13 @@ int wmi_stop_sched_scan(struct wil6210_priv *wil) struct { struct wmi_cmd_hdr wmi; struct wmi_stop_sched_scan_event evt; - } __packed reply; + } __packed reply = { + .evt = {.result = WMI_PNO_REJECT}, + }; if (!test_bit(WMI_FW_CAPABILITY_PNO, wil->fw_capabilities)) return -ENOTSUPP; - reply.evt.result = WMI_PNO_REJECT; - rc = wmi_call(wil, WMI_STOP_SCHED_SCAN_CMDID, vif->mid, NULL, 0, WMI_STOP_SCHED_SCAN_EVENTID, &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS); -- GitLab From 70b1c2f6045cec8ef3819a11f04a4c464d5f3d52 Mon Sep 17 00:00:00 2001 From: Srinivas Rao L Date: Fri, 25 May 2018 17:37:31 +0530 Subject: [PATCH 0422/1299] ARM: dts: msm: Add CommandDB device bindings for sdmmagpie CommandDB exports target specific RPMH resource information. Add device bindings for this. Change-Id: Ief4d0e0a8d7080ee628afca2d658d92ea5ed2c7e Signed-off-by: Srinivas Rao L --- arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index 6215a90adb4c..ab204a1dcd93 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -943,6 +943,11 @@ compatible = "qcom,system-pm"; mboxes = <&apps_rsc 0>; }; + + cmd_db: qcom,cmd-db@c3f000c { + compatible = "qcom,cmd-db"; + reg = <0xc3f000c 8>; + }; }; #include "sdmmagpie-pinctrl.dtsi" -- GitLab From 89c28c31e99f4cc668ce2f20ebf3cc4706e81ed5 Mon Sep 17 00:00:00 2001 From: Dedy Lansky Date: Thu, 14 Jun 2018 19:23:51 +0300 Subject: [PATCH 0423/1299] wil6210: remove unused rx_reorder members Remove unused members from struct wil_tid_ampdu_rx Change-Id: I193d6d610ce615bd114d5a8356fa8c182c747f8a Signed-off-by: Dedy Lansky Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 37f8d26d8347f659e4677b4e438708ce492262bf Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git --- drivers/net/wireless/ath/wil6210/debugfs.c | 3 +-- drivers/net/wireless/ath/wil6210/rx_reorder.c | 7 +------ drivers/net/wireless/ath/wil6210/wil6210.h | 10 ---------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index c079ce07474d..15ed905792ea 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1680,8 +1680,7 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size; unsigned long long drop_dup = r->drop_dup, drop_old = r->drop_old; - seq_printf(s, "([%2d] %3d TU) 0x%03x [", r->buf_size, r->timeout, - r->head_seq_num); + seq_printf(s, "([%2d]) 0x%03x [", r->buf_size, r->head_seq_num); for (i = 0; i < r->buf_size; i++) { if (i == index) seq_printf(s, "%c", r->reorder_buf[i] ? 'O' : '|'); diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 9321b5e91a9c..ce017e4bdd6e 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -205,7 +205,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) /* put the frame in the reordering buffer */ r->reorder_buf[index] = skb; - r->reorder_time[index] = jiffies; r->stored_mpdu_num++; wil_reorder_release(ndev, r); @@ -251,11 +250,8 @@ struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, r->reorder_buf = kcalloc(size, sizeof(struct sk_buff *), GFP_KERNEL); - r->reorder_time = - kcalloc(size, sizeof(unsigned long), GFP_KERNEL); - if (!r->reorder_buf || !r->reorder_time) { + if (!r->reorder_buf) { kfree(r->reorder_buf); - kfree(r->reorder_time); kfree(r); return NULL; } @@ -285,7 +281,6 @@ void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, kfree_skb(r->reorder_buf[i]); kfree(r->reorder_buf); - kfree(r->reorder_time); kfree(r); } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index bfff0b93a658..dffb00c8857a 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -620,38 +620,28 @@ struct pci_dev; * struct tid_ampdu_rx - TID aggregation information (Rx). * * @reorder_buf: buffer to reorder incoming aggregated MPDUs - * @reorder_time: jiffies when skb was added - * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) - * @reorder_timer: releases expired frames from the reorder buffer. * @last_rx: jiffies of last rx activity * @head_seq_num: head sequence number in reordering buffer. * @stored_mpdu_num: number of MPDUs in reordering buffer * @ssn: Starting Sequence Number expected to be aggregated. * @buf_size: buffer size for incoming A-MPDUs - * @timeout: reset timer value (in TUs). * @ssn_last_drop: SSN of the last dropped frame * @total: total number of processed incoming frames * @drop_dup: duplicate frames dropped for this reorder buffer * @drop_old: old frames dropped for this reorder buffer - * @dialog_token: dialog token for aggregation session * @first_time: true when this buffer used 1-st time */ struct wil_tid_ampdu_rx { struct sk_buff **reorder_buf; - unsigned long *reorder_time; - struct timer_list session_timer; - struct timer_list reorder_timer; unsigned long last_rx; u16 head_seq_num; u16 stored_mpdu_num; u16 ssn; u16 buf_size; - u16 timeout; u16 ssn_last_drop; unsigned long long total; /* frames processed */ unsigned long long drop_dup; unsigned long long drop_old; - u8 dialog_token; bool first_time; /* is it 1-st time this buffer used? */ }; -- GitLab From 6a7d66bd59e693d4b0f1330ce226b2e2a013af6f Mon Sep 17 00:00:00 2001 From: Dedy Lansky Date: Thu, 14 Jun 2018 19:25:01 +0300 Subject: [PATCH 0424/1299] wil6210: rate limit wil_rx_refill error wil_err inside wil_rx_refill can flood the log buffer. Replace it with wil_err_ratelimited. Change-Id: I636c898e518d98a1e42c9fef18c89a1dd5fd0375 Signed-off-by: Dedy Lansky Signed-off-by: Maya Erez Signed-off-by: Kalle Valo Git-commit: 3d6b72729cc2933906de8d2c602ae05e920b2122 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git --- drivers/net/wireless/ath/wil6210/txrx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 277a162107b7..8991d136916f 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -608,8 +608,8 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) v->swtail = next_tail) { rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom); if (unlikely(rc)) { - wil_err(wil, "Error %d in wil_rx_refill[%d]\n", - rc, v->swtail); + wil_err_ratelimited(wil, "Error %d in rx refill[%d]\n", + rc, v->swtail); break; } } -- GitLab From d2d0874339e20565497074beeadc4a8aca1b49d2 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Tue, 19 Jun 2018 17:46:39 +0530 Subject: [PATCH 0425/1299] ARM: dts: msm: Disable USB3.0 core for QCS405 on rumi USB3.0 core is not supported on rumi for QCS405. Hence disable the USB3.0 core on rumi. Change-Id: I32148a68c3dd06bfb47fe6d77399fb956d3aa8de Signed-off-by: Sriharsha Allenki --- arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi b/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi index c6a7675bcb4e..c2885d95855f 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-rumi.dtsi @@ -44,6 +44,7 @@ &usb3 { /delete-property/ extcon; + status = "disabled"; }; &usb2s { -- GitLab From 9e37c7b2d397c08c9839ae0b61371acde947d737 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Tue, 27 Mar 2018 14:54:29 +0530 Subject: [PATCH 0426/1299] leds: qpnp-flash-v2: Add support for multi-strobe Multi-strobe option is used to enable/disable the LEDs back-to-back without disabling the module in the HW_STROBE mode. Hence, enable the multi-strobe option if the LED is configured in HW_STROBE mode. Change-Id: I3e16254c6dcb4c4ae0b295cd7eea4e8ee8e1c2c7 Signed-off-by: Kiran Gunda --- drivers/leds/leds-qpnp-flash-v2.c | 40 ++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index de74c2ba61ec..9842e0bf2071 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -393,7 +393,7 @@ led_brightness qpnp_flash_led_brightness_get(struct led_classdev *led_cdev) static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) { int rc, i, addr_offset; - u8 val = 0, mask; + u8 val = 0, mask, strobe_mask = 0; for (i = 0; i < led->num_fnodes; i++) { addr_offset = led->fnode[i].id; @@ -404,6 +404,31 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) return rc; val |= 0x1 << led->fnode[i].id; + + if (led->fnode[i].strobe_sel == HW_STROBE) { + if (led->fnode[i].id == LED3) + strobe_mask |= LED3_FLASH_ONCE_ONLY_BIT; + else + strobe_mask |= LED1N2_FLASH_ONCE_ONLY_BIT; + } + + if (led->fnode[i].id == LED3 && + led->fnode[i].strobe_sel == LPG_STROBE) + strobe_mask |= LED3_FLASH_ONCE_ONLY_BIT; + } + + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_MULTI_STROBE_CTRL(led->base), + strobe_mask, 0); + if (rc < 0) + return rc; + + if (led->fnode[LED3].strobe_sel == LPG_STROBE) { + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_LPG_INPUT_CTRL(led->base), + LPG_INPUT_SEL_BIT, LPG_INPUT_SEL_BIT); + if (rc < 0) + return rc; } rc = qpnp_flash_led_write(led, @@ -597,19 +622,6 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) return rc; } - if (led->fnode[LED3].strobe_sel == LPG_STROBE) { - rc = qpnp_flash_led_masked_write(led, - FLASH_LED_REG_MULTI_STROBE_CTRL(led->base), - LED3_FLASH_ONCE_ONLY_BIT, 0); - if (rc < 0) - return rc; - - rc = qpnp_flash_led_masked_write(led, - FLASH_LED_REG_LPG_INPUT_CTRL(led->base), - LPG_INPUT_SEL_BIT, LPG_INPUT_SEL_BIT); - if (rc < 0) - return rc; - } return 0; } -- GitLab From 5d9e0514ba71e91fc3408b43e83d3cbf9ee4299a Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Tue, 27 Mar 2018 18:35:00 +0530 Subject: [PATCH 0427/1299] leds: qpnp-flash-v2: Fix HW_STROBE configuration As per the hardware recommendation, configure the LED1 to HW_STROBE mode when LED2 or LED3 is configured in HW_STROBE mode. This enables hardware strobe option working for LED2/3 channels. CRs-Fixed: 2213325 Change-Id: I1ceaa7477b8d0c18e03fbdea9d5347d0e75fc0f0 Signed-off-by: Kiran Gunda --- drivers/leds/leds-qpnp-flash-v2.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index 9842e0bf2071..7b139f45f409 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -393,7 +393,7 @@ led_brightness qpnp_flash_led_brightness_get(struct led_classdev *led_cdev) static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) { int rc, i, addr_offset; - u8 val = 0, mask, strobe_mask = 0; + u8 val = 0, mask, strobe_mask = 0, strobe_ctrl; for (i = 0; i < led->num_fnodes; i++) { addr_offset = led->fnode[i].id; @@ -415,6 +415,26 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) if (led->fnode[i].id == LED3 && led->fnode[i].strobe_sel == LPG_STROBE) strobe_mask |= LED3_FLASH_ONCE_ONLY_BIT; + /* + * As per the hardware recommendation, to use LED2/LED3 in HW + * strobe mode, LED1 should be set to HW strobe mode as well. + */ + if (led->fnode[i].strobe_sel == HW_STROBE && + (led->fnode[i].id == LED2 || led->fnode[i].id == LED3)) { + mask = FLASH_HW_STROBE_MASK; + addr_offset = led->fnode[LED1].id; + /* + * HW_STROBE: enable, TRIGGER: level, + * POLARITY: active high + */ + strobe_ctrl = BIT(2) | BIT(0); + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_STROBE_CTRL( + led->base + addr_offset), + mask, strobe_ctrl); + if (rc < 0) + return rc; + } } rc = qpnp_flash_led_masked_write(led, -- GitLab From 5245320db2729960fce2ba9a43ef541d997b0575 Mon Sep 17 00:00:00 2001 From: Narendra Muppalla Date: Thu, 14 Jun 2018 15:13:29 -0700 Subject: [PATCH 0428/1299] drm/msm/sde: add null checks in drm module This change adds null checks in drm msm framework and drm sde kms level. Change-Id: I3c9a15392a132a81372edd4a69739c3d5308b1ba Signed-off-by: Narendra Muppalla --- drivers/gpu/drm/msm/msm_smmu.c | 9 ++++----- drivers/gpu/drm/msm/sde/sde_encoder.c | 8 +++++--- drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 2 +- drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c | 1 + drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c | 2 +- drivers/gpu/drm/msm/sde/sde_hw_cdm.c | 4 +++- drivers/gpu/drm/msm/sde/sde_rm.c | 2 +- 7 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c index adc440cee46b..69ab06af5a09 100644 --- a/drivers/gpu/drm/msm/msm_smmu.c +++ b/drivers/gpu/drm/msm/msm_smmu.c @@ -173,13 +173,12 @@ static int msm_smmu_map(struct msm_mmu *mmu, uint64_t iova, { struct msm_smmu *smmu = to_msm_smmu(mmu); struct msm_smmu_client *client = msm_smmu_to_client(smmu); - size_t ret; - - ret = iommu_map_sg(client->mmu_mapping->domain, iova, sgt->sgl, - sgt->nents, prot); - WARN_ON(ret < 0); + size_t ret = 0; if (sgt && sgt->sgl) { + ret = iommu_map_sg(client->mmu_mapping->domain, iova, sgt->sgl, + sgt->nents, prot); + WARN_ON(ret < 0); DRM_DEBUG("%pad/0x%x/0x%x/\n", &sgt->sgl->dma_address, sgt->sgl->dma_length, prot); SDE_EVT32(sgt->sgl->dma_address, sgt->sgl->dma_length, diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index f1499487adee..35a8cb5107ef 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -1195,7 +1195,7 @@ static int _sde_encoder_dsc_n_lm_1_enc_1_intf(struct sde_encoder_virt *sde_enc) const struct sde_rect *roi = &sde_enc->cur_conn_roi; struct msm_mode_info mode_info; struct msm_display_dsc_info *dsc = NULL; - struct sde_hw_ctl *hw_ctl = enc_master->hw_ctl; + struct sde_hw_ctl *hw_ctl; struct sde_ctl_dsc_cfg cfg; int rc; @@ -1210,6 +1210,8 @@ static int _sde_encoder_dsc_n_lm_1_enc_1_intf(struct sde_encoder_virt *sde_enc) return -EINVAL; } + hw_ctl = enc_master->hw_ctl; + memset(&cfg, 0, sizeof(cfg)); dsc = &mode_info.comp_info.dsc_info; _sde_encoder_dsc_update_pic_dim(dsc, roi->w, roi->h); @@ -1582,6 +1584,8 @@ void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc, struct sde_encoder_virt *sde_enc; int i, rc = 0; + sde_enc = to_sde_encoder_virt(phys_enc->parent); + if (!sde_enc) { SDE_ERROR("invalid param sde_enc:%d\n", sde_enc != NULL); return; @@ -1592,8 +1596,6 @@ void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc, return; } - sde_enc = to_sde_encoder_virt(phys_enc->parent); - drm_enc = &sde_enc->base; /* this pointers are checked in virt_enable_helper */ priv = drm_enc->dev->dev_private; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index 128b9d7a71dd..b72e5f2b17bb 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -131,7 +131,7 @@ static void _sde_encoder_phys_cmd_update_flush_mask( struct sde_hw_ctl *ctl; bool merge_3d_enable = false; - if (!phys_enc && !phys_enc->hw_intf && !phys_enc->hw_pp) + if (!phys_enc || !phys_enc->hw_intf || !phys_enc->hw_pp) return; cmd_enc = to_sde_encoder_phys_cmd(phys_enc); diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index ea0fb886776f..60a00e325aa1 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -835,6 +835,7 @@ static void sde_encoder_phys_vid_get_hw_resources( return; } + vid_enc = to_sde_encoder_phys_vid(phys_enc); SDE_DEBUG_VIDENC(vid_enc, "\n"); hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_VIDEO; } diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c index 59acecf73550..d9597933ed0d 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c @@ -1178,7 +1178,7 @@ static int _sde_encoder_phys_wb_init_internal_fb( /* allocate gem tracking object */ nplanes = drm_format_num_planes(pixel_format); - if (nplanes > SDE_MAX_PLANES) { + if (nplanes >= SDE_MAX_PLANES) { SDE_ERROR("requested format has too many planes\n"); return -EINVAL; } diff --git a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c index 5025eaac99a0..d25d1ce686de 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c @@ -223,7 +223,7 @@ int sde_hw_cdm_enable(struct sde_hw_cdm *ctx, struct sde_hw_cdm_cfg *cdm) { struct sde_hw_blk_reg_map *c = &ctx->hw; - const struct sde_format *fmt = cdm->output_fmt; + const struct sde_format *fmt; struct cdm_output_cfg cdm_cfg = { 0 }; u32 opmode = 0; u32 csc = 0; @@ -231,6 +231,8 @@ int sde_hw_cdm_enable(struct sde_hw_cdm *ctx, if (!ctx || !cdm) return -EINVAL; + fmt = cdm->output_fmt; + if (!SDE_FORMAT_IS_YUV(fmt)) return -EINVAL; diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c index 92734565d80b..82891477c403 100644 --- a/drivers/gpu/drm/msm/sde/sde_rm.c +++ b/drivers/gpu/drm/msm/sde/sde_rm.c @@ -421,7 +421,7 @@ int sde_rm_init(struct sde_rm *rm, void __iomem *mmio, struct drm_device *dev) { - int rc, i; + int i, rc = 0; enum sde_hw_blk_type type; if (!rm || !cat || !mmio || !dev) { -- GitLab From 6e8804734ae041ad6ebf7e06abf570f492638194 Mon Sep 17 00:00:00 2001 From: Deepak Katragadda Date: Mon, 18 Jun 2018 11:45:24 -0700 Subject: [PATCH 0429/1299] ARM: dts: msm: Add the parent-supply property to the GPU CX GDSC on SM8150 Cast an explicit vote on the CX rail on behalf of the GPU_CX GDSC since not doing do might lead to the CX rail turning off whilst the GDSC is still enabled. This in turn might lead to issues with retention. Change-Id: I5e165cb99220b391176c1599da0c09f5c2d50b4c Signed-off-by: Deepak Katragadda --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index afc1a293c19d..fd398fc9a9a7 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -3728,6 +3728,7 @@ }; &gpu_cx_gdsc { + parent-supply = <&VDD_CX_LEVEL>; status = "ok"; }; -- GitLab From a8ce96adaea261758ccd475aa72cc4eb5a3bd2ce Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Mon, 18 Jun 2018 19:51:48 -0700 Subject: [PATCH 0430/1299] sched/sysctl: check for min/max values for sched_{up,down}_migrate knobs Now that the sched_{up,down}_migrate knobs accept multiple values in case of multi cluster systems, make sure each value supplied by user is with in the range. Otherwise, user would see weird behavior when the knobs are read back after writing values (especially zero for downmigrate) supplied because one of the value supplied would be updated. For example: # cat /proc/sys/kernel/sched_downmigrate 85 85 # cat /proc/sys/kernel/sched_upmigrate 95 95 # echo "0 0" > /proc/sys/kernel/sched_downmigrate # echo "100 100" > /proc/sys/kernel/sched_upmigrate # cat /proc/sys/kernel/sched_downmigrate 85 0 # cat /proc/sys/kernel/sched_upmigrate 95 100 Expected Results: # cat /proc/sys/kernel/sched_downmigrate 0 0 # cat /proc/sys/kernel/sched_upmigrate 100 100 Change-Id: Id6db51656b71c3399ecd16ff5ef7c85ced6d7ceb Signed-off-by: Satya Durga Srinivasu Prabhala --- kernel/sysctl.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 0ed69a527bb5..daa2c9024ed0 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -380,6 +380,8 @@ static struct ctl_table kern_table[] = { .maxlen = sizeof(unsigned int) * MAX_MARGIN_LEVELS, .mode = 0644, .proc_handler = sched_updown_migrate_handler, + .extra1 = &one, + .extra2 = &sysctl_sched_capacity_margin_down, }, { .procname = "sched_downmigrate", @@ -387,6 +389,7 @@ static struct ctl_table kern_table[] = { .maxlen = sizeof(unsigned int) * MAX_MARGIN_LEVELS, .mode = 0644, .proc_handler = sched_updown_migrate_handler, + .extra1 = &sysctl_sched_capacity_margin_up, }, #ifdef CONFIG_SCHED_DEBUG { @@ -3249,10 +3252,20 @@ int proc_do_large_bitmap(struct ctl_table *table, int write, static int do_proc_douintvec_capacity_conv(bool *negp, unsigned long *lvalp, int *valp, int write, void *data) { + struct do_proc_douintvec_minmax_conv_param *param = data; + if (write) { + int val; + if (*negp) return -EINVAL; - *valp = SCHED_FIXEDPOINT_SCALE * 100 / *lvalp; + + val = SCHED_FIXEDPOINT_SCALE * 100 / *lvalp; + if ((param->min && *param->min > val) || + (param->max && *param->max < val)) + return -ERANGE; + + *valp = val; } else { *negp = false; *lvalp = SCHED_FIXEDPOINT_SCALE * 100 / *valp; @@ -3275,8 +3288,13 @@ static int do_proc_douintvec_capacity_conv(bool *negp, unsigned long *lvalp, int proc_douintvec_capacity(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { + struct do_proc_douintvec_minmax_conv_param param = { + .min = (unsigned int *) table->extra1, + .max = (unsigned int *) table->extra2, + }; + return do_proc_dointvec(table, write, buffer, lenp, ppos, - do_proc_douintvec_capacity_conv, NULL); + do_proc_douintvec_capacity_conv, ¶m); } #else /* CONFIG_PROC_SYSCTL */ -- GitLab From a25145102a66a80d2acc0e1a7c1016a85960b240 Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Wed, 6 Jun 2018 15:43:36 -0700 Subject: [PATCH 0431/1299] ARM: dts: msm: enable display rsc for sm8150 Enable display rsc on sm8150 target for clock gating and bw update. This hardware blocks has additional clocks requirement for mode2 entry and exit sequences due to VBIF fetch halt support. It also redirect all active BW vote through display rsc instead of apps rsc. That allows single node creation on apps rsc to reduce the bus vote latency. Change-Id: I3f629323492c58c08a54d640e5b4f3076322a157 Signed-off-by: Dhaval Patel --- .../boot/dts/qcom/sm8150-sde-display.dtsi | 2 +- arch/arm64/boot/dts/qcom/sm8150-sde-pll.dtsi | 17 ------ arch/arm64/boot/dts/qcom/sm8150-sde.dtsi | 58 +++++-------------- 3 files changed, 14 insertions(+), 63 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi index 38a805f27487..c45aa33b115a 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi @@ -421,7 +421,7 @@ }; &mdss_mdp { - connectors = <&sde_wb &sde_dp &sde_dsi>; + connectors = <&sde_rscc &sde_wb &sde_dp &sde_dsi>; }; /* PHY TIMINGS REVISION P */ diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde-pll.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde-pll.dtsi index d6d0388f2258..ea5861d61963 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde-pll.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde-pll.dtsi @@ -79,8 +79,6 @@ reg-names = "pll_base", "phy_base", "ln_tx0_base", "ln_tx1_base", "gdsc_base"; - gdsc-supply = <&mdss_core_gdsc>; - clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>, <&clock_rpmh RPMH_CXO_CLK>, <&clock_gcc GCC_DISP_AHB_CLK>, @@ -89,21 +87,6 @@ clock-names = "iface_clk", "ref_clk_src", "gcc_iface", "ref_clk", "pipe_clk"; clock-rate = <0>; - - qcom,platform-supply-entries { - #address-cells = <1>; - #size-cells = <0>; - - qcom,platform-supply-entry@0 { - reg = <0>; - qcom,supply-name = "gdsc"; - qcom,supply-min-voltage = <0>; - qcom,supply-max-voltage = <0>; - qcom,supply-enable-load = <0>; - qcom,supply-disable-load = <0>; - }; - - }; }; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi index 78780b926d67..295fb680c8ef 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi @@ -24,17 +24,20 @@ clocks = <&clock_gcc GCC_DISP_AHB_CLK>, <&clock_gcc GCC_DISP_HF_AXI_CLK>, + <&clock_gcc GCC_DISP_SF_AXI_CLK>, <&clock_dispcc DISP_CC_MDSS_AHB_CLK>, <&clock_dispcc DISP_CC_MDSS_MDP_CLK>, <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>, - <&clock_dispcc DISP_CC_MDSS_MDP_LUT_CLK>; - clock-names = "gcc_iface", "gcc_bus", + <&clock_dispcc DISP_CC_MDSS_MDP_LUT_CLK>, + <&clock_dispcc DISP_CC_MDSS_ROT_CLK>; + clock-names = "gcc_iface", "gcc_bus", "gcc_nrt_bus", "iface_clk", "core_clk", "vsync_clk", - "lut_clk"; - clock-rate = <0 0 0 300000000 19200000 300000000>; - clock-max-rate = <0 0 0 460000000 19200000 460000000>; + "lut_clk", "rot_clk"; + clock-rate = <0 0 0 0 300000000 19200000 300000000>; + clock-max-rate = <0 0 0 0 460000000 19200000 460000000>; sde-vdd-supply = <&mdss_core_gdsc>; + mmcx-supply = <&VDD_MMCX_LEVEL>; /* interrupt config */ interrupts = <0 83 0>; @@ -246,7 +249,7 @@ qcom,platform-supply-entry@0 { reg = <0>; - qcom,supply-name = "sde-vdd"; + qcom,supply-name = "mmcx"; qcom,supply-min-voltage = <0>; qcom,supply-max-voltage = <0>; qcom,supply-enable-load = <0>; @@ -261,33 +264,13 @@ /* data and reg bus scale settings */ qcom,sde-data-bus { - qcom,msm-bus,name = "mdss_sde_mnoc"; + qcom,msm-bus,name = "mdss_sde"; qcom,msm-bus,num-cases = <3>; qcom,msm-bus,num-paths = <2>; qcom,msm-bus,vectors-KBps = - <22 773 0 0>, <23 773 0 0>, - <22 773 0 6400000>, <23 773 0 6400000>, - <22 773 0 6400000>, <23 773 0 6400000>; - }; - - qcom,sde-llcc-bus { - qcom,msm-bus,name = "mdss_sde_llcc"; - qcom,msm-bus,num-cases = <3>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - <132 770 0 0>, - <132 770 0 6400000>, - <132 770 0 6400000>; - }; - - qcom,sde-ebi-bus { - qcom,msm-bus,name = "mdss_sde_ebi"; - qcom,msm-bus,num-cases = <3>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - <129 512 0 0>, - <129 512 0 6400000>, - <129 512 0 6400000>; + <22 512 0 0>, <23 512 0 0>, + <22 512 0 6400000>, <23 512 0 6400000>, + <22 512 0 6400000>, <23 512 0 6400000>; }; qcom,sde-reg-bus { @@ -309,7 +292,6 @@ <0xaf30000 0x3fd4>; reg-names = "drv", "wrapper"; qcom,sde-rsc-version = <2>; - status = "disabled"; vdd-supply = <&mdss_core_gdsc>; clocks = <&clock_dispcc DISP_CC_MDSS_RSCC_VSYNC_CLK>, @@ -356,20 +338,6 @@ <20000 20512 0 6400000>, <20000 20512 0 6400000>; }; - - qcom,platform-supply-entries { - #address-cells = <1>; - #size-cells = <0>; - - qcom,platform-supply-entry@0 { - reg = <0>; - qcom,supply-name = "mmcx"; - qcom,supply-min-voltage = <0>; - qcom,supply-max-voltage = <0>; - qcom,supply-enable-load = <0>; - qcom,supply-disable-load = <0>; - }; - }; }; mdss_rotator: qcom,mdss_rotator@ae00000 { -- GitLab From fdefcaeb3459b7a174f06a8e8308221667c5adb1 Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Wed, 13 Jun 2018 13:55:46 -0700 Subject: [PATCH 0432/1299] drm/msm/sde: signal pageflip event after frame kickoff sde_crtc module updates the event status before frame kickoff and triggers the pageflip event on vsync callback. That may lead to trigger pageflip event before actual frame kickoff if there is pending vsync process. This change updates the crtc event status after frame kickoff and triggers the pageflip event in wait_for_commit done to avoid race condition. Change-Id: Ibfbef206495cbd66e2c401afaf4ba056439cf738 Signed-off-by: Dhaval Patel --- drivers/gpu/drm/msm/sde/sde_crtc.c | 71 ++++++++++++------------------ drivers/gpu/drm/msm/sde/sde_crtc.h | 4 +- drivers/gpu/drm/msm/sde/sde_kms.c | 5 ++- 3 files changed, 34 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 310d6498df61..fd2df28b7b27 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -2186,7 +2186,7 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, } /** - * _sde_crtc_complete_flip - signal pending page_flip events + * sde_crtc_complete_flip - signal pending page_flip events * Any pending vblank events are added to the vblank_event_list * so that the next vblank interrupt shall signal them. * However PAGE_FLIP events are not handled through the vblank_event_list. @@ -2196,7 +2196,7 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, * @crtc: Pointer to drm crtc structure * @file: Pointer to drm file */ -static void _sde_crtc_complete_flip(struct drm_crtc *crtc, +void sde_crtc_complete_flip(struct drm_crtc *crtc, struct drm_file *file) { struct sde_crtc *sde_crtc = to_sde_crtc(crtc); @@ -2206,19 +2206,23 @@ static void _sde_crtc_complete_flip(struct drm_crtc *crtc, spin_lock_irqsave(&dev->event_lock, flags); event = sde_crtc->event; - if (event) { - /* if regular vblank case (!file) or if cancel-flip from - * preclose on file that requested flip, then send the - * event: - */ - if (!file || (event->base.file_priv == file)) { - sde_crtc->event = NULL; - DRM_DEBUG_VBL("%s: send event: %pK\n", - sde_crtc->name, event); - SDE_EVT32_VERBOSE(DRMID(crtc)); - drm_crtc_send_vblank_event(crtc, event); - } + if (!event) + goto end; + + /* + * if regular vblank case (!file) or if cancel-flip from + * preclose on file that requested flip, then send the + * event: + */ + if (!file || (event->base.file_priv == file)) { + sde_crtc->event = NULL; + DRM_DEBUG_VBL("%s: send event: %pK\n", + sde_crtc->name, event); + SDE_EVT32_VERBOSE(DRMID(crtc)); + drm_crtc_send_vblank_event(crtc, event); } + +end: spin_unlock_irqrestore(&dev->event_lock, flags); } @@ -2252,7 +2256,6 @@ static void sde_crtc_vblank_cb(void *data) sde_crtc->vblank_last_cb_time = ktime_get(); sysfs_notify_dirent(sde_crtc->vsync_event_sf); - _sde_crtc_complete_flip(crtc, NULL); drm_crtc_handle_vblank(crtc); DRM_DEBUG_VBL("crtc%d\n", crtc->base.id); SDE_EVT32_VERBOSE(DRMID(crtc)); @@ -3054,7 +3057,6 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, struct sde_crtc *sde_crtc; struct drm_encoder *encoder; struct drm_device *dev; - unsigned long flags; struct sde_kms *sde_kms; if (!crtc) { @@ -3088,14 +3090,6 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, _sde_crtc_setup_lm_bounds(crtc, crtc->state); } - if (sde_crtc->event) { - WARN_ON(sde_crtc->event); - } else { - spin_lock_irqsave(&dev->event_lock, flags); - sde_crtc->event = crtc->state->event; - spin_unlock_irqrestore(&dev->event_lock, flags); - } - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc != crtc) continue; @@ -3148,7 +3142,6 @@ static void sde_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_plane *plane; struct msm_drm_private *priv; struct msm_drm_thread *event_thread; - unsigned long flags; struct sde_crtc_state *cstate; struct sde_kms *sde_kms; int idle_time = 0; @@ -3190,14 +3183,6 @@ static void sde_crtc_atomic_flush(struct drm_crtc *crtc, event_thread = &priv->event_thread[crtc->index]; idle_time = sde_crtc_get_property(cstate, CRTC_PROP_IDLE_TIMEOUT); - if (sde_crtc->event) { - SDE_DEBUG("already received sde_crtc->event\n"); - } else { - spin_lock_irqsave(&dev->event_lock, flags); - sde_crtc->event = crtc->state->event; - spin_unlock_irqrestore(&dev->event_lock, flags); - } - /* * If no mixers has been allocated in sde_crtc_atomic_check(), * it means we are trying to flush a CRTC whose state is disabled: @@ -3638,6 +3623,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, struct sde_kms *sde_kms; struct sde_crtc_state *cstate; bool is_error, reset_req, recovery_events; + unsigned long flags; if (!crtc) { SDE_ERROR("invalid argument\n"); @@ -3738,6 +3724,15 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, sde_encoder_kickoff(encoder, false); } + /* store the event after frame trigger */ + if (sde_crtc->event) { + WARN_ON(sde_crtc->event); + } else { + spin_lock_irqsave(&dev->event_lock, flags); + sde_crtc->event = crtc->state->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + } + SDE_ATRACE_END("crtc_commit"); } @@ -4907,16 +4902,6 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en) return 0; } -void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file) -{ - struct sde_crtc *sde_crtc = to_sde_crtc(crtc); - - SDE_DEBUG("%s: cancel: %pK\n", sde_crtc->name, file); - _sde_crtc_complete_flip(crtc, file); -} - - - /** * sde_crtc_install_properties - install all drm properties for crtc * @crtc: Pointer to drm crtc structure diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h index 37e197e1e37a..92b8fea93aab 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.h +++ b/drivers/gpu/drm/msm/sde/sde_crtc.h @@ -526,11 +526,11 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane); int sde_crtc_post_init(struct drm_device *dev, struct drm_crtc *crtc); /** - * sde_crtc_cancel_pending_flip - complete flip for clients on lastclose + * sde_crtc_complete_flip - complete flip for clients * @crtc: Pointer to drm crtc object * @file: client to cancel's file handle */ -void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file); +void sde_crtc_complete_flip(struct drm_crtc *crtc, struct drm_file *file); /** * sde_crtc_register_custom_event - api for enabling/disabling crtc event diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 72f1f1a96166..c43977cec65b 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -1096,6 +1096,8 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms, SDE_ERROR("wait for commit done returned %d\n", ret); break; } + + sde_crtc_complete_flip(crtc, NULL); } } @@ -1928,8 +1930,9 @@ static void sde_kms_preclose(struct msm_kms *kms, struct drm_file *file) struct drm_modeset_acquire_ctx ctx; int ret = 0; + /* cancel pending flip event */ for (i = 0; i < priv->num_crtcs; i++) - sde_crtc_cancel_pending_flip(priv->crtcs[i], file); + sde_crtc_complete_flip(priv->crtcs[i], file); drm_modeset_acquire_init(&ctx, 0); retry: -- GitLab From 2a90a806635559ff1c6f1a28d2ca486184be2df8 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Fri, 15 Jun 2018 20:47:24 -0700 Subject: [PATCH 0433/1299] mhi: core: remove having compile option for CONFIG_OF flag All new targets are compiled with devicetree support, no need to have compile option in driver. CRs-Fixed: 2258358 Change-Id: I722dcd2fd1d4b635ac7ec41f6a4dfc3479361bd4 Signed-off-by: Sujeev Dias --- drivers/bus/mhi/core/mhi_init.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 0b8403277bdc..d9e740cff125 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -736,7 +736,6 @@ int mhi_device_configure(struct mhi_device *mhi_dev, return 0; } -#if defined(CONFIG_OF) static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl, struct device_node *of_node) { @@ -1046,13 +1045,6 @@ static int of_parse_dt(struct mhi_controller *mhi_cntrl, return ret; } -#else -static int of_parse_dt(struct mhi_controller *mhi_cntrl, - struct device_node *of_node) -{ - return -EINVAL; -} -#endif int of_register_mhi_controller(struct mhi_controller *mhi_cntrl) { -- GitLab From a5c630bb28ed30b6d9f19b9510c535a086fd1767 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Sat, 16 Jun 2018 16:02:16 -0700 Subject: [PATCH 0434/1299] mhi: core: marked __packed only members that's required It's recommended style to mark __packed only members that does not have natural alignment for clarity. CRs-Fixed: 2258358 Change-Id: Id560e23427d932c9e15cc7e4872366f130d7e8df Signed-off-by: Sujeev Dias --- drivers/bus/mhi/core/mhi_boot.c | 2 +- drivers/bus/mhi/core/mhi_init.c | 6 ++--- drivers/bus/mhi/core/mhi_internal.h | 34 ++++++++++++++--------------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_boot.c b/drivers/bus/mhi/core/mhi_boot.c index 79a25d5a055b..8f4583a3982f 100644 --- a/drivers/bus/mhi/core/mhi_boot.c +++ b/drivers/bus/mhi/core/mhi_boot.c @@ -394,7 +394,7 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, /* last entry is for vector table */ if (i == segments - 1) - vec_size = sizeof(struct __packed bhi_vec_entry) * i; + vec_size = sizeof(struct bhi_vec_entry) * i; mhi_buf->len = vec_size; mhi_buf->buf = mhi_alloc_coherent(mhi_cntrl, vec_size, diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index d9e740cff125..5fc9c7f17618 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -333,7 +333,7 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl) er_ctxt->msivec = mhi_event->msi; mhi_event->db_cfg.db_mode = true; - ring->el_size = sizeof(struct __packed mhi_tre); + ring->el_size = sizeof(struct mhi_tre); ring->len = ring->el_size * ring->elements; ret = mhi_alloc_aligned_ring(mhi_cntrl, ring, ring->len); if (ret) @@ -358,7 +358,7 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl) for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++, cmd_ctxt++) { struct mhi_ring *ring = &mhi_cmd->ring; - ring->el_size = sizeof(struct __packed mhi_tre); + ring->el_size = sizeof(struct mhi_tre); ring->elements = CMD_EL_PER_RING; ring->len = ring->el_size * ring->elements; ret = mhi_alloc_aligned_ring(mhi_cntrl, ring, ring->len); @@ -643,7 +643,7 @@ int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl, buf_ring = &mhi_chan->buf_ring; tre_ring = &mhi_chan->tre_ring; - tre_ring->el_size = sizeof(struct __packed mhi_tre); + tre_ring->el_size = sizeof(struct mhi_tre); tre_ring->len = tre_ring->el_size * tre_ring->elements; chan_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[mhi_chan->chan]; ret = mhi_alloc_aligned_ring(mhi_cntrl, tre_ring, tre_ring->len); diff --git a/drivers/bus/mhi/core/mhi_internal.h b/drivers/bus/mhi/core/mhi_internal.h index 9d39040c5590..cfae808c61de 100644 --- a/drivers/bus/mhi/core/mhi_internal.h +++ b/drivers/bus/mhi/core/mhi_internal.h @@ -220,47 +220,47 @@ extern struct bus_type mhi_bus_type; #define BHIE_RXVECSTATUS_STATUS_XFER_COMPL (0x02) #define BHIE_RXVECSTATUS_STATUS_ERROR (0x03) -struct __packed mhi_event_ctxt { +struct mhi_event_ctxt { u32 reserved : 8; u32 intmodc : 8; u32 intmodt : 16; u32 ertype; u32 msivec; - u64 rbase; - u64 rlen; - u64 rp; - u64 wp; + u64 rbase __packed __aligned(4); + u64 rlen __packed __aligned(4); + u64 rp __packed __aligned(4); + u64 wp __packed __aligned(4); }; -struct __packed mhi_chan_ctxt { +struct mhi_chan_ctxt { u32 chstate : 8; u32 brstmode : 2; u32 pollcfg : 6; u32 reserved : 16; u32 chtype; u32 erindex; - u64 rbase; - u64 rlen; - u64 rp; - u64 wp; + u64 rbase __packed __aligned(4); + u64 rlen __packed __aligned(4); + u64 rp __packed __aligned(4); + u64 wp __packed __aligned(4); }; -struct __packed mhi_cmd_ctxt { +struct mhi_cmd_ctxt { u32 reserved0; u32 reserved1; u32 reserved2; - u64 rbase; - u64 rlen; - u64 rp; - u64 wp; + u64 rbase __packed __aligned(4); + u64 rlen __packed __aligned(4); + u64 rp __packed __aligned(4); + u64 wp __packed __aligned(4); }; -struct __packed mhi_tre { +struct mhi_tre { u64 ptr; u32 dword[2]; }; -struct __packed bhi_vec_entry { +struct bhi_vec_entry { u64 dma_addr; u64 size; }; -- GitLab From a3c82028fa94d81caeb626e919d1c3a856e7c0f6 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Mon, 18 Jun 2018 16:28:48 -0700 Subject: [PATCH 0435/1299] mhi: core: use fixed-length string for mhi_device_id If we don't use a fixed-length string, dynamically loadable modules related to MHI will not load properly. CRs-Fixed: 2258358 Change-Id: Ice7c6d42c26807a5085e22b44451f57d6edf81dd Signed-off-by: Sujeev Dias --- drivers/bus/mhi/core/mhi_dtr.c | 2 +- drivers/bus/mhi/core/mhi_init.c | 2 +- drivers/bus/mhi/devices/mhi_netdev.c | 2 +- drivers/bus/mhi/devices/mhi_uci.c | 2 +- drivers/char/diag/diagfwd_mhi.c | 2 +- drivers/soc/qcom/qdss_bridge.c | 2 +- include/linux/mod_devicetable.h | 4 +++- 7 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_dtr.c b/drivers/bus/mhi/core/mhi_dtr.c index 6ffe80163a96..1db34b69eace 100644 --- a/drivers/bus/mhi/core/mhi_dtr.c +++ b/drivers/bus/mhi/core/mhi_dtr.c @@ -212,7 +212,7 @@ static int mhi_dtr_probe(struct mhi_device *mhi_dev, static const struct mhi_device_id mhi_dtr_table[] = { { .chan = "IP_CTRL" }, - { NULL }, + {}, }; static struct mhi_driver mhi_dtr_driver = { diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 5fc9c7f17618..b5b9d6fd6bca 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -1283,7 +1283,7 @@ static int mhi_match(struct device *dev, struct device_driver *drv) if (mhi_dev->dev_type == MHI_CONTROLLER_TYPE) return 0; - for (id = mhi_drv->id_table; id->chan; id++) + for (id = mhi_drv->id_table; id->chan[0]; id++) if (!strcmp(mhi_dev->chan_name, id->chan)) { mhi_dev->id = id; return 1; diff --git a/drivers/bus/mhi/devices/mhi_netdev.c b/drivers/bus/mhi/devices/mhi_netdev.c index 8b4ba7080036..c6ec258d43cb 100644 --- a/drivers/bus/mhi/devices/mhi_netdev.c +++ b/drivers/bus/mhi/devices/mhi_netdev.c @@ -977,7 +977,7 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev, static const struct mhi_device_id mhi_netdev_match_table[] = { { .chan = "IP_HW0" }, { .chan = "IP_HW_ADPL" }, - { NULL }, + {}, }; static struct mhi_driver mhi_netdev_driver = { diff --git a/drivers/bus/mhi/devices/mhi_uci.c b/drivers/bus/mhi/devices/mhi_uci.c index 12934efcd4a8..eed5429e918a 100644 --- a/drivers/bus/mhi/devices/mhi_uci.c +++ b/drivers/bus/mhi/devices/mhi_uci.c @@ -655,7 +655,7 @@ static const struct mhi_device_id mhi_uci_match_table[] = { { .chan = "TF", .driver_data = 0x1000 }, { .chan = "BL", .driver_data = 0x1000 }, { .chan = "DUN", .driver_data = 0x1000 }, - { NULL }, + {}, }; static struct mhi_driver mhi_uci_driver = { diff --git a/drivers/char/diag/diagfwd_mhi.c b/drivers/char/diag/diagfwd_mhi.c index 58259e1221b8..215f5a54fa07 100644 --- a/drivers/char/diag/diagfwd_mhi.c +++ b/drivers/char/diag/diagfwd_mhi.c @@ -720,7 +720,7 @@ void diag_mhi_exit(void) static const struct mhi_device_id diag_mhi_match_table[] = { { .chan = "DIAG", .driver_data = MHI_1 }, { .chan = "DCI", .driver_data = MHI_DCI_1 }, - {NULL}, + {}, }; static struct mhi_driver diag_mhi_driver = { diff --git a/drivers/soc/qcom/qdss_bridge.c b/drivers/soc/qcom/qdss_bridge.c index f336cfbdca49..79921d2259d3 100644 --- a/drivers/soc/qcom/qdss_bridge.c +++ b/drivers/soc/qcom/qdss_bridge.c @@ -421,7 +421,7 @@ static int qdss_mhi_probe(struct mhi_device *mhi_dev, static const struct mhi_device_id qdss_mhi_match_table[] = { { .chan = "QDSS" }, - { NULL }, + {}, }; static struct mhi_driver qdss_mhi_driver = { diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 76b4958d078f..a08bfd52b360 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -705,6 +705,8 @@ struct fsl_mc_device_id { const char obj_type[16]; }; +#define MHI_NAME_SIZE 32 + /** * struct mhi_device_id - MHI device identification * @chan: MHI channel name @@ -712,7 +714,7 @@ struct fsl_mc_device_id { */ struct mhi_device_id { - const char *chan; + const char chan[MHI_NAME_SIZE]; kernel_ulong_t driver_data; }; -- GitLab From 459964f60c72f26f791816f715b216b21d454c9d Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Mon, 28 Sep 2015 13:10:19 +0530 Subject: [PATCH 0436/1299] USB: f_accessory: Set manufacturer and model string to default value Currently USB driver is resetting strings like manufacturer, model to zero as part of handling control request for protocol version. Some accessory docks may not send manufacturer and model strings before sending control request to enable audiosource USB composition. This results in userspace enabling audio source composition without accessory interface. If accessory dock is connected during bootup, accessory timeouts in configuring android device and results in detection failure. Userspace does have recovery mechanism if incase accessory dock timeouts to configure android device in accessory composition. Hence set manufacturer and model strings to default value so that userspace enables accessory + audiosource composition for userspace recovery to be working and detecting accessory dock successfully during bootup. Change-Id: Ibe4dd9d951a9615ae100e68dc15b3614e9834848 Signed-off-by: Vijayavardhan Vennapusa --- drivers/usb/gadget/function/f_accessory.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c index 7aa2656a2328..24d801f6bfa1 100644 --- a/drivers/usb/gadget/function/f_accessory.c +++ b/drivers/usb/gadget/function/f_accessory.c @@ -906,6 +906,8 @@ int acc_ctrlrequest(struct usb_composite_dev *cdev, memset(dev->serial, 0, sizeof(dev->serial)); dev->start_requested = 0; dev->audio_mode = 0; + strlcpy(dev->manufacturer, "Android", ACC_STRING_SIZE); + strlcpy(dev->model, "Android", ACC_STRING_SIZE); } } -- GitLab From a72dcd5ebd1fa7a8bf56616a4af415f5b68c9582 Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Mon, 2 May 2016 13:26:15 -0700 Subject: [PATCH 0437/1299] usb: gadget: f_accessory: Make RX buffer size aligned to EP's MTU Synopsys USB3 Controller (DWC3) has a restriction where size of OUT requests (TRB) queued to the controller must be aligned with the endpoint's max packet size. Generally, accessory userspace module submits RX requests not aligned to endpoint's max packet size. Hence to overcome this, align the size of RX request buffer to endpoint's max packet while submitting to DCD as the buffers are already allocated with the size of 16KB. Change-Id: I3acdfc055d0c6a79a0aa65a715bae06dc475d078 Signed-off-by: Vijayavardhan Vennapusa Signed-off-by: Mayank Rana --- drivers/usb/gadget/function/f_accessory.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c index 24d801f6bfa1..0011be5a97c3 100644 --- a/drivers/usb/gadget/function/f_accessory.c +++ b/drivers/usb/gadget/function/f_accessory.c @@ -567,8 +567,7 @@ static ssize_t acc_read(struct file *fp, char __user *buf, { struct acc_dev *dev = fp->private_data; struct usb_request *req; - ssize_t r = count; - unsigned xfer; + ssize_t r = count, xfer, len; int ret = 0; pr_debug("acc_read(%zu)\n", count); @@ -581,6 +580,8 @@ static ssize_t acc_read(struct file *fp, char __user *buf, if (count > BULK_BUFFER_SIZE) count = BULK_BUFFER_SIZE; + len = ALIGN(count, dev->ep_out->maxpacket); + /* we will block until we're online */ pr_debug("acc_read: waiting for online\n"); ret = wait_event_interruptible(dev->read_wq, dev->online); @@ -598,7 +599,7 @@ static ssize_t acc_read(struct file *fp, char __user *buf, requeue_req: /* queue a request */ req = dev->rx_req[0]; - req->length = count; + req->length = len; dev->rx_done = 0; ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL); if (ret < 0) { -- GitLab From 6203388d1d4d0c0c29aacbed1bd936e4b29a6086 Mon Sep 17 00:00:00 2001 From: Manu Gautam Date: Wed, 20 Apr 2016 09:57:30 +0530 Subject: [PATCH 0438/1299] USB: f_accessory: Fix crash if driver failed to initialize If accessory driver setup fails then _acc_dev points to freed memory and later drivers crashes on disconnect due to invalid memory access. Mark _acc_dev only if acc_setup is successful to prevent the crash. Change-Id: Ica933a7cf710ff082c54db77f94f802b6832bedb Signed-off-by: Manu Gautam Signed-off-by: Mayank Rana --- drivers/usb/gadget/function/f_accessory.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c index 0011be5a97c3..5028fda0913d 100644 --- a/drivers/usb/gadget/function/f_accessory.c +++ b/drivers/usb/gadget/function/f_accessory.c @@ -1211,13 +1211,13 @@ static int acc_setup(void) INIT_DELAYED_WORK(&dev->start_work, acc_start_work); INIT_WORK(&dev->hid_work, acc_hid_work); - /* _acc_dev must be set before calling usb_gadget_register_driver */ - _acc_dev = dev; - ret = misc_register(&acc_device); if (ret) goto err; + /* _acc_dev must be set before calling usb_gadget_register_driver */ + _acc_dev = dev; + return 0; err: -- GitLab From ab39b53feb6a7f6ce60180c30c4d4df09c024f2a Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Fri, 6 May 2016 13:25:11 +0530 Subject: [PATCH 0439/1299] USB: f_accessory: Fix NULL pointer dereference in acc_read() If user tries to read /dev/usb_accessory node, it results in calling acc_read() callback. If accessory interface is not present in current USB composition, it will lead to crash as dev->ep_out is NULL. Fix the issue by moving problematic code down after device becomes online. Change-Id: I6441f6dc3cbe3a84a384fa3e8a6583f65a74659d Signed-off-by: Vijayavardhan Vennapusa --- drivers/usb/gadget/function/f_accessory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c index 5028fda0913d..1242ba78111e 100644 --- a/drivers/usb/gadget/function/f_accessory.c +++ b/drivers/usb/gadget/function/f_accessory.c @@ -580,8 +580,6 @@ static ssize_t acc_read(struct file *fp, char __user *buf, if (count > BULK_BUFFER_SIZE) count = BULK_BUFFER_SIZE; - len = ALIGN(count, dev->ep_out->maxpacket); - /* we will block until we're online */ pr_debug("acc_read: waiting for online\n"); ret = wait_event_interruptible(dev->read_wq, dev->online); @@ -590,6 +588,8 @@ static ssize_t acc_read(struct file *fp, char __user *buf, goto done; } + len = ALIGN(count, dev->ep_out->maxpacket); + if (dev->rx_done) { // last req cancelled. try to get it. req = dev->rx_req[0]; -- GitLab From 8d0313edee62faa8090e6822ad0eba326450fa77 Mon Sep 17 00:00:00 2001 From: Steve Cohen Date: Tue, 19 Jun 2018 16:14:30 -0400 Subject: [PATCH 0440/1299] drm/msm/sde: set correct bit width in qseed op mode Set the correct bit width when programming the qseed op mode register via the reg dma path. The logic was inverted from what HW expects which lead to incorrect processing of alpha blending use cases on VIG RECT0 pipes. Change-Id: I67b10376407ab63e19168e80a714fdeaf18912c5 Signed-off-by: Steve Cohen --- drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c index b03fc9ea1360..fc313dc29aa2 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -2527,7 +2527,7 @@ void reg_dmav1_setup_vig_qseed3(struct sde_hw_pipe *ctx, end: if (sspp->layout.format) { - if (SDE_FORMAT_IS_DX(sspp->layout.format)) + if (!SDE_FORMAT_IS_DX(sspp->layout.format)) op_mode |= BIT(14); if (sspp->layout.format->alpha_enable) { op_mode |= BIT(10); -- GitLab From 7bbb056a5def66fc5f53704b8dab153a2b1de558 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 31 May 2018 17:05:24 -0700 Subject: [PATCH 0441/1299] defconfig: sm8150: Enable USB UAC 2.0 drivers Enable USB UAC2.0 peripheral function driver that enables UAC 2.0 version based audio over USB. Change-Id: I5e5123503c31124f3acff9b838ea0666e15ca802 Signed-off-by: Hemant Kumar --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 418e04724ed9..2c5d2a1004b8 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -425,6 +425,7 @@ CONFIG_USB_CONFIGFS_F_PTP=y CONFIG_USB_CONFIGFS_F_ACC=y CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_F_UAC2=y CONFIG_USB_CONFIGFS_F_MIDI=y CONFIG_USB_CONFIGFS_F_HID=y CONFIG_USB_CONFIGFS_F_DIAG=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 729d35991e5b..ec52f172d9a2 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -441,6 +441,7 @@ CONFIG_USB_CONFIGFS_F_PTP=y CONFIG_USB_CONFIGFS_F_ACC=y CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_F_UAC2=y CONFIG_USB_CONFIGFS_F_MIDI=y CONFIG_USB_CONFIGFS_F_HID=y CONFIG_USB_CONFIGFS_F_DIAG=y -- GitLab From c304b59022d6b5f9e8f1db3325205819ad9ee823 Mon Sep 17 00:00:00 2001 From: Gopikrishnaiah Anandan Date: Wed, 21 Feb 2018 14:09:08 -0800 Subject: [PATCH 0442/1299] drm/msm/sde: fix race condition between enable/disable events When crtc event disable api is called, we search for the node with spin lock to avoid race condition in traversing list with other threads.Currently driver should remove the node with spin lock held before freeing the node to avoid list corruption. Change-Id: Iece8678c92e4bd6ed858e3e5174682fa01b28a0f Signed-off-by: Gopikrishnaiah Anandan --- drivers/gpu/drm/msm/sde/sde_crtc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 310d6498df61..966791b22ddf 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -6161,6 +6161,7 @@ static int _sde_crtc_event_disable(struct sde_kms *kms, spin_lock_irqsave(&crtc->spin_lock, flags); list_for_each_entry(node, &crtc->user_event_list, list) { if (node->event == event) { + list_del(&node->list); found = true; break; } @@ -6176,7 +6177,6 @@ static int _sde_crtc_event_disable(struct sde_kms *kms, * no need to disable/de-register. */ if (!crtc_drm->enabled) { - list_del(&node->list); kfree(node); return 0; } @@ -6185,13 +6185,11 @@ static int _sde_crtc_event_disable(struct sde_kms *kms, if (ret) { SDE_ERROR("failed to enable power resource %d\n", ret); SDE_EVT32(ret, SDE_EVTLOG_ERROR); - list_del(&node->list); kfree(node); return ret; } ret = node->func(crtc_drm, false, &node->irq); - list_del(&node->list); kfree(node); sde_power_resource_enable(&priv->phandle, kms->core_client, false); return ret; -- GitLab From d5f6cd8ae3adc9ad38fe303b7d5fe1f094f51ab6 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Wed, 20 Jun 2018 03:13:28 +0530 Subject: [PATCH 0443/1299] msm: adsprpc: use right DMA bit mask for 32 and 64 bit systems Use right length of DMA bit mask for 32 and 64 bit systems by typecasting it to the appropriate data type Change-Id: Ie7346fe950408e510a6b529b25f0dc57eb3ee438 Acked-by: Thyagarajan Venkatanarayanan Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 4d1f43bcef9c..906845977690 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -3124,7 +3124,7 @@ static int fastrpc_cb_probe(struct device *dev) sess->smmu.dev->dma_parms = devm_kzalloc(sess->smmu.dev, sizeof(*sess->smmu.dev->dma_parms), GFP_KERNEL); dma_set_max_seg_size(sess->smmu.dev, DMA_BIT_MASK(32)); - dma_set_seg_boundary(sess->smmu.dev, DMA_BIT_MASK(64)); + dma_set_seg_boundary(sess->smmu.dev, (unsigned long)DMA_BIT_MASK(64)); if (of_get_property(dev->of_node, "shared-cb", NULL) != NULL) { VERIFY(err, !of_property_read_u32(dev->of_node, "shared-cb", -- GitLab From a7c91c2ed7ddd0c85a919fe2909f9f2fdf1fb09a Mon Sep 17 00:00:00 2001 From: Shubhashree Dhar Date: Wed, 30 May 2018 15:42:04 +0530 Subject: [PATCH 0444/1299] msm/sde: Unregister input handler during encoder disable Flush and unregister input handler in encoder disable and register again in encoder enable. This is done to ensure that input handler doesn't work during suspend mode. Change-Id: I457a7e88bdf3bfd966da69edc81d14584dbeb784 Signed-off-by: Shubhashree Dhar --- drivers/gpu/drm/msm/sde/sde_encoder.c | 216 ++++++++++++++------------ 1 file changed, 119 insertions(+), 97 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index f1499487adee..df29b32c9a51 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -733,8 +733,8 @@ void sde_encoder_destroy(struct drm_encoder *drm_enc) mutex_destroy(&sde_enc->enc_lock); if (sde_enc->input_handler) { - input_unregister_handler(sde_enc->input_handler); kfree(sde_enc->input_handler); + sde_enc->input_handler = NULL; } kfree(sde_enc); @@ -2691,6 +2691,109 @@ void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable) } } +static int _sde_encoder_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) +{ + struct input_handle *handle; + int rc = 0; + + handle = kzalloc(sizeof(*handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = handler->name; + + rc = input_register_handle(handle); + if (rc) { + pr_err("failed to register input handle\n"); + goto error; + } + + rc = input_open_device(handle); + if (rc) { + pr_err("failed to open input device\n"); + goto error_unregister; + } + + return 0; + +error_unregister: + input_unregister_handle(handle); + +error: + kfree(handle); + + return rc; +} + +static void _sde_encoder_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +/** + * Structure for specifying event parameters on which to receive callbacks. + * This structure will trigger a callback in case of a touch event (specified by + * EV_ABS) where there is a change in X and Y coordinates, + */ +static const struct input_device_id sde_input_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) }, + }, + { }, +}; + +static int _sde_encoder_input_handler_register( + struct input_handler *input_handler) +{ + int rc = 0; + + rc = input_register_handler(input_handler); + if (rc) { + pr_err("input_register_handler failed, rc= %d\n", rc); + kfree(input_handler); + return rc; + } + + return rc; +} + +static int _sde_encoder_input_handler( + struct sde_encoder_virt *sde_enc) +{ + struct input_handler *input_handler = NULL; + int rc = 0; + + if (sde_enc->input_handler) { + SDE_ERROR_ENC(sde_enc, + "input_handle is active. unexpected\n"); + return -EINVAL; + } + + input_handler = kzalloc(sizeof(*sde_enc->input_handler), GFP_KERNEL); + if (!input_handler) + return -ENOMEM; + + input_handler->event = sde_encoder_input_event_handler; + input_handler->connect = _sde_encoder_input_connect; + input_handler->disconnect = _sde_encoder_input_disconnect; + input_handler->name = "sde"; + input_handler->id_table = sde_input_ids; + input_handler->private = sde_enc; + + sde_enc->input_handler = input_handler; + + return rc; +} + static void _sde_encoder_virt_enable_helper(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = NULL; @@ -2781,12 +2884,14 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) struct msm_compression_info *comp_info = NULL; struct drm_display_mode *cur_mode = NULL; struct msm_mode_info mode_info; + struct msm_display_info *disp_info; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); return; } sde_enc = to_sde_encoder_virt(drm_enc); + disp_info = &sde_enc->disp_info; if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) { SDE_ERROR("power resource is not enabled\n"); @@ -2824,6 +2929,14 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) return; } + if (sde_enc->input_handler) { + ret = _sde_encoder_input_handler_register( + sde_enc->input_handler); + if (ret) + SDE_ERROR( + "input handler registration failed, rc = %d\n", ret); + } + ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF); if (ret) { SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n", @@ -2910,6 +3023,11 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) /* wait for idle */ sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); + kthread_flush_work(&sde_enc->input_event_work); + + if (sde_enc->input_handler) + input_unregister_handler(sde_enc->input_handler); + /* * For primary command mode encoders, execute the resource control * pre-stop operations before the physical encoders are disabled, to @@ -3890,102 +4008,6 @@ static void sde_encoder_input_event_work_handler(struct kthread_work *work) SDE_ENC_RC_EVENT_EARLY_WAKEUP); } -static int _sde_encoder_input_connect(struct input_handler *handler, - struct input_dev *dev, const struct input_device_id *id) -{ - struct input_handle *handle; - int rc = 0; - - handle = kzalloc(sizeof(*handle), GFP_KERNEL); - if (!handle) - return -ENOMEM; - - handle->dev = dev; - handle->handler = handler; - handle->name = handler->name; - - rc = input_register_handle(handle); - if (rc) { - pr_err("failed to register input handle\n"); - goto error; - } - - rc = input_open_device(handle); - if (rc) { - pr_err("failed to open input device\n"); - goto error_unregister; - } - - return 0; - -error_unregister: - input_unregister_handle(handle); - -error: - kfree(handle); - - return rc; -} - -static void _sde_encoder_input_disconnect(struct input_handle *handle) -{ - input_close_device(handle); - input_unregister_handle(handle); - kfree(handle); -} - -/** - * Structure for specifying event parameters on which to receive callbacks. - * This structure will trigger a callback in case of a touch event (specified by - * EV_ABS) where there is a change in X and Y coordinates, - */ -static const struct input_device_id sde_input_ids[] = { - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT, - .evbit = { BIT_MASK(EV_ABS) }, - .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = - BIT_MASK(ABS_MT_POSITION_X) | - BIT_MASK(ABS_MT_POSITION_Y) }, - }, - { }, -}; - -static int _sde_encoder_input_handler( - struct sde_encoder_virt *sde_enc) -{ - struct input_handler *input_handler = NULL; - int rc = 0; - - if (sde_enc->input_handler) { - SDE_ERROR_ENC(sde_enc, - "input_handle is active. unexpected\n"); - return -EINVAL; - } - - input_handler = kzalloc(sizeof(*sde_enc->input_handler), GFP_KERNEL); - if (!input_handler) - return -ENOMEM; - - input_handler->event = sde_encoder_input_event_handler; - input_handler->connect = _sde_encoder_input_connect; - input_handler->disconnect = _sde_encoder_input_disconnect; - input_handler->name = "sde"; - input_handler->id_table = sde_input_ids; - input_handler->private = sde_enc; - - rc = input_register_handler(input_handler); - if (rc) { - SDE_ERROR_ENC(sde_enc, - "input_register_handler failed, rc= %d\n", rc); - kfree(input_handler); - return rc; - } - - sde_enc->input_handler = input_handler; - - return rc; -} - static void sde_encoder_vsync_event_work_handler(struct kthread_work *work) { struct sde_encoder_virt *sde_enc = container_of(work, -- GitLab From be1489ba09ca7c8a074da41b87816bda5c36d320 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Fri, 8 Jun 2018 15:54:42 -0700 Subject: [PATCH 0445/1299] f_gsi: Increase number of TRBs and its buffer size This change increases number of TRBs and its buffer size as below for better tethering throughput: RMNET: number of TRBs as 50, and buffer size to 31KB RNDIS: buffer size to 16KB Change-Id: I426958e0869e6a9f056ad8a21df56c9e801811d1 Signed-off-by: Mayank Rana --- drivers/usb/gadget/function/f_gsi.c | 6 +++--- drivers/usb/gadget/function/f_gsi.h | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 177b7b85326c..3717ab527008 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -2574,7 +2574,7 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f) info.ss_desc_hdr = gsi_eth_ss_function; info.in_epname = "gsi-epin"; info.out_epname = "gsi-epout"; - info.in_req_buf_len = GSI_IN_BUFF_SIZE; + info.in_req_buf_len = GSI_IN_RNDIS_BUFF_SIZE; gsi->d_port.in_aggr_size = GSI_IN_RNDIS_AGGR_SIZE; info.in_req_num_buf = GSI_NUM_IN_RNDIS_BUFFERS; gsi->d_port.out_aggr_size = GSI_OUT_AGGR_SIZE; @@ -2763,8 +2763,8 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f) info.in_epname = "gsi-epin"; info.out_epname = "gsi-epout"; gsi->d_port.in_aggr_size = GSI_IN_RMNET_AGGR_SIZE; - info.in_req_buf_len = GSI_IN_BUFF_SIZE; - info.in_req_num_buf = GSI_NUM_IN_BUFFERS; + info.in_req_buf_len = GSI_IN_RMNET_BUFF_SIZE; + info.in_req_num_buf = GSI_NUM_IN_RMNET_BUFFERS; gsi->d_port.out_aggr_size = GSI_OUT_AGGR_SIZE; info.out_req_buf_len = GSI_OUT_RMNET_BUF_LEN; info.out_req_num_buf = GSI_NUM_OUT_BUFFERS; diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h index 19f872b44f8e..e9ff9341fdbd 100644 --- a/drivers/usb/gadget/function/f_gsi.h +++ b/drivers/usb/gadget/function/f_gsi.h @@ -35,8 +35,11 @@ #define GSI_CTRL_DTR (1 << 0) #define GSI_NUM_IN_RNDIS_BUFFERS 50 +#define GSI_NUM_IN_RMNET_BUFFERS 50 #define GSI_NUM_IN_BUFFERS 15 #define GSI_IN_BUFF_SIZE 2048 +#define GSI_IN_RMNET_BUFF_SIZE 31744 +#define GSI_IN_RNDIS_BUFF_SIZE 16384 #define GSI_NUM_OUT_BUFFERS 14 #define GSI_OUT_AGGR_SIZE 24576 -- GitLab From d36974bb13bd5edc91fe9ca0d4f090e3c1ad530b Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Tue, 19 Jun 2018 18:17:23 -0400 Subject: [PATCH 0446/1299] Revert "msm: npu: Enable npu cti/apb/atb clocks" This reverts commit c3539a58d76647b8f8e6e1ee40e2b85ea2855f8f. Change-Id: Ia9baa3928ac1ede5917b4563083512cb7b4b6c97 Signed-off-by: Jilai Wang --- drivers/media/platform/msm/npu/npu_dev.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/msm/npu/npu_dev.c b/drivers/media/platform/msm/npu/npu_dev.c index 1df4e8363e58..2cc21518989c 100644 --- a/drivers/media/platform/msm/npu/npu_dev.c +++ b/drivers/media/platform/msm/npu/npu_dev.c @@ -99,13 +99,13 @@ static void __exit npu_exit(void); * ------------------------------------------------------------------------- */ static const char * const npu_clock_order[] = { - "at_clk", - "trig_clk", "armwic_core_clk", + "cal_dp_clk_src", "cal_dp_clk", "cal_dp_cdc_clk", "conf_noc_ahb_clk", "comp_noc_axi_clk", + "npu_core_clk_src", "npu_core_clk", "npu_core_cti_clk", "npu_core_apb_clk", @@ -126,16 +126,18 @@ static const char * const npu_post_clocks[] = { }; static const char * const npu_exclude_clocks[] = { + "npu_core_clk_src", + "cal_dp_clk_src", "perf_cnt_clk", + "npu_core_cti_clk", + "npu_core_apb_clk", + "npu_core_atb_clk" }; static const char * const npu_exclude_rate_clocks[] = { - "at_clk", - "trig_clk", "sleep_clk", "xo_clk", "conf_noc_ahb_clk", - "comp_noc_axi_clk", "npu_core_cti_clk", "npu_core_apb_clk", "npu_core_atb_clk", @@ -555,7 +557,7 @@ static int npu_enable_core_clocks(struct npu_device *npu_dev, bool post_pil) rc = clk_set_rate(core_clks[i].clk, pwrlevel->clk_freq[i]); if (rc) { - pr_err("clk_set_rate %s to %ld failed\n", + pr_debug("clk_set_rate %s to %ld failed\n", core_clks[i].clk_name, pwrlevel->clk_freq[i]); break; -- GitLab From 37a5a1e6d7c21ee0382793fa36ec0073ab12842c Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Tue, 19 Jun 2018 18:19:12 -0400 Subject: [PATCH 0447/1299] Revert "ARM: dts: Update NPU clocks for sm8150" This reverts commit a849d364ebf96e1896b69ff5d76ed264874ee004. Change-Id: I1594ac81f1143f190c24d35caa7a9c70a2ead3ce Signed-off-by: Jilai Wang --- arch/arm64/boot/dts/qcom/sm8150-npu.dtsi | 288 +++++++++++------------ 1 file changed, 144 insertions(+), 144 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi b/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi index d006daa38f95..fd99bfeb4482 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi @@ -24,43 +24,43 @@ cache-slice-names = "npu"; cache-slices = <&llcc 23>; clocks = <&clock_npucc NPU_CC_CAL_DP_CLK>, - <&clock_npucc NPU_CC_XO_CLK>, - <&clock_npucc NPU_CC_ARMWIC_CORE_CLK>, - <&clock_npucc NPU_CC_BTO_CORE_CLK>, - <&clock_npucc NPU_CC_BWMON_CLK>, - <&clock_npucc NPU_CC_CAL_DP_CDC_CLK>, - <&clock_npucc NPU_CC_COMP_NOC_AXI_CLK>, - <&clock_npucc NPU_CC_CONF_NOC_AHB_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_APB_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_ATB_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_CTI_CLK>, - <&clock_npucc NPU_CC_NPU_CPC_CLK>, - <&clock_npucc NPU_CC_NPU_CPC_TIMER_CLK>, - <&clock_npucc NPU_CC_PERF_CNT_CLK>, - <&clock_npucc NPU_CC_QTIMER_CORE_CLK>, - <&clock_npucc NPU_CC_SLEEP_CLK>, - <&clock_gcc GCC_NPU_AT_CLK>, - <&clock_gcc GCC_NPU_TRIG_CLK>; + <&clock_npucc NPU_CC_CAL_DP_CLK_SRC>, + <&clock_npucc NPU_CC_XO_CLK>, + <&clock_npucc NPU_CC_ARMWIC_CORE_CLK>, + <&clock_npucc NPU_CC_BTO_CORE_CLK>, + <&clock_npucc NPU_CC_BWMON_CLK>, + <&clock_npucc NPU_CC_CAL_DP_CDC_CLK>, + <&clock_npucc NPU_CC_COMP_NOC_AXI_CLK>, + <&clock_npucc NPU_CC_CONF_NOC_AHB_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_APB_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_ATB_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_CLK>, + <&clock_npucc NPU_CC_NPU_CORE_CLK_SRC>, + <&clock_npucc NPU_CC_NPU_CORE_CTI_CLK>, + <&clock_npucc NPU_CC_NPU_CPC_CLK>, + <&clock_npucc NPU_CC_NPU_CPC_TIMER_CLK>, + <&clock_npucc NPU_CC_PERF_CNT_CLK>, + <&clock_npucc NPU_CC_QTIMER_CORE_CLK>, + <&clock_npucc NPU_CC_SLEEP_CLK>; clock-names = "cal_dp_clk", - "xo_clk", - "armwic_core_clk", - "bto_core_clk", - "bwmon_clk", - "cal_dp_cdc_clk", - "comp_noc_axi_clk", - "conf_noc_ahb_clk", - "npu_core_apb_clk", - "npu_core_atb_clk", - "npu_core_clk", - "npu_core_cti_clk", - "npu_cpc_clk", - "npu_cpc_timer_clk", - "perf_cnt_clk", - "qtimer_core_clk", - "sleep_clk", - "at_clk", - "trig_clk"; + "cal_dp_clk_src", + "xo_clk", + "armwic_core_clk", + "bto_core_clk", + "bwmon_clk", + "cal_dp_cdc_clk", + "comp_noc_axi_clk", + "conf_noc_ahb_clk", + "npu_core_apb_clk", + "npu_core_atb_clk", + "npu_core_clk", + "npu_core_clk_src", + "npu_core_cti_clk", + "npu_cpc_clk", + "npu_cpc_timer_clk", + "perf_cnt_clk", + "qtimer_core_clk", + "sleep_clk"; vdd-supply = <&npu_core_gdsc>; vdd_cx-supply = <&VDD_CX_LEVEL>; qcom,proxy-reg-names ="vdd", "vdd_cx"; @@ -77,134 +77,134 @@ qcom,npu-pwrlevel@0 { reg = <0>; clk-freq = <9600000 - 19200000 - 19200000 - 19200000 - 19200000 - 9600000 - 60000000 - 19200000 - 19200000 - 30000000 - 19200000 - 19200000 - 19200000 - 19200000 - 9600000 - 19200000 - 0 - 0 - 0>; + 9600000 + 19200000 + 19200000 + 19200000 + 19200000 + 9600000 + 60000000 + 19200000 + 19200000 + 30000000 + 19200000 + 19200000 + 19200000 + 19200000 + 19200000 + 9600000 + 19200000 + 0>; }; qcom,npu-pwrlevel@1 { reg = <1>; clk-freq = <300000000 - 19200000 - 100000000 - 19200000 - 19200000 - 300000000 - 150000000 - 19200000 - 19200000 - 60000000 - 100000000 - 37500000 - 100000000 - 19200000 - 300000000 - 19200000 - 0 - 0 - 0>; + 300000000 + 19200000 + 100000000 + 19200000 + 19200000 + 300000000 + 150000000 + 19200000 + 19200000 + 60000000 + 100000000 + 100000000 + 37500000 + 100000000 + 19200000 + 300000000 + 19200000 + 0>; }; qcom,npu-pwrlevel@2 { reg = <2>; clk-freq = <350000000 - 19200000 - 150000000 - 19200000 - 19200000 - 350000000 - 200000000 - 37500000 - 19200000 - 120000000 - 150000000 - 75000000 - 150000000 - 19200000 - 350000000 - 19200000 - 0 - 0 - 0>; + 350000000 + 19200000 + 150000000 + 19200000 + 19200000 + 350000000 + 200000000 + 37500000 + 19200000 + 120000000 + 150000000 + 150000000 + 75000000 + 150000000 + 19200000 + 350000000 + 19200000 + 0>; }; qcom,npu-pwrlevel@3 { reg = <3>; clk-freq = <400000000 - 19200000 - 200000000 - 19200000 - 19200000 - 400000000 - 300000000 - 37500000 - 19200000 - 120000000 - 200000000 - 75000000 - 200000000 - 19200000 - 400000000 - 19200000 - 0 - 0 - 0>; + 400000000 + 19200000 + 200000000 + 19200000 + 19200000 + 400000000 + 300000000 + 37500000 + 19200000 + 120000000 + 200000000 + 200000000 + 75000000 + 200000000 + 19200000 + 400000000 + 19200000 + 0>; }; qcom,npu-pwrlevel@4 { reg = <4>; clk-freq = <600000000 - 19200000 - 300000000 - 19200000 - 19200000 - 600000000 - 403000000 - 75000000 - 19200000 - 240000000 - 300000000 - 150000000 - 300000000 - 19200000 - 600000000 - 19200000 - 0 - 0 - 0>; + 600000000 + 19200000 + 300000000 + 19200000 + 19200000 + 600000000 + 403000000 + 75000000 + 19200000 + 240000000 + 300000000 + 300000000 + 150000000 + 300000000 + 19200000 + 600000000 + 19200000 + 0>; }; qcom,npu-pwrlevel@5 { reg = <5>; clk-freq = <715000000 - 19200000 - 350000000 - 19200000 - 19200000 - 715000000 - 533000000 - 75000000 - 19200000 - 240000000 - 350000000 - 150000000 - 350000000 - 19200000 - 715000000 - 19200000 - 0 - 0 - 0>; + 715000000 + 19200000 + 350000000 + 19200000 + 19200000 + 715000000 + 533000000 + 75000000 + 19200000 + 240000000 + 350000000 + 350000000 + 150000000 + 350000000 + 19200000 + 715000000 + 19200000 + 0>; }; }; }; -- GitLab From 1108e9ec5f0c9296bc4246880c965f64ff3b5a7a Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Fri, 8 Jun 2018 16:11:51 -0700 Subject: [PATCH 0448/1299] dwc3: gadget: Increase TXFIFO size as 6KB for GSI IN endpoint For better tethering throughput, increase TXFIFO size as 6KB for GSI IN endpoint which enables bursting of more than 2. Change-Id: Ia6b86b90fb874bdc06065de51e65a9872022b372 Signed-off-by: Mayank Rana --- drivers/usb/dwc3/gadget.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1e0b33ccc4d6..61840a952489 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -225,14 +225,15 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc, struct dwc3_ep *dep) /* MDWIDTH is represented in bits, we need it in bytes */ mdwidth >>= 3; - if (dep->endpoint.ep_type == EP_TYPE_GSI || dep->endpoint.endless) - mult = 3; - if (((dep->endpoint.maxburst > 1) && usb_endpoint_xfer_bulk(dep->endpoint.desc)) || usb_endpoint_xfer_isoc(dep->endpoint.desc)) mult = 3; + if ((dep->endpoint.maxburst > 2) && + dep->endpoint.ep_type == EP_TYPE_GSI) + mult = 6; + tmp = ((max_packet + mdwidth) * mult) + mdwidth; fifo_size = DIV_ROUND_UP(tmp, mdwidth); dep->fifo_depth = fifo_size; -- GitLab From 26758ac623a6bf38a93255dfbf8a6ebabbe5073b Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Sun, 27 May 2018 10:34:13 -0600 Subject: [PATCH 0449/1299] net: qualcomm: rmnet: Add support for dowlink marker The downlink marker command packets provides information about the total packets which will arrive from the physical device. Each marker will have information about all the flows present in the burst regarding the byte and packet counts. CRs-Fixed: 2233026 Change-Id: If10394aaa5ed83ea20cb5211d11a47370cc5c41c Signed-off-by: Subash Abhinov Kasiviswanathan --- .../ethernet/qualcomm/rmnet/rmnet_config.c | 2 + .../ethernet/qualcomm/rmnet/rmnet_config.h | 4 + .../ethernet/qualcomm/rmnet/rmnet_handlers.c | 5 + .../net/ethernet/qualcomm/rmnet/rmnet_map.h | 64 +++++++- .../qualcomm/rmnet/rmnet_map_command.c | 147 ++++++++++++++++++ .../ethernet/qualcomm/rmnet/rmnet_private.h | 1 + 6 files changed, 222 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c index 30de5df17106..b0b0dbfa2f22 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c @@ -70,6 +70,7 @@ static int rmnet_unregister_real_device(struct net_device *real_dev, if (port->nr_rmnet_devs) return -EINVAL; + rmnet_map_cmd_exit(port); rmnet_map_tx_aggregate_exit(port); kfree(port); @@ -111,6 +112,7 @@ static int rmnet_register_real_device(struct net_device *real_dev) INIT_HLIST_HEAD(&port->muxed_ep[entry]); rmnet_map_tx_aggregate_init(port); + rmnet_map_cmd_init(port); netdev_dbg(real_dev, "registered with rmnet\n"); return 0; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h index 2dff6f688582..fd1d331bf1b3 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h @@ -52,6 +52,10 @@ struct rmnet_port { struct hrtimer hrtimer; void *qmi_info; + + /* dl marker elements */ + spinlock_t dl_list_lock; + struct list_head dl_list; }; extern struct rtnl_link_ops rmnet_link_ops; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c index 7350852311be..6bb3f6f8773e 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c @@ -92,6 +92,11 @@ __rmnet_map_ingress_handler(struct sk_buff *skb, u8 mux_id; if (RMNET_MAP_GET_CD_BIT(skb)) { + if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) { + if (!rmnet_map_flow_command(skb, port)) + return; + } + if (port->data_format & RMNET_FLAGS_INGRESS_MAP_COMMANDS) return rmnet_map_command(skb, port); diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h index 13d5e1af7742..c0179b901b04 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h @@ -34,6 +34,8 @@ enum rmnet_map_commands { RMNET_MAP_COMMAND_NONE, RMNET_MAP_COMMAND_FLOW_DISABLE, RMNET_MAP_COMMAND_FLOW_ENABLE, + RMNET_MAP_COMMAND_FLOW_START = 7, + RMNET_MAP_COMMAND_FLOW_END = 8, /* These should always be the last 2 elements */ RMNET_MAP_COMMAND_UNKNOWN, RMNET_MAP_COMMAND_ENUM_LENGTH @@ -63,6 +65,60 @@ struct rmnet_map_ul_csum_header { u16 csum_enabled:1; } __aligned(1); +struct rmnet_map_control_command_header { + u8 command_name; + u8 cmd_type:2; + u8 reserved:6; + u16 reserved2; + u32 transaction_id; +} __aligned(1); + +struct rmnet_map_flow_info_le { + __be32 mux_id; + __be32 flow_id; + __be32 bytes; + __be32 pkts; +} __aligned(1); + +struct rmnet_map_flow_info_be { + u32 mux_id; + u32 flow_id; + u32 bytes; + u32 pkts; +} __aligned(1); + +struct rmnet_map_dl_ind_hdr { + union { + struct { + u32 seq; + u32 bytes; + u32 pkts; + u32 flows; + struct rmnet_map_flow_info_le flow[0]; + } le __aligned(1); + struct { + __be32 seq; + __be32 bytes; + __be32 pkts; + __be32 flows; + struct rmnet_map_flow_info_be flow[0]; + } be __aligned(1); + } __aligned(1); +} __aligned(1); + +struct rmnet_map_dl_ind_trl { + union { + __be32 seq_be; + u32 seq_le; + } __aligned(1); +} __aligned(1); + +struct rmnet_map_dl_ind { + void (*dl_hdr_handler)(struct rmnet_map_dl_ind_hdr *); + void (*dl_trl_handler)(struct rmnet_map_dl_ind_trl *); + struct list_head list; +}; + #define RMNET_MAP_GET_MUX_ID(Y) (((struct rmnet_map_header *) \ (Y)->data)->mux_id) #define RMNET_MAP_GET_CD_BIT(Y) (((struct rmnet_map_header *) \ @@ -95,5 +151,11 @@ int rmnet_map_tx_agg_skip(struct sk_buff *skb, int offset); void rmnet_map_tx_aggregate(struct sk_buff *skb, struct rmnet_port *port); void rmnet_map_tx_aggregate_init(struct rmnet_port *port); void rmnet_map_tx_aggregate_exit(struct rmnet_port *port); - +int rmnet_map_flow_command(struct sk_buff *skb, struct rmnet_port *port); +void rmnet_map_cmd_init(struct rmnet_port *port); +int rmnet_map_dl_ind_register(struct rmnet_port *port, + struct rmnet_map_dl_ind *dl_ind); +int rmnet_map_dl_ind_deregister(struct rmnet_port *port, + struct rmnet_map_dl_ind *dl_ind); +void rmnet_map_cmd_exit(struct rmnet_port *port); #endif /* _RMNET_MAP_H_ */ diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c index 3ee8ae9b6838..9c92074456fb 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c @@ -16,6 +16,17 @@ #include "rmnet_private.h" #include "rmnet_vnd.h" +#define RMNET_DL_IND_HDR_SIZE (sizeof(struct rmnet_map_dl_ind_hdr) + \ + sizeof(struct rmnet_map_header) + \ + sizeof(struct rmnet_map_control_command_header)) + +#define RMNET_MAP_CMD_SIZE (sizeof(struct rmnet_map_header) + \ + sizeof(struct rmnet_map_control_command_header)) + +#define RMNET_DL_IND_TRL_SIZE (sizeof(struct rmnet_map_dl_ind_trl) + \ + sizeof(struct rmnet_map_header) + \ + sizeof(struct rmnet_map_control_command_header)) + static u8 rmnet_map_do_flow_control(struct sk_buff *skb, struct rmnet_port *port, int enable) @@ -83,6 +94,62 @@ static void rmnet_map_send_ack(struct sk_buff *skb, netif_tx_unlock(dev); } +static void rmnet_map_dl_hdr_notify(struct rmnet_port *port, + struct rmnet_map_dl_ind_hdr *dlhdr) +{ + struct rmnet_map_dl_ind *tmp; + + spin_lock(&port->dl_list_lock); + + list_for_each_entry(tmp, &port->dl_list, list) + tmp->dl_hdr_handler(dlhdr); + + spin_unlock(&port->dl_list_lock); +} + +static void rmnet_map_dl_trl_notify(struct rmnet_port *port, + struct rmnet_map_dl_ind_trl *dltrl) +{ + struct rmnet_map_dl_ind *tmp; + + spin_lock(&port->dl_list_lock); + + list_for_each_entry(tmp, &port->dl_list, list) + tmp->dl_trl_handler(dltrl); + + spin_unlock(&port->dl_list_lock); +} + +static void rmnet_map_process_flow_start(struct sk_buff *skb, + struct rmnet_port *port) +{ + struct rmnet_map_dl_ind_hdr *dlhdr; + + if (skb->len < RMNET_DL_IND_HDR_SIZE) + return; + + skb_pull(skb, RMNET_MAP_CMD_SIZE); + + dlhdr = (struct rmnet_map_dl_ind_hdr *)skb->data; + + rmnet_map_dl_hdr_notify(port, dlhdr); +} + +static void rmnet_map_process_flow_end(struct sk_buff *skb, + struct rmnet_port *port) +{ + struct rmnet_map_dl_ind_trl *dltrl; + + if (skb->len < RMNET_DL_IND_TRL_SIZE) + return; + + skb_pull(skb, RMNET_MAP_CMD_SIZE); + + dltrl = (struct rmnet_map_dl_ind_trl *)skb->data; + + rmnet_map_dl_trl_notify(port, dltrl); +} + /* Process MAP command frame and send N/ACK message as appropriate. Message cmd * name is decoded here and appropriate handler is called. */ @@ -112,3 +179,83 @@ void rmnet_map_command(struct sk_buff *skb, struct rmnet_port *port) if (rc == RMNET_MAP_COMMAND_ACK) rmnet_map_send_ack(skb, rc, port); } + +int rmnet_map_flow_command(struct sk_buff *skb, struct rmnet_port *port) +{ + struct rmnet_map_control_command *cmd; + unsigned char command_name; + + cmd = RMNET_MAP_GET_CMD_START(skb); + command_name = cmd->command_name; + + switch (command_name) { + case RMNET_MAP_COMMAND_FLOW_START: + rmnet_map_process_flow_start(skb, port); + break; + + case RMNET_MAP_COMMAND_FLOW_END: + rmnet_map_process_flow_end(skb, port); + break; + + default: + return 1; + } + + consume_skb(skb); + return 0; +} + +void rmnet_map_cmd_exit(struct rmnet_port *port) +{ + struct rmnet_map_dl_ind *tmp, *idx; + + spin_lock(&port->dl_list_lock); + + list_for_each_entry_safe(tmp, idx, &port->dl_list, list) + list_del_rcu(&tmp->list); + + spin_unlock(&port->dl_list_lock); +} + +void rmnet_map_cmd_init(struct rmnet_port *port) +{ + INIT_LIST_HEAD(&port->dl_list); + spin_lock_init(&port->dl_list_lock); +} + +int rmnet_map_dl_ind_register(struct rmnet_port *port, + struct rmnet_map_dl_ind *dl_ind) +{ + if (!port || !dl_ind || !dl_ind->dl_hdr_handler || + !dl_ind->dl_trl_handler) + return -EINVAL; + + spin_lock(&port->dl_list_lock); + list_add_rcu(&dl_ind->list, &port->dl_list); + spin_unlock(&port->dl_list_lock); + + return 0; +} + +int rmnet_map_dl_ind_deregister(struct rmnet_port *port, + struct rmnet_map_dl_ind *dl_ind) +{ + struct rmnet_map_dl_ind *tmp; + + if (!port || !dl_ind) + return -EINVAL; + + spin_lock(&port->dl_list_lock); + + list_for_each_entry(tmp, &port->dl_list, list) { + if (tmp == dl_ind) { + list_del_rcu(&dl_ind->list); + goto done; + } + } + +done: + spin_unlock(&port->dl_list_lock); + + return 0; +} diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h index c30100ced465..823337c75ea7 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h @@ -20,6 +20,7 @@ /* Constants */ #define RMNET_EGRESS_FORMAT_AGGREGATION BIT(31) +#define RMNET_INGRESS_FORMAT_DL_MARKER BIT(30) /* Replace skb->dev to a virtual rmnet device and pass up the stack */ #define RMNET_EPMODE_VND (1) -- GitLab From c2ee56fde9c13d15b1a2cbd78d608116b20966db Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Mon, 18 Jun 2018 18:47:44 -0600 Subject: [PATCH 0450/1299] net: qualcomm: rmnet: Add support for ethtool private stats for port Add ethtool private stats handler to debug the handling of packets with downlink header and trailer. This functionality is added as part of a new private structure for statistics in the rmnet port structure. CRs-Fixed: 2233026 Change-Id: Iefd3687b7d61d314e363be556e71ac419b5119ea Signed-off-by: Subash Abhinov Kasiviswanathan --- .../ethernet/qualcomm/rmnet/rmnet_config.h | 15 ++++++++++ .../qualcomm/rmnet/rmnet_map_command.c | 20 +++++++++++++ .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 30 +++++++++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h index fd1d331bf1b3..06a93b53e4f6 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h @@ -27,6 +27,20 @@ struct rmnet_endpoint { struct hlist_node hlnode; }; +struct rmnet_port_priv_stats { + u64 dl_hdr_last_seq; + u64 dl_hdr_last_bytes; + u64 dl_hdr_last_pkts; + u64 dl_hdr_last_flows; + u64 dl_hdr_count; + u64 dl_hdr_total_bytes; + u64 dl_hdr_total_pkts; + u64 dl_hdr_avg_bytes; + u64 dl_hdr_avg_pkts; + u64 dl_trl_last_seq; + u64 dl_trl_count; +}; + /* One instance of this structure is instantiated for each real_dev associated * with rmnet. */ @@ -56,6 +70,7 @@ struct rmnet_port { /* dl marker elements */ spinlock_t dl_list_lock; struct list_head dl_list; + struct rmnet_port_priv_stats stats; }; extern struct rtnl_link_ops rmnet_link_ops; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c index 9c92074456fb..fba75f2e964d 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c @@ -132,6 +132,23 @@ static void rmnet_map_process_flow_start(struct sk_buff *skb, dlhdr = (struct rmnet_map_dl_ind_hdr *)skb->data; + port->stats.dl_hdr_last_seq = dlhdr->le.seq; + port->stats.dl_hdr_last_bytes = dlhdr->le.bytes; + port->stats.dl_hdr_last_pkts = dlhdr->le.pkts; + port->stats.dl_hdr_last_flows = dlhdr->le.flows; + port->stats.dl_hdr_total_bytes += port->stats.dl_hdr_last_bytes; + port->stats.dl_hdr_total_pkts += port->stats.dl_hdr_last_pkts; + port->stats.dl_hdr_count++; + + if (unlikely(!(port->stats.dl_hdr_count))) + port->stats.dl_hdr_count = 1; + + port->stats.dl_hdr_avg_bytes = port->stats.dl_hdr_total_bytes / + port->stats.dl_hdr_count; + + port->stats.dl_hdr_avg_pkts = port->stats.dl_hdr_total_pkts / + port->stats.dl_hdr_count; + rmnet_map_dl_hdr_notify(port, dlhdr); } @@ -147,6 +164,9 @@ static void rmnet_map_process_flow_end(struct sk_buff *skb, dltrl = (struct rmnet_map_dl_ind_trl *)skb->data; + port->stats.dl_trl_last_seq = dltrl->seq_le; + port->stats.dl_trl_count++; + rmnet_map_dl_trl_notify(port, dltrl); } diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c index 72fa095e756f..037fc7aba3ed 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c @@ -170,12 +170,29 @@ static const char rmnet_gstrings_stats[][ETH_GSTRING_LEN] = { "Checksum computed in software", }; +static const char rmnet_port_gstrings_stats[][ETH_GSTRING_LEN] = { + "DL header last seen sequence", + "DL header last seen bytes", + "DL header last seen packets", + "DL header last seen flows", + "DL header pkts received", + "DL header total bytes received", + "DL header total pkts received", + "DL header average bytes", + "DL header average packets", + "DL trailer last seen sequence", + "DL trailer pkts received", +}; + static void rmnet_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { switch (stringset) { case ETH_SS_STATS: memcpy(buf, &rmnet_gstrings_stats, sizeof(rmnet_gstrings_stats)); + memcpy(buf + sizeof(rmnet_gstrings_stats), + &rmnet_port_gstrings_stats, + sizeof(rmnet_port_gstrings_stats)); break; } } @@ -184,7 +201,8 @@ static int rmnet_get_sset_count(struct net_device *dev, int sset) { switch (sset) { case ETH_SS_STATS: - return ARRAY_SIZE(rmnet_gstrings_stats); + return ARRAY_SIZE(rmnet_gstrings_stats) + + ARRAY_SIZE(rmnet_port_gstrings_stats); default: return -EOPNOTSUPP; } @@ -195,11 +213,19 @@ static void rmnet_get_ethtool_stats(struct net_device *dev, { struct rmnet_priv *priv = netdev_priv(dev); struct rmnet_priv_stats *st = &priv->stats; + struct rmnet_port_priv_stats *stp; + struct rmnet_port *port; - if (!data) + port = rmnet_get_port(priv->real_dev); + + if (!data || !port) return; + stp = &port->stats; + memcpy(data, st, ARRAY_SIZE(rmnet_gstrings_stats) * sizeof(u64)); + memcpy(data + ARRAY_SIZE(rmnet_gstrings_stats), stp, + ARRAY_SIZE(rmnet_port_gstrings_stats) * sizeof(u64)); } static const struct ethtool_ops rmnet_ethtool_ops = { -- GitLab From 99771a537002488b75b0134e728c3e6bdea2bb29 Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Wed, 28 Mar 2018 11:44:09 -0700 Subject: [PATCH 0451/1299] drm/msm/sde: propagate frame error through fence DMA fence driver supports error status indication to fence reader. Populate the frame status for sde fences so that client can consume or discard the buffer. Change-Id: I9b10f4ff3c97aa2c018a5f0b7f40089590aac3ae Signed-off-by: Prabhanjan Kandula --- drivers/gpu/drm/msm/sde/sde_connector.c | 8 +++++--- drivers/gpu/drm/msm/sde/sde_connector.h | 4 +++- drivers/gpu/drm/msm/sde/sde_crtc.c | 18 ++++++++++++------ drivers/gpu/drm/msm/sde/sde_fence.c | 16 +++++++++------- drivers/gpu/drm/msm/sde/sde_fence.h | 18 +++++++++++++++--- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 54f38cf509ec..692e24e3eb85 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -1219,7 +1219,7 @@ void sde_connector_prepare_fence(struct drm_connector *connector) } void sde_connector_complete_commit(struct drm_connector *connector, - ktime_t ts) + ktime_t ts, enum sde_fence_event fence_event) { if (!connector) { SDE_ERROR("invalid connector\n"); @@ -1227,7 +1227,8 @@ void sde_connector_complete_commit(struct drm_connector *connector, } /* signal connector's retire fence */ - sde_fence_signal(&to_sde_connector(connector)->retire_fence, ts, false); + sde_fence_signal(&to_sde_connector(connector)->retire_fence, + ts, fence_event); } void sde_connector_commit_reset(struct drm_connector *connector, ktime_t ts) @@ -1238,7 +1239,8 @@ void sde_connector_commit_reset(struct drm_connector *connector, ktime_t ts) } /* signal connector's retire fence */ - sde_fence_signal(&to_sde_connector(connector)->retire_fence, ts, true); + sde_fence_signal(&to_sde_connector(connector)->retire_fence, + ts, SDE_FENCE_RESET_TIMELINE); } static void sde_connector_update_hdr_props(struct drm_connector *connector) diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h index 220b0cab53ad..70d8f6458c24 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.h +++ b/drivers/gpu/drm/msm/sde/sde_connector.h @@ -632,8 +632,10 @@ void sde_connector_prepare_fence(struct drm_connector *connector); * sde_connector_complete_commit - signal completion of current commit * @connector: Pointer to drm connector object * @ts: timestamp to be updated in the fence signalling + * @fence_event: enum value to indicate nature of fence event */ -void sde_connector_complete_commit(struct drm_connector *connector, ktime_t ts); +void sde_connector_complete_commit(struct drm_connector *connector, + ktime_t ts, enum sde_fence_event fence_event); /** * sde_connector_commit_reset - reset the completion signal diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 310d6498df61..875567411d0a 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -2258,7 +2258,8 @@ static void sde_crtc_vblank_cb(void *data) SDE_EVT32_VERBOSE(DRMID(crtc)); } -static void _sde_crtc_retire_event(struct drm_crtc *crtc, ktime_t ts) +static void _sde_crtc_retire_event(struct drm_crtc *crtc, ktime_t ts, + bool is_error) { struct sde_crtc_retire_event *retire_event; struct sde_crtc *sde_crtc; @@ -2288,8 +2289,8 @@ static void _sde_crtc_retire_event(struct drm_crtc *crtc, ktime_t ts) SDE_ATRACE_BEGIN("signal_retire_fence"); for (i = 0; (i < retire_event->num_connectors) && retire_event->connectors[i]; ++i) - sde_connector_complete_commit( - retire_event->connectors[i], ts); + sde_connector_complete_commit(retire_event->connectors[i], + ts, is_error); SDE_ATRACE_END("signal_retire_fence"); } @@ -2357,13 +2358,17 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) if (fevent->event & SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE) { SDE_ATRACE_BEGIN("signal_release_fence"); - sde_fence_signal(&sde_crtc->output_fence, fevent->ts, false); + sde_fence_signal(&sde_crtc->output_fence, fevent->ts, + (fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR) + ? SDE_FENCE_SIGNAL_ERROR : SDE_FENCE_SIGNAL); SDE_ATRACE_END("signal_release_fence"); } if (fevent->event & SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE) /* this api should be called without spin_lock */ - _sde_crtc_retire_event(crtc, fevent->ts); + _sde_crtc_retire_event(crtc, fevent->ts, + (fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR) + ? SDE_FENCE_SIGNAL_ERROR : SDE_FENCE_SIGNAL); if (fevent->event & SDE_ENCODER_FRAME_EVENT_PANEL_DEAD) SDE_ERROR("crtc%d ts:%lld received panel dead event\n", @@ -4198,7 +4203,8 @@ static void sde_crtc_disable(struct drm_crtc *crtc) * reset the fence timeline if crtc will not be enabled for this commit */ if (!crtc->state->active || !crtc->state->enable) { - sde_fence_signal(&sde_crtc->output_fence, ktime_get(), true); + sde_fence_signal(&sde_crtc->output_fence, + ktime_get(), SDE_FENCE_RESET_TIMELINE); for (i = 0; i < cstate->num_connectors; ++i) sde_connector_commit_reset(cstate->connectors[i], ktime_get()); diff --git a/drivers/gpu/drm/msm/sde/sde_fence.c b/drivers/gpu/drm/msm/sde/sde_fence.c index c764ceb8c18f..0371a3f6abbf 100644 --- a/drivers/gpu/drm/msm/sde/sde_fence.c +++ b/drivers/gpu/drm/msm/sde/sde_fence.c @@ -279,7 +279,8 @@ void sde_fence_prepare(struct sde_fence_context *ctx) } } -static void _sde_fence_trigger(struct sde_fence_context *ctx, ktime_t ts) +static void _sde_fence_trigger(struct sde_fence_context *ctx, + ktime_t ts, bool error) { unsigned long flags; struct sde_fence *fc, *next; @@ -301,6 +302,7 @@ static void _sde_fence_trigger(struct sde_fence_context *ctx, ktime_t ts) list_for_each_entry_safe(fc, next, &local_list_head, fence_list) { spin_lock_irqsave(&ctx->lock, flags); + fc->base.error = error ? -EBUSY : 0; fc->base.timestamp = ts; is_signaled = dma_fence_is_signaled_locked(&fc->base); spin_unlock_irqrestore(&ctx->lock, flags); @@ -352,7 +354,7 @@ int sde_fence_create(struct sde_fence_context *ctx, uint64_t *val, if (fd >= 0) { rc = 0; - _sde_fence_trigger(ctx, ktime_get()); + _sde_fence_trigger(ctx, ktime_get(), false); } else { rc = fd; } @@ -361,7 +363,7 @@ int sde_fence_create(struct sde_fence_context *ctx, uint64_t *val, } void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts, - bool reset_timeline) + enum sde_fence_event fence_event) { unsigned long flags; @@ -371,7 +373,7 @@ void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts, } spin_lock_irqsave(&ctx->lock, flags); - if (reset_timeline) { + if (fence_event == SDE_FENCE_RESET_TIMELINE) { if ((int)(ctx->done_count - ctx->commit_count) < 0) { SDE_ERROR( "timeline reset attempt! done count:%d commit:%d\n", @@ -379,7 +381,7 @@ void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts, ctx->done_count = ctx->commit_count; SDE_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count, ktime_to_us(ts), - reset_timeline, SDE_EVTLOG_FATAL); + fence_event, SDE_EVTLOG_FATAL); } else { spin_unlock_irqrestore(&ctx->lock, flags); return; @@ -392,7 +394,7 @@ void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts, SDE_ERROR("extra signal attempt! done count:%d commit:%d\n", ctx->done_count, ctx->commit_count); SDE_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count, - ktime_to_us(ts), reset_timeline, SDE_EVTLOG_FATAL); + ktime_to_us(ts), fence_event, SDE_EVTLOG_FATAL); spin_unlock_irqrestore(&ctx->lock, flags); return; } @@ -401,7 +403,7 @@ void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts, SDE_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count, ktime_to_us(ts)); - _sde_fence_trigger(ctx, ts); + _sde_fence_trigger(ctx, ts, (fence_event == SDE_FENCE_SIGNAL_ERROR)); } void sde_fence_timeline_status(struct sde_fence_context *ctx, diff --git a/drivers/gpu/drm/msm/sde/sde_fence.h b/drivers/gpu/drm/msm/sde/sde_fence.h index 29d2ec740e4f..7891be45f138 100644 --- a/drivers/gpu/drm/msm/sde/sde_fence.h +++ b/drivers/gpu/drm/msm/sde/sde_fence.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -47,6 +47,18 @@ struct sde_fence_context { char name[SDE_FENCE_NAME_SIZE]; }; +/** + * enum sde_fence_event - sde fence event as hint fence operation + * @SDE_FENCE_SIGNAL: Signal the fence cleanly with current timeline + * @SDE_FENCE_RESET_TIMELINE: Reset timeline of the fence context + * @SDE_FENCE_SIGNAL: Signal the fence but indicate error throughfence status + */ +enum sde_fence_event { + SDE_FENCE_SIGNAL, + SDE_FENCE_RESET_TIMELINE, + SDE_FENCE_SIGNAL_ERROR +}; + #if IS_ENABLED(CONFIG_SYNC_FILE) /** * sde_sync_get - Query sync fence object from a file handle @@ -128,10 +140,10 @@ int sde_fence_create(struct sde_fence_context *fence, uint64_t *val, * sde_fence_signal - advance fence timeline to signal outstanding fences * @fence: Pointer fence container * @ts: fence timestamp - * @reset_timeline: reset the fence timeline to done count equal to commit count + * @fence_event: fence event to indicate nature of fence signal. */ void sde_fence_signal(struct sde_fence_context *fence, ktime_t ts, - bool reset_timeline); + enum sde_fence_event fence_event); /** * sde_fence_timeline_status - prints fence timeline status -- GitLab From d6dc46ebee398e2b22735b5adf2aa3f09adf31f2 Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Wed, 28 Mar 2018 11:45:20 -0700 Subject: [PATCH 0452/1299] drm/msm/sde: extend frame retire event handling Simplify retire event by avoiding special handling and extend frame event to identify the connector or encoder firing the frame event. As crtc can be really driving multiple connectors whose frame events are not same or synchronized, this isolation of events per connector is required to handle fences. Change-Id: I2e82ae2288da4206afa197749aa57a2621b4d3f7 Signed-off-by: Prabhanjan Kandula --- drivers/gpu/drm/msm/sde/sde_crtc.c | 168 +++++++++------------ drivers/gpu/drm/msm/sde/sde_crtc.h | 19 ++- drivers/gpu/drm/msm/sde/sde_encoder.c | 23 ++- drivers/gpu/drm/msm/sde/sde_encoder.h | 11 +- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 2 + 5 files changed, 110 insertions(+), 113 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 875567411d0a..ac97ba14b8ed 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -2126,6 +2126,55 @@ static void _sde_crtc_dest_scaler_setup(struct drm_crtc *crtc) } } +static void sde_crtc_frame_event_cb(void *data, u32 event) +{ + struct drm_crtc *crtc = (struct drm_crtc *)data; + struct sde_crtc *sde_crtc; + struct msm_drm_private *priv; + struct sde_crtc_frame_event *fevent; + struct sde_crtc_frame_event_cb_data *cb_data; + unsigned long flags; + u32 crtc_id; + + cb_data = (struct sde_crtc_frame_event_cb_data *)data; + if (!data) { + SDE_ERROR("invalid parameters\n"); + return; + } + + crtc = cb_data->crtc; + if (!crtc || !crtc->dev || !crtc->dev->dev_private) { + SDE_ERROR("invalid parameters\n"); + return; + } + sde_crtc = to_sde_crtc(crtc); + priv = crtc->dev->dev_private; + crtc_id = drm_crtc_index(crtc); + + SDE_DEBUG("crtc%d\n", crtc->base.id); + SDE_EVT32_VERBOSE(DRMID(crtc), event); + + spin_lock_irqsave(&sde_crtc->spin_lock, flags); + fevent = list_first_entry_or_null(&sde_crtc->frame_event_list, + struct sde_crtc_frame_event, list); + if (fevent) + list_del_init(&fevent->list); + spin_unlock_irqrestore(&sde_crtc->spin_lock, flags); + + if (!fevent) { + SDE_ERROR("crtc%d event %d overflow\n", + crtc->base.id, event); + SDE_EVT32(DRMID(crtc), event); + return; + } + + fevent->event = event; + fevent->crtc = crtc; + fevent->connector = cb_data->connector; + fevent->ts = ktime_get(); + kthread_queue_work(&priv->event_thread[crtc_id].worker, &fevent->work); +} + void sde_crtc_prepare_commit(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { @@ -2133,10 +2182,8 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, struct sde_crtc *sde_crtc; struct sde_crtc_state *cstate; struct drm_connector *conn; + struct drm_encoder *encoder; struct drm_connector_list_iter conn_iter; - struct sde_crtc_retire_event *retire_event = NULL; - unsigned long flags; - int i; if (!crtc || !crtc->state) { SDE_ERROR("invalid crtc\n"); @@ -2155,32 +2202,18 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, drm_for_each_connector_iter(conn, &conn_iter) if (conn->state && conn->state->crtc == crtc && cstate->num_connectors < MAX_CONNECTORS) { + encoder = conn->state->best_encoder; + if (encoder) + sde_encoder_register_frame_event_callback( + encoder, + sde_crtc_frame_event_cb, + crtc); + cstate->connectors[cstate->num_connectors++] = conn; sde_connector_prepare_fence(conn); } drm_connector_list_iter_end(&conn_iter); - for (i = 0; i < SDE_CRTC_FRAME_EVENT_SIZE; i++) { - retire_event = &sde_crtc->retire_events[i]; - if (list_empty(&retire_event->list)) - break; - retire_event = NULL; - } - - if (retire_event) { - retire_event->num_connectors = cstate->num_connectors; - for (i = 0; i < cstate->num_connectors; i++) - retire_event->connectors[i] = cstate->connectors[i]; - - spin_lock_irqsave(&sde_crtc->spin_lock, flags); - list_add_tail(&retire_event->list, - &sde_crtc->retire_event_list); - spin_unlock_irqrestore(&sde_crtc->spin_lock, flags); - } else { - SDE_ERROR("crtc%d retire event overflow\n", crtc->base.id); - SDE_EVT32(DRMID(crtc), SDE_EVTLOG_ERROR); - } - /* prepare main output fence */ sde_fence_prepare(&sde_crtc->output_fence); } @@ -2258,39 +2291,16 @@ static void sde_crtc_vblank_cb(void *data) SDE_EVT32_VERBOSE(DRMID(crtc)); } -static void _sde_crtc_retire_event(struct drm_crtc *crtc, ktime_t ts, - bool is_error) +static void _sde_crtc_retire_event(struct drm_connector *connector, + ktime_t ts, bool is_error) { - struct sde_crtc_retire_event *retire_event; - struct sde_crtc *sde_crtc; - unsigned long flags; - int i; - - if (!crtc) { + if (!connector) { SDE_ERROR("invalid param\n"); return; } - sde_crtc = to_sde_crtc(crtc); - spin_lock_irqsave(&sde_crtc->spin_lock, flags); - retire_event = list_first_entry_or_null(&sde_crtc->retire_event_list, - struct sde_crtc_retire_event, list); - if (retire_event) - list_del_init(&retire_event->list); - spin_unlock_irqrestore(&sde_crtc->spin_lock, flags); - - if (!retire_event) { - SDE_ERROR("crtc%d retire event without kickoff\n", - crtc->base.id); - SDE_EVT32(DRMID(crtc), SDE_EVTLOG_ERROR); - return; - } - SDE_ATRACE_BEGIN("signal_retire_fence"); - for (i = 0; (i < retire_event->num_connectors) && - retire_event->connectors[i]; ++i) - sde_connector_complete_commit(retire_event->connectors[i], - ts, is_error); + sde_connector_complete_commit(connector, ts, is_error); SDE_ATRACE_END("signal_retire_fence"); } @@ -2302,6 +2312,7 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) struct sde_crtc *sde_crtc; struct sde_kms *sde_kms; unsigned long flags; + bool in_clone_mode = false; if (!work) { SDE_ERROR("invalid work handle\n"); @@ -2330,10 +2341,11 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) SDE_EVT32_VERBOSE(DRMID(crtc), fevent->event, SDE_EVTLOG_FUNC_ENTRY); - if (fevent->event & (SDE_ENCODER_FRAME_EVENT_DONE - | SDE_ENCODER_FRAME_EVENT_ERROR - | SDE_ENCODER_FRAME_EVENT_PANEL_DEAD)) { + in_clone_mode = sde_encoder_in_clone_mode(fevent->connector->encoder); + if (!in_clone_mode && (fevent->event & (SDE_ENCODER_FRAME_EVENT_ERROR + | SDE_ENCODER_FRAME_EVENT_PANEL_DEAD + | SDE_ENCODER_FRAME_EVENT_DONE))) { if (atomic_read(&sde_crtc->frame_pending) < 1) { /* this should not happen */ SDE_ERROR("crtc%d ts:%lld invalid frame_pending:%d\n", @@ -2366,7 +2378,7 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) if (fevent->event & SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE) /* this api should be called without spin_lock */ - _sde_crtc_retire_event(crtc, fevent->ts, + _sde_crtc_retire_event(fevent->connector, fevent->ts, (fevent->event & SDE_ENCODER_FRAME_EVENT_ERROR) ? SDE_FENCE_SIGNAL_ERROR : SDE_FENCE_SIGNAL); @@ -2380,46 +2392,6 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) SDE_ATRACE_END("crtc_frame_event"); } -static void sde_crtc_frame_event_cb(void *data, u32 event) -{ - struct drm_crtc *crtc = (struct drm_crtc *)data; - struct sde_crtc *sde_crtc; - struct msm_drm_private *priv; - struct sde_crtc_frame_event *fevent; - unsigned long flags; - u32 crtc_id; - - if (!crtc || !crtc->dev || !crtc->dev->dev_private) { - SDE_ERROR("invalid parameters\n"); - return; - } - sde_crtc = to_sde_crtc(crtc); - priv = crtc->dev->dev_private; - crtc_id = drm_crtc_index(crtc); - - SDE_DEBUG("crtc%d\n", crtc->base.id); - SDE_EVT32_VERBOSE(DRMID(crtc), event); - - spin_lock_irqsave(&sde_crtc->spin_lock, flags); - fevent = list_first_entry_or_null(&sde_crtc->frame_event_list, - struct sde_crtc_frame_event, list); - if (fevent) - list_del_init(&fevent->list); - spin_unlock_irqrestore(&sde_crtc->spin_lock, flags); - - if (!fevent) { - SDE_ERROR("crtc%d event %d overflow\n", - crtc->base.id, event); - SDE_EVT32(DRMID(crtc), event); - return; - } - - fevent->event = event; - fevent->crtc = crtc; - fevent->ts = ktime_get(); - kthread_queue_work(&priv->event_thread[crtc_id].worker, &fevent->work); -} - void sde_crtc_complete_commit(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { @@ -4270,7 +4242,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; sde_encoder_register_frame_event_callback(encoder, - sde_crtc_frame_event_cb, (void *)crtc); + sde_crtc_frame_event_cb, crtc); } if (!sde_crtc->enabled && !sde_crtc->suspend && @@ -5934,10 +5906,6 @@ static int _sde_crtc_init_events(struct sde_crtc *sde_crtc) list_add_tail(&sde_crtc->event_cache[i].list, &sde_crtc->event_free_list); - INIT_LIST_HEAD(&sde_crtc->retire_event_list); - for (i = 0; i < ARRAY_SIZE(sde_crtc->retire_events); i++) - INIT_LIST_HEAD(&sde_crtc->retire_events[i].list); - return rc; } diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h index 37e197e1e37a..2894520c0455 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.h +++ b/drivers/gpu/drm/msm/sde/sde_crtc.h @@ -31,7 +31,8 @@ #define SDE_CRTC_NAME_SIZE 12 /* define the maximum number of in-flight frame events */ -#define SDE_CRTC_FRAME_EVENT_SIZE 4 +/* Expand it to 2x for handling atleast 2 connectors safely */ +#define SDE_CRTC_FRAME_EVENT_SIZE (4 * 2) /** * enum sde_crtc_client_type: crtc client type @@ -76,10 +77,21 @@ struct sde_crtc_mixer { u32 mixer_op_mode; }; +/** + * struct sde_crtc_frame_event_cb_data : info of drm objects of a frame event + * @crtc: pointer to drm crtc object registered for frame event + * @connector: pointer to drm connector which is source of frame event + */ +struct sde_crtc_frame_event_cb_data { + struct drm_crtc *crtc; + struct drm_connector *connector; +}; + /** * struct sde_crtc_frame_event: stores crtc frame event for crtc processing * @work: base work structure * @crtc: Pointer to crtc handling this event + * @connector: pointer to drm connector which is source of frame event * @list: event list * @ts: timestamp at queue entry * @event: event identifier @@ -87,6 +99,7 @@ struct sde_crtc_mixer { struct sde_crtc_frame_event { struct kthread_work work; struct drm_crtc *crtc; + struct drm_connector *connector; struct list_head list; ktime_t ts; u32 event; @@ -154,8 +167,6 @@ struct sde_crtc_event { * @frame_events : static allocation of in-flight frame events * @frame_event_list : available frame event list * @spin_lock : spin lock for frame event, transaction status, etc... - * @retire_events : static allocation of retire fence connector - * @retire_event_list : available retire fence connector list * @event_thread : Pointer to event handler thread * @event_worker : Event worker queue * @event_cache : Local cache of event worker structures @@ -222,8 +233,6 @@ struct sde_crtc { struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE]; struct list_head frame_event_list; spinlock_t spin_lock; - struct sde_crtc_retire_event retire_events[SDE_CRTC_FRAME_EVENT_SIZE]; - struct list_head retire_event_list; /* for handling internal event thread */ struct sde_crtc_event event_cache[SDE_CRTC_MAX_EVENT_COUNT]; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index f1499487adee..f054bd78f4be 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -240,7 +240,7 @@ struct sde_encoder_virt { struct mutex enc_lock; DECLARE_BITMAP(frame_busy_mask, MAX_PHYS_ENCODERS_PER_VIRTUAL); void (*crtc_frame_event_cb)(void *, u32 event); - void *crtc_frame_event_cb_data; + struct sde_crtc_frame_event_cb_data crtc_frame_event_cb_data; struct timer_list vsync_event_timer; @@ -425,6 +425,14 @@ bool sde_encoder_is_dsc_merge(struct drm_encoder *drm_enc) return false; } +int sde_encoder_in_clone_mode(struct drm_encoder *drm_enc) +{ + struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); + + return sde_enc && sde_enc->cur_master && + sde_enc->cur_master->in_clone_mode; +} + static inline int _sde_encoder_power_enable(struct sde_encoder_virt *sde_enc, bool enable) { @@ -3064,8 +3072,8 @@ void sde_encoder_register_vblank_callback(struct drm_encoder *drm_enc, } void sde_encoder_register_frame_event_callback(struct drm_encoder *drm_enc, - void (*frame_event_cb)(void *, u32 event), - void *frame_event_cb_data) + void (*frame_event_cb)(void *, u32 event), + struct drm_crtc *crtc) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); unsigned long lock_flags; @@ -3082,7 +3090,7 @@ void sde_encoder_register_frame_event_callback(struct drm_encoder *drm_enc, spin_lock_irqsave(&sde_enc->enc_spinlock, lock_flags); sde_enc->crtc_frame_event_cb = frame_event_cb; - sde_enc->crtc_frame_event_cb_data = frame_event_cb_data; + sde_enc->crtc_frame_event_cb_data.crtc = crtc; spin_unlock_irqrestore(&sde_enc->enc_spinlock, lock_flags); } @@ -3093,6 +3101,9 @@ static void sde_encoder_frame_done_callback( struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); unsigned int i; + sde_enc->crtc_frame_event_cb_data.connector = + sde_enc->cur_master->connector; + if (event & (SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_ERROR | SDE_ENCODER_FRAME_EVENT_PANEL_DEAD)) { @@ -3121,13 +3132,13 @@ static void sde_encoder_frame_done_callback( if (sde_enc->crtc_frame_event_cb) sde_enc->crtc_frame_event_cb( - sde_enc->crtc_frame_event_cb_data, + &sde_enc->crtc_frame_event_cb_data, event); } } else { if (sde_enc->crtc_frame_event_cb) sde_enc->crtc_frame_event_cb( - sde_enc->crtc_frame_event_cb_data, event); + &sde_enc->crtc_frame_event_cb_data, event); } } diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h index 881520fc536b..9adebb53b783 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder.h @@ -99,10 +99,10 @@ void sde_encoder_register_vblank_callback(struct drm_encoder *encoder, * will be called after the request is complete, or other events. * @encoder: encoder pointer * @cb: callback pointer, provide NULL to deregister - * @data: user data provided to callback + * @crtc: pointer to drm_crtc object interested in frame events */ void sde_encoder_register_frame_event_callback(struct drm_encoder *encoder, - void (*cb)(void *, u32), void *data); + void (*cb)(void *, u32), struct drm_crtc *crtc); /** * sde_encoder_get_rsc_client - gets the rsc client state for primary @@ -269,5 +269,12 @@ bool sde_encoder_recovery_events_enabled(struct drm_encoder *encoder); */ void sde_encoder_recovery_events_handler(struct drm_encoder *encoder, bool val); +/** + * sde_encoder_in_clone_mode - checks if underlying phys encoder is in clone + * mode or independent display mode. ref@ WB in Concurrent writeback mode. + * @drm_enc: Pointer to drm encoder structure + * @Return: true if successful in updating the encoder structure + */ +int sde_encoder_in_clone_mode(struct drm_encoder *enc); #endif /* __SDE_ENCODER_H__ */ diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 5c403ef6bef2..e882c90ab522 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -274,6 +274,7 @@ struct sde_encoder_irq { * @has_intf_te: Interface TE configuration support * @cont_splash_single_flush Variable to check if single flush is enabled. * @cont_splash_settings Variable to store continuous splash settings. + * @in_clone_mode Indicates if encoder is in clone mode ref@CWB */ struct sde_encoder_phys { struct drm_encoder *parent; @@ -307,6 +308,7 @@ struct sde_encoder_phys { bool has_intf_te; u32 cont_splash_single_flush; bool cont_splash_settings; + bool in_clone_mode; }; static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys) -- GitLab From 2165d6d673b73e898ee0acecc42908c86d4e586e Mon Sep 17 00:00:00 2001 From: Ch Ganesh Kumar Date: Tue, 6 Mar 2018 18:08:12 +0530 Subject: [PATCH 0453/1299] drm/msm/sde: avoid partial update when DS is enabled Partial Update and Destination Scaler concurrency is not supported on sde. This change will revert DS standalone check, because concurrency validation is evaluated by crtc while setting layer mixer ROI. Change-Id: I66e7ea18e8a4b5780ab0988e5841aafecaf0dae8 Signed-off-by: Ch Ganesh Kumar --- drivers/gpu/drm/msm/sde/sde_crtc.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index ac97ba14b8ed..ae39a1c464c2 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -1322,15 +1322,6 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc, return -E2BIG; } - /** - * TODO: Need to check against ROI alignment restrictions if partial - * update support is added for destination scalar configurations - */ - if (sde_crtc_state->num_ds_enabled) { - SDE_ERROR("DS and PU concurrency is not supported\n"); - return -EINVAL; - } - rc = _sde_crtc_set_crtc_roi(crtc, state); if (rc) return rc; -- GitLab From 65d13472a797579855f70152ee7d8a7d1c5bd0d0 Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Sun, 1 Apr 2018 12:12:33 -0700 Subject: [PATCH 0454/1299] drm/msm/sde: relax crtc for driving multiple connectors Extend crtc implemtation for supporting a copy connector by limiting roi checks and mixer info population for only primary connector and remove existing bail out checks to restrict crtc to single connector. Change-Id: I6272d75625770e19b0fbb0427d262d349827390d Signed-off-by: Prabhanjan Kandula --- drivers/gpu/drm/msm/sde/sde_crtc.c | 92 ++++++++++++++++-------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index ae39a1c464c2..93b44a9ea653 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -937,7 +937,9 @@ static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc, struct sde_crtc *sde_crtc; struct sde_crtc_state *crtc_state; struct sde_rect *crtc_roi; - int i, num_attached_conns = 0; + struct msm_mode_info mode_info; + int i = 0; + int rc; bool is_crtc_roi_dirty; bool is_any_conn_roi_dirty; @@ -959,13 +961,14 @@ static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc, if (!conn_state || conn_state->crtc != crtc) continue; - if (num_attached_conns) { - SDE_ERROR( - "crtc%d: unsupported: roi on crtc w/ >1 connectors\n", - DRMID(crtc)); + rc = sde_connector_get_mode_info(conn_state, &mode_info); + if (rc) { + SDE_ERROR("failed to get mode info\n"); return -EINVAL; } - ++num_attached_conns; + + if (!mode_info.roi_caps.enabled) + continue; sde_conn = to_sde_connector(conn_state->connector); sde_conn_state = to_sde_connector_state(conn_state); @@ -1286,13 +1289,6 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc, sde_crtc = to_sde_crtc(crtc); sde_crtc_state = to_sde_crtc_state(state); - if (hweight_long(state->connector_mask) != 1) { - SDE_ERROR("invalid connector count(%d) for crtc: %d\n", - (int)hweight_long(state->connector_mask), - crtc->base.id); - return -EINVAL; - } - /* * check connector array cached at modeset time since incoming atomic * state may not include any connectors if they aren't modified @@ -1308,41 +1304,40 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc, SDE_ERROR("failed to get mode info\n"); return -EINVAL; } - break; - } - if (!mode_info.roi_caps.enabled) - return 0; - - if (sde_crtc_state->user_roi_list.num_rects > - mode_info.roi_caps.num_roi) { - SDE_ERROR("roi count is more than supported limit, %d > %d\n", - sde_crtc_state->user_roi_list.num_rects, - mode_info.roi_caps.num_roi); - return -E2BIG; - } + if (!mode_info.roi_caps.enabled) + continue; - rc = _sde_crtc_set_crtc_roi(crtc, state); - if (rc) - return rc; + if (sde_crtc_state->user_roi_list.num_rects > + mode_info.roi_caps.num_roi) { + SDE_ERROR("roi count is exceeding limit, %d > %d\n", + sde_crtc_state->user_roi_list.num_rects, + mode_info.roi_caps.num_roi); + return -E2BIG; + } - rc = _sde_crtc_check_autorefresh(crtc, state); - if (rc) - return rc; + rc = _sde_crtc_set_crtc_roi(crtc, state); + if (rc) + return rc; - for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) { - rc = _sde_crtc_set_lm_roi(crtc, state, lm_idx); + rc = _sde_crtc_check_autorefresh(crtc, state); if (rc) return rc; - } - rc = _sde_crtc_check_rois_centered_and_symmetric(crtc, state); - if (rc) - return rc; + for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) { + rc = _sde_crtc_set_lm_roi(crtc, state, lm_idx); + if (rc) + return rc; + } - rc = _sde_crtc_check_planes_within_crtc_roi(crtc, state); - if (rc) - return rc; + rc = _sde_crtc_check_rois_centered_and_symmetric(crtc, state); + if (rc) + return rc; + + rc = _sde_crtc_check_planes_within_crtc_roi(crtc, state); + if (rc) + return rc; + } return 0; } @@ -2255,9 +2250,16 @@ enum sde_intf_mode sde_crtc_get_intf_mode(struct drm_crtc *crtc) return INTF_MODE_NONE; } - drm_for_each_encoder(encoder, crtc->dev) - if (encoder->crtc == crtc) - return sde_encoder_get_intf_mode(encoder); + drm_for_each_encoder(encoder, crtc->dev) { + if (encoder->crtc != crtc) + continue; + + /* continue if copy encoder is encountered */ + if (sde_encoder_in_clone_mode(encoder)) + continue; + + return sde_encoder_get_intf_mode(encoder); + } return INTF_MODE_NONE; } @@ -2954,6 +2956,10 @@ static void _sde_crtc_setup_mixers(struct drm_crtc *crtc) if (enc->crtc != crtc) continue; + /* avoid overwriting mixers info from a copy encoder */ + if (sde_encoder_in_clone_mode(enc)) + continue; + _sde_crtc_setup_mixer_for_encoder(crtc, enc); } -- GitLab From daea63bac3f7bdea67939c7d9b832551b906e5ff Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Mon, 23 Apr 2018 19:02:00 -0700 Subject: [PATCH 0455/1299] drm/msm/sde: add CWB custom property support If concurrent writeback feature is supported by HW, add a new property on each CRTC through which client can request the data point of capture (LM or DSSP output). Availability of this property on crtc itself is indication for client about the availability of CWB feature. Change-Id: Ia6cf3b3f544d8d2f71fc2bcd376081f629e9d8ba Signed-off-by: Prabhanjan Kandula --- drivers/gpu/drm/msm/msm_drv.h | 1 + drivers/gpu/drm/msm/sde/sde_crtc.c | 11 +++++++++++ drivers/gpu/drm/msm/sde/sde_crtc.h | 10 ++++++++++ drivers/gpu/drm/msm/sde/sde_hw_catalog.c | 4 ++++ drivers/gpu/drm/msm/sde/sde_hw_catalog.h | 4 ++++ 5 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index b19c4532a8dd..1695a3c40c9b 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -161,6 +161,7 @@ enum msm_mdp_crtc_property { CRTC_PROP_SECURITY_LEVEL, CRTC_PROP_IDLE_TIMEOUT, CRTC_PROP_DEST_SCALER, + CRTC_PROP_CAPTURE_OUTPUT, /* total # of properties */ CRTC_PROP_COUNT diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 93b44a9ea653..1523029c2869 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -4908,6 +4908,11 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, {SDE_DRM_SEC_ONLY, "sec_only"}, }; + static const struct drm_prop_enum_list e_cwb_data_points[] = { + {CAPTURE_MIXER_OUT, "capture_mixer_out"}, + {CAPTURE_DSPP_OUT, "capture_pp_out"}, + }; + SDE_DEBUG("\n"); if (!crtc || !catalog) { @@ -4983,6 +4988,12 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, "idle_time", 0, 0, U64_MAX, 0, CRTC_PROP_IDLE_TIMEOUT); + if (catalog->has_cwb_support) + msm_property_install_enum(&sde_crtc->property_info, + "capture_mode", 0, 0, e_cwb_data_points, + ARRAY_SIZE(e_cwb_data_points), + CRTC_PROP_CAPTURE_OUTPUT); + msm_property_install_blob(&sde_crtc->property_info, "capabilities", DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_INFO); diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h index 2894520c0455..18229eaf210a 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.h +++ b/drivers/gpu/drm/msm/sde/sde_crtc.h @@ -48,6 +48,16 @@ enum sde_crtc_client_type { RT_RSC_CLIENT, }; +/** + * enum sde_crtc_output_capture_point + * @MIXER_OUT : capture mixer output + * @DSPP_OUT : capture output of dspp + */ +enum sde_crtc_output_capture_point { + CAPTURE_MIXER_OUT, + CAPTURE_DSPP_OUT +}; + /** * @connectors : Currently associated drm connectors for retire event * @num_connectors: Number of associated drm connectors for retire event diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c index 99a48a9f0433..b5c546cbb1a4 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c @@ -1876,6 +1876,9 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) set_bit(SDE_WB_INPUT_CTRL, &wb->features); + if (sde_cfg->has_cwb_support) + set_bit(SDE_WB_HAS_CWB, &wb->features); + for (j = 0; j < sde_cfg->mdp_count; j++) { sde_cfg->mdp[j].clk_ctrls[wb->clk_ctrl].reg_off = PROP_BITVALUE_ACCESS(prop_value, @@ -3552,6 +3555,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->ts_prefill_rev = 1; } else if (IS_SDM845_TARGET(hw_rev)) { sde_cfg->has_wb_ubwc = true; + sde_cfg->has_cwb_support = true; sde_cfg->perf.min_prefill_lines = 24; sde_cfg->vbif_qos_nlvl = 8; sde_cfg->ts_prefill_rev = 2; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h index eef9e2110e52..b337afca72d2 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h @@ -328,6 +328,7 @@ enum { * @SDE_WB_CDP Writeback supports client driven prefetch * @SDE_WB_INPUT_CTRL Writeback supports from which pp block input pixel * data arrives. + * @SDE_WB_HAS_CWB Writeback block supports concurrent writeback * @SDE_WB_MAX maximum value */ enum { @@ -347,6 +348,7 @@ enum { SDE_WB_QOS_8LVL, SDE_WB_CDP, SDE_WB_INPUT_CTRL, + SDE_WB_HAS_CWB, SDE_WB_MAX }; @@ -1028,6 +1030,7 @@ struct sde_perf_cfg { * @has_src_split source split feature status * @has_cdp Client driven prefetch feature status * @has_wb_ubwc UBWC feature supported on WB + * @has_cwb_support indicates if device supports primary capture through CWB * @ubwc_version UBWC feature version (0x0 for not supported) * @ubwc_bw_calc_version indicate how UBWC BW has to be calculated * @has_sbuf indicate if stream buffer is available @@ -1078,6 +1081,7 @@ struct sde_mdss_cfg { bool has_cdp; bool has_dim_layer; bool has_wb_ubwc; + bool has_cwb_support; u32 ubwc_version; u32 ubwc_bw_calc_version; bool has_sbuf; -- GitLab From 3186afefb16bce4e899a14a0286ad842f5780496 Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Wed, 28 Mar 2018 11:46:23 -0700 Subject: [PATCH 0456/1299] drm/msm: atomic seamless connector change Handle dynamic connector attach or detach of additional connector on crtc. Avoid full modeset disable and enable if multiple connectors connected to single CRTC. It allows seamless handling of usecase like concurrent writeback. Attempt to keep existing seamless mode checks intact. Change-Id: Ia8ab0ef27400f2ba08a7d2dc6984820f3c956231 Signed-off-by: Prabhanjan Kandula --- drivers/gpu/drm/msm/msm_atomic.c | 107 +++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 9e4c7b1e713f..cea416f42788 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2014 Red Hat * Author: Rob Clark * @@ -25,6 +25,8 @@ #include "msm_fence.h" #include "sde_trace.h" +#define MULTIPLE_CONN_DETECTED(x) (x > 1) + struct msm_commit { struct drm_device *dev; struct drm_atomic_state *state; @@ -111,6 +113,66 @@ static void commit_destroy(struct msm_commit *c) kfree(c); } +static inline bool _msm_seamless_for_crtc(struct drm_atomic_state *state, + struct drm_crtc_state *crtc_state, bool enable) +{ + struct drm_connector *connector = NULL; + struct drm_connector_state *conn_state = NULL; + int i = 0; + int conn_cnt = 0; + + if (msm_is_mode_seamless(&crtc_state->mode) || + msm_is_mode_seamless_vrr(&crtc_state->adjusted_mode)) + return true; + + if (msm_is_mode_seamless_dms(&crtc_state->adjusted_mode) && !enable) + return true; + + if (!crtc_state->mode_changed && crtc_state->connectors_changed) { + for_each_connector_in_state(state, connector, conn_state, i) { + if ((conn_state->crtc == crtc_state->crtc) || + (connector->state->crtc == + crtc_state->crtc)) + conn_cnt++; + + if (MULTIPLE_CONN_DETECTED(conn_cnt)) + return true; + } + } + + return false; +} + +static inline bool _msm_seamless_for_conn(struct drm_connector *connector, + struct drm_connector_state *old_conn_state, bool enable) +{ + if (!old_conn_state || !old_conn_state->crtc) + return false; + + if (!old_conn_state->crtc->state->mode_changed && + !old_conn_state->crtc->state->active_changed && + old_conn_state->crtc->state->connectors_changed) { + if (old_conn_state->crtc == connector->state->crtc) + return true; + } + + if (enable) + return false; + + if (msm_is_mode_seamless(&connector->encoder->crtc->state->mode)) + return true; + + if (msm_is_mode_seamless_vrr( + &connector->encoder->crtc->state->adjusted_mode)) + return true; + + if (msm_is_mode_seamless_dms( + &connector->encoder->crtc->state->adjusted_mode)) + return true; + + return false; +} + static void msm_atomic_wait_for_commit_done( struct drm_device *dev, struct drm_atomic_state *old_state) @@ -169,14 +231,7 @@ msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) if (WARN_ON(!encoder)) continue; - if (msm_is_mode_seamless( - &connector->encoder->crtc->state->mode) || - msm_is_mode_seamless_vrr( - &connector->encoder->crtc->state->adjusted_mode)) - continue; - - if (msm_is_mode_seamless_dms( - &connector->encoder->crtc->state->adjusted_mode)) + if (_msm_seamless_for_conn(connector, old_conn_state, false)) continue; funcs = encoder->helper_private; @@ -218,11 +273,7 @@ msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) if (!old_crtc_state->active) continue; - if (msm_is_mode_seamless(&crtc->state->mode) || - msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode)) - continue; - - if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode)) + if (_msm_seamless_for_crtc(old_state, crtc->state, false)) continue; funcs = crtc->helper_private; @@ -281,8 +332,14 @@ msm_crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) mode = &new_crtc_state->mode; adjusted_mode = &new_crtc_state->adjusted_mode; - if (!new_crtc_state->mode_changed) + if (!new_crtc_state->mode_changed && + new_crtc_state->connectors_changed) { + if (_msm_seamless_for_conn(connector, + old_conn_state, false)) + continue; + } else if (!new_crtc_state->mode_changed) { continue; + } DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n", encoder->base.id, encoder->name); @@ -362,9 +419,7 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, if (!new_crtc_state->active) continue; - if (msm_is_mode_seamless(&new_crtc_state->mode) || - msm_is_mode_seamless_vrr( - &new_crtc_state->adjusted_mode)) + if (_msm_seamless_for_crtc(old_state, crtc->state, true)) continue; funcs = crtc->helper_private; @@ -389,6 +444,7 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, new_conn_state, i) { const struct drm_encoder_helper_funcs *funcs; struct drm_encoder *encoder; + struct drm_connector_state *old_conn_state; if (!new_conn_state->best_encoder) continue; @@ -398,7 +454,12 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, new_conn_state->crtc->state)) continue; - encoder = new_conn_state->best_encoder; + old_conn_state = drm_atomic_get_old_connector_state( + old_state, connector); + if (_msm_seamless_for_conn(connector, old_conn_state, true)) + continue; + + encoder = connector->state->best_encoder; funcs = encoder->helper_private; DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n", @@ -437,6 +498,7 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { struct drm_encoder *encoder; + struct drm_connector_state *old_conn_state; if (!new_conn_state->best_encoder) continue; @@ -446,7 +508,12 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, new_conn_state->crtc->state)) continue; - encoder = new_conn_state->best_encoder; + old_conn_state = drm_atomic_get_old_connector_state( + old_state, connector); + if (_msm_seamless_for_conn(connector, old_conn_state, true)) + continue; + + encoder = connector->state->best_encoder; DRM_DEBUG_ATOMIC("bridge enable enabling [ENCODER:%d:%s]\n", encoder->base.id, encoder->name); -- GitLab From b396452017fae00e7fe12829243ec7968258384c Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Sun, 15 Apr 2018 21:44:50 -0700 Subject: [PATCH 0457/1299] drm/msm/sde: concurrent writeback support Add support for capturing frame on primary through WB using concurrent writeback HW feature if supported. Changes include detecting CWB usecase by finding if WB is in clone mode, reserve same set of hw resources as in plain WB case and program CWB specific registers like ctrl_top and flush on primary. This change support dynamic capture enable or disable per frame. Signal only retire fence for CWB case as primary crtc handles release fence. WB irq handling is improved using helper functions in virtual encoder. Change also supports notifying frame error by registering for ping-pong overflow & signal retire fence with frame error if overflows. Change-Id: Ia9eebd0224282e87a758e848eb4e1d4ca7871059 Signed-off-by: Prabhanjan Kandula --- drivers/gpu/drm/msm/sde/sde_encoder.c | 18 +- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 9 +- drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c | 394 +++++++++++++----- drivers/gpu/drm/msm/sde/sde_hw_ctl.c | 19 + drivers/gpu/drm/msm/sde/sde_hw_ctl.h | 8 + drivers/gpu/drm/msm/sde/sde_hw_top.c | 13 + drivers/gpu/drm/msm/sde/sde_hw_top.h | 9 + drivers/gpu/drm/msm/sde/sde_hwio.h | 4 +- 8 files changed, 368 insertions(+), 106 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index f054bd78f4be..a97e4a7caa4f 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -1774,6 +1774,7 @@ static int _sde_encoder_update_rsc_client( * only primary command mode panel without Qsync can request CMD state. * all other panels/displays can request for VID state including * secondary command mode panel. + * Clone mode encoder can request CLK STATE only. */ for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; @@ -1786,13 +1787,17 @@ static int _sde_encoder_update_rsc_client( } } - rsc_state = enable ? - (((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) && - disp_info->is_primary && !qsync_mode) ? - SDE_RSC_CMD_STATE : SDE_RSC_VID_STATE) : - SDE_RSC_IDLE_STATE; + if (sde_encoder_in_clone_mode(drm_enc)) + rsc_state = enable ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE; + else + rsc_state = enable ? + (((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) + && disp_info->is_primary && !qsync_mode) ? + SDE_RSC_CMD_STATE : SDE_RSC_VID_STATE) : + SDE_RSC_IDLE_STATE; SDE_EVT32(rsc_state, qsync_mode); + prefill_lines = config ? mode_info.prefill_lines + config->inline_rotate_prefill : mode_info.prefill_lines; @@ -3285,6 +3290,9 @@ static inline void _sde_encoder_trigger_start(struct sde_encoder_phys *phys) SDE_ERROR("invalid parent\n"); return; } + /* avoid ctrl start for encoder in clone mode */ + if (phys->in_clone_mode) + return; ctl = phys->hw_ctl; sde_enc = to_sde_encoder_virt(phys->parent); diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index e882c90ab522..37735df1cd54 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -200,6 +200,9 @@ struct sde_encoder_phys_ops { * @INTR_IDX_PINGPONG: Pingpong done unterrupt for cmd mode panel * @INTR_IDX_UNDERRUN: Underrun unterrupt for video and cmd mode panel * @INTR_IDX_RDPTR: Readpointer done unterrupt for cmd mode panel + * @INTR_IDX_WB_DONE: Writeback done interrupt for WB + * @INTR_IDX_PP2_OVFL: Pingpong overflow interrupt on PP2 for Concurrent WB + * @INTR_IDX_PP2_OVFL: Pingpong overflow interrupt on PP3 for Concurrent WB * @INTR_IDX_AUTOREFRESH_DONE: Autorefresh done for cmd mode panel meaning * autorefresh has triggered a double buffer flip */ @@ -210,6 +213,9 @@ enum sde_intr_idx { INTR_IDX_CTL_START, INTR_IDX_RDPTR, INTR_IDX_AUTOREFRESH_DONE, + INTR_IDX_WB_DONE, + INTR_IDX_PP2_OVFL, + INTR_IDX_PP3_OVFL, INTR_IDX_MAX, }; @@ -379,7 +385,6 @@ struct sde_encoder_phys_cmd { * writeback specific operations * @base: Baseclass physical encoder structure * @hw_wb: Hardware interface to the wb registers - * @irq_idx: IRQ interface lookup index * @wbdone_timeout: Timeout value for writeback done in msec * @bypass_irqreg: Bypass irq register/unregister if non-zero * @wbdone_complete: for wbdone irq synchronization @@ -402,8 +407,6 @@ struct sde_encoder_phys_cmd { struct sde_encoder_phys_wb { struct sde_encoder_phys base; struct sde_hw_wb *hw_wb; - int irq_idx; - struct sde_irq_callback irq_cb; u32 wbdone_timeout; u32 bypass_irqreg; struct completion wbdone_complete; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c index 59acecf73550..b67cfa4b7f09 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c @@ -32,6 +32,7 @@ #define TO_S15D16(_x_) ((_x_) << 7) +#define MULTIPLE_CONN_DETECTED(x) (x > 1) /** * sde_rgb2yuv_601l - rgb to yuv color space conversion matrix * @@ -465,6 +466,31 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc, } } +static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc, + bool enable) +{ + struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); + struct sde_hw_wb *hw_wb = wb_enc->hw_wb; + struct sde_hw_intf_cfg *intf_cfg = &phys_enc->intf_cfg; + struct sde_hw_ctl *hw_ctl = phys_enc->hw_ctl; + struct sde_crtc *crtc = to_sde_crtc(wb_enc->crtc); + + if (!phys_enc->in_clone_mode) { + SDE_DEBUG("not in CWB mode. early return\n"); + return; + } + + memset(intf_cfg, 0, sizeof(struct sde_hw_intf_cfg)); + intf_cfg->intf = SDE_NONE; + intf_cfg->wb = hw_wb->idx; + + hw_ctl = crtc->mixers[0].hw_ctl; + if (hw_ctl && hw_ctl->ops.update_wb_cfg) { + hw_ctl->ops.update_wb_cfg(hw_ctl, intf_cfg, enable); + SDE_DEBUG("in CWB mode adding WB for CTL_%d\n", + hw_ctl->idx - CTL_0); + } +} /** * sde_encoder_phys_wb_setup_cdp - setup chroma down prefetch block * @phys_enc: Pointer to physical encoder @@ -483,6 +509,11 @@ static void sde_encoder_phys_wb_setup_cdp(struct sde_encoder_phys *phys_enc, return; } + if (phys_enc->in_clone_mode) { + SDE_DEBUG("in CWB mode. early return\n"); + return; + } + wb_enc = to_sde_encoder_phys_wb(phys_enc); hw_wb = wb_enc->hw_wb; hw_cdm = phys_enc->hw_cdm; @@ -530,10 +561,104 @@ static void sde_encoder_phys_wb_setup_cdp(struct sde_encoder_phys *phys_enc, intf_cfg->wb = hw_wb->idx; intf_cfg->mode_3d = sde_encoder_helper_get_3d_blend_mode(phys_enc); - phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, intf_cfg); } + +} + +static void _sde_enc_phys_wb_detect_cwb(struct sde_encoder_phys *phys_enc, + struct drm_crtc_state *crtc_state) +{ + struct drm_connector *conn; + struct drm_connector_state *conn_state; + struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); + const struct sde_wb_cfg *wb_cfg = wb_enc->hw_wb->caps; + struct drm_connector_list_iter conn_iter; + int conn_count = 0; + + phys_enc->in_clone_mode = false; + + /* Check if WB has CWB support */ + if (!(wb_cfg->features & SDE_WB_HAS_CWB)) + return; + + /* Count the number of connectors on the given crtc */ + drm_connector_list_iter_begin(crtc_state->crtc->dev, &conn_iter); + drm_for_each_connector_iter(conn, &conn_iter) { + conn_state = + drm_atomic_get_connector_state(crtc_state->state, conn); + if ((conn->state && conn->state->crtc == crtc_state->crtc) || + (conn_state && + conn_state->crtc == crtc_state->crtc)) + conn_count++; + } + drm_connector_list_iter_end(&conn_iter); + + + /* Enable clone mode If crtc has multiple connectors & one is WB */ + if (MULTIPLE_CONN_DETECTED(conn_count)) + phys_enc->in_clone_mode = true; + + SDE_DEBUG("detect CWB - status:%d\n", phys_enc->in_clone_mode); +} + +static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state); + struct sde_rect wb_roi = {0,}; + int data_pt; + int ds_outw = 0; + int ds_outh = 0; + int ds_in_use = false; + int i = 0; + int ret = 0; + + if (!phys_enc->in_clone_mode) { + SDE_DEBUG("not in CWB mode. early return\n"); + goto exit; + } + + ret = sde_wb_connector_state_get_output_roi(conn_state, &wb_roi); + if (ret) { + SDE_ERROR("failed to get roi %d\n", ret); + goto exit; + } + + data_pt = sde_crtc_get_property(cstate, CRTC_PROP_CAPTURE_OUTPUT); + + /* compute cumulative ds output dimensions if in use */ + for (i = 0; i < cstate->num_ds; i++) + if (cstate->ds_cfg[i].scl3_cfg.enable) { + ds_in_use = true; + ds_outw += cstate->ds_cfg[i].scl3_cfg.dst_width; + ds_outh += cstate->ds_cfg[i].scl3_cfg.dst_height; + } + + /* if ds in use check wb roi against ds output dimensions */ + if ((data_pt == CAPTURE_DSPP_OUT) && ds_in_use && + ((wb_roi.w != ds_outw) || (wb_roi.h != ds_outh))) { + SDE_ERROR("invalid wb roi with dest scalar [%dx%d vs %dx%d]\n", + wb_roi.w, wb_roi.h, ds_outw, ds_outh); + ret = -EINVAL; + goto exit; + } + + /* validate conn roi against pu rect */ + if (!sde_kms_rect_is_null(&cstate->crtc_roi)) { + if (wb_roi.w != cstate->crtc_roi.w || + wb_roi.h != cstate->crtc_roi.h) { + SDE_ERROR("invalid wb roi with pu [%dx%d vs %dx%d]\n", + wb_roi.w, wb_roi.h, cstate->crtc_roi.w, + cstate->crtc_roi.h); + ret = -EINVAL; + goto exit; + } + } +exit: + return ret; } /** @@ -570,6 +695,8 @@ static int sde_encoder_phys_wb_atomic_check( return -EINVAL; } + _sde_enc_phys_wb_detect_cwb(phys_enc, crtc_state); + memset(&wb_roi, 0, sizeof(struct sde_rect)); rc = sde_wb_connector_state_get_output_roi(conn_state, &wb_roi); @@ -658,7 +785,58 @@ static int sde_encoder_phys_wb_atomic_check( } } - return 0; + rc = _sde_enc_phys_wb_validate_cwb(phys_enc, crtc_state, conn_state); + if (rc) { + SDE_ERROR("failed in cwb validation %d\n", rc); + return rc; + } + + return rc; +} + +static void _sde_encoder_phys_wb_update_cwb_flush( + struct sde_encoder_phys *phys_enc) +{ + struct sde_encoder_phys_wb *wb_enc; + struct sde_hw_wb *hw_wb; + struct sde_hw_ctl *hw_ctl; + struct sde_hw_cdm *hw_cdm; + struct sde_crtc *crtc; + struct sde_crtc_state *crtc_state; + int capture_point = 0; + + if (!phys_enc->in_clone_mode) { + SDE_DEBUG("not in CWB mode. early return\n"); + return; + } + + wb_enc = to_sde_encoder_phys_wb(phys_enc); + crtc = to_sde_crtc(wb_enc->crtc); + crtc_state = to_sde_crtc_state(wb_enc->crtc->state); + + hw_wb = wb_enc->hw_wb; + hw_cdm = phys_enc->hw_cdm; + + /* In CWB mode, program actual source master sde_hw_ctl from crtc */ + hw_ctl = crtc->mixers[0].hw_ctl; + if (!hw_ctl) { + SDE_DEBUG("[wb:%d] no ctl assigned for CWB\n", + hw_wb->idx - WB_0); + return; + } + + capture_point = sde_crtc_get_property(crtc_state, + CRTC_PROP_CAPTURE_OUTPUT); + + phys_enc->hw_mdptop->ops.set_cwb_ppb_cntl(phys_enc->hw_mdptop, + crtc->num_mixers == CRTC_DUAL_MIXERS, + capture_point == CAPTURE_DSPP_OUT); + + if (hw_ctl->ops.update_bitmask_wb) + hw_ctl->ops.update_bitmask_wb(hw_ctl, hw_wb->idx, 1); + + if (hw_ctl->ops.update_bitmask_cdm && hw_cdm) + hw_ctl->ops.update_bitmask_cdm(hw_ctl, hw_cdm->idx, 1); } /** @@ -667,7 +845,7 @@ static int sde_encoder_phys_wb_atomic_check( */ static void _sde_encoder_phys_wb_update_flush(struct sde_encoder_phys *phys_enc) { - struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); + struct sde_encoder_phys_wb *wb_enc; struct sde_hw_wb *hw_wb; struct sde_hw_ctl *hw_ctl; struct sde_hw_cdm *hw_cdm; @@ -677,13 +855,19 @@ static void _sde_encoder_phys_wb_update_flush(struct sde_encoder_phys *phys_enc) if (!phys_enc) return; + wb_enc = to_sde_encoder_phys_wb(phys_enc); hw_wb = wb_enc->hw_wb; - hw_ctl = phys_enc->hw_ctl; hw_cdm = phys_enc->hw_cdm; hw_pp = phys_enc->hw_pp; + hw_ctl = phys_enc->hw_ctl; SDE_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0); + if (phys_enc->in_clone_mode) { + SDE_DEBUG("in CWB mode. early return\n"); + return; + } + if (!hw_ctl) { SDE_DEBUG("[wb:%d] no ctl assigned\n", hw_wb->idx - WB_0); return; @@ -782,54 +966,28 @@ static void sde_encoder_phys_wb_setup( sde_encoder_phys_wb_setup_fb(phys_enc, fb, wb_roi); sde_encoder_phys_wb_setup_cdp(phys_enc, wb_enc->wb_fmt); -} - -/** - * sde_encoder_phys_wb_unregister_irq - unregister writeback interrupt handler - * @phys_enc: Pointer to physical encoder - */ -static int sde_encoder_phys_wb_unregister_irq( - struct sde_encoder_phys *phys_enc) -{ - struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); - struct sde_hw_wb *hw_wb = wb_enc->hw_wb; - - if (wb_enc->bypass_irqreg) - return 0; - - sde_core_irq_disable(phys_enc->sde_kms, &wb_enc->irq_idx, 1); - sde_core_irq_unregister_callback(phys_enc->sde_kms, wb_enc->irq_idx, - &wb_enc->irq_cb); - SDE_DEBUG("un-register IRQ for wb %d, irq_idx=%d\n", - hw_wb->idx - WB_0, - wb_enc->irq_idx); - - return 0; + _sde_encoder_phys_wb_setup_cwb(phys_enc, true); } -/** - * sde_encoder_phys_wb_done_irq - writeback interrupt handler - * @arg: Pointer to writeback encoder - * @irq_idx: interrupt index - */ -static void sde_encoder_phys_wb_done_irq(void *arg, int irq_idx) +static void _sde_encoder_phys_wb_frame_done_helper(void *arg, bool frame_error) { struct sde_encoder_phys_wb *wb_enc = arg; struct sde_encoder_phys *phys_enc = &wb_enc->base; struct sde_hw_wb *hw_wb = wb_enc->hw_wb; - u32 event = 0; + u32 event = frame_error ? SDE_ENCODER_FRAME_EVENT_ERROR : 0; + + event |= SDE_ENCODER_FRAME_EVENT_DONE | + SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; - SDE_DEBUG("[wb:%d,%u]\n", hw_wb->idx - WB_0, - wb_enc->frame_count); + SDE_DEBUG("[wb:%d,%u]\n", hw_wb->idx - WB_0, wb_enc->frame_count); /* don't notify upper layer for internal commit */ if (phys_enc->enable_state == SDE_ENC_DISABLING) goto complete; - event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE - | SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE - | SDE_ENCODER_FRAME_EVENT_DONE; + if (!phys_enc->in_clone_mode) + event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0); if (phys_enc->parent_ops.handle_frame_done) @@ -847,58 +1005,60 @@ static void sde_encoder_phys_wb_done_irq(void *arg, int irq_idx) } /** - * sde_encoder_phys_wb_register_irq - register writeback interrupt handler - * @phys_enc: Pointer to physical encoder + * sde_encoder_phys_wb_done_irq - Pingpong overflow interrupt handler for CWB + * @arg: Pointer to writeback encoder + * @irq_idx: interrupt index */ -static int sde_encoder_phys_wb_register_irq(struct sde_encoder_phys *phys_enc) +static void sde_encoder_phys_cwb_ovflow(void *arg, int irq_idx) { - struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); - struct sde_hw_wb *hw_wb = wb_enc->hw_wb; - struct sde_irq_callback *irq_cb = &wb_enc->irq_cb; - enum sde_intr_type intr_type; - int ret = 0; + _sde_encoder_phys_wb_frame_done_helper(arg, true); +} - if (wb_enc->bypass_irqreg) - return 0; +/** + * sde_encoder_phys_wb_done_irq - writeback interrupt handler + * @arg: Pointer to writeback encoder + * @irq_idx: interrupt index + */ +static void sde_encoder_phys_wb_done_irq(void *arg, int irq_idx) +{ + _sde_encoder_phys_wb_frame_done_helper(arg, false); +} - intr_type = sde_encoder_phys_wb_get_intr_type(hw_wb); - wb_enc->irq_idx = sde_core_irq_idx_lookup(phys_enc->sde_kms, - intr_type, hw_wb->idx); - if (wb_enc->irq_idx < 0) { - SDE_ERROR( - "failed to lookup IRQ index for WB_DONE with wb=%d\n", - hw_wb->idx - WB_0); - return -EINVAL; - } +/** + * sde_encoder_phys_wb_irq_ctrl - irq control of WB + * @phys: Pointer to physical encoder + * @enable: indicates enable or disable interrupts + */ +static void sde_encoder_phys_wb_irq_ctrl( + struct sde_encoder_phys *phys, bool enable) +{ - irq_cb->func = sde_encoder_phys_wb_done_irq; - irq_cb->arg = wb_enc; - ret = sde_core_irq_register_callback(phys_enc->sde_kms, - wb_enc->irq_idx, irq_cb); - if (ret) { - SDE_ERROR("failed to register IRQ callback WB_DONE\n"); - return ret; - } + struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys); + int index = 0; - ret = sde_core_irq_enable(phys_enc->sde_kms, &wb_enc->irq_idx, 1); - if (ret) { - SDE_ERROR( - "failed to enable IRQ for WB_DONE, wb %d, irq_idx=%d\n", - hw_wb->idx - WB_0, - wb_enc->irq_idx); - wb_enc->irq_idx = -EINVAL; - - /* Unregister callback on IRQ enable failure */ - sde_core_irq_unregister_callback(phys_enc->sde_kms, - wb_enc->irq_idx, irq_cb); - return ret; - } + if (!wb_enc) + return; - SDE_DEBUG("registered IRQ for wb %d, irq_idx=%d\n", - hw_wb->idx - WB_0, - wb_enc->irq_idx); + if (wb_enc->bypass_irqreg) + return; - return ret; + if (enable) { + sde_encoder_helper_register_irq(phys, INTR_IDX_WB_DONE); + if (phys->in_clone_mode) { + for (index = 0; index < CRTC_DUAL_MIXERS; index++) + sde_encoder_helper_register_irq(phys, + index ? INTR_IDX_PP3_OVFL + : INTR_IDX_PP2_OVFL); + } + } else { + sde_encoder_helper_unregister_irq(phys, INTR_IDX_WB_DONE); + if (phys->in_clone_mode) { + for (index = 0; index < CRTC_DUAL_MIXERS; index++) + sde_encoder_helper_unregister_irq(phys, + index ? INTR_IDX_PP3_OVFL + : INTR_IDX_PP2_OVFL); + } + } } /** @@ -969,6 +1129,7 @@ static int sde_encoder_phys_wb_wait_for_commit_done( u32 irq_status, event = 0; u64 wb_time = 0; int rc = 0; + int irq_idx = phys_enc->irq[INTR_IDX_WB_DONE].irq_idx; u32 timeout = max_t(u32, wb_enc->wbdone_timeout, KICKOFF_TIMEOUT_MS); /* Return EWOULDBLOCK since we know the wait isn't necessary */ @@ -983,7 +1144,7 @@ static int sde_encoder_phys_wb_wait_for_commit_done( /* signal completion if commit with no framebuffer */ if (!wb_enc->wb_fb) { SDE_DEBUG("no output framebuffer\n"); - sde_encoder_phys_wb_done_irq(wb_enc, wb_enc->irq_idx); + _sde_encoder_phys_wb_frame_done_helper(wb_enc, false); } ret = wait_for_completion_timeout(&wb_enc->wbdone_complete, @@ -993,11 +1154,11 @@ static int sde_encoder_phys_wb_wait_for_commit_done( SDE_EVT32(DRMID(phys_enc->parent), WBID(wb_enc), wb_enc->frame_count); irq_status = sde_core_irq_read(phys_enc->sde_kms, - wb_enc->irq_idx, true); + irq_idx, true); if (irq_status) { SDE_DEBUG("wb:%d done but irq not triggered\n", WBID(wb_enc)); - sde_encoder_phys_wb_done_irq(wb_enc, wb_enc->irq_idx); + _sde_encoder_phys_wb_frame_done_helper(wb_enc, false); } else { SDE_ERROR("wb:%d kickoff timed out\n", WBID(wb_enc)); @@ -1014,8 +1175,6 @@ static int sde_encoder_phys_wb_wait_for_commit_done( } } - sde_encoder_phys_wb_unregister_irq(phys_enc); - if (!rc) wb_enc->end_time = ktime_get(); @@ -1060,19 +1219,12 @@ static int sde_encoder_phys_wb_prepare_for_kickoff( struct sde_encoder_kickoff_params *params) { struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); - int ret; SDE_DEBUG("[wb:%d,%u]\n", wb_enc->hw_wb->idx - WB_0, wb_enc->kickoff_count); reinit_completion(&wb_enc->wbdone_complete); - ret = sde_encoder_phys_wb_register_irq(phys_enc); - if (ret) { - SDE_ERROR("failed to register irq %d\n", ret); - return ret; - } - wb_enc->kickoff_count++; /* set OT limit & enable traffic shaper */ @@ -1080,6 +1232,8 @@ static int sde_encoder_phys_wb_prepare_for_kickoff( _sde_encoder_phys_wb_update_flush(phys_enc); + _sde_encoder_phys_wb_update_cwb_flush(phys_enc); + /* vote for iommu/clk/bus */ wb_enc->start_time = ktime_get(); @@ -1100,6 +1254,15 @@ static void sde_encoder_phys_wb_trigger_flush(struct sde_encoder_phys *phys_enc) return; } + /* + * Bail out iff in CWB mode. In case of CWB, primary control-path + * which is actually driving would trigger the flush + */ + if (phys_enc->in_clone_mode) { + SDE_DEBUG("in CWB mode. early return\n"); + return; + } + SDE_DEBUG("[wb:%d]\n", wb_enc->hw_wb->idx - WB_0); /* clear pending flush if commit with no framebuffer */ @@ -1304,6 +1467,13 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc) goto exit; } + /* avoid reset frame for CWB */ + if (phys_enc->in_clone_mode) { + _sde_encoder_phys_wb_setup_cwb(phys_enc, false); + phys_enc->in_clone_mode = false; + goto exit; + } + /* reset h/w before final flush */ if (phys_enc->hw_ctl->ops.clear_pending_flush) phys_enc->hw_ctl->ops.clear_pending_flush(phys_enc->hw_ctl); @@ -1440,6 +1610,7 @@ static void sde_encoder_phys_wb_init_ops(struct sde_encoder_phys_ops *ops) ops->trigger_flush = sde_encoder_phys_wb_trigger_flush; ops->trigger_start = sde_encoder_helper_trigger_start; ops->hw_reset = sde_encoder_helper_hw_reset; + ops->irq_control = sde_encoder_phys_wb_irq_ctrl; } /** @@ -1452,6 +1623,7 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init( struct sde_encoder_phys *phys_enc; struct sde_encoder_phys_wb *wb_enc; struct sde_hw_mdp *hw_mdp; + struct sde_encoder_irq *irq; int ret = 0; SDE_DEBUG("\n"); @@ -1468,7 +1640,6 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init( ret = -ENOMEM; goto fail_alloc; } - wb_enc->irq_idx = -EINVAL; wb_enc->wbdone_timeout = KICKOFF_TIMEOUT_MS; init_completion(&wb_enc->wbdone_complete); @@ -1531,7 +1702,36 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init( phys_enc->intf_idx = p->intf_idx; phys_enc->enc_spinlock = p->enc_spinlock; atomic_set(&phys_enc->pending_retire_fence_cnt, 0); - INIT_LIST_HEAD(&wb_enc->irq_cb.list); + + irq = &phys_enc->irq[INTR_IDX_WB_DONE]; + INIT_LIST_HEAD(&irq->cb.list); + irq->name = "wb_done"; + irq->hw_idx = wb_enc->hw_wb->idx; + irq->irq_idx = -1; + irq->intr_type = sde_encoder_phys_wb_get_intr_type(wb_enc->hw_wb); + irq->intr_idx = INTR_IDX_WB_DONE; + irq->cb.arg = wb_enc; + irq->cb.func = sde_encoder_phys_wb_done_irq; + + irq = &phys_enc->irq[INTR_IDX_PP2_OVFL]; + INIT_LIST_HEAD(&irq->cb.list); + irq->name = "pp2_overflow"; + irq->hw_idx = CWB_2; + irq->irq_idx = -1; + irq->intr_type = SDE_IRQ_TYPE_CWB_OVERFLOW; + irq->intr_idx = INTR_IDX_PP2_OVFL; + irq->cb.arg = wb_enc; + irq->cb.func = sde_encoder_phys_cwb_ovflow; + + irq = &phys_enc->irq[INTR_IDX_PP3_OVFL]; + INIT_LIST_HEAD(&irq->cb.list); + irq->name = "pp3_overflow"; + irq->hw_idx = CWB_3; + irq->irq_idx = -1; + irq->intr_type = SDE_IRQ_TYPE_CWB_OVERFLOW; + irq->intr_idx = INTR_IDX_PP3_OVFL; + irq->cb.arg = wb_enc; + irq->cb.func = sde_encoder_phys_cwb_ovflow; /* create internal buffer for disable logic */ if (_sde_encoder_phys_wb_init_internal_fb(wb_enc, diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c index 12130822cfb9..8d7402b0c87a 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c @@ -1011,6 +1011,24 @@ static int sde_hw_ctl_intf_cfg(struct sde_hw_ctl *ctx, return 0; } +static void sde_hw_ctl_update_wb_cfg(struct sde_hw_ctl *ctx, + struct sde_hw_intf_cfg *cfg, bool enable) +{ + struct sde_hw_blk_reg_map *c = &ctx->hw; + u32 intf_cfg = 0; + + if (!cfg->wb) + return; + + intf_cfg = SDE_REG_READ(c, CTL_TOP); + if (enable) + intf_cfg |= (cfg->wb & 0x3) + 2; + else + intf_cfg &= ~((cfg->wb & 0x3) + 2); + + SDE_REG_WRITE(c, CTL_TOP, intf_cfg); +} + static inline u32 sde_hw_ctl_read_ctl_top(struct sde_hw_ctl *ctx) { struct sde_hw_blk_reg_map *c; @@ -1109,6 +1127,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, ops->trigger_pending = sde_hw_ctl_trigger_pending; ops->read_ctl_top = sde_hw_ctl_read_ctl_top; ops->read_ctl_layers = sde_hw_ctl_read_ctl_layers; + ops->update_wb_cfg = sde_hw_ctl_update_wb_cfg; ops->reset = sde_hw_ctl_reset_control; ops->get_reset = sde_hw_ctl_get_reset_status; ops->hard_reset = sde_hw_ctl_hard_reset; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h index a4b1dd745827..a231e8a2f787 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h @@ -268,6 +268,14 @@ struct sde_hw_ctl_ops { int (*setup_dsc_cfg)(struct sde_hw_ctl *ctx, struct sde_ctl_dsc_cfg *cfg); + /** Update the interface selection with input WB config + * @ctx : ctl path ctx pointer + * @cfg : pointer to input wb config + * @enable : set if true, clear otherwise + */ + void (*update_wb_cfg)(struct sde_hw_ctl *ctx, + struct sde_hw_intf_cfg *cfg, bool enable); + int (*reset)(struct sde_hw_ctl *c); /** diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.c b/drivers/gpu/drm/msm/sde/sde_hw_top.c index 82840e64d12f..7128f64ba30d 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_top.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_top.c @@ -413,6 +413,18 @@ static void sde_hw_intf_audio_select(struct sde_hw_mdp *mdp) SDE_REG_WRITE(c, HDMI_DP_CORE_SELECT, 0x1); } +static void sde_hw_program_cwb_ppb_ctrl(struct sde_hw_mdp *mdp, + bool dual, bool dspp_out) +{ + u32 value = dspp_out ? 0x4 : 0x0; + + SDE_REG_WRITE(&mdp->hw, PPB2_CNTL, value); + if (dual) { + value |= 0x1; + SDE_REG_WRITE(&mdp->hw, PPB3_CNTL, value); + } +} + static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops, unsigned long cap) { @@ -422,6 +434,7 @@ static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops, ops->setup_clk_force_ctrl = sde_hw_setup_clk_force_ctrl; ops->get_danger_status = sde_hw_get_danger_status; ops->setup_vsync_source = sde_hw_setup_vsync_source; + ops->set_cwb_ppb_cntl = sde_hw_program_cwb_ppb_ctrl; ops->get_safe_status = sde_hw_get_safe_status; ops->get_split_flush_status = sde_hw_get_split_flush; ops->setup_dce = sde_hw_setup_dce; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.h b/drivers/gpu/drm/msm/sde/sde_hw_top.h index 950a62cee8ef..210ea5379e3b 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_top.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_top.h @@ -194,6 +194,15 @@ struct sde_hw_mdp_ops { * @mdp: mdp top context driver */ void (*intf_audio_select)(struct sde_hw_mdp *mdp); + + /** + * set_cwb_ppb_cntl - select the data point for CWB + * @mdp: mdp top context driver + * @dual: indicates if dual pipe line needs to be programmed + * @dspp_out : true if dspp output required. LM is default tap point + */ + void (*set_cwb_ppb_cntl)(struct sde_hw_mdp *mdp, + bool dual, bool dspp_out); }; struct sde_hw_mdp { diff --git a/drivers/gpu/drm/msm/sde/sde_hwio.h b/drivers/gpu/drm/msm/sde/sde_hwio.h index cc020d993def..a59222350a11 100644 --- a/drivers/gpu/drm/msm/sde/sde_hwio.h +++ b/drivers/gpu/drm/msm/sde/sde_hwio.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -40,6 +40,8 @@ #define PPB0_CONFIG 0x334 #define PPB1_CNTL 0x338 #define PPB1_CONFIG 0x33C +#define PPB2_CNTL 0x370 +#define PPB3_CNTL 0x374 #define HW_EVENTS_CTL 0x37C #define CLK_CTRL3 0x3A8 #define CLK_STATUS3 0x3AC -- GitLab From 4fb00b4ed0efde5b04447477536e0e06c98989cc Mon Sep 17 00:00:00 2001 From: Shubhashree Dhar Date: Mon, 23 Apr 2018 16:25:10 +0530 Subject: [PATCH 0458/1299] sde: rotator: Add null pointer checks Pointers in some cases are dereferenced even after freeing memory region pointed by them. Assign NULL to free pointers and perform proper NULL pointer checks. Change-Id: Id9caef8af0c9d06e40e99ed71db68197fc6cf4f4 Signed-off-by: Shubhashree Dhar --- .../platform/msm/sde/rotator/sde_rotator_dev.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c index 7d8f5fc9caeb..b6d681a07df1 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c @@ -1077,6 +1077,7 @@ struct sde_rotator_ctx *sde_rotator_ctx_open( mutex_unlock(&rot_dev->lock); error_lock: kfree(ctx); + ctx = NULL; return ERR_PTR(ret); } @@ -1089,10 +1090,18 @@ struct sde_rotator_ctx *sde_rotator_ctx_open( static int sde_rotator_ctx_release(struct sde_rotator_ctx *ctx, struct file *file) { - struct sde_rotator_device *rot_dev = ctx->rot_dev; - u32 session_id = ctx->session_id; + struct sde_rotator_device *rot_dev; + u32 session_id; struct list_head *curr, *next; + if (!ctx) { + SDEROT_DBG("ctx is NULL\n"); + return -EINVAL; + } + + rot_dev = ctx->rot_dev; + session_id = ctx->session_id; + ATRACE_END(ctx->kobj.name); SDEDEV_DBG(rot_dev->dev, "release s:%d\n", session_id); -- GitLab From 18305c75b6d12663afa7185a177c6152acea4a32 Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Wed, 11 Apr 2018 17:26:26 +0530 Subject: [PATCH 0459/1299] drm/msm/sde: signal release and retire fence during timeout Signal release and retire fences in the case of wait timeout for video mode interface. Change-Id: I4c228257b761e264a13fff29da81baffe37496a8 Signed-off-by: Kalyan Thota --- drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index ea0fb886776f..afc3f6b069fc 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -881,7 +881,7 @@ static int _sde_encoder_phys_vid_wait_for_vblank( if (phys_enc->parent_ops.handle_frame_done && event) phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, - SDE_ENCODER_FRAME_EVENT_DONE); + event); return ret; } -- GitLab From 5895a280da047ee04aa19278a07d06c380f34b5a Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Tue, 19 Jun 2018 15:26:17 -0600 Subject: [PATCH 0460/1299] soc: qcom: qmi: Fix possible use after free Packets in transmit path maybe freed before checking for the content for bearer level flow control limit. Fix this by checking this before the transmit. CRs-Fixed: 2259239 Change-Id: If50af5a2e6c6bb3bfddfe583c422c7f648783aea Signed-off-by: Subash Abhinov Kasiviswanathan --- .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 2 +- drivers/soc/qcom/dfc_qmi.c | 40 +------------------ 2 files changed, 3 insertions(+), 39 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c index 72fa095e756f..560a38a5cb07 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c @@ -62,8 +62,8 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, priv = netdev_priv(dev); if (priv->real_dev) { - rmnet_egress_handler(skb); qmi_rmnet_burst_fc_check(dev, skb); + rmnet_egress_handler(skb); } else { this_cpu_inc(priv->pcpu_stats->stats.tx_drops); kfree_skb(skb); diff --git a/drivers/soc/qcom/dfc_qmi.c b/drivers/soc/qcom/dfc_qmi.c index 4ea628924d6c..05ab56cd2e65 100644 --- a/drivers/soc/qcom/dfc_qmi.c +++ b/drivers/soc/qcom/dfc_qmi.c @@ -28,15 +28,6 @@ #define NO_CHANGE 1 #define UPDATED 2 -struct dfc_work { - struct work_struct work; - struct net_device *dev; - u8 bearer_id; - u8 ack_req; - u16 seq; - u8 mux_id; -}; - struct dfc_qmi_data { void *rmnet_port; struct workqueue_struct *dfc_wq; @@ -63,7 +54,6 @@ static void dfc_ind_reg_dereg(struct work_struct *work); static void dfc_svc_init(struct work_struct *work); static void dfc_do_burst_flow_control(struct work_struct *work); -static void dfc_disable_flow(struct work_struct *work); /* **************************************************** */ #define DFC_SERVICE_ID_V01 0x4E @@ -546,9 +536,7 @@ static int dfc_disable_bearer_flows(struct net_device *dev, u8 bearer_id) return 0; if (itm->bearer_id == bearer_id) { - rtnl_lock(); tc_qdisc_flow_control(dev, itm->tcm_handle, 0); - rtnl_unlock(); rc++; } } @@ -595,15 +583,6 @@ static int dfc_do_fc(struct net_device *dev, u32 flow_id, return len; } -static void dfc_disable_flow(struct work_struct *work) -{ - struct dfc_work *data = (struct dfc_work *)work; - int rc = dfc_disable_bearer_flows(data->dev, data->bearer_id); - - pr_debug("%s() %d flows disabled\n", __func__, rc); - kfree(data); -} - static void dfc_do_flow_controls(struct net_device *dev, struct dfc_flow_status_info_type_v01 *flow) { @@ -865,11 +844,10 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, struct sk_buff *skb) { struct rmnet_bearer_map *bearer; - struct dfc_work *svc_check; struct rmnet_flow_map *itm; int ip_type; - if (!qos || !skb) + if (!qos) return; if (!rtnl_trylock()) @@ -888,22 +866,8 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, if (bearer->counter >= bearer->grant_size) { bearer->counter = 0; - svc_check = kmalloc(sizeof(struct dfc_work), - GFP_ATOMIC); - if (!svc_check) { - rtnl_unlock(); - return; - } - - INIT_WORK((struct work_struct *)svc_check, - dfc_disable_flow); - svc_check->dev = dev; - svc_check->bearer_id = bearer->bearer_id; - svc_check->ack_req = bearer->ack_req; - svc_check->seq = bearer->seq; - svc_check->mux_id = qos->mux_id; + dfc_disable_bearer_flows(dev, bearer->bearer_id); rtnl_unlock(); - schedule_work((struct work_struct *)svc_check); } else { rtnl_unlock(); } -- GitLab From b1e31d88f505d23c8b823a8da81e4585681d9561 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Tue, 19 Jun 2018 18:42:40 -0700 Subject: [PATCH 0461/1299] usb: dwc3: gadget: delay clearing run/stop when setup just arrived There still exists a small window in which dwc3_gadget_pullup() is called while a new control transfer setup packet had newly arrived. In the case where it needs to be delegated to the gadget driver, it releases dwc3->lock and allows pullup() to proceed to call run_stop() to attempt to stop the controller. The lock will get released again when calling dwc3_stop_active_transfers() which allows the gadget driver to meanwhile call ep_queue() for a three-stage control transfer and sneak in a Start Transfer. By the time the DCTL register is written, the controller will fail to halt due to having an outstanding transfer in progress. CPU0 CPU1 ...dwc3->lock held... dwc3_ep0_inspect_setup() dwc3_gadget_pullup() dwc3_ep0_delegate_req() spin_lock_irq_save() spin_unlock() ... unblocked composite_setup() dwc3_gadget_run_stop() usb_ep_queue() dwc3_stop_active_transfers() dwc3_gadget_ep0_queue() dwc3_gadget_remove_requests() spin_lock_irqsave() dwc3_gadget_giveback() ... unblocked spin_unlock() __dwc3_ep0_do_control_data() spin_lock() issues Start Transfer spin_unlock_irqrestore() ... unblocked spin_lock() clear DCTL_RUN_STOP ... wait for DSTS_DEVCTRLHLT time out This change attempts to fix the issue by additionally checking the dwc->ep0_next_event state in dwc3_gadget_pullup() to catch the case when a SETUP packet had just been received and handled by dwc3_ep0_inspect_setup but is still waiting to proceed to either a DATA or STATUS stage. This allows pullup() to wait for completion of the transfer before moving on to clear run/stop. Change-Id: Ib2da3c86213ade1a61fb82f95a1f7c9534d9df3f Signed-off-by: Jack Pham --- drivers/usb/dwc3/gadget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1e0b33ccc4d6..d6e9fead5316 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2188,7 +2188,8 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) * Per databook, when we want to stop the gadget, if a control transfer * is still in process, complete it and get the core into setup phase. */ - if (!is_on && dwc->ep0state != EP0_SETUP_PHASE) { + if (!is_on && (dwc->ep0state != EP0_SETUP_PHASE || + dwc->ep0_next_event != DWC3_EP0_COMPLETE)) { reinit_completion(&dwc->ep0_in_setup); ret = wait_for_completion_timeout(&dwc->ep0_in_setup, -- GitLab From ae042c80d02b813eddbdead0b81e4b5b96e4ec31 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Tue, 20 Mar 2018 18:02:11 +0530 Subject: [PATCH 0462/1299] msm: kgsl: Add support for A608 GPU Add new GPU ID and required initial settings to support Graphics functionality on SM6150. Change-Id: I8877cb9860c73ca493e1d4879f9f40de052695f0 Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno-gpulist.h | 13 +++++ drivers/gpu/msm/adreno.h | 2 + drivers/gpu/msm/adreno_a6xx.c | 90 ++++++++++++++++++++++++++++---- 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index f461bc1649d3..c0275d781dfc 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -419,4 +419,17 @@ static const struct adreno_gpu_core adreno_gpulist[] = { .gpmu_tsens = 0x000C000D, .max_power = 5448, }, + { + .gpurev = ADRENO_REV_A608, + .core = 6, + .major = 0, + .minor = 8, + .patchid = ANY_ID, + .features = ADRENO_64BIT, + .sqefw_name = "a630_sqe.fw", + .gpudev = &adreno_a6xx_gpudev, + .gmem_size = (SZ_128K + SZ_4K), + .num_protected_regs = 0x20, + .busy_mask = 0xFFFFFFFE, + }, }; diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 1209103e868f..ddda2bc1453f 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -210,6 +210,7 @@ enum adreno_gpurev { ADRENO_REV_A512 = 512, ADRENO_REV_A530 = 530, ADRENO_REV_A540 = 540, + ADRENO_REV_A608 = 608, ADRENO_REV_A615 = 615, ADRENO_REV_A630 = 630, ADRENO_REV_A640 = 640, @@ -1254,6 +1255,7 @@ static inline int adreno_is_a6xx(struct adreno_device *adreno_dev) ADRENO_GPUREV(adreno_dev) < 700; } +ADRENO_TARGET(a608, ADRENO_REV_A608) ADRENO_TARGET(a615, ADRENO_REV_A615) ADRENO_TARGET(a630, ADRENO_REV_A630) ADRENO_TARGET(a640, ADRENO_REV_A640) diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index b537c97777bc..49174774c54f 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -69,6 +69,7 @@ static const struct adreno_vbif_platform a6xx_vbif_platforms[] = { { adreno_is_a615, a615_gbif }, { adreno_is_a640, a640_gbif }, { adreno_is_a680, a640_gbif }, + { adreno_is_a608, a615_gbif }, }; struct kgsl_hwcg_reg { @@ -301,6 +302,58 @@ static const struct kgsl_hwcg_reg a640_hwcg_regs[] = { {A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555}, }; +static const struct kgsl_hwcg_reg a608_hwcg_regs[] = { + {A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222}, + {A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, + {A6XX_RBBM_CLOCK_DELAY_SP0, 0x0000F3CF}, + {A6XX_RBBM_CLOCK_HYST_SP0, 0x00000081}, + {A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222}, + {A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, + {A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222}, + {A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222}, + {A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, + {A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, + {A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111}, + {A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111}, + {A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, + {A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, + {A6XX_RBBM_CLOCK_HYST3_TP0, 0x77777777}, + {A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777}, + {A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, + {A6XX_RBBM_CLOCK_CNTL2_RB0, 0x01202222}, + {A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220}, + {A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00}, + {A6XX_RBBM_CLOCK_CNTL_RAC, 0x05522022}, + {A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555}, + {A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011}, + {A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044}, + {A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, + {A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, + {A6XX_RBBM_CLOCK_MODE_GPC, 0x02222222}, + {A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002}, + {A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222}, + {A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, + {A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}, + {A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, + {A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, + {A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, + {A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, + {A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, + {A6XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000}, + {A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, + {A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222}, + {A6XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222}, + {A6XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222}, + {A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004}, + {A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, + {A6XX_RBBM_ISDB_CNT, 0x00000182}, + {A6XX_RBBM_RAC_THRESHOLD_CNT, 0x00000000}, + {A6XX_RBBM_SP_HYST_CNT, 0x00000000}, + {A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222}, + {A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111}, + {A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555}, +}; + static const struct { int (*devfunc)(struct adreno_device *adreno_dev); const struct kgsl_hwcg_reg *regs; @@ -310,6 +363,7 @@ static const struct { {adreno_is_a615, a615_hwcg_regs, ARRAY_SIZE(a615_hwcg_regs)}, {adreno_is_a640, a640_hwcg_regs, ARRAY_SIZE(a640_hwcg_regs)}, {adreno_is_a680, a640_hwcg_regs, ARRAY_SIZE(a640_hwcg_regs)}, + {adreno_is_a608, a608_hwcg_regs, ARRAY_SIZE(a608_hwcg_regs)}, }; static struct a6xx_protected_regs { @@ -545,6 +599,8 @@ __get_rbbm_clock_cntl_on(struct adreno_device *adreno_dev) { if (adreno_is_a630(adreno_dev)) return 0x8AA8AA02; + else if (adreno_is_a608(adreno_dev)) + return 0xAAA8AA82; else return 0x8AA8AA82; } @@ -552,7 +608,9 @@ __get_rbbm_clock_cntl_on(struct adreno_device *adreno_dev) static inline unsigned int __get_gmu_ao_cgc_mode_cntl(struct adreno_device *adreno_dev) { - if (adreno_is_a615(adreno_dev)) + if (adreno_is_a608(adreno_dev)) + return 0x00000022; + else if (adreno_is_a615(adreno_dev)) return 0x00000222; else return 0x00020202; @@ -561,7 +619,9 @@ __get_gmu_ao_cgc_mode_cntl(struct adreno_device *adreno_dev) static inline unsigned int __get_gmu_ao_cgc_delay_cntl(struct adreno_device *adreno_dev) { - if (adreno_is_a615(adreno_dev)) + if (adreno_is_a608(adreno_dev)) + return 0x00000011; + else if (adreno_is_a615(adreno_dev)) return 0x00000111; else return 0x00010111; @@ -570,7 +630,9 @@ __get_gmu_ao_cgc_delay_cntl(struct adreno_device *adreno_dev) static inline unsigned int __get_gmu_ao_cgc_hyst_cntl(struct adreno_device *adreno_dev) { - if (adreno_is_a615(adreno_dev)) + if (adreno_is_a608(adreno_dev)) + return 0x00000055; + else if (adreno_is_a615(adreno_dev)) return 0x00000555; else return 0x00005555; @@ -671,7 +733,7 @@ static void a6xx_patch_pwrup_reglist(struct adreno_device *adreno_dev) + sizeof(a6xx_ifpc_pwrup_reglist), a6xx_pwrup_reglist, sizeof(a6xx_pwrup_reglist)); - if (adreno_is_a615(adreno_dev)) { + if (adreno_is_a615(adreno_dev) || adreno_is_a608(adreno_dev)) { for (i = 0; i < ARRAY_SIZE(a615_pwrup_reglist); i++) { r = &a615_pwrup_reglist[i]; kgsl_regread(KGSL_DEVICE(adreno_dev), @@ -744,20 +806,30 @@ static void a6xx_start(struct adreno_device *adreno_dev) kgsl_regwrite(device, A6XX_UCHE_CACHE_WAYS, 0x4); /* ROQ sizes are twice as big on a640/a680 than on a630 */ - if (adreno_is_a640(adreno_dev) || adreno_is_a680(adreno_dev)) + if (adreno_is_a640(adreno_dev) || adreno_is_a680(adreno_dev)) { kgsl_regwrite(device, A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140); - else + kgsl_regwrite(device, A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362C); + } else if (adreno_is_a608(adreno_dev)) { + kgsl_regwrite(device, A6XX_CP_ROQ_THRESHOLDS_2, 0x800060); + kgsl_regwrite(device, A6XX_CP_ROQ_THRESHOLDS_1, 0x40201b16); + } else { kgsl_regwrite(device, A6XX_CP_ROQ_THRESHOLDS_2, 0x010000C0); - kgsl_regwrite(device, A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362C); + kgsl_regwrite(device, A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362C); + } - /* Setting the mem pool size */ - kgsl_regwrite(device, A6XX_CP_MEM_POOL_SIZE, 128); + /* For a608 Mem pool size is reduced to 1/4 */ + if (adreno_is_a608(adreno_dev)) + kgsl_regwrite(device, A6XX_CP_MEM_POOL_SIZE, 32); + else + kgsl_regwrite(device, A6XX_CP_MEM_POOL_SIZE, 128); /* Setting the primFifo thresholds values */ if (adreno_is_a640(adreno_dev)) kgsl_regwrite(device, A6XX_PC_DBG_ECO_CNTL, (0x400 << 11)); else if (adreno_is_a680(adreno_dev)) kgsl_regwrite(device, A6XX_PC_DBG_ECO_CNTL, (0x800 << 11)); + else if (adreno_is_a608(adreno_dev)) + kgsl_regwrite(device, A6XX_PC_DBG_ECO_CNTL, (0x100 << 11)); else kgsl_regwrite(device, A6XX_PC_DBG_ECO_CNTL, (0x300 << 11)); -- GitLab From 2f5a3dd3da3e331caf58e4ea41cc5aac16e05f0b Mon Sep 17 00:00:00 2001 From: Prateek Sood Date: Tue, 19 Jun 2018 19:05:57 +0530 Subject: [PATCH 0463/1299] llcc: Update SCT table entries Modify llcc SCT table entries for sdmmagpie. Change-Id: I0922d076685ba020088ad094514d5b17541c04d4 Signed-off-by: Prateek Sood --- drivers/soc/qcom/llcc-sdmmagpie.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/llcc-sdmmagpie.c b/drivers/soc/qcom/llcc-sdmmagpie.c index 7e772cf7151c..4f7397e83957 100644 --- a/drivers/soc/qcom/llcc-sdmmagpie.c +++ b/drivers/soc/qcom/llcc-sdmmagpie.c @@ -60,7 +60,8 @@ static struct llcc_slice_config sdmmagpie_data[] = { SCT_ENTRY("cpuss", 1, 1, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 1), SCT_ENTRY("modem", 8, 8, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 0), SCT_ENTRY("modemhw", 9, 9, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 0), - SCT_ENTRY("mmuhwt", 13, 13, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 0, 1), + SCT_ENTRY("gpuhtw", 11, 11, 128, 0, 1, 0xF, 0x0, 0, 0, 0, 1, 0), + SCT_ENTRY("gpu", 12, 12, 384, 0, 1, 0xF, 0x0, 0, 0, 0, 1, 0), }; static int sdmmagpie_qcom_llcc_probe(struct platform_device *pdev) -- GitLab From e54b71ebbfa821f558a02664d866b302ed58cb53 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Mon, 18 Jun 2018 17:20:11 -0700 Subject: [PATCH 0464/1299] mhi: core: use kmemdup rather than duplicating it's implementation Use kmemdup, instead of using kmalloc, and memcpy combo. CRs-Fixed: 2258358 Change-Id: I941ee2fa3a4b47dd0a2a5833ee52445a553f3aa6 Signed-off-by: Sujeev Dias --- drivers/bus/mhi/core/mhi_boot.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_boot.c b/drivers/bus/mhi/core/mhi_boot.c index 8f4583a3982f..b05493fcdd60 100644 --- a/drivers/bus/mhi/core/mhi_boot.c +++ b/drivers/bus/mhi/core/mhi_boot.c @@ -506,7 +506,7 @@ void mhi_fw_load_worker(struct work_struct *work) if (size > firmware->size) size = firmware->size; - buf = kmalloc(size, GFP_KERNEL); + buf = kmemdup(firmware->data, size, GFP_KERNEL); if (!buf) { MHI_ERR("Could not allocate memory for image\n"); release_firmware(firmware); @@ -514,7 +514,6 @@ void mhi_fw_load_worker(struct work_struct *work) } /* load sbl image */ - memcpy(buf, firmware->data, size); ret = mhi_fw_load_sbl(mhi_cntrl, buf, size); kfree(buf); -- GitLab From 173e5a10b22ee5a1ce3941f48bbb8320e9768d27 Mon Sep 17 00:00:00 2001 From: "Bao D. Nguyen" Date: Mon, 18 Jun 2018 15:19:28 -0700 Subject: [PATCH 0465/1299] scsi: ufs-qcom: Add flag to keep track of PHY's power state Add a flag to keep track of the UFS PHY's power state. This flag is used to prevent the phy_power_on() and phy_power_off() functions from being called multiple times consecutively. Each time the phy_power_on() is called, a reference count maintained in the PHY driver is incremented by 1. In the same manner, each time phy_power_off() is called, this reference count is decremented by 1. The PHY resources can only be turned off by the PHY driver if this reference count being 1 when the phy_power_off() is called indicating this is the last client using the PHY resources. Therefore, to ensure that the UFS PHY resources can be turned off in case of UFS clock gate/ungate and suspend/resume scenarios, the UFS driver needs to keep track of the PHY power state and avoids any extra phy_power_on() calls. Change-Id: Ia4af2fbb1d23028692f91f7df4f2eab6947bad4d Signed-off-by: Bao D. Nguyen --- drivers/scsi/ufs/ufs-qcom.c | 44 ++++++++++++++++++++++--------------- drivers/scsi/ufs/ufs-qcom.h | 1 + 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index d759ddc272e4..119b3d8de689 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -834,8 +834,10 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) */ if (!ufs_qcom_is_link_active(hba)) { ufs_qcom_disable_lane_clks(host); - phy_power_off(phy); - + if (host->is_phy_pwr_on) { + phy_power_off(phy); + host->is_phy_pwr_on = false; + } if (host->vddp_ref_clk && ufs_qcom_is_link_off(hba)) ret = ufs_qcom_disable_vreg(hba->dev, host->vddp_ref_clk); @@ -859,13 +861,15 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) struct phy *phy = host->generic_phy; int err; - err = phy_power_on(phy); - if (err) { - dev_err(hba->dev, "%s: failed enabling regs, err = %d\n", - __func__, err); - goto out; + if (!host->is_phy_pwr_on) { + err = phy_power_on(phy); + if (err) { + dev_err(hba->dev, "%s: failed enabling regs, err = %d\n", + __func__, err); + goto out; + } + host->is_phy_pwr_on = true; } - if (host->vddp_ref_clk && (hba->rpm_lvl > UFS_PM_LVL_3 || hba->spm_lvl > UFS_PM_LVL_3)) ufs_qcom_enable_vreg(hba->dev, @@ -1590,8 +1594,10 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, return 0; if (on && (status == POST_CHANGE)) { - phy_power_on(host->generic_phy); - + if (!host->is_phy_pwr_on) { + phy_power_on(host->generic_phy); + host->is_phy_pwr_on = true; + } /* enable the device ref clock for HS mode*/ if (ufshcd_is_hs_mode(&hba->pwr_info)) ufs_qcom_dev_ref_clk_ctrl(host, true); @@ -1614,7 +1620,10 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, ufs_qcom_dev_ref_clk_ctrl(host, false); /* powering off PHY during aggressive clk gating */ - phy_power_off(host->generic_phy); + if (host->is_phy_pwr_on) { + phy_power_off(host->generic_phy); + host->is_phy_pwr_on = false; + } } } @@ -2221,15 +2230,13 @@ static int ufs_qcom_init(struct ufs_hba *hba) err = ufs_qcom_parse_reg_info(host, "qcom,vddp-ref-clk", &host->vddp_ref_clk); phy_init(host->generic_phy); - err = phy_power_on(host->generic_phy); - if (err) - goto out_unregister_bus; + if (host->vddp_ref_clk) { err = ufs_qcom_enable_vreg(dev, host->vddp_ref_clk); if (err) { dev_err(dev, "%s: failed enabling ref clk supply: %d\n", __func__, err); - goto out_disable_phy; + goto out_unregister_bus; } } @@ -2262,8 +2269,6 @@ static int ufs_qcom_init(struct ufs_hba *hba) out_disable_vddp: if (host->vddp_ref_clk) ufs_qcom_disable_vreg(dev, host->vddp_ref_clk); -out_disable_phy: - phy_power_off(host->generic_phy); out_unregister_bus: phy_exit(host->generic_phy); msm_bus_scale_unregister_client(host->bus_vote.client_handle); @@ -2280,7 +2285,10 @@ static void ufs_qcom_exit(struct ufs_hba *hba) msm_bus_scale_unregister_client(host->bus_vote.client_handle); ufs_qcom_disable_lane_clks(host); - phy_power_off(host->generic_phy); + if (host->is_phy_pwr_on) { + phy_power_off(host->generic_phy); + host->is_phy_pwr_on = false; + } phy_exit(host->generic_phy); ufs_qcom_pm_qos_remove(host); } diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index 84f5cbd8b477..f3f60c2a4dbb 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -383,6 +383,7 @@ struct ufs_qcom_host { struct request *req_pending; struct ufs_vreg *vddp_ref_clk; bool work_pending; + bool is_phy_pwr_on; }; static inline u32 -- GitLab From b7c1a7970153df7e850bd6dabc558b37a7307267 Mon Sep 17 00:00:00 2001 From: muluhe Date: Mon, 9 Apr 2018 15:42:15 +0800 Subject: [PATCH 0466/1299] ARM: dts: msm: Add wcss tpdm node for sm8150 Enable tpdm wcss node for sm8150, it is used for WCSS subsystem debug. Change-Id: I302af35be117139b118a799015e413ad7e3497da Signed-off-by: muluhe --- .../arm64/boot/dts/qcom/sm8150-coresight.dtsi | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi b/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi index deac2e6b7602..68ca9f1ba507 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi @@ -1099,6 +1099,28 @@ <&tpda_dl_north_out_funnel_dl_north>; }; }; + + port@2 { + reg = <1>; + funnel_dl_north_in_tpdm_wcss: endpoint { + slave-mode; + remote-endpoint = + <&tpdm_wcss_out_funnel_dl_north>; + }; + }; + }; + }; + + tpdm_wcss: tpdm@699c000 { + compatible = "qcom,coresight-dummy"; + + coresight-name = "coresight-tpdm-wcss"; + qcom,dummy-source; + + port { + tpdm_wcss_out_funnel_dl_north: endpoint { + remote-endpoint = <&funnel_dl_north_in_tpdm_wcss>; + }; }; }; -- GitLab From e8d773caf04ebaef09092f4a1549ff0a81e8831b Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 6 Jun 2018 10:47:27 +0530 Subject: [PATCH 0467/1299] Documentation: sound: Add documentation for qcs405 nodes Add documentation for the new audio nodes introduced to support qcs405 target. Change-Id: I4c78eea7f1e578eac1004a0a79f117f844f5fee1 Signed-off-by: Aditya Bavanari --- .../bindings/pinctrl/qcom,lpi-pinctrl.txt | 172 ++++++++++++++++++ .../bindings/sound/qcom-audio-dev.txt | 169 +++++++++++++++++ .../devicetree/bindings/sound/wcd_codec.txt | 43 +++++ 3 files changed, 384 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,lpi-pinctrl.txt diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,lpi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,lpi-pinctrl.txt new file mode 100644 index 000000000000..2d09a6a01457 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,lpi-pinctrl.txt @@ -0,0 +1,172 @@ +Qualcomm Technologies, Inc. LPI GPIO controller driver + +This DT bindings describes the GPIO controller driver +being added for supporting LPI (Low Power Island) TLMM +from QTI chipsets. + +Following properties are for LPI GPIO controller device main node. +- compatible: + Usage: required + Value type: + Definition: must be "qcom,lpi-pinctrl" + +- reg: + Usage: required + Value type: + Definition: Register base of the GPIO controller and length. + +- qcom,num-gpios: + Usage: required + Value type: + Definition: Number of GPIOs supported by the controller. + +- qcom,lpi-offset-tbl + Usage: required + Value type: + Definition: Offset table of GPIOs supported by the controller. + +- gpio-controller: + Usage: required + Value type: + Definition: Used to mark the device node as a GPIO controller. + +- #gpio-cells: + Usage: required + Value type: + Definition: Must be 2; + The first cell will be used to define gpio number and the + second denotes the flags for this gpio. + +Please refer to ../gpio/gpio.txt for general description of GPIO bindings. + +Please refer to pinctrl-bindings.txt in this directory for details of the +common pinctrl bindings used by client devices, including the meaning of the +phrase "pin configuration node". + +The pin configuration nodes act as a container for an arbitrary number of +subnodes. Each of these subnodes represents some desired configuration for a +pin or a list of pins. This configuration can include the +mux function to select on those pin(s), and various pin configuration +parameters, as listed below. + +SUBNODES: + +The name of each subnode is not important; all subnodes should be enumerated +and processed purely based on their content. + +Each subnode only affects those parameters that are explicitly listed. In +other words, a subnode that lists a mux function but no pin configuration +parameters implies no information about any pin configuration parameters. +Similarly, a pin subnode that describes a pullup parameter implies no +information about e.g. the mux function. + +The following generic properties as defined in pinctrl-bindings.txt are valid +to specify in a pin configuration subnode: + +- pins: + Usage: required + Value type: + Definition: List of gpio pins affected by the properties specified in + this subnode. Valid pins are: gpio0-gpio31 for LPI. + +- function: + Usage: required + Value type: + Definition: Specify the alternative function to be configured for the + specified pins. Valid values are: + "gpio", + "func1", + "func2", + "func3", + "func4", + "func5" + +- bias-disable: + Usage: optional + Value type: + Definition: The specified pins should be configured as no pull. + +- bias-pull-down: + Usage: optional + Value type: + Definition: The specified pins should be configured as pull down. + +- bias-bus-hold: + Usage: optional + Value type: + Definition: The specified pins should be configured as bus-keeper mode. + +- bias-pull-up: + Usage: optional + Value type: + Definition: The specified pins should be configured as pull up. + +- input-enable: + Usage: optional + Value type: + Definition: The specified pins are put in input mode. + +- output-high: + Usage: optional + Value type: + Definition: The specified pins are configured in output mode, driven + high. + +- output-low: + Usage: optional + Value type: + Definition: The specified pins are configured in output mode, driven + low. + +- qcom,drive-strength: + Usage: optional + Value type: + Definition: Selects the drive strength for the specified pins. + +Example: + + lpi_tlmm: lpi_pinctrl@152c000 { + compatible = "qcom,lpi-pinctrl"; + qcom,num-gpios = <32>; + reg = <0x152c000 0>; + gpio-controller; + #gpio-cells = <2>; + qcom,lpi-offset-tbl = <0x00000010>, <0x00000020>, + <0x00000030>, <0x00000040>, + <0x00000050>, <0x00000060>, + <0x00000070>, <0x00000080>, + <0x00000090>, <0x00000100>, + <0x00000110>, <0x00000120>, + <0x00000130>, <0x00000140>, + <0x00000150>, <0x00000160>, + <0x00000170>, <0x00000180>, + <0x00000190>, <0x00000200>, + <0x00000210>; + + + hph_comp_active: hph_comp_active { + mux { + pins = "gpio22"; + function = "func1"; + }; + + config { + pins = "gpio22"; + output-high; + qcom,drive-strength = <8>; + }; + }; + + hph_comp_sleep: hph_comp_sleep { + mux { + pins = "gpio22"; + function = "func1"; + }; + + config { + pins = "gpio22"; + qcom,drive-strength = <2>; + }; + }; + }; + diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index f1273d30b081..ecbc7c2095d8 100644 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -220,6 +220,23 @@ Required properties: inCall Music Delivery port ID is 32773. incall Music 2 Delivery port ID is 32770. +* msm_dai_cdc_dma + +[First Level Nodes] + +Required properties: + + - compatible : "qcom,msm-dai-cdc-dma" + +[Second Level Nodes] + +Required properties: + + - compatible : "qcom,msm-dai-cdc-dma-dev" + - qcom,msm-dai-cdc-dma-dev-id : WSA codec dma port ID + Value is from 45056 to 45061. + VA codec dma port ID Value is from 45089 to 45091. + * msm-auxpcm Required properties: @@ -656,6 +673,12 @@ Example: audio_apr: qcom,msm-audio-apr { compatible = "qcom,msm-audio-apr"; qcom,subsys-name = "apr_adsp"; + q6core { + compatible = "qcom,q6core-audio"; + bolero: bolero-cdc { + compatible = "qcom,bolero-cdc"; + }; + }; }; qcom,msm-ocmem-audio { @@ -1191,3 +1214,149 @@ Example: qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight", "SpkrLeft", "SpkrRight"; }; + + +* QCS405 ASoC Machine driver + +Required properties: +- compatible : "qcom,qcs405-asoc-snd". +- qcom,model : The user-visible name of this sound card. +- qcom,audio-routing : A list of the connections between audio components. +- asoc-platform: This is phandle list containing the references to platform device + nodes that are used as part of the sound card dai-links. +- asoc-platform-names: This property contains list of platform names. The order of + the platform names should match to that of the phandle order + given in "asoc-platform". +- asoc-cpu: This is phandle list containing the references to cpu dai device nodes + that are used as part of the sound card dai-links. +- asoc-cpu-names: This property contains list of cpu dai names. The order of the + cpu dai names should match to that of the phandle order given + in "asoc-cpu". The cpu names are in the form of "%s.%d" form, + where the id (%d) field represents the back-end AFE port id that + this CPU dai is associated with. +- asoc-codec: This is phandle list containing the references to codec dai device + nodes that are used as part of the sound card dai-links. +- asoc-codec-names: This property contains list of codec dai names. The order of the + codec dai names should match to that of the phandle order given + in "asoc-codec". +Optional properties: +- clock-names : clock name defined for external clock. +- clocks : external clock defined for codec clock. +- qcom,wsa-max-devs : Maximum number of WSA881x devices present in the target +- qcom,wsa-devs : List of phandles for all possible WSA881x devices supported for the target +- qcom,wsa-aux-dev-prefix : Name prefix with Left/Right configuration for WSA881x device +- qcom,wcn-btfm : Property to specify if WCN BT/FM chip is used for the target +- qcom,wsa_bolero_codec : Property to specify if WSA macro in Bolero codec is used for this target +- qcom,va_bolero_codec : Property to specify if VA macro in Bolero codec is used for this target +- qcom,tasha_codec : Property to specify if Tasha codec is used for this target +- qcom,cdc-dmic-gpios : phandle for Digital mic clk and data gpios. +Example: + + qcs405_snd { + compatible = "qcom,qcs405-asoc-snd"; + qcom,wsa_bolero_codec = <1>; + qcom,va_bolero_codec = <1>; + qcom,tasha_codec = <1>; + qcom,ext-disp-audio-rx = <1>; + qcom,wcn-btfm = <1>; + qcom,mi2s-audio-intf = <1>; + qcom,auxpcm-audio-intf = <1>; + qcom,msm-mi2s-master = <1>, <1>, <1>, <1>; + + qcom,audio-routing = + "MADINPUT", "MCLK", + "AMIC2", "MIC BIAS2", + "AMIC3", "MIC BIAS2", + "AMIC4", "MIC BIAS2", + "AMIC5", "MIC BIAS3", + "MIC BIAS3", "Handset Mic", + "DMIC0", "MIC BIAS1", + "MIC BIAS1", "Digital Mic0", + "DMIC1", "MIC BIAS1", + "MIC BIAS1", "Digital Mic1", + "DMIC2", "MIC BIAS3", + "MIC BIAS3", "Digital Mic2", + "DMIC3", "MIC BIAS3", + "MIC BIAS3", "Digital Mic3", + "DMIC4", "MIC BIAS4", + "MIC BIAS4", "Digital Mic4", + "DMIC5", "MIC BIAS4", + "MIC BIAS4", "Digital Mic5", + "SpkrLeft IN", "SPK1 OUT", + "SpkrRight IN", "SPK2 OUT"; + + asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>, + <&loopback>, <&compress>, <&hostless>, + <&afe>, <&lsm>, <&routing>, <&cpe>, <&compr>, + <&pcm_noirq>; + asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1", + "msm-pcm-dsp.2", "msm-voip-dsp", + "msm-pcm-voice", "msm-pcm-loopback", + "msm-compress-dsp", "msm-pcm-hostless", + "msm-pcm-afe", "msm-lsm-client", + "msm-pcm-routing", "msm-cpe-lsm", + "msm-compr-dsp", "msm-pcm-dsp-noirq"; + asoc-cpu = <&dai_hdmi>, <&dai_dp>, + <&dai_mi2s0>, <&dai_mi2s1>, + <&dai_mi2s2>, <&dai_mi2s3>, + <&dai_pri_auxpcm>, <&dai_sec_auxpcm>, + <&dai_tert_auxpcm>, <&dai_quat_auxpcm>, + <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, + <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>, + <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>, + <&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>, + <&afe_proxy_tx>, <&incall_record_rx>, + <&incall_record_tx>, <&incall_music_rx>, + <&incall_music_2_rx>, <&sb_5_rx>, <&sb_6_rx>, + <&sb_7_rx>, <&sb_7_tx>, <&sb_8_tx>, + <&usb_audio_rx>, <&usb_audio_tx>, + <&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>, + <&dai_sec_tdm_rx_0>, <&dai_sec_tdm_tx_0>, + <&dai_tert_tdm_rx_0>, <&dai_tert_tdm_tx_0>, + <&dai_quat_tdm_rx_0>, <&dai_quat_tdm_tx_0>, + <&wsa_cdc_dma_0_rx>, <&wsa_cdc_dma_0_tx>, + <&wsa_cdc_dma_1_rx>, <&wsa_cdc_dma_1_tx>, + <&wsa_cdc_dma_2_tx>, <&va_cdc_dma_0_tx>, + <&va_cdc_dma_1_tx>; + asoc-cpu-names = "msm-dai-q6-hdmi.8", "msm-dai-q6-dp.24608", + "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1", + "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", + "msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2", + "msm-dai-q6-auxpcm.3", "msm-dai-q6-auxpcm.4", + "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", + "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", + "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389", + "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", + "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393", + "msm-dai-q6-dev.16395", "msm-dai-q6-dev.224", + "msm-dai-q6-dev.225", "msm-dai-q6-dev.241", + "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771", + "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773", + "msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394", + "msm-dai-q6-dev.16396", "msm-dai-q6-dev.16398", + "msm-dai-q6-dev.16399", "msm-dai-q6-dev.16401", + "msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673", + "msm-dai-q6-tdm.36864", "msm-dai-q6-tdm.36865", + "msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881", + "msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897", + "msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913", + "msm-dai-q6-cdc-dma-dev.45056", + "msm-dai-q6-cdc-dma-dev.45057", + "msm-dai-q6-cdc-dma-dev.45058", + "msm-dai-q6-cdc-dma-dev.45059", + "msm-dai-q6-cdc-dma-dev.45061", + "msm-dai-q6-cdc-dma-dev.45089", + "msm-dai-q6-cdc-dma-dev.45091"; + asoc-codec = <&stub_codec>, <&ext_disp_audio_codec>, + <&bolero>;; + asoc-codec-names = "msm-stub-codec.1", + "msm-ext-disp-audio-codec-rx", + "bolero_codec"; + qcom,wsa-max-devs = <2>; + qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0212>, + <&wsa881x_0213>, <&wsa881x_0214>; + qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight", + "SpkrLeft", "SpkrRight"; + qcom,cdc-dmic-gpios = <&cdc_dmic12_gpios>, <&cdc_dmic34_gpios>, + <&cdc_dmic56_gpios>, <&cdc_dmic78_gpios>; + }; diff --git a/Documentation/devicetree/bindings/sound/wcd_codec.txt b/Documentation/devicetree/bindings/sound/wcd_codec.txt index 4cfe918dd17b..28556a1fb2cf 100644 --- a/Documentation/devicetree/bindings/sound/wcd_codec.txt +++ b/Documentation/devicetree/bindings/sound/wcd_codec.txt @@ -4,6 +4,7 @@ Required properties: - compatible : "qcom,pahu-slim-pgd" or "qcom,pahu-i2c" for pahu Codec "qcom,tavil-slim-pgd" or "qcom,tavil-i2c-pgd" for Tavil codec + "qcom,tasha-slim-pgd" or "qcom,tasha-i2c-pgd" for Tasha Codec - elemental-addr: codec slimbus slave PGD enumeration address.(48 bits) - qcom,cdc-reset-gpio: gpio used for codec SOC reset. @@ -439,3 +440,45 @@ msm_sdw_codec: qcom,msm-sdw-codec@152c1000 { }; }; }; + +WSA macro in Bolero codec + +Required properties: + - compatible = "qcom,wsa-macro"; + - reg: Specifies the WSA macro base address for Bolero + soundwire core registers. + - clock-names : clock names defined for WSA macro + - clocks : clock handles defined for WSA macro + +Example: + +&bolero { + wsa_macro: wsa-macro { + compatible = "qcom,wsa-macro"; + reg = <0x0C2C0000 0x0>; + clock-names = "wsa_core_clk", "wsa_npl_clk"; + clocks = <&clock_audio_wsa_1 AUDIO_LPASS_MCLK>, + <&clock_audio_wsa_2 AUDIO_LPASS_MCLK>; + qcom,wsa-swr-gpios = &wsa_swr_gpios; + }; +}; + +VA macro in bolero codec + +Required properties: + - compatible = "qcom,va-macro"; + - reg: Specifies the VA macro base address for Bolero + soundwire core registers. + - clock-names : clock names defined for WSA macro + - clocks : clock handles defined for WSA macro + +Example: + +&bolero { + va_macro: va-macro { + compatible = "qcom,va-macro"; + reg = <0x0C490000 0x0>; + clock-names = "va_core_clk"; + clocks = <&clock_audio_va AUDIO_LPASS_MCLK>; + }; +}; -- GitLab From 8524cb32b2eee5946612e5bc6843c91ec295a77e Mon Sep 17 00:00:00 2001 From: Srinivas Ramana Date: Wed, 20 Jun 2018 15:14:46 +0530 Subject: [PATCH 0468/1299] defconfig: msm: Create symlinks for sdmsteppe defconfigs Defconfigs are moved to vendor sub-directory. Create symlinks for sdmsteppe defconfigs as necessary for userspace components that are still hard-coded to the older location. Change-Id: I99242c894afbab6ceeebc04789cb54fc15931671 Signed-off-by: Srinivas Ramana --- arch/arm64/configs/sdmsteppe-perf_defconfig | 1 + arch/arm64/configs/sdmsteppe_defconfig | 1 + 2 files changed, 2 insertions(+) create mode 120000 arch/arm64/configs/sdmsteppe-perf_defconfig create mode 120000 arch/arm64/configs/sdmsteppe_defconfig diff --git a/arch/arm64/configs/sdmsteppe-perf_defconfig b/arch/arm64/configs/sdmsteppe-perf_defconfig new file mode 120000 index 000000000000..7b9298c42bcb --- /dev/null +++ b/arch/arm64/configs/sdmsteppe-perf_defconfig @@ -0,0 +1 @@ +vendor/sdmsteppe-perf_defconfig \ No newline at end of file diff --git a/arch/arm64/configs/sdmsteppe_defconfig b/arch/arm64/configs/sdmsteppe_defconfig new file mode 120000 index 000000000000..502031ffe286 --- /dev/null +++ b/arch/arm64/configs/sdmsteppe_defconfig @@ -0,0 +1 @@ +vendor/sdmsteppe_defconfig \ No newline at end of file -- GitLab From caa9dfd855a7fdc6dea3f0f7df006c05feef9074 Mon Sep 17 00:00:00 2001 From: Hardik Arya Date: Thu, 5 Apr 2018 13:05:04 +0530 Subject: [PATCH 0469/1299] diag: Validate peripheral received from user for switch logging Currently check is missing for peripheral sent by user for switch logging, due to this there is a possibility of out-of-bound read. The patch adds proper check for peripheral and protection before accessing global variable md_session_map. Change-Id: I165b9a7900cec20ca7970b37ca4823e2186fe27c Signed-off-by: Hardik Arya --- drivers/char/diag/diagchar_core.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 427dc84f2780..d49c822c5545 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -1721,8 +1721,8 @@ static void diag_switch_logging_clear_mask( static int diag_switch_logging(struct diag_logging_mode_param_t *param) { int new_mode, i = 0; - int curr_mode, err = 0; - uint8_t do_switch = 1, peripheral = 0; + int curr_mode, err = 0, peripheral = 0; + uint8_t do_switch = 1; uint32_t peripheral_mask = 0, pd_mask = 0; if (!param) @@ -1736,6 +1736,10 @@ static int diag_switch_logging(struct diag_logging_mode_param_t *param) if (param->pd_mask) { pd_mask = diag_translate_mask(param->pd_mask); + param->diag_id = 0; + param->pd_val = 0; + param->peripheral = -EINVAL; + for (i = UPD_WLAN; i < NUM_MD_SESSIONS; i++) { if (pd_mask & (1 << i)) { if (diag_search_diagid_by_pd(i, ¶m->diag_id, @@ -1745,6 +1749,12 @@ static int diag_switch_logging(struct diag_logging_mode_param_t *param) } } } + + DIAG_LOG(DIAG_DEBUG_USERSPACE, + "diag: pd_mask = %d, diag_id = %d, peripheral = %d, pd_val = %d\n", + param->pd_mask, param->diag_id, + param->peripheral, param->pd_val); + if (!param->diag_id || (param->pd_val < UPD_WLAN) || (param->pd_val >= NUM_MD_SESSIONS)) { @@ -1754,22 +1764,26 @@ static int diag_switch_logging(struct diag_logging_mode_param_t *param) return -EINVAL; } - DIAG_LOG(DIAG_DEBUG_USERSPACE, - "diag: pd_mask = %d, diag_id = %d, peripheral = %d, pd_val = %d\n", - param->pd_mask, param->diag_id, - param->peripheral, param->pd_val); - peripheral = param->peripheral; + if ((peripheral < PERIPHERAL_MODEM) || + (peripheral >= NUM_PERIPHERALS)) { + DIAG_LOG(DIAG_DEBUG_USERSPACE, + "Invalid peripheral: %d\n", peripheral); + return -EINVAL; + } i = param->pd_val - UPD_WLAN; + mutex_lock(&driver->md_session_lock); if (driver->md_session_map[peripheral] && (MD_PERIPHERAL_MASK(peripheral) & diag_mux->mux_mask) && !driver->pd_session_clear[i]) { DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag_fr: User PD is already logging onto active peripheral logging\n"); + mutex_unlock(&driver->md_session_lock); driver->pd_session_clear[i] = 0; return -EINVAL; } + mutex_unlock(&driver->md_session_lock); peripheral_mask = diag_translate_mask(param->pd_mask); param->peripheral_mask = peripheral_mask; -- GitLab From 2ac92fbde453327e5a9d92cf0b68875fe8874af5 Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Wed, 20 Jun 2018 12:43:58 +0530 Subject: [PATCH 0470/1299] drivers: qcom: rpm-smd: Remove glink and smd based rpm-smd support Newer kernel uses rpmsg framework for communication to RPM. Modify rpm-smd driver accordigly to use rpmsg framework. Remove support for glink and smd. Change-Id: I3c030aaef4ea33447802e68f67088ddb51337cbc Signed-off-by: Raghavendra Kakarla --- .../devicetree/bindings/arm/msm/rpm-smd.txt | 12 +- drivers/rpmsg/Kconfig | 9 + drivers/rpmsg/Makefile | 1 + drivers/{soc/qcom => rpmsg}/rpm-smd.c | 892 ++++-------------- drivers/soc/qcom/Kconfig | 8 - drivers/soc/qcom/Makefile | 1 - include/soc/qcom/rpm-smd.h | 183 ---- 7 files changed, 205 insertions(+), 901 deletions(-) rename drivers/{soc/qcom => rpmsg}/rpm-smd.c (68%) diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-smd.txt b/Documentation/devicetree/bindings/arm/msm/rpm-smd.txt index 4cba3ecaeb90..5c5aa5143013 100644 --- a/Documentation/devicetree/bindings/arm/msm/rpm-smd.txt +++ b/Documentation/devicetree/bindings/arm/msm/rpm-smd.txt @@ -10,18 +10,18 @@ the application processor, the modem processor, as well as hardware accelerators. The RPM driver communicates with the hardware engine using SMD. -The devicetree representation of the SPM block should be: +The devicetree representation of the RPM block should be: Required properties -- compatible: "qcom,rpm-smd" or "qcom,rpm-glink" +- compatible: "qcom,rpm-smd" - rpm-channel-name: The string corresponding to the channel name of the peripheral subsystem. Required for both smd and glink transports. - rpm-channel-type: The interal SMD edge for this subsystem found in -- qcom,glink-edge: Logical name of the remote subsystem. This is a required - property when rpm-smd driver using glink as trasport. +- interrupts: The IRQ used by remote processor to inform APSS about + reception of response message packet. Optional properties - rpm-standalone: Allow RPM driver to run in standalone mode irrespective of RPM @@ -32,10 +32,10 @@ Optional properties Example: qcom,rpm-smd@68150 { - compatible = "qcom,rpm-smd", "qcom,rpm-glink"; + compatible = "qcom,rpm-smd"; reg = <0x68150 0x3200>; + interrupts = ; qcom,rpm-channel-name = "rpm_requests"; qcom,rpm-channel-type = 15; /* SMD_APPS_RPM */ - qcom,glink-edge = "rpm"; } } diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index a3b621d37ff5..299dbc6f3e67 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig @@ -73,4 +73,13 @@ config RPMSG_VIRTIO select RPMSG select VIRTIO +config MSM_RPM_SMD + bool "RPM driver using SMD protocol" + help + RPM is the dedicated hardware engine for managing shared SoC + resources. This config adds driver support for using SMD as a + transport layer communication with RPM hardware. It also selects + the MSM_MPM config that programs the MPM module to monitor interrupts + during sleep modes. + endmenu diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile index 1680763bb8b5..131052abeaf5 100644 --- a/drivers/rpmsg/Makefile +++ b/drivers/rpmsg/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_RPMSG_QCOM_GLINK_SPSS) += qcom_glink_spss.o obj-$(CONFIG_RPMSG_QCOM_GLINK_SPI) += qcom_glink_spi.o obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o +obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o diff --git a/drivers/soc/qcom/rpm-smd.c b/drivers/rpmsg/rpm-smd.c similarity index 68% rename from drivers/soc/qcom/rpm-smd.c rename to drivers/rpmsg/rpm-smd.c index c04916cfbd77..65f2fbb9d4fc 100644 --- a/drivers/soc/qcom/rpm-smd.c +++ b/drivers/rpmsg/rpm-smd.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -34,53 +34,19 @@ #include #include #include +#include #include #include #include #include +#include #define CREATE_TRACE_POINTS #include -/* Debug Definitions */ -enum { - MSM_RPM_LOG_REQUEST_PRETTY = BIT(0), - MSM_RPM_LOG_REQUEST_RAW = BIT(1), - MSM_RPM_LOG_REQUEST_SHOW_MSG_ID = BIT(2), -}; - -static int msm_rpm_debug_mask; -module_param_named( - debug_mask, msm_rpm_debug_mask, int, 0644 -); - -struct msm_rpm_driver_data { - const char *ch_name; - uint32_t ch_type; - struct smd_channel *ch_info; - struct work_struct work; - spinlock_t smd_lock_write; - spinlock_t smd_lock_read; - struct completion smd_open; -}; - -struct glink_apps_rpm_data { - const char *name; - const char *edge; - const char *xprt; - void *glink_handle; - struct glink_link_info *link_info; - struct glink_open_config *open_cfg; - struct work_struct work; -}; - -static bool glink_enabled; -static struct glink_apps_rpm_data *glink_data; - #define DEFAULT_BUFFER_SIZE 256 #define DEBUG_PRINT_BUFFER_SIZE 512 #define MAX_SLEEP_BUFFER 128 -#define GFP_FLAG(noirq) (noirq ? GFP_ATOMIC : GFP_NOIO) #define INV_RSC "resource does not exist" #define ERR "err\0" #define MAX_ERR_BUFFER_SIZE 128 @@ -107,10 +73,55 @@ static struct glink_apps_rpm_data *glink_data; sizeof(struct rpm_v0_hdr) : sizeof(struct rpm_v1_hdr)) #define CLEAR_FIELD(offset, size) (~GENMASK(offset + size - 1, offset)) +#define for_each_kvp(buf, k) \ + for (k = (struct kvp *)get_first_kvp(buf); \ + ((void *)k - (void *)get_first_kvp(buf)) < \ + get_data_len(buf);\ + k = get_next_kvp(k)) + + +/* Debug Definitions */ +enum { + MSM_RPM_LOG_REQUEST_PRETTY = BIT(0), + MSM_RPM_LOG_REQUEST_RAW = BIT(1), + MSM_RPM_LOG_REQUEST_SHOW_MSG_ID = BIT(2), +}; + +static int msm_rpm_debug_mask; +module_param_named( + debug_mask, msm_rpm_debug_mask, int, 0644 +); + +static uint32_t rpm_msg_fmt_ver; +module_param_named( + rpm_msg_fmt_ver, rpm_msg_fmt_ver, uint, 0444 +); + +struct msm_rpm_driver_data { + const char *ch_name; + uint32_t ch_type; + struct smd_channel *ch_info; + struct work_struct work; + spinlock_t smd_lock_write; + spinlock_t smd_lock_read; + struct completion smd_open; +}; + +struct qcom_smd_rpm { + struct rpmsg_endpoint *rpm_channel; + struct device *dev; + int irq; + struct completion ack; + struct mutex lock; + int ack_status; +}; + +struct qcom_smd_rpm *rpm; +struct qcom_smd_rpm priv_rpm; + static ATOMIC_NOTIFIER_HEAD(msm_rpm_sleep_notifier); static bool standalone; static int probe_status = -EPROBE_DEFER; -static int msm_rpm_read_smd_data(char *buf); static void msm_rpm_process_ack(uint32_t msg_id, int errno); int msm_rpm_register_notifier(struct notifier_block *nb) @@ -123,8 +134,6 @@ int msm_rpm_unregister_notifier(struct notifier_block *nb) return atomic_notifier_chain_unregister(&msm_rpm_sleep_notifier, nb); } -static struct workqueue_struct *msm_rpm_smd_wq; - enum { MSM_RPM_MSG_REQUEST_TYPE = 0, MSM_RPM_MSG_TYPE_NR, @@ -204,15 +213,8 @@ enum rpm_msg_fmts { RPM_MSG_V1_FMT }; -static uint32_t rpm_msg_fmt_ver; -module_param_named( - rpm_msg_fmt_ver, rpm_msg_fmt_ver, uint, 0444 -); - static struct rb_root tr_root = RB_ROOT; -static int (*msm_rpm_send_buffer)(char *buf, uint32_t size, bool noirq); -static int msm_rpm_send_smd_buffer(char *buf, uint32_t size, bool noirq); -static int msm_rpm_glink_send_buffer(char *buf, uint32_t size, bool noirq); +static int msm_rpm_send_smd_buffer(char *buf, uint32_t size); static uint32_t msm_rpm_get_next_msg_id(void); static inline uint32_t get_offset_value(uint32_t val, uint32_t offset, @@ -242,6 +244,7 @@ static inline void set_offset_value(uint32_t *val, uint32_t offset, *val &= CLEAR_FIELD(offset, size); *val |= ((val1 & mask) << offset); } + static uint32_t get_msg_id(char *buf) { if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) @@ -344,9 +347,9 @@ static void set_msg_ver(char *buf, uint32_t val) static void set_req_len(char *buf, uint32_t val) { - if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) { + if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) ((struct rpm_message_header_v0 *)buf)->hdr.request_len = val; - } else { + else { set_offset_value(&((struct rpm_message_header_v1 *)buf)-> hdr.request_hdr, RPM_REQ_LEN_OFFSET, RPM_REQ_LEN_SIZE, val); @@ -355,9 +358,9 @@ static void set_req_len(char *buf, uint32_t val) static void change_req_len(char *buf, int32_t val) { - if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) { + if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) ((struct rpm_message_header_v0 *)buf)->hdr.request_len += val; - } else { + else { change_offset_value(&((struct rpm_message_header_v1 *)buf)-> hdr.request_hdr, RPM_REQ_LEN_OFFSET, RPM_REQ_LEN_SIZE, val); @@ -366,10 +369,10 @@ static void change_req_len(char *buf, int32_t val) static void set_msg_type(char *buf, uint32_t val) { - if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) { + if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) ((struct rpm_message_header_v0 *)buf)->hdr.service_type = msm_rpm_request_service_v1[val]; - } else { + else { set_offset_value(&((struct rpm_message_header_v1 *)buf)-> hdr.request_hdr, RPM_MSG_TYPE_OFFSET, RPM_MSG_TYPE_SIZE, RPM_V1_REQUEST_SERVICE); @@ -414,6 +417,7 @@ static void set_set_type(char *buf, uint32_t val) request_details, RPM_SET_TYPE_OFFSET, RPM_SET_TYPE_SIZE, val); } + static void set_msg_id(char *buf, uint32_t val) { if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) @@ -456,7 +460,6 @@ static inline void *get_data(struct kvp *k) return (void *)k + sizeof(*k); } - static void delete_kvp(char *buf, struct kvp *d) { struct kvp *n; @@ -550,13 +553,6 @@ static int tr_insert(struct rb_root *root, struct slp_buf *slp) return 0; } -#define for_each_kvp(buf, k) \ - for (k = (struct kvp *)get_first_kvp(buf); \ - ((void *)k - (void *)get_first_kvp(buf)) < \ - get_data_len(buf);\ - k = get_next_kvp(k)) - - static void tr_update(struct slp_buf *s, char *buf) { struct kvp *e, *n; @@ -615,14 +611,10 @@ struct msm_rpm_wait_data { struct completion ack; bool delete_on_ack; }; -DEFINE_SPINLOCK(msm_rpm_list_lock); - - +DEFINE_SPINLOCK(msm_rpm_list_lock); LIST_HEAD(msm_rpm_ack_list); -static struct tasklet_struct data_tasklet; - static inline uint32_t msm_rpm_get_msg_id_from_ack(uint8_t *buf) { return get_ack_msg_id(buf); @@ -718,46 +710,6 @@ static struct msm_rpm_driver_data msm_rpm_data = { .smd_open = COMPLETION_INITIALIZER(msm_rpm_data.smd_open), }; -static int msm_rpm_glink_rx_poll(void *glink_handle) -{ - int ret; - - ret = glink_rpm_rx_poll(glink_handle); - if (ret >= 0) - /* - * Sleep for 50us at a time before checking - * for packet availability. The 50us is based - * on the the time rpm could take to process - * and send an ack for the sleep set request. - */ - udelay(50); - else - pr_err("Not receieve an ACK from RPM. ret = %d\n", ret); - - return ret; -} - -/* - * Returns - * = 0 on successful reads - * > 0 on successful reads with no further data - * standard Linux error codes on failure. - */ -static int msm_rpm_read_sleep_ack(void) -{ - int ret; - char buf[MAX_ERR_BUFFER_SIZE] = {0}; - - if (glink_enabled) - ret = msm_rpm_glink_rx_poll(glink_data->glink_handle); - else { - ret = msm_rpm_read_smd_data(buf); - if (!ret) - ret = smd_is_pkt_avail(msm_rpm_data.ch_info); - } - return ret; -} - static int msm_rpm_flush_requests(bool print) { struct rb_node *t; @@ -775,14 +727,9 @@ static int msm_rpm_flush_requests(bool print) set_msg_id(s->buf, msm_rpm_get_next_msg_id()); - if (!glink_enabled) - ret = msm_rpm_send_smd_buffer(s->buf, - get_buf_len(s->buf), true); - else - ret = msm_rpm_glink_send_buffer(s->buf, - get_buf_len(s->buf), true); - - WARN_ON(ret != get_buf_len(s->buf)); + ret = msm_rpm_send_smd_buffer(s->buf, + get_buf_len(s->buf)); + WARN_ON(ret != 0); trace_rpm_smd_send_sleep_set(get_msg_id(s->buf), type, id); s->valid = false; @@ -796,12 +743,9 @@ static int msm_rpm_flush_requests(bool print) * process these sleep set acks. */ if (count >= MAX_WAIT_ON_ACK) { - int ret = msm_rpm_read_sleep_ack(); - - if (ret >= 0) - count--; - else - return ret; + pr_err("Error: more than %d requests are buffered\n", + MAX_WAIT_ON_ACK); + return -ENOSPC; } } return 0; @@ -821,7 +765,7 @@ static void msm_rpm_notify_sleep_chain(char *buf, } static int msm_rpm_add_kvp_data_common(struct msm_rpm_request *handle, - uint32_t key, const uint8_t *data, int size, bool noirq) + uint32_t key, const uint8_t *data, int size) { uint32_t i; uint32_t data_size, msg_size; @@ -862,12 +806,13 @@ static int msm_rpm_add_kvp_data_common(struct msm_rpm_request *handle, handle->write_idx++; if (!handle->kvp[i].value) { - handle->kvp[i].value = kzalloc(data_size, GFP_FLAG(noirq)); + handle->kvp[i].value = kzalloc(data_size, GFP_NOIO); if (!handle->kvp[i].value) return -ENOMEM; } else { - /* We enter the else case, if a key already exists but the + /* + * We enter the else case, if a key already exists but the * data doesn't match. In which case, we should zero the data * out. */ @@ -891,7 +836,7 @@ static int msm_rpm_add_kvp_data_common(struct msm_rpm_request *handle, static struct msm_rpm_request *msm_rpm_create_request_common( enum msm_rpm_set set, uint32_t rsc_type, uint32_t rsc_id, - int num_elements, bool noirq) + int num_elements) { struct msm_rpm_request *cdata; uint32_t buf_size; @@ -899,20 +844,17 @@ static struct msm_rpm_request *msm_rpm_create_request_common( if (probe_status) return ERR_PTR(probe_status); - cdata = kzalloc(sizeof(struct msm_rpm_request), - GFP_FLAG(noirq)); + cdata = kzalloc(sizeof(struct msm_rpm_request), GFP_NOIO); - if (!cdata) { - pr_err("Cannot allocate memory for client data\n"); + if (!cdata) goto cdata_alloc_fail; - } if (rpm_msg_fmt_ver == RPM_MSG_V0_FMT) buf_size = sizeof(struct rpm_message_header_v0); else buf_size = sizeof(struct rpm_message_header_v1); - cdata->client_buf = kzalloc(buf_size, GFP_FLAG(noirq)); + cdata->client_buf = kzalloc(buf_size, GFP_NOIO); if (!cdata->client_buf) goto client_buf_alloc_fail; @@ -925,7 +867,7 @@ static struct msm_rpm_request *msm_rpm_create_request_common( cdata->write_idx = 0; cdata->kvp = kcalloc(num_elements, sizeof(struct msm_rpm_kvp_data), - GFP_FLAG(noirq)); + GFP_NOIO); if (!cdata->kvp) { pr_warn("%s(): Cannot allocate memory for key value data\n", @@ -933,7 +875,7 @@ static struct msm_rpm_request *msm_rpm_create_request_common( goto kvp_alloc_fail; } - cdata->buf = kzalloc(DEFAULT_BUFFER_SIZE, GFP_FLAG(noirq)); + cdata->buf = kzalloc(DEFAULT_BUFFER_SIZE, GFP_NOIO); if (!cdata->buf) goto buf_alloc_fail; @@ -972,23 +914,14 @@ struct msm_rpm_request *msm_rpm_create_request( uint32_t rsc_id, int num_elements) { return msm_rpm_create_request_common(set, rsc_type, rsc_id, - num_elements, false); + num_elements); } EXPORT_SYMBOL(msm_rpm_create_request); -struct msm_rpm_request *msm_rpm_create_request_noirq( - enum msm_rpm_set set, uint32_t rsc_type, - uint32_t rsc_id, int num_elements) -{ - return msm_rpm_create_request_common(set, rsc_type, rsc_id, - num_elements, true); -} -EXPORT_SYMBOL(msm_rpm_create_request_noirq); - int msm_rpm_add_kvp_data(struct msm_rpm_request *handle, uint32_t key, const uint8_t *data, int size) { - return msm_rpm_add_kvp_data_common(handle, key, data, size, false); + return msm_rpm_add_kvp_data_common(handle, key, data, size); } EXPORT_SYMBOL(msm_rpm_add_kvp_data); @@ -996,37 +929,10 @@ EXPORT_SYMBOL(msm_rpm_add_kvp_data); int msm_rpm_add_kvp_data_noirq(struct msm_rpm_request *handle, uint32_t key, const uint8_t *data, int size) { - return msm_rpm_add_kvp_data_common(handle, key, data, size, true); -} -EXPORT_SYMBOL(msm_rpm_add_kvp_data_noirq); - -/* Runs in interrupt context */ -static void msm_rpm_notify(void *data, unsigned int event) -{ - struct msm_rpm_driver_data *pdata = (struct msm_rpm_driver_data *)data; - - WARN_ON(!pdata); - - if (!(pdata->ch_info)) - return; - - switch (event) { - case SMD_EVENT_DATA: - tasklet_schedule(&data_tasklet); - trace_rpm_smd_interrupt_notify("interrupt notification"); - break; - case SMD_EVENT_OPEN: - complete(&pdata->smd_open); - break; - case SMD_EVENT_CLOSE: - case SMD_EVENT_STATUS: - case SMD_EVENT_REOPEN_READY: - break; - default: - pr_info("Unknown SMD event\n"); + return msm_rpm_add_kvp_data_common(handle, key, data, size); - } } +EXPORT_SYMBOL(msm_rpm_add_kvp_data_noirq); bool msm_rpm_waiting_for_ack(void) { @@ -1054,6 +960,7 @@ static struct msm_rpm_wait_data *msm_rpm_get_entry_from_msg_id(uint32_t msg_id) break; elem = NULL; } + spin_unlock_irqrestore(&msm_rpm_list_lock, flags); return elem; } @@ -1131,10 +1038,12 @@ static void msm_rpm_process_ack(uint32_t msg_id, int errno) break; } } - /* Special case where the sleep driver doesn't + /* + * Special case where the sleep driver doesn't * wait for ACKs. This would decrease the latency involved with * entering RPM assisted power collapse. */ + if (!elem) trace_rpm_smd_ack_recvd(0, msg_id, 0xDEADBEEF); @@ -1147,62 +1056,6 @@ struct msm_rpm_kvp_packet { uint32_t val; }; -static int msm_rpm_read_smd_data(char *buf) -{ - int pkt_sz; - int bytes_read = 0; - - pkt_sz = smd_cur_packet_size(msm_rpm_data.ch_info); - - if (!pkt_sz) - return -EAGAIN; - - if (pkt_sz > MAX_ERR_BUFFER_SIZE) { - pr_err("rpm_smd pkt_sz is greater than max size\n"); - goto error; - } - - if (pkt_sz != smd_read_avail(msm_rpm_data.ch_info)) - return -EAGAIN; - - do { - int len; - - len = smd_read(msm_rpm_data.ch_info, buf + bytes_read, pkt_sz); - pkt_sz -= len; - bytes_read += len; - - } while (pkt_sz > 0); - - if (pkt_sz < 0) { - pr_err("rpm_smd pkt_sz is less than zero\n"); - goto error; - } - return 0; -error: - WARN_ON(1); - - return 0; -} - -static void data_fn_tasklet(unsigned long data) -{ - uint32_t msg_id; - int errno; - char buf[MAX_ERR_BUFFER_SIZE] = {0}; - - spin_lock(&msm_rpm_data.smd_lock_read); - while (smd_is_pkt_avail(msm_rpm_data.ch_info)) { - if (msm_rpm_read_smd_data(buf)) - break; - msg_id = msm_rpm_get_msg_id_from_ack(buf); - errno = msm_rpm_get_error_from_ack(buf); - trace_rpm_smd_ack_recvd(0, msg_id, errno); - msm_rpm_process_ack(msg_id, errno); - } - spin_unlock(&msm_rpm_data.smd_lock_read); -} - static void msm_rpm_log_request(struct msm_rpm_request *cdata) { char buf[DEBUG_PRINT_BUFFER_SIZE]; @@ -1337,74 +1190,19 @@ static void msm_rpm_log_request(struct msm_rpm_request *cdata) printk(buf); } -static int msm_rpm_send_smd_buffer(char *buf, uint32_t size, bool noirq) +static int msm_rpm_send_smd_buffer(char *buf, uint32_t size) { unsigned long flags; int ret; spin_lock_irqsave(&msm_rpm_data.smd_lock_write, flags); - ret = smd_write_avail(msm_rpm_data.ch_info); - - while ((ret = smd_write_avail(msm_rpm_data.ch_info)) < size) { - if (ret < 0) - break; - if (!noirq) { - spin_unlock_irqrestore( - &msm_rpm_data.smd_lock_write, flags); - cpu_relax(); - spin_lock_irqsave( - &msm_rpm_data.smd_lock_write, flags); - } else - udelay(5); - } - - if (ret < 0) { - pr_err("SMD not initialized\n"); - spin_unlock_irqrestore( - &msm_rpm_data.smd_lock_write, flags); - return ret; - } - - ret = smd_write(msm_rpm_data.ch_info, buf, size); + ret = rpmsg_send(rpm->rpm_channel, buf, size); spin_unlock_irqrestore(&msm_rpm_data.smd_lock_write, flags); return ret; } -static int msm_rpm_glink_send_buffer(char *buf, uint32_t size, bool noirq) -{ - int ret; - unsigned long flags; - int timeout = 50; - - spin_lock_irqsave(&msm_rpm_data.smd_lock_write, flags); - do { - ret = glink_tx(glink_data->glink_handle, buf, buf, - size, GLINK_TX_SINGLE_THREADED); - if (ret == -EBUSY || ret == -ENOSPC) { - if (!noirq) { - spin_unlock_irqrestore( - &msm_rpm_data.smd_lock_write, flags); - cpu_relax(); - spin_lock_irqsave( - &msm_rpm_data.smd_lock_write, flags); - } else { - udelay(5); - } - timeout--; - } else { - ret = 0; - } - } while (ret && timeout); - spin_unlock_irqrestore(&msm_rpm_data.smd_lock_write, flags); - - if (!timeout) - return 0; - else - return size; -} - static int msm_rpm_send_data(struct msm_rpm_request *cdata, - int msg_type, bool noirq, bool noack) + int msg_type, bool noack) { uint8_t *tmpbuff; int ret; @@ -1415,11 +1213,14 @@ static int msm_rpm_send_data(struct msm_rpm_request *cdata, uint32_t set = get_set_type(cdata->client_buf); uint32_t msg_id; - if (probe_status) + if (probe_status) { + pr_err("probe failed\n"); return probe_status; - - if (!data_len) + } + if (!data_len) { + pr_err("no data len\n"); return 1; + } msg_hdr_sz = rpm_msg_fmt_ver ? sizeof(struct rpm_message_header_v1) : sizeof(struct rpm_message_header_v0); @@ -1434,7 +1235,7 @@ static int msm_rpm_send_data(struct msm_rpm_request *cdata, if (msg_size > cdata->numbytes) { kfree(cdata->buf); cdata->numbytes = msg_size; - cdata->buf = kzalloc(msg_size, GFP_FLAG(noirq)); + cdata->buf = kzalloc(msg_size, GFP_NOIO); } if (!cdata->buf) { @@ -1469,9 +1270,9 @@ static int msm_rpm_send_data(struct msm_rpm_request *cdata, memcpy(cdata->buf, cdata->client_buf, msg_hdr_sz); if ((set == MSM_RPM_CTX_SLEEP_SET) && - !msm_rpm_smd_buffer_request(cdata, msg_size, - GFP_FLAG(noirq))) + !msm_rpm_smd_buffer_request(cdata, msg_size, GFP_NOIO)) { return 1; + } msg_id = msm_rpm_get_next_msg_id(); /* Set the version bit for new protocol */ @@ -1494,9 +1295,9 @@ static int msm_rpm_send_data(struct msm_rpm_request *cdata, msm_rpm_add_wait_list(msg_id, noack); - ret = msm_rpm_send_buffer(&cdata->buf[0], msg_size, noirq); + ret = msm_rpm_send_smd_buffer(&cdata->buf[0], msg_size); - if (ret == msg_size) { + if (!ret) { for (i = 0; (i < cdata->write_idx); i++) cdata->kvp[i].valid = false; set_data_len(cdata->client_buf, 0); @@ -1504,7 +1305,7 @@ static int msm_rpm_send_data(struct msm_rpm_request *cdata, trace_rpm_smd_send_active_set(msg_id, get_rsc_type(cdata->client_buf), get_rsc_id(cdata->client_buf)); - } else if (ret < msg_size) { + } else if (ret < 0) { struct msm_rpm_wait_data *rc; ret = 0; @@ -1523,23 +1324,23 @@ static int _msm_rpm_send_request(struct msm_rpm_request *handle, bool noack) static DEFINE_MUTEX(send_mtx); mutex_lock(&send_mtx); - ret = msm_rpm_send_data(handle, MSM_RPM_MSG_REQUEST_TYPE, false, noack); + ret = msm_rpm_send_data(handle, MSM_RPM_MSG_REQUEST_TYPE, noack); mutex_unlock(&send_mtx); return ret; } -int msm_rpm_send_request(struct msm_rpm_request *handle) +int msm_rpm_send_request_noirq(struct msm_rpm_request *handle) { return _msm_rpm_send_request(handle, false); } -EXPORT_SYMBOL(msm_rpm_send_request); +EXPORT_SYMBOL(msm_rpm_send_request_noirq); -int msm_rpm_send_request_noirq(struct msm_rpm_request *handle) +int msm_rpm_send_request(struct msm_rpm_request *handle) { - return msm_rpm_send_data(handle, MSM_RPM_MSG_REQUEST_TYPE, true, false); + return _msm_rpm_send_request(handle, false); } -EXPORT_SYMBOL(msm_rpm_send_request_noirq); +EXPORT_SYMBOL(msm_rpm_send_request); void *msm_rpm_send_request_noack(struct msm_rpm_request *handle) { @@ -1581,94 +1382,9 @@ int msm_rpm_wait_for_ack(uint32_t msg_id) } EXPORT_SYMBOL(msm_rpm_wait_for_ack); -static void msm_rpm_smd_read_data_noirq(uint32_t msg_id) -{ - uint32_t id = 0; - - while (id != msg_id) { - if (smd_is_pkt_avail(msm_rpm_data.ch_info)) { - int errno; - char buf[MAX_ERR_BUFFER_SIZE] = {}; - - msm_rpm_read_smd_data(buf); - id = msm_rpm_get_msg_id_from_ack(buf); - errno = msm_rpm_get_error_from_ack(buf); - trace_rpm_smd_ack_recvd(1, msg_id, errno); - msm_rpm_process_ack(id, errno); - } - } -} - -static void msm_rpm_glink_read_data_noirq(struct msm_rpm_wait_data *elem) -{ - int ret; - - /* Use rx_poll method to read the message from RPM */ - while (elem->errno) { - ret = glink_rpm_rx_poll(glink_data->glink_handle); - if (ret >= 0) { - /* - * We might have receieve the notification. - * Now we have to check whether the notification - * received is what we are interested? - * Wait for few usec to get the notification - * before re-trying the poll again. - */ - udelay(50); - } else { - pr_err("rx poll return error = %d\n", ret); - } - } -} - int msm_rpm_wait_for_ack_noirq(uint32_t msg_id) { - struct msm_rpm_wait_data *elem; - unsigned long flags; - int rc = 0; - - if (!msg_id) { - pr_err("Invalid msg id\n"); - return -ENOMEM; - } - - if (msg_id == 1) - return 0; - - if (standalone) - return 0; - - spin_lock_irqsave(&msm_rpm_data.smd_lock_read, flags); - - elem = msm_rpm_get_entry_from_msg_id(msg_id); - - if (!elem) - /* Should this be a bug - * Is it ok for another thread to read the msg? - */ - goto wait_ack_cleanup; - - if (elem->errno != INIT_ERROR) { - rc = elem->errno; - msm_rpm_free_list_entry(elem); - goto wait_ack_cleanup; - } - - if (!glink_enabled) - msm_rpm_smd_read_data_noirq(msg_id); - else - msm_rpm_glink_read_data_noirq(elem); - - rc = elem->errno; - - msm_rpm_free_list_entry(elem); -wait_ack_cleanup: - spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read, flags); - - if (!glink_enabled) - if (smd_is_pkt_avail(msm_rpm_data.ch_info)) - tasklet_schedule(&data_tasklet); - return rc; + return msm_rpm_wait_for_ack(msg_id); } EXPORT_SYMBOL(msm_rpm_wait_for_ack_noirq); @@ -1677,8 +1393,7 @@ void *msm_rpm_send_message_noack(enum msm_rpm_set set, uint32_t rsc_type, { int i, rc; struct msm_rpm_request *req = - msm_rpm_create_request_common(set, rsc_type, rsc_id, nelems, - false); + msm_rpm_create_request_common(set, rsc_type, rsc_id, nelems); if (IS_ERR(req)) return req; @@ -1728,31 +1443,37 @@ int msm_rpm_send_message(enum msm_rpm_set set, uint32_t rsc_type, EXPORT_SYMBOL(msm_rpm_send_message); int msm_rpm_send_message_noirq(enum msm_rpm_set set, uint32_t rsc_type, - uint32_t rsc_id, struct msm_rpm_kvp *kvp, int nelems) + uint32_t rsc_id, struct msm_rpm_kvp *kvp, int nelems) { - int i, rc; - struct msm_rpm_request *req = - msm_rpm_create_request_noirq(set, rsc_type, rsc_id, nelems); - if (IS_ERR(req)) - return PTR_ERR(req); + return msm_rpm_send_message(set, rsc_type, rsc_id, kvp, nelems); +} +EXPORT_SYMBOL(msm_rpm_send_message_noirq); - if (!req) - return -ENOMEM; +static int smd_mask_receive_interrupt(bool mask, + const struct cpumask *cpumask) +{ + struct irq_chip *irq_chip; + struct irq_data *irq_data; - for (i = 0; i < nelems; i++) { - rc = msm_rpm_add_kvp_data_noirq(req, kvp[i].key, - kvp[i].data, kvp[i].length); - if (rc) - goto bail; + irq_data = irq_get_irq_data(rpm->irq); + if (!irq_data) + return -ENODEV; + + irq_chip = irq_data->chip; + if (!irq_chip) + return -ENODEV; + + if (mask) { + irq_chip->irq_mask(irq_data); + if (cpumask) + irq_set_affinity(rpm->irq, cpumask); + } else { + irq_chip->irq_unmask(irq_data); } - rc = msm_rpm_wait_for_ack_noirq(msm_rpm_send_request_noirq(req)); -bail: - msm_rpm_free_request(req); - return rc; + return 0; } -EXPORT_SYMBOL(msm_rpm_send_message_noirq); /** * During power collapse, the rpm driver disables the SMD interrupts to make @@ -1765,24 +1486,12 @@ int msm_rpm_enter_sleep(bool print, const struct cpumask *cpumask) if (standalone) return 0; - if (!glink_enabled) - ret = smd_mask_receive_interrupt(msm_rpm_data.ch_info, - true, cpumask); - else - ret = glink_rpm_mask_rx_interrupt(glink_data->glink_handle, - true, (void *)cpumask); + ret = smd_mask_receive_interrupt(true, cpumask); if (!ret) { ret = msm_rpm_flush_requests(print); - - if (ret) { - if (!glink_enabled) - smd_mask_receive_interrupt( - msm_rpm_data.ch_info, false, NULL); - else - glink_rpm_mask_rx_interrupt( - glink_data->glink_handle, false, NULL); - } + if (ret) + smd_mask_receive_interrupt(false, NULL); } return ret; } @@ -1794,29 +1503,16 @@ EXPORT_SYMBOL(msm_rpm_enter_sleep); */ void msm_rpm_exit_sleep(void) { - int ret; if (standalone) return; - do { - ret = msm_rpm_read_sleep_ack(); - } while (ret > 0); - - if (!glink_enabled) - smd_mask_receive_interrupt(msm_rpm_data.ch_info, false, NULL); - else - glink_rpm_mask_rx_interrupt(glink_data->glink_handle, - false, NULL); + smd_mask_receive_interrupt(false, NULL); } EXPORT_SYMBOL(msm_rpm_exit_sleep); -/* - * Whenever there is a data from RPM, notify_rx will be called. - * This function is invoked either interrupt OR polling context. - */ -static void msm_rpm_trans_notify_rx(void *handle, const void *priv, - const void *pkt_priv, const void *ptr, size_t size) +static int qcom_smd_rpm_callback(struct rpmsg_device *rpdev, void *ptr, + int size, void *priv, u32 addr) { uint32_t msg_id; int errno; @@ -1826,7 +1522,7 @@ static void msm_rpm_trans_notify_rx(void *handle, const void *priv, unsigned long flags; if (!size) - return; + return -EINVAL; WARN_ON(size > MAX_ERR_BUFFER_SIZE); @@ -1844,219 +1540,39 @@ static void msm_rpm_trans_notify_rx(void *handle, const void *priv, */ if (!elem) { spin_unlock_irqrestore(&rx_notify_lock, flags); - glink_rx_done(handle, ptr, 0); - return; + return 0; } msm_rpm_process_ack(msg_id, errno); spin_unlock_irqrestore(&rx_notify_lock, flags); - glink_rx_done(handle, ptr, 0); -} - -static void msm_rpm_trans_notify_state(void *handle, const void *priv, - unsigned int event) -{ - switch (event) { - case GLINK_CONNECTED: - glink_data->glink_handle = handle; - - if (IS_ERR_OR_NULL(glink_data->glink_handle)) { - pr_err("glink_handle %d\n", - (int)PTR_ERR(glink_data->glink_handle)); - WARN_ON(1); - } - - /* - * Do not allow clients to send data to RPM until glink - * is fully open. - */ - probe_status = 0; - pr_info("glink config params: transport=%s, edge=%s, name=%s\n", - glink_data->xprt, - glink_data->edge, - glink_data->name); - break; - default: - pr_err("Unrecognized event %d\n", event); - break; - }; -} - -static void msm_rpm_trans_notify_tx_done(void *handle, const void *priv, - const void *pkt_priv, const void *ptr) -{ -} - -static void msm_rpm_glink_open_work(struct work_struct *work) -{ - pr_debug("Opening glink channel\n"); - glink_data->glink_handle = glink_open(glink_data->open_cfg); - - if (IS_ERR_OR_NULL(glink_data->glink_handle)) { - pr_err("Error: glink_open failed %d\n", - (int)PTR_ERR(glink_data->glink_handle)); - WARN_ON(1); - } -} - -static void msm_rpm_glink_notifier_cb(struct glink_link_state_cb_info *cb_info, - void *priv) -{ - struct glink_open_config *open_config; - static bool first = true; - - if (!cb_info) { - pr_err("Missing callback data\n"); - return; - } - - switch (cb_info->link_state) { - case GLINK_LINK_STATE_UP: - if (first) - first = false; - else - break; - open_config = kzalloc(sizeof(*open_config), GFP_KERNEL); - if (!open_config) { - pr_err("Could not allocate memory\n"); - break; - } - - glink_data->open_cfg = open_config; - pr_debug("glink link state up cb receieved\n"); - INIT_WORK(&glink_data->work, msm_rpm_glink_open_work); - - open_config->priv = glink_data; - open_config->name = glink_data->name; - open_config->edge = glink_data->edge; - open_config->notify_rx = msm_rpm_trans_notify_rx; - open_config->notify_tx_done = msm_rpm_trans_notify_tx_done; - open_config->notify_state = msm_rpm_trans_notify_state; - schedule_work(&glink_data->work); - break; - default: - pr_err("Unrecognised state = %d\n", cb_info->link_state); - break; - }; -} - -static int msm_rpm_glink_dt_parse(struct platform_device *pdev, - struct glink_apps_rpm_data *glink_data) -{ - char *key = NULL; - int ret; - - if (of_device_is_compatible(pdev->dev.of_node, "qcom,rpm-glink")) { - glink_enabled = true; - } else { - pr_warn("qcom,rpm-glink compatible not matches\n"); - ret = -EINVAL; - return ret; - } - - key = "qcom,glink-edge"; - ret = of_property_read_string(pdev->dev.of_node, key, - &glink_data->edge); - if (ret) { - pr_err("Failed to read node: %s, key=%s\n", - pdev->dev.of_node->full_name, key); - return ret; - } - - key = "rpm-channel-name"; - ret = of_property_read_string(pdev->dev.of_node, key, - &glink_data->name); - if (ret) - pr_err("%s(): Failed to read node: %s, key=%s\n", __func__, - pdev->dev.of_node->full_name, key); - - return ret; -} - -static int msm_rpm_glink_link_setup(struct glink_apps_rpm_data *glink_data, - struct platform_device *pdev) -{ - struct glink_link_info *link_info; - void *link_state_cb_handle; - struct device *dev = &pdev->dev; - int ret = 0; - - link_info = devm_kzalloc(dev, sizeof(struct glink_link_info), - GFP_KERNEL); - if (!link_info) { - ret = -ENOMEM; - return ret; - } - - glink_data->link_info = link_info; - - /* - * Setup link info parameters - */ - link_info->edge = glink_data->edge; - link_info->glink_link_state_notif_cb = - msm_rpm_glink_notifier_cb; - link_state_cb_handle = glink_register_link_state_cb(link_info, NULL); - if (IS_ERR_OR_NULL(link_state_cb_handle)) { - pr_err("Could not register cb\n"); - ret = PTR_ERR(link_state_cb_handle); - return ret; - } - - spin_lock_init(&msm_rpm_data.smd_lock_read); - spin_lock_init(&msm_rpm_data.smd_lock_write); - - return ret; -} - -static int msm_rpm_dev_glink_probe(struct platform_device *pdev) -{ - int ret = -ENOMEM; - struct device *dev = &pdev->dev; - - glink_data = devm_kzalloc(dev, sizeof(*glink_data), GFP_KERNEL); - if (!glink_data) - return ret; - - ret = msm_rpm_glink_dt_parse(pdev, glink_data); - if (ret < 0) { - devm_kfree(dev, glink_data); - return ret; - } - - ret = msm_rpm_glink_link_setup(glink_data, pdev); - if (ret < 0) { - /* - * If the glink setup fails there is no - * fall back mechanism to SMD. - */ - pr_err("GLINK setup fail ret = %d\n", ret); - WARN_ON(1); - } - - return ret; + return 0; } -static int msm_rpm_dev_probe(struct platform_device *pdev) +static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev) { char *key = NULL; + struct device_node *p; int ret = 0; + int irq; void __iomem *reg_base; uint32_t version = V0_PROTOCOL_VERSION; /* set to default v0 format */ - /* - * Check for standalone support - */ + p = of_find_compatible_node(NULL, NULL, "qcom,rpm-smd"); + if (!p) { + pr_err("Unable to find rpm-smd\n"); + probe_status = -ENODEV; + goto fail; + } + key = "rpm-standalone"; - standalone = of_property_read_bool(pdev->dev.of_node, key); + standalone = of_property_read_bool(p, key); if (standalone) { probe_status = ret; goto skip_init; } - reg_base = of_iomap(pdev->dev.of_node, 0); - + reg_base = of_iomap(p, 0); if (reg_base) { version = readq_relaxed(reg_base); iounmap(reg_base); @@ -2065,70 +1581,35 @@ static int msm_rpm_dev_probe(struct platform_device *pdev) if (version == V1_PROTOCOL_VERSION) rpm_msg_fmt_ver = RPM_MSG_V1_FMT; - pr_debug("RPM-SMD running version %d/n", rpm_msg_fmt_ver); + pr_info("RPM-SMD running version %d\n", rpm_msg_fmt_ver); - ret = msm_rpm_dev_glink_probe(pdev); - if (!ret) { - pr_info("APSS-RPM communication over GLINK\n"); - msm_rpm_send_buffer = msm_rpm_glink_send_buffer; - of_platform_populate(pdev->dev.of_node, NULL, NULL, - &pdev->dev); - return ret; - } - msm_rpm_send_buffer = msm_rpm_send_smd_buffer; - - key = "rpm-channel-name"; - ret = of_property_read_string(pdev->dev.of_node, key, - &msm_rpm_data.ch_name); - if (ret) { - pr_err("%s(): Failed to read node: %s, key=%s\n", __func__, - pdev->dev.of_node->full_name, key); + irq = of_irq_get(p, 0); + if (!irq) { + pr_err("Unable to get rpm-smd interrupt number\n"); + probe_status = -ENODEV; goto fail; } - key = "rpm-channel-type"; - ret = of_property_read_u32(pdev->dev.of_node, key, - &msm_rpm_data.ch_type); - if (ret) { - pr_err("%s(): Failed to read node: %s, key=%s\n", __func__, - pdev->dev.of_node->full_name, key); + rpm = devm_kzalloc(&rpdev->dev, sizeof(*rpm), GFP_KERNEL); + if (!rpm) { + probe_status = -ENOMEM; goto fail; } - ret = smd_named_open_on_edge(msm_rpm_data.ch_name, - msm_rpm_data.ch_type, - &msm_rpm_data.ch_info, - &msm_rpm_data, - msm_rpm_notify); - if (ret) { - if (ret != -EPROBE_DEFER) { - pr_err("%s: Cannot open RPM channel %s %d\n", - __func__, msm_rpm_data.ch_name, - msm_rpm_data.ch_type); - } - goto fail; - } + rpm->dev = &rpdev->dev; + rpm->rpm_channel = rpdev->ept; + dev_set_drvdata(&rpdev->dev, rpm); + priv_rpm = *rpm; + rpm->irq = irq; + mutex_init(&rpm->lock); + init_completion(&rpm->ack); spin_lock_init(&msm_rpm_data.smd_lock_write); spin_lock_init(&msm_rpm_data.smd_lock_read); - tasklet_init(&data_tasklet, data_fn_tasklet, 0); - - wait_for_completion(&msm_rpm_data.smd_open); - - smd_disable_read_intr(msm_rpm_data.ch_info); - - msm_rpm_smd_wq = alloc_workqueue("rpm-smd", - WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI, 1); - if (!msm_rpm_smd_wq) { - pr_err("%s: Unable to alloc rpm-smd workqueue\n", __func__); - ret = -EINVAL; - goto fail; - } - queue_work(msm_rpm_smd_wq, &msm_rpm_data.work); - probe_status = ret; skip_init: - of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); + probe_status = of_platform_populate(rpdev->dev.of_node, + NULL, NULL, &rpdev->dev); if (standalone) pr_info("RPM running in standalone mode\n"); @@ -2136,30 +1617,35 @@ static int msm_rpm_dev_probe(struct platform_device *pdev) return probe_status; } -static const struct of_device_id msm_rpm_match_table[] = { - {.compatible = "qcom,rpm-smd"}, - {.compatible = "qcom,rpm-glink"}, - {}, +static void qcom_smd_rpm_remove(struct rpmsg_device *rpdev) +{ + of_platform_depopulate(&rpdev->dev); +} + +static struct rpmsg_device_id rpmsg_driver_rpm_id_table[] = { + { .name = "rpm_requests" }, + { }, }; -static struct platform_driver msm_rpm_device_driver = { - .probe = msm_rpm_dev_probe, - .driver = { - .name = "rpm-smd", +static struct rpmsg_driver qcom_smd_rpm_driver = { + .probe = qcom_smd_rpm_probe, + .remove = qcom_smd_rpm_remove, + .callback = qcom_smd_rpm_callback, + .id_table = rpmsg_driver_rpm_id_table, + .drv = { + .name = "qcom_rpm_smd", .owner = THIS_MODULE, - .of_match_table = msm_rpm_match_table, }, }; int __init msm_rpm_driver_init(void) { - static bool registered; + unsigned int ret = 0; - if (registered) - return 0; - registered = true; + ret = register_rpmsg_driver(&qcom_smd_rpm_driver); + if (ret) + pr_err("register_rpmsg_driver: failed with err %d\n", ret); - return platform_driver_register(&msm_rpm_device_driver); + return ret; } -EXPORT_SYMBOL(msm_rpm_driver_init); -arch_initcall(msm_rpm_driver_init); +postcore_initcall(msm_rpm_driver_init); diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 42f1833680cb..25dbb32e2dae 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -479,14 +479,6 @@ config MINIDUMP_MAX_ENTRIES help This defines maximum number of entries to be allocated for application subsytem in Minidump table. -config MSM_RPM_SMD - bool "RPM driver using SMD protocol" - help - RPM is the dedicated hardware engine for managing shared SoC - resources. This config adds driver support for using SMD as a - transport layer communication with RPM hardware. It also selects - the MSM_MPM config that programs the MPM module to monitor interrupts - during sleep modes. config QCOM_BUS_SCALING bool "Bus scaling driver" diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 9c537bf3c813..ff06b4a5b107 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -84,7 +84,6 @@ ifdef CONFIG_MSM_RPM_SMD endif obj-$(CONFIG_QMP_DEBUGFS_CLIENT) += qmp-debugfs-client.o obj-$(CONFIG_MSM_PERFORMANCE) += msm_performance.o -obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o ifdef CONFIG_DEBUG_FS obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd-debug.o endif diff --git a/include/soc/qcom/rpm-smd.h b/include/soc/qcom/rpm-smd.h index 853f82341556..889ec4ce4656 100644 --- a/include/soc/qcom/rpm-smd.h +++ b/include/soc/qcom/rpm-smd.h @@ -16,111 +16,6 @@ #ifndef __ARCH_ARM_MACH_MSM_RPM_SMD_H #define __ARCH_ARM_MACH_MSM_RPM_SMD_H -#define SMD_EVENT_DATA 1 -#define SMD_EVENT_OPEN 2 -#define SMD_EVENT_CLOSE 3 -#define SMD_EVENT_STATUS 4 -#define SMD_EVENT_REOPEN_READY 5 - -enum { - GLINK_CONNECTED, - GLINK_LOCAL_DISCONNECTED, - GLINK_REMOTE_DISCONNECTED, -}; - -enum tx_flags { - GLINK_TX_REQ_INTENT = 0x1, - GLINK_TX_SINGLE_THREADED = 0x2, - GLINK_TX_TRACER_PKT = 0x4, - GLINK_TX_ATOMIC = 0x8, -}; - -enum glink_link_state { - GLINK_LINK_STATE_UP, - GLINK_LINK_STATE_DOWN, -}; - -struct glink_link_state_cb_info { - const char *transport; - const char *edge; - enum glink_link_state link_state; -}; - -struct glink_link_info { - const char *transport; - const char *edge; - void (*glink_link_state_notif_cb)( - struct glink_link_state_cb_info *cb_info, - void *priv); -}; - -struct smd_channel { - void __iomem *send; /* some variant of smd_half_channel */ - void __iomem *recv; /* some variant of smd_half_channel */ - unsigned char *send_data; - unsigned char *recv_data; - unsigned int fifo_size; - struct list_head ch_list; - unsigned int current_packet; - unsigned int n; - void *priv; - void (*notify)(void *priv, unsigned int flags); - int (*read)(struct smd_channel *ch, void *data, int len); - int (*write)(struct smd_channel *ch, const void *data, int len, - bool int_ntfy); - int (*read_avail)(struct smd_channel *ch); - int (*write_avail)(struct smd_channel *ch); - int (*read_from_cb)(struct smd_channel *ch, void *data, int len); - void (*update_state)(struct smd_channel *ch); - unsigned int last_state; - void (*notify_other_cpu)(struct smd_channel *ch); - void * (*read_from_fifo)(void *dest, const void *src, size_t num_bytes); - void * (*write_to_fifo)(void *dest, const void *src, size_t num_bytes); - char name[20]; - struct platform_device pdev; - unsigned int type; - int pending_pkt_sz; - char is_pkt_ch; - /* - * private internal functions to access *send and *recv. - * never to be exported outside of smd - */ - struct smd_half_channel_access *half_ch; -}; - -struct glink_open_config { - void *priv; - uint32_t options; - const char *transport; - const char *edge; - const char *name; - unsigned int rx_intent_req_timeout_ms; - void (*notify_rx)(void *handle, const void *priv, const void *pkt_priv, - const void *ptr, size_t size); - void (*notify_tx_done)(void *handle, const void *priv, - const void *pkt_priv, const void *ptr); - void (*notify_state)(void *handle, const void *priv, - unsigned int event); - bool (*notify_rx_intent_req)(void *handle, const void *priv, - size_t req_size); - void (*notify_rxv)(void *handle, const void *priv, const void *pkt_priv, - void *iovec, size_t size, - void * (*vbuf_provider)(void *iovec, size_t offset, - size_t *size), - void * (*pbuf_provider)(void *iovec, size_t offset, - size_t *size)); - void (*notify_rx_sigs)(void *handle, const void *priv, - uint32_t old_sigs, uint32_t new_sigs); - void (*notify_rx_abort)(void *handle, const void *priv, - const void *pkt_priv); - void (*notify_tx_abort)(void *handle, const void *priv, - const void *pkt_priv); - void (*notify_rx_tracer_pkt)(void *handle, const void *priv, - const void *pkt_priv, const void *ptr, size_t size); - void (*notify_remote_rx_intent)(void *handle, const void *priv, - size_t size); -}; - /** * enum msm_rpm_set - RPM enumerations for sleep/active set * %MSM_RPM_CTX_SET_0: Set resource parameters for active mode. @@ -413,82 +308,4 @@ static inline int __init msm_rpm_driver_init(void) } #endif -static inline int glink_rpm_rx_poll(void *handle) -{ - return -ENODEV; -} - -static inline int smd_is_pkt_avail(struct smd_channel *ch) -{ - return -ENODEV; -} - -static inline int smd_cur_packet_size(struct smd_channel *ch) -{ - return -ENODEV; -} - -static inline int smd_read_avail(struct smd_channel *ch) -{ - return -ENODEV; -} - -static inline int smd_read(struct smd_channel *ch, void *data, int len) -{ - return -ENODEV; -} - -static inline int smd_write_avail(struct smd_channel *ch) -{ - return -ENODEV; -} -static inline int smd_write(struct smd_channel *ch, const void *data, int len) -{ - return -ENODEV; -} - -static inline int glink_tx(void *handle, void *pkt_priv, void *data, - size_t size, uint32_t tx_flags) -{ - return -ENODEV; -} - -static inline int smd_mask_receive_interrupt(struct smd_channel *ch, bool mask, - const struct cpumask *cpumask) -{ - return -ENODEV; -} - -static inline int glink_rpm_mask_rx_interrupt(void *handle, bool mask, - void *pstruct) -{ - return -ENODEV; -} - -static inline int glink_rx_done(void *handle, const void *ptr, bool reuse) -{ - return -ENODEV; -} -static inline void *glink_open(const struct glink_open_config *cfg_ptr) -{ - return NULL; -} - -static inline void *glink_register_link_state_cb( - struct glink_link_info *link_info, void *priv) -{ - return NULL; -} - -static inline int smd_named_open_on_edge(const char *name, uint32_t edge, - struct smd_channel **_ch, void *priv, - void (*notify)(void *, unsigned int)) -{ - return -ENODEV; -} - -static inline void smd_disable_read_intr(struct smd_channel *ch) -{ -} - #endif /*__ARCH_ARM_MACH_MSM_RPM_SMD_H*/ -- GitLab From b8f42d089c43e31cdfcb5fa0e1081865cf85fefd Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Thu, 7 Jun 2018 20:13:12 +0530 Subject: [PATCH 0471/1299] ARM: dts: msm: Add rpm-smd irq number for qcs405 Add rpm-smd irq number for qcs405. This IRQ used by remote processor to inform APSS about reception of response message packet. Change-Id: I5546e180696e071c0fc2f63c2737c074246d55e6 Signed-off-by: Raghavendra Kakarla --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 2732a939e71d..94a61ad6738a 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -350,6 +350,7 @@ rpm_bus: qcom,rpm-smd { compatible = "qcom,rpm-smd"; rpm-channel-name = "rpm_requests"; + interrupts = ; rpm-channel-type = <15>; /* SMD_APPS_RPM */ }; -- GitLab From a711ecefc80495a7f4657df7e5bfef37eb36381a Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Wed, 13 Jun 2018 12:29:03 -0400 Subject: [PATCH 0472/1299] msm: npu: Add loopback test This change is to add npu loopback test via debugfs. Change-Id: I9091e0cbc353bee788cd22efe3c3c7d07c5cf227 Signed-off-by: Jilai Wang --- drivers/media/platform/msm/npu/npu_debugfs.c | 5 +++ drivers/media/platform/msm/npu/npu_host_ipc.h | 20 +++++++++ drivers/media/platform/msm/npu/npu_mgr.c | 44 +++++++++++++++++++ drivers/media/platform/msm/npu/npu_mgr.h | 2 + 4 files changed, 71 insertions(+) diff --git a/drivers/media/platform/msm/npu/npu_debugfs.c b/drivers/media/platform/msm/npu/npu_debugfs.c index 996ca91ed44d..95f3d7d93f01 100644 --- a/drivers/media/platform/msm/npu/npu_debugfs.c +++ b/drivers/media/platform/msm/npu/npu_debugfs.c @@ -351,6 +351,7 @@ static ssize_t npu_debug_ctrl_write(struct file *file, char buf[24]; struct npu_device *npu_dev = file->private_data; struct npu_debugfs_ctx *debugfs; + int32_t rc = 0; pr_debug("npu_dev %pK %pK\n", npu_dev, g_npu_dev); npu_dev = g_npu_dev; @@ -381,6 +382,10 @@ static ssize_t npu_debug_ctrl_write(struct file *file, REGW(npu_dev, NPU_MASTERn_ERROR_IRQ_SET(0), 2); npu_disable_core_power(npu_dev); + } else if (strcmp(buf, "loopback") == 0) { + pr_debug("loopback test\n"); + rc = npu_host_loopback_test(npu_dev); + pr_debug("loopback test end: %d\n", rc); } else if (strcmp(buf, "0") == 0) { pr_info("setting power state to 0\n"); npu_dev->pwrctrl.active_pwrlevel = 0; diff --git a/drivers/media/platform/msm/npu/npu_host_ipc.h b/drivers/media/platform/msm/npu/npu_host_ipc.h index 2acdced5550a..e15db0c3e8fb 100644 --- a/drivers/media/platform/msm/npu/npu_host_ipc.h +++ b/drivers/media/platform/msm/npu/npu_host_ipc.h @@ -32,6 +32,8 @@ #define NPU_IPC_CMD_CONFIG_PERFORMANCE 0x00000005 #define NPU_IPC_CMD_CONFIG_DEBUG 0x00000006 #define NPU_IPC_CMD_SHUTDOWN 0x00000007 +/* npu_ipc_cmd_loopback_packet_t */ +#define NPU_IPC_CMD_LOOPBACK 0x00000008 /* Messages sent **from** NPU */ /* IPC Message Response -- uint32_t */ @@ -45,6 +47,8 @@ #define NPU_IPC_MSG_EXECUTE_DONE 0x00010003 /* ipc_msg_event_notify_pkt */ #define NPU_IPC_MSG_EVENT_NOTIFY 0x00010004 +/* npu_ipc_msg_loopback_packet_t */ +#define NPU_IPC_MSG_LOOPBACK_DONE 0x00010005 /* Logging message size */ /* Number 32-bit elements for the maximum log message size */ @@ -191,6 +195,14 @@ struct ipc_cmd_execute_pkt { uint32_t aco_hdl; }; +/* + * Loopback packet definition + */ +struct ipc_cmd_loopback_pkt { + struct ipc_cmd_header_pkt header; + uint32_t loopbackParams; +}; + /* * LOAD response packet definition */ @@ -257,6 +269,14 @@ struct ipc_msg_execute_pkt { struct ipc_execute_stats stats; }; +/* + * LOOPBACK response packet definition + */ +struct ipc_msg_loopback_pkt { + struct ipc_msg_header_pkt header; + uint32_t loopbackParams; +}; + /* Logging Related */ /* diff --git a/drivers/media/platform/msm/npu/npu_mgr.c b/drivers/media/platform/msm/npu/npu_mgr.c index 6861455d1101..0041a85e071e 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.c +++ b/drivers/media/platform/msm/npu/npu_mgr.c @@ -211,6 +211,7 @@ int npu_host_init(struct npu_device *npu_dev) init_completion(&host_ctx->exec_done); init_completion(&host_ctx->load_done); init_completion(&host_ctx->unload_done); + init_completion(&host_ctx->loopback_done); host_ctx->sys_cache_disable = 0; spin_lock_init(&host_ctx->lock); @@ -287,6 +288,7 @@ static int host_error_hdlr(struct npu_device *npu_dev) complete_all(&host_ctx->exec_done); complete_all(&host_ctx->load_done); complete_all(&host_ctx->unload_done); + complete_all(&host_ctx->loopback_done); return 1; } @@ -430,6 +432,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) struct ipc_msg_header_pkt *resp_pkt; struct ipc_msg_load_pkt *load_rsp_pkt; struct ipc_msg_execute_pkt *exe_rsp_pkt; + struct ipc_msg_loopback_pkt *lb_rsp_pkt; msg_id = msg[1]; switch (msg_id) { @@ -481,6 +484,14 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg) resp_pkt->status, resp_pkt->trans_id); complete_all(&host_ctx->unload_done); break; + + case NPU_IPC_MSG_LOOPBACK_DONE: + lb_rsp_pkt = (struct ipc_msg_loopback_pkt *)msg; + pr_debug("NPU_IPC_MSG_LOOPBACK_DONE loopbackParams: 0x%x\n", + lb_rsp_pkt->loopbackParams); + complete_all(&host_ctx->loopback_done); + break; + default: pr_err("Not supported apps response received %d\n", msg_id); @@ -807,3 +818,36 @@ int32_t npu_host_exec_network(struct npu_device *npu_dev, return ret; } + +int32_t npu_host_loopback_test(struct npu_device *npu_dev) +{ + struct ipc_cmd_loopback_pkt loopback_packet; + struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; + int32_t ret; + + ret = fw_init(npu_dev); + if (ret) + return ret; + + loopback_packet.header.cmd_type = NPU_IPC_CMD_LOOPBACK; + loopback_packet.header.size = sizeof(struct ipc_cmd_loopback_pkt); + loopback_packet.header.trans_id = 0; + loopback_packet.header.flags = 0; + loopback_packet.loopbackParams = 15; + + reinit_completion(&host_ctx->loopback_done); + ret = npu_host_ipc_send_cmd(npu_dev, + IPC_QUEUE_APPS_EXEC, &loopback_packet); + + if (ret) { + pr_err("NPU_IPC_CMD_LOOPBACK sent failed: %d\n", ret); + } else if (!wait_for_completion_interruptible_timeout( + &host_ctx->loopback_done, NW_LOAD_TIMEOUT)) { + pr_err_ratelimited("npu: NPU_IPC_CMD_LOOPBACK time out\n"); + ret = -ETIMEDOUT; + } + + fw_deinit(npu_dev, true); + + return ret; +} diff --git a/drivers/media/platform/msm/npu/npu_mgr.h b/drivers/media/platform/msm/npu/npu_mgr.h index 80eaca528587..ade06bbf7de2 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.h +++ b/drivers/media/platform/msm/npu/npu_mgr.h @@ -73,6 +73,7 @@ struct npu_host_ctx { struct completion exec_done; struct completion load_done; struct completion unload_done; + struct completion loopback_done; int32_t network_num; struct npu_network networks[MAX_LOADED_NETWORK]; bool sys_cache_disable; @@ -111,6 +112,7 @@ int32_t npu_host_unload_network(struct npu_device *npu_dev, struct msm_npu_unload_network_ioctl *unload); int32_t npu_host_exec_network(struct npu_device *npu_dev, struct msm_npu_exec_network_ioctl *exec_ioctl); +int32_t npu_host_loopback_test(struct npu_device *npu_dev); void npu_dump_debug_timeout_stats(struct npu_device *npu_dev); void npu_dump_cal_state(struct npu_device *npu_dev); -- GitLab From bf89621d84d82aadb73cd0d2a28f0930074eedf2 Mon Sep 17 00:00:00 2001 From: Vijay Viswanath Date: Wed, 20 Jun 2018 18:42:47 +0530 Subject: [PATCH 0473/1299] mmc: sdhci: Avoid accessing register when clocks are turned off When we disable the clocks, the SDHCI_CLOCK_CONTROL register is already updated by sdhci-msm platform driver. So avoid writing the same value again in sdhci_set_clock() API when we are disabling clock. This also prevents unclocked access issue. Change-Id: Id5a89f8832ea439e1e2ab6f91a851963c2ac12c8 Signed-off-by: Vijay Viswanath --- drivers/mmc/host/sdhci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 77d0c7de6b2e..6feaab573fe8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1597,6 +1597,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) host->mmc->actual_clock = 0; + if (host->clock) sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); if (clock == 0) -- GitLab From 9da9e4fcd2c503adf6d72492544b0a04827cb386 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Wed, 20 Jun 2018 13:42:19 +0300 Subject: [PATCH 0474/1299] msm: gsi: Update GSI driver to support 24 event ring channels GSI 2.5 supports 24 event ring channels as opposed to 22 at previous versions. Update driver to support it. CRs-Fixed: 2264249 Change-Id: I4b80a5b24c3dad8950ccc2b0a6839fb86879399d Signed-off-by: Ghanim Fodi --- drivers/platform/msm/gsi/gsi.c | 7 ++++++- drivers/platform/msm/gsi/gsi.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index c94a8658aa70..ac00093c6590 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -905,6 +905,11 @@ int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl) return -GSI_STATUS_ERROR; } + if (gsi_ctx->max_ev > GSI_EVT_RING_MAX) { + GSIERR("max event rings are beyond absolute maximum\n"); + return -GSI_STATUS_ERROR; + } + if (props->mhi_er_id_limits_valid && props->mhi_er_id_limits[0] > (gsi_ctx->max_ev - 1)) { devm_iounmap(gsi_ctx->dev, gsi_ctx->base); @@ -1847,7 +1852,7 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, } if (props->evt_ring_hdl != ~0) { - if (props->evt_ring_hdl >= GSI_EVT_RING_MAX) { + if (props->evt_ring_hdl >= gsi_ctx->max_ev) { GSIERR("invalid evt ring=%lu\n", props->evt_ring_hdl); return -GSI_STATUS_INVALID_PARAMS; } diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h index 9b5dead02fd5..478af3fe6d21 100644 --- a/drivers/platform/msm/gsi/gsi.h +++ b/drivers/platform/msm/gsi/gsi.h @@ -21,7 +21,7 @@ #include #define GSI_CHAN_MAX 31 -#define GSI_EVT_RING_MAX 23 +#define GSI_EVT_RING_MAX 24 #define GSI_NO_EVT_ERINDEX 31 #define gsi_readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) -- GitLab From d3d0440cfd0f6a44724edb9a9307e88f97800051 Mon Sep 17 00:00:00 2001 From: Narendra Muppalla Date: Wed, 28 Mar 2018 16:30:54 +0530 Subject: [PATCH 0475/1299] drm/msm/sde: set VBIF Amem type during rotator hw config Program vbif Amem type during rotator hw config as clk ctrl might be still on during gdsc toggle which will reset the register. Change-Id: I199c345d2f9a7ea084f5dc63ddeed69fee091003 Signed-off-by: Kalyan Thota Signed-off-by: Narendra Muppalla --- drivers/media/platform/msm/sde/rotator/sde_rotator_core.c | 3 --- drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c index 30ffcfc89746..1132ec582012 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c @@ -418,9 +418,6 @@ int sde_rotator_clk_ctrl(struct sde_rot_mgr *mgr, int enable) if (ret) goto error_rot_sub; - /* reinitialize static vbif setting */ - sde_mdp_init_vbif(); - /* Active+Sleep */ msm_bus_scale_client_update_context( mgr->data_bus.bus_hdl, false, diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index d9f3fdc012cd..7bdbc7f84d0f 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -2795,6 +2795,9 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, item->input.format, item->output.format, entry->perf->config.frame_rate); + /* initialize static vbif setting */ + sde_mdp_init_vbif(); + if (!ctx->sbuf_mode && mdata->default_ot_rd_limit) { struct sde_mdp_set_ot_params ot_params; -- GitLab From 8f7d99ae909528fee29d0b71e4cb151cd9eb5541 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Tue, 19 Jun 2018 16:12:02 +0530 Subject: [PATCH 0476/1299] adsprpc: Disable dynamic loading from HLOS_PHYSPOOL for qcs405 Disable dynamic loading of shared objects from HLOS_PHYSPOOL. Change-Id: I01f78dbd81de97482e6f32be30229ce4fda91496 Acked-by: Chenna Kesava Raju Signed-off-by: Tharun Kumar Merugu --- .../devicetree/bindings/qdsp/msm-fastrpc.txt | 1 + drivers/char/adsprpc.c | 22 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt index ff5bb515b4c0..e302bab4e0b9 100644 --- a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt +++ b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt @@ -14,6 +14,7 @@ Optional properties: - qcom,rpc-latency-us: FastRPC QoS latency vote - qcom,adsp-remoteheap-vmid: FastRPC remote heap VMID list - qcom,secure-context-bank : Bool indicating secure FastRPC context bank. +- qcom,fastrpc-legacy-remote-heap : Bool indicating hypervisor is not supported. Optional subnodes: - qcom,msm_fastrpc_compute_cb : Child nodes representing the compute context diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index f0c6fc1fe1c1..6dc3acbe320b 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -265,6 +265,7 @@ struct fastrpc_apps { int rpmsg_register; spinlock_t ctxlock; struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX]; + bool legacy_remote_heap; }; struct fastrpc_mmap { @@ -1877,7 +1878,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl, inbuf.pgid = current->tgid; inbuf.namelen = init->filelen; inbuf.pageslen = 0; - if (!me->staticpd_flags) { + if (!me->staticpd_flags && !(me->legacy_remote_heap)) { inbuf.pageslen = 1; mutex_lock(&fl->map_mutex); VERIFY(err, !fastrpc_mmap_create(fl, -1, 0, init->mem, @@ -2058,6 +2059,7 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, { int err = 0; struct fastrpc_apps *me = &gfa; + int tgid = 0; int destVM[1] = {VMID_HLOS}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; @@ -2070,17 +2072,21 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint8_t skey; } routargs; - ra[0].buf.pv = (void *)&routargs; - ra[0].buf.len = sizeof(routargs); + if (fl == NULL) + goto bail; + tgid = fl->tgid; + ra[0].buf.pv = (void *)&tgid; + ra[0].buf.len = sizeof(tgid); + + ra[1].buf.pv = (void *)&routargs; + ra[1].buf.len = sizeof(routargs); ioctl.inv.handle = 1; - ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 0, 1); + ioctl.inv.sc = REMOTE_SCALARS_MAKE(9, 1, 1); ioctl.inv.pra = ra; ioctl.fds = NULL; ioctl.attrs = NULL; ioctl.crc = NULL; - if (fl == NULL) - goto bail; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); @@ -3256,7 +3262,8 @@ static int fastrpc_probe(struct platform_device *pdev) } return 0; } - + me->legacy_remote_heap = of_property_read_bool(dev->of_node, + "qcom,fastrpc-legacy-remote-heap"); VERIFY(err, !of_platform_populate(pdev->dev.of_node, fastrpc_match_table, NULL, &pdev->dev)); @@ -3330,6 +3337,7 @@ static int __init fastrpc_device_init(void) fastrpc_init(me); me->dev = NULL; + me->legacy_remote_heap = 0; VERIFY(err, 0 == platform_driver_register(&fastrpc_driver)); if (err) goto register_bail; -- GitLab From 5da72b7c02d1b4a530c0d92b4ed40b2284c13c01 Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Fri, 15 Jun 2018 16:55:46 -0700 Subject: [PATCH 0477/1299] ARM: dts: msm: change clk name for QRNG driver on SM8150 Change the clock name to the correct value to enable QRNG driver to start as part of boot. Change-Id: Ic19dda82dceb52732350f41d7f4e9c35081956dd Signed-off-by: Zhen Kong --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index 9a4dff897f84..1507fb8762df 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -2869,7 +2869,7 @@ <1 618 0 0>, /* No vote */ <1 618 0 300000>; /* 75 MHz */ clocks = <&clock_gcc GCC_PRNG_AHB_CLK>; - clock-names = "iface"; + clock-names = "iface_clk"; }; qcom_cedev: qcedev@1de0000 { -- GitLab From 50563f68e8a0005f8d1251739abd026fdbc83ba9 Mon Sep 17 00:00:00 2001 From: Jeevan Shriram Date: Wed, 16 May 2018 23:23:20 -0700 Subject: [PATCH 0478/1299] ARM: dts: msm: Add support for UART console on sdxprairie target Add devicetree node to bringup UART console on sdxprairie target for logs and executing shell commands. Change-Id: I1b6fd500769843c8f87a50d0d8255e52a18229bb Signed-off-by: Jeevan Shriram --- arch/arm64/boot/dts/qcom/sdxprairie.dtsi | 20 +++ .../dt-bindings/clock/qcom,gcc-sdxprairie.h | 132 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 include/dt-bindings/clock/qcom,gcc-sdxprairie.h diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi index b5659a5fe02b..e33dfd6d908c 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi @@ -12,6 +12,7 @@ #include "skeleton.dtsi" +#include #include / { @@ -135,6 +136,25 @@ status = "disabled"; }; }; + + clock_gcc: qcom,gcc { + compatible = "qcom,dummycc"; + clock-output-names = "gcc_clocks"; + #clock-cells = <1>; + }; + + serial_uart: serial@831000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x831000 0x200>; + interrupts = <0 26 0>; + clocks = <&clock_gcc GCC_BLSP1_UART3_APPS_CLK>, + <&clock_gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&uart3_console_active>; + pinctrl-1 = <&uart3_console_sleep>; + status = "ok"; + }; }; #include "sdxprairie-pinctrl.dtsi" diff --git a/include/dt-bindings/clock/qcom,gcc-sdxprairie.h b/include/dt-bindings/clock/qcom,gcc-sdxprairie.h new file mode 100644 index 000000000000..18fe72a018d6 --- /dev/null +++ b/include/dt-bindings/clock/qcom,gcc-sdxprairie.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_CLK_MSM_GCC_SDXPRAIRIE_H +#define _DT_BINDINGS_CLK_MSM_GCC_SDXPRAIRIE_H + +/* GCC clock registers */ +#define GCC_BLSP1_AHB_CLK 0 +#define GCC_BLSP1_QUP1_I2C_APPS_CLK 1 +#define GCC_BLSP1_QUP1_I2C_APPS_CLK_SRC 2 +#define GCC_BLSP1_QUP1_SPI_APPS_CLK 3 +#define GCC_BLSP1_QUP1_SPI_APPS_CLK_SRC 4 +#define GCC_BLSP1_QUP2_I2C_APPS_CLK 5 +#define GCC_BLSP1_QUP2_I2C_APPS_CLK_SRC 6 +#define GCC_BLSP1_QUP2_SPI_APPS_CLK 7 +#define GCC_BLSP1_QUP2_SPI_APPS_CLK_SRC 8 +#define GCC_BLSP1_QUP3_I2C_APPS_CLK 9 +#define GCC_BLSP1_QUP3_I2C_APPS_CLK_SRC 10 +#define GCC_BLSP1_QUP3_SPI_APPS_CLK 11 +#define GCC_BLSP1_QUP3_SPI_APPS_CLK_SRC 12 +#define GCC_BLSP1_QUP4_I2C_APPS_CLK 13 +#define GCC_BLSP1_QUP4_I2C_APPS_CLK_SRC 14 +#define GCC_BLSP1_QUP4_SPI_APPS_CLK 15 +#define GCC_BLSP1_QUP4_SPI_APPS_CLK_SRC 16 +#define GCC_BLSP1_SLEEP_CLK 17 +#define GCC_BLSP1_UART1_APPS_CLK 18 +#define GCC_BLSP1_UART1_APPS_CLK_SRC 19 +#define GCC_BLSP1_UART2_APPS_CLK 20 +#define GCC_BLSP1_UART2_APPS_CLK_SRC 21 +#define GCC_BLSP1_UART3_APPS_CLK 22 +#define GCC_BLSP1_UART3_APPS_CLK_SRC 23 +#define GCC_BLSP1_UART4_APPS_CLK 24 +#define GCC_BLSP1_UART4_APPS_CLK_SRC 25 +#define GCC_BOOT_ROM_AHB_CLK 26 +#define GCC_CE1_AHB_CLK 27 +#define GCC_CE1_AXI_CLK 28 +#define GCC_CE1_CLK 29 +#define GCC_CPUSS_AHB_CLK 30 +#define GCC_CPUSS_AHB_CLK_SRC 31 +#define GCC_CPUSS_GNOC_CLK 32 +#define GCC_CPUSS_RBCPR_CLK 33 +#define GCC_CPUSS_RBCPR_CLK_SRC 34 +#define GCC_EMAC_CLK_SRC 35 +#define GCC_EMAC_PTP_CLK_SRC 36 +#define GCC_ETH_AXI_CLK 37 +#define GCC_ETH_PTP_CLK 38 +#define GCC_ETH_RGMII_CLK 39 +#define GCC_ETH_SLAVE_AHB_CLK 40 +#define GCC_GP1_CLK 41 +#define GCC_GP1_CLK_SRC 42 +#define GCC_GP2_CLK 43 +#define GCC_GP2_CLK_SRC 44 +#define GCC_GP3_CLK 45 +#define GCC_GP3_CLK_SRC 46 +#define GCC_PCIE_0_CLKREF_CLK 47 +#define GCC_PCIE_AUX_CLK 48 +#define GCC_PCIE_AUX_PHY_CLK_SRC 49 +#define GCC_PCIE_CFG_AHB_CLK 50 +#define GCC_PCIE_MSTR_AXI_CLK 51 +#define GCC_PCIE_PHY_REFGEN_CLK 52 +#define GCC_PCIE_PHY_REFGEN_CLK_SRC 53 +#define GCC_PCIE_PIPE_CLK 54 +#define GCC_PCIE_SLEEP_CLK 55 +#define GCC_PCIE_SLV_AXI_CLK 56 +#define GCC_PCIE_SLV_Q2A_AXI_CLK 57 +#define GCC_PDM2_CLK 58 +#define GCC_PDM2_CLK_SRC 59 +#define GCC_PDM_AHB_CLK 60 +#define GCC_PDM_XO4_CLK 61 +#define GCC_PRNG_AHB_CLK 62 +#define GCC_SDCC1_AHB_CLK 63 +#define GCC_SDCC1_APPS_CLK 64 +#define GCC_SDCC1_APPS_CLK_SRC 65 +#define GCC_SPMI_FETCHER_AHB_CLK 66 +#define GCC_SPMI_FETCHER_CLK 67 +#define GCC_SPMI_FETCHER_CLK_SRC 68 +#define GCC_SYS_NOC_CPUSS_AHB_CLK 69 +#define GCC_SYS_NOC_USB3_CLK 70 +#define GCC_USB30_MASTER_CLK 71 +#define GCC_USB30_MASTER_CLK_SRC 72 +#define GCC_USB30_MOCK_UTMI_CLK 73 +#define GCC_USB30_MOCK_UTMI_CLK_SRC 74 +#define GCC_USB30_SLEEP_CLK 75 +#define GCC_USB3_PHY_AUX_CLK 76 +#define GCC_USB3_PHY_AUX_CLK_SRC 77 +#define GCC_USB3_PHY_PIPE_CLK 78 +#define GCC_USB3_PRIM_CLKREF_CLK 79 +#define GCC_USB_PHY_CFG_AHB2PHY_CLK 80 +#define GPLL0 81 +#define GPLL0_OUT_EVEN 82 +#define GPLL4 83 +#define GPLL4_OUT_EVEN 84 + +/* CPU clocks */ +#define CLOCK_A7SS 0 + +/* GCC reset clocks */ +#define GCC_BLSP1_QUP1_BCR 0 +#define GCC_BLSP1_QUP2_BCR 1 +#define GCC_BLSP1_QUP3_BCR 2 +#define GCC_BLSP1_QUP4_BCR 3 +#define GCC_BLSP1_UART2_BCR 4 +#define GCC_BLSP1_UART3_BCR 5 +#define GCC_BLSP1_UART4_BCR 6 +#define GCC_CE1_BCR 7 +#define GCC_PCIE_BCR 8 +#define GCC_PCIE_PHY_BCR 9 +#define GCC_PDM_BCR 10 +#define GCC_PRNG_BCR 11 +#define GCC_SDCC1_BCR 12 +#define GCC_SPMI_FETCHER_BCR 13 +#define GCC_USB30_BCR 14 +#define GCC_USB3_PHY_BCR 15 +#define GCC_USB3PHY_PHY_BCR 16 +#define GCC_QUSB2PHY_BCR 17 +#define GCC_USB_PHY_CFG_AHB2PHY_BCR 18 +#define GCC_EMAC_BCR 19 + +/* Dummy clocks for rate measurement */ +#define MEASURE_ONLY_IPA_2X_CLK 0 + +#endif -- GitLab From f3b3f667c5e4cdd07c78c355a02344ca111a70d5 Mon Sep 17 00:00:00 2001 From: Jeevan Shriram Date: Thu, 10 May 2018 22:26:55 -0700 Subject: [PATCH 0479/1299] defconfig: Add support for compiling sdxprairie target Add debug and perf defconfig files for supporting sdxprairie target Change-Id: I2d2290311720b2717d757deef428c6a69794b4f1 Signed-off-by: Jeevan Shriram --- arch/arm/configs/sdxprairie-perf_defconfig | 1 + arch/arm/configs/sdxprairie_defconfig | 1 + .../configs/vendor/sdxprairie-perf_defconfig | 269 +++++++++++++++++ arch/arm/configs/vendor/sdxprairie_defconfig | 278 ++++++++++++++++++ 4 files changed, 549 insertions(+) create mode 120000 arch/arm/configs/sdxprairie-perf_defconfig create mode 120000 arch/arm/configs/sdxprairie_defconfig create mode 100644 arch/arm/configs/vendor/sdxprairie-perf_defconfig create mode 100644 arch/arm/configs/vendor/sdxprairie_defconfig diff --git a/arch/arm/configs/sdxprairie-perf_defconfig b/arch/arm/configs/sdxprairie-perf_defconfig new file mode 120000 index 000000000000..771ec5304d7d --- /dev/null +++ b/arch/arm/configs/sdxprairie-perf_defconfig @@ -0,0 +1 @@ +vendor/sdxprairie-perf_defconfig \ No newline at end of file diff --git a/arch/arm/configs/sdxprairie_defconfig b/arch/arm/configs/sdxprairie_defconfig new file mode 120000 index 000000000000..744d827b789a --- /dev/null +++ b/arch/arm/configs/sdxprairie_defconfig @@ -0,0 +1 @@ +vendor/sdxprairie_defconfig \ No newline at end of file diff --git a/arch/arm/configs/vendor/sdxprairie-perf_defconfig b/arch/arm/configs/vendor/sdxprairie-perf_defconfig new file mode 100644 index 000000000000..2eec35da3b18 --- /dev/null +++ b/arch/arm/configs/vendor/sdxprairie-perf_defconfig @@ -0,0 +1,269 @@ +CONFIG_LOCALVERSION="-perf" +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_SCHED=y +# CONFIG_FAIR_GROUP_SCHED is not set +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_DEBUG=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_SDXPRAIRIE=y +# CONFIG_VDSO is not set +CONFIG_PREEMPT=y +CONFIG_CMA=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_IDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V2=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_SNMP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SIP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NF_CT_NETLINK_TIMEOUT=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_IP_SET=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_TARGET_ECN=y +CONFIG_IP_NF_TARGET_TTL=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_AH=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_OPTS=y +CONFIG_IP6_NF_MATCH_HL=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_MATCH_MH=y +CONFIG_IP6_NF_MATCH_RT=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_BRIDGE_EBT_T_FILTER=y +CONFIG_BRIDGE_EBT_T_NAT=y +CONFIG_BRIDGE_EBT_ARP=y +CONFIG_BRIDGE_EBT_IP=y +CONFIG_BRIDGE_EBT_IP6=y +CONFIG_BRIDGE_EBT_ARPREPLY=y +CONFIG_BRIDGE_EBT_DNAT=y +CONFIG_BRIDGE_EBT_SNAT=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_PRIO=y +CONFIG_BT=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y +CONFIG_BT_HCIUART=y +CONFIG_BT_HCIUART_H4=y +CONFIG_MSM_BT_POWER=y +CONFIG_CFG80211=y +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_CFG80211_WEXT=y +CONFIG_RFKILL=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=12 +CONFIG_MTD=y +CONFIG_MTD_TESTS=m +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_UBI=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_NETDEVICES=y +CONFIG_TUN=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +CONFIG_KS8851=y +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_PPP=y +CONFIG_PPP_ASYNC=y +CONFIG_USB_USBNET=y +CONFIG_USB_NET_SMSC75XX=y +CONFIG_USB_NET_SMSC95XX=y +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=m +CONFIG_SERIO_LIBPS2=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_MSM=y +CONFIG_HW_RANDOM=y +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_SPI=y +CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=m +CONFIG_PINCTRL_SDXPRAIRIE=y +CONFIG_GPIOLIB=y +CONFIG_POWER_RESET=y +CONFIG_POWER_SUPPLY=y +CONFIG_THERMAL=y +CONFIG_REGULATOR=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SOC=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_MSM_SSPHY_QMP=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_UIO=y +CONFIG_STAGING=y +CONFIG_SPS=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_USB_BAM=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_QCOM_SMEM=y +CONFIG_PWM=y +CONFIG_ANDROID=y +CONFIG_EXT3_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_TIMEOUT=5 +# CONFIG_SCHED_DEBUG is not set +CONFIG_SCHEDSTATS=y +CONFIG_IPC_LOGGING=y +# CONFIG_FTRACE is not set diff --git a/arch/arm/configs/vendor/sdxprairie_defconfig b/arch/arm/configs/vendor/sdxprairie_defconfig new file mode 100644 index 000000000000..06a40fd9ab18 --- /dev/null +++ b/arch/arm/configs/vendor/sdxprairie_defconfig @@ -0,0 +1,278 @@ +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_SCHED=y +# CONFIG_FAIR_GROUP_SCHED is not set +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_DEBUG=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_SDXPRAIRIE=y +# CONFIG_VDSO is not set +CONFIG_PREEMPT=y +CONFIG_CMA=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_IDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V2=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_SNMP=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SIP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NF_CT_NETLINK_TIMEOUT=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_IP_SET=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_TARGET_ECN=y +CONFIG_IP_NF_TARGET_TTL=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_AH=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_OPTS=y +CONFIG_IP6_NF_MATCH_HL=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_MATCH_MH=y +CONFIG_IP6_NF_MATCH_RT=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_BRIDGE_EBT_T_FILTER=y +CONFIG_BRIDGE_EBT_T_NAT=y +CONFIG_BRIDGE_EBT_ARP=y +CONFIG_BRIDGE_EBT_IP=y +CONFIG_BRIDGE_EBT_IP6=y +CONFIG_BRIDGE_EBT_ARPREPLY=y +CONFIG_BRIDGE_EBT_DNAT=y +CONFIG_BRIDGE_EBT_SNAT=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_PRIO=y +CONFIG_CFG80211=y +CONFIG_RFKILL=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=12 +CONFIG_MTD=y +CONFIG_MTD_TESTS=m +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_UBI=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_NETDEVICES=y +CONFIG_TUN=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +CONFIG_KS8851=y +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_PPP=y +CONFIG_PPP_ASYNC=y +CONFIG_USB_USBNET=y +CONFIG_USB_NET_SMSC75XX=y +CONFIG_USB_NET_SMSC95XX=y +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=m +CONFIG_SERIO_LIBPS2=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SERIAL_MSM_HS=y +CONFIG_HVC_DCC=y +CONFIG_HW_RANDOM=y +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_SPI=y +CONFIG_SPI_SPIDEV=m +CONFIG_SLIMBUS=y +CONFIG_PINCTRL_SDXPRAIRIE=y +CONFIG_GPIOLIB=y +CONFIG_POWER_RESET=y +CONFIG_POWER_SUPPLY=y +CONFIG_THERMAL=y +CONFIG_REGULATOR=y +CONFIG_FB=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SOC=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_UIO=y +CONFIG_STAGING=y +CONFIG_SPS=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_QCOM_SMEM=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_PWM=y +CONFIG_ANDROID=y +CONFIG_STM=y +CONFIG_EXT3_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_PAGEALLOC=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_FAULT_INJECTION=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_IPC_LOGGING=y +# CONFIG_FTRACE is not set +CONFIG_DEBUG_USER=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_XZ_DEC=y -- GitLab From 65783949c813d0cad88b6a30f47737e8dfc00c86 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 28 Mar 2018 11:22:37 +0800 Subject: [PATCH 0480/1299] clocksource/drivers/imx-tpm: Correct some registers operation flow [ Upstream commit 506a7be93ff773d5d4cf75a59f342865605b4910 ] According to i.MX7ULP reference manual, TPM_SC_CPWMS can ONLY be written when counter is disabled, TPM_SC_TOF is write-1-clear, TPM_C0SC_CHF is also write-1-clear, correct these registers initialization flow; Signed-off-by: Anson Huang Signed-off-by: Daniel Lezcano Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/clocksource/timer-imx-tpm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/timer-imx-tpm.c b/drivers/clocksource/timer-imx-tpm.c index 557ed25b42e3..d175b9545581 100644 --- a/drivers/clocksource/timer-imx-tpm.c +++ b/drivers/clocksource/timer-imx-tpm.c @@ -20,6 +20,7 @@ #define TPM_SC 0x10 #define TPM_SC_CMOD_INC_PER_CNT (0x1 << 3) #define TPM_SC_CMOD_DIV_DEFAULT 0x3 +#define TPM_SC_TOF_MASK (0x1 << 7) #define TPM_CNT 0x14 #define TPM_MOD 0x18 #define TPM_STATUS 0x1c @@ -29,6 +30,7 @@ #define TPM_C0SC_MODE_SHIFT 2 #define TPM_C0SC_MODE_MASK 0x3c #define TPM_C0SC_MODE_SW_COMPARE 0x4 +#define TPM_C0SC_CHF_MASK (0x1 << 7) #define TPM_C0V 0x24 static void __iomem *timer_base; @@ -205,9 +207,13 @@ static int __init tpm_timer_init(struct device_node *np) * 4) Channel0 disabled * 5) DMA transfers disabled */ + /* make sure counter is disabled */ writel(0, timer_base + TPM_SC); + /* TOF is W1C */ + writel(TPM_SC_TOF_MASK, timer_base + TPM_SC); writel(0, timer_base + TPM_CNT); - writel(0, timer_base + TPM_C0SC); + /* CHF is W1C */ + writel(TPM_C0SC_CHF_MASK, timer_base + TPM_C0SC); /* increase per cnt, div 8 by default */ writel(TPM_SC_CMOD_INC_PER_CNT | TPM_SC_CMOD_DIV_DEFAULT, -- GitLab From 176ebf4df9710fefe751d6565c35da5a45aeece3 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 6 Apr 2018 15:36:11 -0700 Subject: [PATCH 0481/1299] Input: synaptics-rmi4 - fix an unchecked out of memory error path [ Upstream commit 839c42273617787318da7baf6151d553108f5e17 ] When extending the rmi_spi buffers, we must check that no out of memory error occurs, otherwise we may access data above the currently allocated memory. Propagate the error code returned by 'rmi_spi_manage_pools()' instead. Signed-off-by: Christophe JAILLET Reviewed-by: Andrew Duggan Signed-off-by: Dmitry Torokhov Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/input/rmi4/rmi_spi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/input/rmi4/rmi_spi.c b/drivers/input/rmi4/rmi_spi.c index d97a85907ed6..d0c3d275bf9f 100644 --- a/drivers/input/rmi4/rmi_spi.c +++ b/drivers/input/rmi4/rmi_spi.c @@ -147,8 +147,11 @@ static int rmi_spi_xfer(struct rmi_spi_xport *rmi_spi, if (len > RMI_SPI_XFER_SIZE_LIMIT) return -EINVAL; - if (rmi_spi->xfer_buf_size < len) - rmi_spi_manage_pools(rmi_spi, len); + if (rmi_spi->xfer_buf_size < len) { + ret = rmi_spi_manage_pools(rmi_spi, len); + if (ret < 0) + return ret; + } if (addr == 0) /* -- GitLab From 9b78e9ddc47ac2da31db600065ea6577dc9f8170 Mon Sep 17 00:00:00 2001 From: hu huajun Date: Wed, 11 Apr 2018 15:16:40 +0800 Subject: [PATCH 0482/1299] KVM: X86: fix incorrect reference of trace_kvm_pi_irte_update [ Upstream commit 2698d82e519413c6ad287e6f14b29e0373ed37f8 ] In arch/x86/kvm/trace.h, this function is declared as host_irq the first input, and vcpu_id the second, instead of otherwise. Signed-off-by: hu huajun Signed-off-by: Paolo Bonzini Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/svm.c | 5 ++--- arch/x86/kvm/vmx.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 029aa1318874..cfa155078ebb 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -4756,9 +4756,8 @@ static int svm_update_pi_irte(struct kvm *kvm, unsigned int host_irq, } if (!ret && svm) { - trace_kvm_pi_irte_update(svm->vcpu.vcpu_id, - host_irq, e->gsi, - vcpu_info.vector, + trace_kvm_pi_irte_update(host_irq, svm->vcpu.vcpu_id, + e->gsi, vcpu_info.vector, vcpu_info.pi_desc_addr, set); } diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index b1556166a06d..4676156753d6 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -12171,7 +12171,7 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq, vcpu_info.pi_desc_addr = __pa(vcpu_to_pi_desc(vcpu)); vcpu_info.vector = irq.vector; - trace_kvm_pi_irte_update(vcpu->vcpu_id, host_irq, e->gsi, + trace_kvm_pi_irte_update(host_irq, vcpu->vcpu_id, e->gsi, vcpu_info.vector, vcpu_info.pi_desc_addr, set); if (set) -- GitLab From df5524e5483b6a29c011721131a510fae3ce0f45 Mon Sep 17 00:00:00 2001 From: Krish Sadhukhan Date: Wed, 11 Apr 2018 01:10:16 -0400 Subject: [PATCH 0483/1299] x86: Add check for APIC access address for vmentry of L2 guests [ Upstream commit f0f4cf5b306620282db0c59ff963012e1973e025 ] According to the sub-section titled 'VM-Execution Control Fields' in the section titled 'Basic VM-Entry Checks' in Intel SDM vol. 3C, the following vmentry check must be enforced: If the 'virtualize APIC-accesses' VM-execution control is 1, the APIC-access address must satisfy the following checks: - Bits 11:0 of the address must be 0. - The address should not set any bits beyond the processor's physical-address width. This patch adds the necessary check to conform to this rule. If the check fails, we cause the L2 VMENTRY to fail which is what the associated unit test (following patch) expects. Reviewed-by: Mihai Carabas Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Jim Mattson Reviewed-by: Wanpeng Li Signed-off-by: Krish Sadhukhan Signed-off-by: Paolo Bonzini Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/vmx.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 4676156753d6..90747865205d 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -10318,6 +10318,16 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu, return true; } +static int nested_vmx_check_apic_access_controls(struct kvm_vcpu *vcpu, + struct vmcs12 *vmcs12) +{ + if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) && + !page_address_valid(vcpu, vmcs12->apic_access_addr)) + return -EINVAL; + else + return 0; +} + static int nested_vmx_check_apicv_controls(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) { @@ -10961,6 +10971,9 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) if (nested_vmx_check_msr_bitmap_controls(vcpu, vmcs12)) return VMXERR_ENTRY_INVALID_CONTROL_FIELD; + if (nested_vmx_check_apic_access_controls(vcpu, vmcs12)) + return VMXERR_ENTRY_INVALID_CONTROL_FIELD; + if (nested_vmx_check_tpr_shadow_controls(vcpu, vmcs12)) return VMXERR_ENTRY_INVALID_CONTROL_FIELD; -- GitLab From d96da2acac5dcf3d8187794b5ef86481ddcf2791 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Tue, 3 Apr 2018 08:55:03 -0400 Subject: [PATCH 0484/1299] MIPS: io: Prevent compiler reordering writeX() [ Upstream commit f6b7aeee8f167409195fbf1364d02988fecad1d0 ] writeX() has strong ordering semantics with respect to memory updates. In the absence of a write barrier or a compiler barrier, the compiler can reorder register and memory update instructions. This breaks the writeX() API. Signed-off-by: Sinan Kaya Cc: Arnd Bergmann Cc: Ralf Baechle Cc: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/18997/ [jhogan@kernel.org: Tidy commit message] Signed-off-by: James Hogan Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/mips/include/asm/io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 0cbf3af37eca..fd00ddafb425 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -307,7 +307,7 @@ static inline void iounmap(const volatile void __iomem *addr) #if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_LOONGSON3_ENHANCEMENT) #define war_io_reorder_wmb() wmb() #else -#define war_io_reorder_wmb() do { } while (0) +#define war_io_reorder_wmb() barrier() #endif #define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq) \ -- GitLab From 7bb0c4bd79ab318225f4dfd9e2394c998a6bd566 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 11 Apr 2018 16:47:35 -0700 Subject: [PATCH 0485/1299] nfp: ignore signals when communicating with management FW [ Upstream commit 5496295aefe86995e41398b0f76de601308fc3f5 ] We currently allow signals to interrupt the wait for management FW commands. Exiting the wait should not cause trouble, the FW will just finish executing the command in the background and new commands will wait for the old one to finish. However, this may not be what users expect (Ctrl-C not actually stopping the command). Moreover some systems routinely request link information with signals pending (Ubuntu 14.04 runs a landscape-sysinfo python tool from MOTD) worrying users with errors like these: nfp 0000:04:00.0: nfp_nsp: Error -512 waiting for code 0x0007 to start nfp 0000:04:00.0: nfp: reading port table failed -512 Make the wait for management FW responses non-interruptible. Fixes: 1a64821c6af7 ("nfp: add support for service processor access") Signed-off-by: Jakub Kicinski Reviewed-by: Dirk van der Merwe Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c index f88ff3f4b661..35d14af235f7 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c @@ -277,8 +277,7 @@ nfp_nsp_wait_reg(struct nfp_cpp *cpp, u64 *reg, if ((*reg & mask) == val) return 0; - if (msleep_interruptible(25)) - return -ERESTARTSYS; + msleep(25); if (time_after(start_time, wait_until)) return -ETIMEDOUT; -- GitLab From 025e42a5e7a318572d0ea2b94b508011bcaff306 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 12 Apr 2018 14:58:24 -0300 Subject: [PATCH 0486/1299] perf report: Fix switching to another perf.data file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 7b366142a50ad79e48de8e67c5b3e8cfb9fa82dd ] In the TUI the 's' hotkey can be used to switch to another perf.data file in the current directory, but that got broken in Fixes: b01141f4f59c ("perf annotate: Initialize the priv are in symbol__new()"), that would show this once another file was chosen: ┌─Fatal Error─────────────────────────────────────┐ │Annotation needs to be init before symbol__init()│ │ │ │ │ │Press any key... │ └─────────────────────────────────────────────────┘ Fix it by just silently bailing out if symbol__annotation_init() was already called, just like is done with symbol__init(), i.e. they are done just once at session start, not when switching to a new perf.data file. Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Martin Liška Cc: Namhyung Kim Cc: Ravi Bangoria Cc: Thomas Richter Cc: Wang Nan Fixes: b01141f4f59c ("perf annotate: Initialize the priv are in symbol__new()") Link: https://lkml.kernel.org/n/tip-ogppdtpzfax7y1h6gjdv5s6u@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/symbol.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 4e8dd5fd45fd..ec40e47aa198 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -2093,16 +2093,14 @@ static bool symbol__read_kptr_restrict(void) int symbol__annotation_init(void) { + if (symbol_conf.init_annotation) + return 0; + if (symbol_conf.initialized) { pr_err("Annotation needs to be init before symbol__init()\n"); return -1; } - if (symbol_conf.init_annotation) { - pr_warning("Annotation being initialized multiple times\n"); - return 0; - } - symbol_conf.priv_size += sizeof(struct annotation); symbol_conf.init_annotation = true; return 0; -- GitLab From dc94ac5fc41054c16824b01683fade1b77a07c7a Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Thu, 5 Apr 2018 16:18:03 +0300 Subject: [PATCH 0487/1299] fsnotify: fix ignore mask logic in send_to_group() [ Upstream commit 92183a42898dc400b89da35685d1814ac6acd3d8 ] The ignore mask logic in send_to_group() does not match the logic in fanotify_should_send_event(). In the latter, a vfsmount mark ignore mask precedes an inode mark mask and in the former, it does not. That difference may cause events to be sent to fanotify backend for no reason. Fix the logic in send_to_group() to match that of fanotify_should_send_event(). Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/notify/fsnotify.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 074716293829..d76c81323dc1 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -192,8 +192,9 @@ static int send_to_group(struct inode *to_tell, struct fsnotify_iter_info *iter_info) { struct fsnotify_group *group = NULL; - __u32 inode_test_mask = 0; - __u32 vfsmount_test_mask = 0; + __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); + __u32 marks_mask = 0; + __u32 marks_ignored_mask = 0; if (unlikely(!inode_mark && !vfsmount_mark)) { BUG(); @@ -213,29 +214,25 @@ static int send_to_group(struct inode *to_tell, /* does the inode mark tell us to do something? */ if (inode_mark) { group = inode_mark->group; - inode_test_mask = (mask & ~FS_EVENT_ON_CHILD); - inode_test_mask &= inode_mark->mask; - inode_test_mask &= ~inode_mark->ignored_mask; + marks_mask |= inode_mark->mask; + marks_ignored_mask |= inode_mark->ignored_mask; } /* does the vfsmount_mark tell us to do something? */ if (vfsmount_mark) { - vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD); group = vfsmount_mark->group; - vfsmount_test_mask &= vfsmount_mark->mask; - vfsmount_test_mask &= ~vfsmount_mark->ignored_mask; - if (inode_mark) - vfsmount_test_mask &= ~inode_mark->ignored_mask; + marks_mask |= vfsmount_mark->mask; + marks_ignored_mask |= vfsmount_mark->ignored_mask; } pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p" - " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x" + " vfsmount_mark=%p marks_mask=%x marks_ignored_mask=%x" " data=%p data_is=%d cookie=%d\n", - __func__, group, to_tell, mask, inode_mark, - inode_test_mask, vfsmount_mark, vfsmount_test_mask, data, + __func__, group, to_tell, mask, inode_mark, vfsmount_mark, + marks_mask, marks_ignored_mask, data, data_is, cookie); - if (!inode_test_mask && !vfsmount_test_mask) + if (!(test_mask & marks_mask & ~marks_ignored_mask)) return 0; return group->ops->handle_event(group, to_tell, inode_mark, -- GitLab From e7b720ef94d8582a1346e6aebf03f8a59e682b17 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Thu, 12 Apr 2018 22:30:44 -0400 Subject: [PATCH 0488/1299] MIPS: io: Add barrier after register read in readX() [ Upstream commit a1cc7034e33d12dc17d13fbcd7d597d552889097 ] While a barrier is present in the writeX() functions before the register write, a similar barrier is missing in the readX() functions after the register read. This could allow memory accesses following readX() to observe stale data. Signed-off-by: Sinan Kaya Reported-by: Arnd Bergmann Cc: Ralf Baechle Cc: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/19069/ [jhogan@kernel.org: Tidy commit message] Signed-off-by: James Hogan Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/mips/include/asm/io.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index fd00ddafb425..a7d0b836f2f7 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -377,6 +377,8 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ BUG(); \ } \ \ + /* prevent prefetching of coherent DMA data prematurely */ \ + rmb(); \ return pfx##ioswab##bwlq(__mem, __val); \ } -- GitLab From d27cd5cb9b384803d69204b07b447e9abe32f127 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Tue, 3 Apr 2018 11:08:52 +0200 Subject: [PATCH 0489/1299] s390/smsgiucv: disable SMSG on module unload [ Upstream commit 760dd0eeaec1689430243ead14e5a429613d8c52 ] The module exit function of the smsgiucv module uses the incorrect CP command to disable SMSG messages. The correct command is "SET SMSG OFF". Use it. Signed-off-by: Martin Schwidefsky Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/s390/net/smsgiucv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index a851d34c642b..04674ce961f1 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -189,7 +189,7 @@ static struct device_driver smsg_driver = { static void __exit smsg_exit(void) { - cpcmd("SET SMSG IUCV", NULL, 0, NULL); + cpcmd("SET SMSG OFF", NULL, 0, NULL); device_unregister(smsg_dev); iucv_unregister(&smsg_handler, 1); driver_unregister(&smsg_driver); -- GitLab From ba041775a9a8291327f958d6337d130217de1bee Mon Sep 17 00:00:00 2001 From: Chengguang Xu Date: Sat, 14 Apr 2018 20:16:06 +0800 Subject: [PATCH 0490/1299] isofs: fix potential memory leak in mount option parsing [ Upstream commit 4f34a5130a471f32f2fe7750769ab4057dc3eaa0 ] When specifying string type mount option (e.g., iocharset) several times in a mount, current option parsing may cause memory leak. Hence, call kfree for previous one in this case. Meanwhile, check memory allocation result for it. Signed-off-by: Chengguang Xu Signed-off-by: Jan Kara Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/isofs/inode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 447a24d77b89..ed4edcd2bc56 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -394,7 +394,10 @@ static int parse_options(char *options, struct iso9660_options *popt) break; #ifdef CONFIG_JOLIET case Opt_iocharset: + kfree(popt->iocharset); popt->iocharset = match_strdup(&args[0]); + if (!popt->iocharset) + return 0; break; #endif case Opt_map_a: -- GitLab From b3ccb8a77ed11c366fe8d3c3d64a71b5ddf44a75 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Fri, 13 Apr 2018 09:50:44 +0100 Subject: [PATCH 0491/1299] MIPS: dts: Boston: Fix PCI bus dtc warnings: [ Upstream commit 2c2bf522ed8cbfaac666f7dc65cfd38de2b89f0f ] dtc recently (v1.4.4-8-g756ffc4f52f6) added PCI bus checks. Fix the warnings now emitted: arch/mips/boot/dts/img/boston.dtb: Warning (pci_bridge): /pci@10000000: missing bus-range for PCI bridge arch/mips/boot/dts/img/boston.dtb: Warning (pci_bridge): /pci@12000000: missing bus-range for PCI bridge arch/mips/boot/dts/img/boston.dtb: Warning (pci_bridge): /pci@14000000: missing bus-range for PCI bridge Signed-off-by: Matt Redfearn Cc: Ralf Baechle Cc: Paul Burton Cc: Rob Herring Cc: Mark Rutland Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/19070/ Signed-off-by: James Hogan Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/mips/boot/dts/img/boston.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/boot/dts/img/boston.dts b/arch/mips/boot/dts/img/boston.dts index 2cd49b60e030..f7aad80c69ab 100644 --- a/arch/mips/boot/dts/img/boston.dts +++ b/arch/mips/boot/dts/img/boston.dts @@ -51,6 +51,8 @@ ranges = <0x02000000 0 0x40000000 0x40000000 0 0x40000000>; + bus-range = <0x00 0xff>; + interrupt-map-mask = <0 0 0 7>; interrupt-map = <0 0 0 1 &pci0_intc 1>, <0 0 0 2 &pci0_intc 2>, @@ -79,6 +81,8 @@ ranges = <0x02000000 0 0x20000000 0x20000000 0 0x20000000>; + bus-range = <0x00 0xff>; + interrupt-map-mask = <0 0 0 7>; interrupt-map = <0 0 0 1 &pci1_intc 1>, <0 0 0 2 &pci1_intc 2>, @@ -107,6 +111,8 @@ ranges = <0x02000000 0 0x16000000 0x16000000 0 0x100000>; + bus-range = <0x00 0xff>; + interrupt-map-mask = <0 0 0 7>; interrupt-map = <0 0 0 1 &pci2_intc 1>, <0 0 0 2 &pci2_intc 2>, -- GitLab From 3ca7dddaa13f8e7f4e618bf54dad2d18e9efc251 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Fri, 13 Apr 2018 15:44:16 +0300 Subject: [PATCH 0492/1299] spi: sh-msiof: Fix bit field overflow writes to TSCR/RSCR [ Upstream commit 10b4640833e95eeacaef8060bc1b35e636df3218 ] The change fixes a bit field overflow which allows to write to higher bits while calculating SPI transfer clock and setting BRPS and BRDV bit fields, the problem is reproduced if 'parent_rate' to 'spi_hz' ratio is greater than 1024, for instance p->min_div = 2, MSO rate = 33333333, SPI device rate = 10000 results in k = 5, i.e. BRDV = 0b100 or 1/32 prescaler output, BRPS = 105, TSCR value = 0x6804, thus MSSEL and MSIMM bit fields are non-zero. Fixes: 65d5665bb260 ("spi: sh-msiof: Update calculation of frequency dividing") Signed-off-by: Vladimir Zapolskiy Signed-off-by: Mark Brown Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/spi/spi-sh-msiof.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 2770fbd4ce49..52056535f54e 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -277,6 +277,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, } k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_div_table) - 1); + brps = min_t(int, brps, 32); scr = sh_msiof_spi_div_table[k].brdv | SCR_BRPS(brps); sh_msiof_write(p, TSCR, scr); -- GitLab From 5eeb26c58c0a66cade30410aaeb112e866cb8c2e Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Wed, 4 Apr 2018 09:52:04 +0200 Subject: [PATCH 0493/1299] doc: Add vendor prefix for Kieback & Peter GmbH [ Upstream commit 99bf8f27f3f94d2a37291354b8dc83f13728f75f ] The 'kiebackpeter' entry has been added to vendor-prefixes.txt to indicate products from Kieback & Peter GmbH. Signed-off-by: Lukasz Majewski Signed-off-by: Rob Herring Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 1afd298eddd7..f4a98c85340a 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -172,6 +172,7 @@ karo Ka-Ro electronics GmbH keithkoep Keith & Koep GmbH keymile Keymile GmbH khadas Khadas +kiebackpeter Kieback & Peter GmbH kinetic Kinetic Technologies kingnovel Kingnovel Technology Co., Ltd. kosagi Sutajio Ko-Usagi PTE Ltd. -- GitLab From 20d3d7fa75b2edf6618d288367ec8de5cac1cf84 Mon Sep 17 00:00:00 2001 From: Matheus Castello Date: Wed, 11 Apr 2018 01:17:03 -0400 Subject: [PATCH 0494/1299] dt-bindings: pinctrl: sunxi: Fix reference to driver [ Upstream commit b614e905a0bc8fc5d4fa72665ac26ae00c874a4e ] Bindings describe hardware, not drivers. Use reference to hardware Allwinner A1X Pin Controller instead driver. Signed-off-by: Matheus Castello Signed-off-by: Rob Herring Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- .../devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt index 6f2ec9af0de2..dee9520224a9 100644 --- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt @@ -55,9 +55,9 @@ pins it needs, and how they should be configured, with regard to muxer configuration, drive strength and pullups. If one of these options is not set, its actual value will be unspecified. -This driver supports the generic pin multiplexing and configuration -bindings. For details on each properties, you can refer to -./pinctrl-bindings.txt. +Allwinner A1X Pin Controller supports the generic pin multiplexing and +configuration bindings. For details on each properties, you can refer to + ./pinctrl-bindings.txt. Required sub-node properties: - pins -- GitLab From 20d68135933707021bdd708cf2238a66975f0dc3 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Mon, 16 Apr 2018 15:55:28 +0200 Subject: [PATCH 0495/1299] dt-bindings: serial: sh-sci: Add support for r8a77965 (H)SCIF [ Upstream commit 7de5b7e5f6a67c285b86d1478e8e150929c93482 ] Add documentation for r8a77965 compatible string to Renesas sci-serial device tree bindings documentation. Signed-off-by: Jacopo Mondi Reviewed-by: Geert Uytterhoeven Signed-off-by: Rob Herring Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/renesas,sci-serial.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt index cf504d0380ae..88f947c47adc 100644 --- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt +++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt @@ -41,6 +41,8 @@ Required properties: - "renesas,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART. - "renesas,scif-r8a7796" for R8A7796 (R-Car M3-W) SCIF compatible UART. - "renesas,hscif-r8a7796" for R8A7796 (R-Car M3-W) HSCIF compatible UART. + - "renesas,scif-r8a77965" for R8A77965 (R-Car M3-N) SCIF compatible UART. + - "renesas,hscif-r8a77965" for R8A77965 (R-Car M3-N) HSCIF compatible UART. - "renesas,scif-r8a77970" for R8A77970 (R-Car V3M) SCIF compatible UART. - "renesas,hscif-r8a77970" for R8A77970 (R-Car V3M) HSCIF compatible UART. - "renesas,scif-r8a77995" for R8A77995 (R-Car D3) SCIF compatible UART. -- GitLab From dccf9862a7f5afe8c81bd52302918c33d9ba57d6 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Mon, 16 Apr 2018 15:56:08 +0200 Subject: [PATCH 0496/1299] dt-bindings: dmaengine: rcar-dmac: document R8A77965 support [ Upstream commit b89bc283286b105e50aab9ab35992c0237ac77d8 ] Add documentation for r8a77965 compatible string to rcar-dmac device tree bindings documentation. Signed-off-by: Jacopo Mondi Reviewed-by: Geert Uytterhoeven Reviewed-by: Simon Horman Signed-off-by: Rob Herring Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt index 891db41e9420..98d7898fcd78 100644 --- a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt +++ b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt @@ -25,6 +25,7 @@ Required Properties: - "renesas,dmac-r8a7794" (R-Car E2) - "renesas,dmac-r8a7795" (R-Car H3) - "renesas,dmac-r8a7796" (R-Car M3-W) + - "renesas,dmac-r8a77965" (R-Car M3-N) - "renesas,dmac-r8a77970" (R-Car V3M) - reg: base address and length of the registers block for the DMAC -- GitLab From 9d33f89c40e9c9ae42a69e49566a3efdc165b0dd Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 9 Apr 2018 15:59:20 +0200 Subject: [PATCH 0497/1299] clk: honor CLK_MUX_ROUND_CLOSEST in generic clk mux [ Upstream commit 4ad69b80e886a845f56ce0a3d10211208693d92b ] CLK_MUX_ROUND_CLOSEST is part of the clk_mux documentation but clk_mux directly calls __clk_mux_determine_rate(), which overrides the flag. As result, if clk_mux is instantiated with CLK_MUX_ROUND_CLOSEST, the flag will be ignored and the clock rounded down. To solve this, this patch expose clk_mux_determine_rate_flags() in the clk-provider API and uses it in the determine_rate() callback of clk_mux. Fixes: 15a02c1f6dd7 ("clk: Add __clk_mux_determine_rate_closest") Signed-off-by: Jerome Brunet Signed-off-by: Stephen Boyd Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/clk/clk-mux.c | 10 +++++++++- drivers/clk/clk.c | 7 ++++--- include/linux/clk-provider.h | 3 +++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 16a3d5717f4e..a062f79bc509 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -101,10 +101,18 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) return 0; } +static int clk_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_mux *mux = to_clk_mux(hw); + + return clk_mux_determine_rate_flags(hw, req, mux->flags); +} + const struct clk_ops clk_mux_ops = { .get_parent = clk_mux_get_parent, .set_parent = clk_mux_set_parent, - .determine_rate = __clk_mux_determine_rate, + .determine_rate = clk_mux_determine_rate, }; EXPORT_SYMBOL_GPL(clk_mux_ops); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 4e21f5bcd954..6f4c98ca6e50 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -351,9 +351,9 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now, return now <= rate && now > best; } -static int -clk_mux_determine_rate_flags(struct clk_hw *hw, struct clk_rate_request *req, - unsigned long flags) +int clk_mux_determine_rate_flags(struct clk_hw *hw, + struct clk_rate_request *req, + unsigned long flags) { struct clk_core *core = hw->core, *parent, *best_parent = NULL; int i, num_parents, ret; @@ -413,6 +413,7 @@ clk_mux_determine_rate_flags(struct clk_hw *hw, struct clk_rate_request *req, return 0; } +EXPORT_SYMBOL_GPL(clk_mux_determine_rate_flags); struct clk *__clk_lookup(const char *name) { diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 86eb33f67618..2f4e79fe7b86 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -752,6 +752,9 @@ int __clk_mux_determine_rate(struct clk_hw *hw, int __clk_determine_rate(struct clk_hw *core, struct clk_rate_request *req); int __clk_mux_determine_rate_closest(struct clk_hw *hw, struct clk_rate_request *req); +int clk_mux_determine_rate_flags(struct clk_hw *hw, + struct clk_rate_request *req, + unsigned long flags); void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent); void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate, unsigned long max_rate); -- GitLab From 3f54483edea26a11f24085cd299707c212762e95 Mon Sep 17 00:00:00 2001 From: "oder_chiou@realtek.com" Date: Fri, 30 Mar 2018 15:41:55 +0800 Subject: [PATCH 0498/1299] ASoC: rt5514: Add the missing register in the readable table [ Upstream commit 5ef5ac8de125fe6b4b23293bee026ca7ea1529b9 ] The patch adds the missing register in the readable table. Signed-off-by: Oder Chiou Signed-off-by: Mark Brown Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/rt5514.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index d7956ababd11..e52e68b56238 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -89,6 +89,7 @@ static const struct reg_default rt5514_reg[] = { {RT5514_PLL3_CALIB_CTRL5, 0x40220012}, {RT5514_DELAY_BUF_CTRL1, 0x7fff006a}, {RT5514_DELAY_BUF_CTRL3, 0x00000000}, + {RT5514_ASRC_IN_CTRL1, 0x00000003}, {RT5514_DOWNFILTER0_CTRL1, 0x00020c2f}, {RT5514_DOWNFILTER0_CTRL2, 0x00020c2f}, {RT5514_DOWNFILTER0_CTRL3, 0x10000362}, @@ -181,6 +182,7 @@ static bool rt5514_readable_register(struct device *dev, unsigned int reg) case RT5514_PLL3_CALIB_CTRL5: case RT5514_DELAY_BUF_CTRL1: case RT5514_DELAY_BUF_CTRL3: + case RT5514_ASRC_IN_CTRL1: case RT5514_DOWNFILTER0_CTRL1: case RT5514_DOWNFILTER0_CTRL2: case RT5514_DOWNFILTER0_CTRL3: @@ -238,6 +240,7 @@ static bool rt5514_i2c_readable_register(struct device *dev, case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL5: case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL1: case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL3: + case RT5514_DSP_MAPPING | RT5514_ASRC_IN_CTRL1: case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL1: case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL2: case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL3: -- GitLab From d066fd9d7e9b41d60c5dca81ec5d5dbb0664a32f Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 28 Mar 2018 23:41:52 +0000 Subject: [PATCH 0499/1299] eCryptfs: don't pass up plaintext names when using filename encryption [ Upstream commit e86281e700cca8a773f9a572fa406adf2784ba5c ] Both ecryptfs_filldir() and ecryptfs_readlink_lower() use ecryptfs_decode_and_decrypt_filename() to translate lower filenames to upper filenames. The function correctly passes up lower filenames, unchanged, when filename encryption isn't in use. However, it was also passing up lower filenames when the filename wasn't encrypted or when decryption failed. Since 88ae4ab9802e, eCryptfs refuses to lookup lower plaintext names when filename encryption is enabled so this resulted in a situation where userspace would see lower plaintext filenames in calls to getdents(2) but then not be able to lookup those filenames. An example of this can be seen when enabling filename encryption on an eCryptfs mount at the root directory of an Ext4 filesystem: $ ls -1i /lower 12 ECRYPTFS_FNEK_ENCRYPTED.FWYZD8TcW.5FV-TKTEYOHsheiHX9a-w.NURCCYIMjI8pn5BDB9-h3fXwrE-- 11 lost+found $ ls -1i /upper ls: cannot access '/upper/lost+found': No such file or directory ? lost+found 12 test With this change, the lower lost+found dentry is ignored: $ ls -1i /lower 12 ECRYPTFS_FNEK_ENCRYPTED.FWYZD8TcW.5FV-TKTEYOHsheiHX9a-w.NURCCYIMjI8pn5BDB9-h3fXwrE-- 11 lost+found $ ls -1i /upper 12 test Additionally, some potentially noisy error/info messages in the related code paths are turned into debug messages so that the logs can't be easily filled. Fixes: 88ae4ab9802e ("ecryptfs_lookup(): try either only encrypted or plaintext name") Reported-by: Guenter Roeck Cc: Al Viro Signed-off-by: Tyler Hicks Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/crypto.c | 41 ++++++++++++++++++++++++++++------------- fs/ecryptfs/file.c | 21 ++++++++++++++++----- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index e5e29f8c920b..9d1823efff34 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -2026,6 +2026,16 @@ int ecryptfs_encrypt_and_encode_filename( return rc; } +static bool is_dot_dotdot(const char *name, size_t name_size) +{ + if (name_size == 1 && name[0] == '.') + return true; + else if (name_size == 2 && name[0] == '.' && name[1] == '.') + return true; + + return false; +} + /** * ecryptfs_decode_and_decrypt_filename - converts the encoded cipher text name to decoded plaintext * @plaintext_name: The plaintext name @@ -2050,13 +2060,21 @@ int ecryptfs_decode_and_decrypt_filename(char **plaintext_name, size_t packet_size; int rc = 0; - if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) - && !(mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) - && (name_size > ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) - && (strncmp(name, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX, - ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) == 0)) { - const char *orig_name = name; - size_t orig_name_size = name_size; + if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) && + !(mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)) { + if (is_dot_dotdot(name, name_size)) { + rc = ecryptfs_copy_filename(plaintext_name, + plaintext_name_size, + name, name_size); + goto out; + } + + if (name_size <= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE || + strncmp(name, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX, + ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE)) { + rc = -EINVAL; + goto out; + } name += ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; name_size -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; @@ -2079,12 +2097,9 @@ int ecryptfs_decode_and_decrypt_filename(char **plaintext_name, decoded_name, decoded_name_size); if (rc) { - printk(KERN_INFO "%s: Could not parse tag 70 packet " - "from filename; copying through filename " - "as-is\n", __func__); - rc = ecryptfs_copy_filename(plaintext_name, - plaintext_name_size, - orig_name, orig_name_size); + ecryptfs_printk(KERN_DEBUG, + "%s: Could not parse tag 70 packet from filename\n", + __func__); goto out_free; } } else { diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index c74ed3ca3372..b76a9853325e 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -82,17 +82,28 @@ ecryptfs_filldir(struct dir_context *ctx, const char *lower_name, buf->sb, lower_name, lower_namelen); if (rc) { - printk(KERN_ERR "%s: Error attempting to decode and decrypt " - "filename [%s]; rc = [%d]\n", __func__, lower_name, - rc); - goto out; + if (rc != -EINVAL) { + ecryptfs_printk(KERN_DEBUG, + "%s: Error attempting to decode and decrypt filename [%s]; rc = [%d]\n", + __func__, lower_name, rc); + return rc; + } + + /* Mask -EINVAL errors as these are most likely due a plaintext + * filename present in the lower filesystem despite filename + * encryption being enabled. One unavoidable example would be + * the "lost+found" dentry in the root directory of an Ext4 + * filesystem. + */ + return 0; } + buf->caller->pos = buf->ctx.pos; rc = !dir_emit(buf->caller, name, name_size, ino, d_type); kfree(name); if (!rc) buf->entries_written++; -out: + return rc; } -- GitLab From 3050437392722eb9eaad327dcd5d10a069010670 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sun, 1 Apr 2018 09:42:25 -0700 Subject: [PATCH 0500/1299] soc: bcm: raspberrypi-power: Fix use of __packed [ Upstream commit 0a12e80ce4230434c2ed66ad0d65af0b7ccecea8 ] Commit a09cd356586d ("ARM: bcm2835: add rpi power domain driver") attempted to annotate the structure rpi_power_domain_packet with __packed but introduced a typo and made it named __packet instead. Just drop the annotation since the structure is naturally aligned already. Fixes: a09cd356586d ("ARM: bcm2835: add rpi power domain driver") Signed-off-by: Florian Fainelli Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/soc/bcm/raspberrypi-power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/bcm/raspberrypi-power.c b/drivers/soc/bcm/raspberrypi-power.c index fe96a8b956fb..f7ed1187518b 100644 --- a/drivers/soc/bcm/raspberrypi-power.c +++ b/drivers/soc/bcm/raspberrypi-power.c @@ -45,7 +45,7 @@ struct rpi_power_domains { struct rpi_power_domain_packet { u32 domain; u32 on; -} __packet; +}; /* * Asks the firmware to enable or disable power on a specific power -- GitLab From 150efd30c3a0d0f1fc250ebdb198dff80bf86730 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 8 Apr 2018 11:05:15 +0200 Subject: [PATCH 0501/1299] soc: bcm2835: Make !RASPBERRYPI_FIRMWARE dummies return failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 144345a4a8c3b497a3f60d3af9d6071a37660186 ] If CONFIG_RASPBERRYPI_FIRMWARE=n: drivers/gpio/gpio-raspberrypi-exp.c: In function ‘rpi_exp_gpio_get_polarity’: drivers/gpio/gpio-raspberrypi-exp.c:71: warning: ‘get.polarity’ is used uninitialized in this function drivers/gpio/gpio-raspberrypi-exp.c: In function ‘rpi_exp_gpio_get_direction’: drivers/gpio/gpio-raspberrypi-exp.c:150: warning: ‘get.direction’ is used uninitialized in this function The dummy firmware interface functions return 0, which means success, causing subsequent code to make use of the never initialized output parameter. Fix this by making the dummy functions return an error code (-ENOSYS) instead. Note that this assumes the firmware always fills in the requested data in the CONFIG_RASPBERRYPI_FIRMWARE=y case. Fixes: d45f1a563b92dac7 ("staging: vc04_services: fix up rpi firmware functions") Signed-off-by: Geert Uytterhoeven Reviewed-by: Eric Anholt Signed-off-by: Florian Fainelli Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- include/soc/bcm2835/raspberrypi-firmware.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h index cb979ad90401..b86c4c367004 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h +++ b/include/soc/bcm2835/raspberrypi-firmware.h @@ -125,13 +125,13 @@ struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node); static inline int rpi_firmware_property(struct rpi_firmware *fw, u32 tag, void *data, size_t len) { - return 0; + return -ENOSYS; } static inline int rpi_firmware_property_list(struct rpi_firmware *fw, void *data, size_t tag_size) { - return 0; + return -ENOSYS; } static inline struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node) -- GitLab From bd8acfd77dd336afa8f22bb6f0ed24a7d479c355 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Tue, 3 Apr 2018 11:19:01 +0200 Subject: [PATCH 0502/1299] PCI: kirin: Fix reset gpio name [ Upstream commit 5db8f8d1099bd93a64a80b609dbcce887327ffc8 ] As documented in the devicetree bindings (pci/kirin-pcie.txt) and the reset gpio name must be 'reset-gpios'. However, current driver erroneously looks for a 'reset-gpio' resource which makes the driver probe fail. Fix it. Fixes: fc5165db245a ("PCI: kirin: Add HiSilicon Kirin SoC PCIe controller driver") Signed-off-by: Loic Poulain [lorenzo.pieralisi@arm.com: updated the commit log] Signed-off-by: Lorenzo Pieralisi Acked-by: Xiaowei Song Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/dwc/pcie-kirin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/dwc/pcie-kirin.c b/drivers/pci/dwc/pcie-kirin.c index dc3033cf3c19..efc317e7669d 100644 --- a/drivers/pci/dwc/pcie-kirin.c +++ b/drivers/pci/dwc/pcie-kirin.c @@ -490,7 +490,7 @@ static int kirin_pcie_probe(struct platform_device *pdev) return ret; kirin_pcie->gpio_id_reset = of_get_named_gpio(dev->of_node, - "reset-gpio", 0); + "reset-gpios", 0); if (kirin_pcie->gpio_id_reset < 0) return -ENODEV; -- GitLab From d5cf1ed8d3ae37a6115a0696a4885df1c777a9e9 Mon Sep 17 00:00:00 2001 From: Yan Wang Date: Mon, 26 Mar 2018 16:48:00 +0100 Subject: [PATCH 0503/1299] ASoC: topology: Fix bugs of freeing soc topology [ Upstream commit feb12f0cd8d7b1e8df2e6fce19fc9a026a468cc2 ] In snd_soc_tplg_component_remove(), it should compare index and not dobj->index with SND_SOC_TPLG_INDEX_ALL for removing all topology objects. Signed-off-by: Yan Wang Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- sound/soc/soc-topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index e5049fbfc4f1..b64d128ecdac 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -2571,7 +2571,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index) /* match index */ if (dobj->index != index && - dobj->index != SND_SOC_TPLG_INDEX_ALL) + index != SND_SOC_TPLG_INDEX_ALL) continue; switch (dobj->type) { -- GitLab From ff3080bab10dcbd694b903eb8d70586c6f48b64b Mon Sep 17 00:00:00 2001 From: Simon Gaiser Date: Thu, 15 Mar 2018 04:08:03 +0100 Subject: [PATCH 0504/1299] xen: xenbus_dev_frontend: Really return response string [ Upstream commit ebf04f331fa15a966262341a7dc6b1a0efd633e4 ] xenbus_command_reply() did not actually copy the response string and leaked stack content instead. Fixes: 9a6161fe73bd ("xen: return xenstore command failures via response instead of rc") Signed-off-by: Simon Gaiser Reviewed-by: Juergen Gross Signed-off-by: Boris Ostrovsky Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/xen/xenbus/xenbus_dev_frontend.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c index d2edbc79384a..83243af22d51 100644 --- a/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -403,7 +403,7 @@ static int xenbus_command_reply(struct xenbus_file_priv *u, { struct { struct xsd_sockmsg hdr; - const char body[16]; + char body[16]; } msg; int rc; @@ -412,6 +412,7 @@ static int xenbus_command_reply(struct xenbus_file_priv *u, msg.hdr.len = strlen(reply) + 1; if (msg.hdr.len > sizeof(msg.body)) return -E2BIG; + memcpy(&msg.body, reply, msg.hdr.len); mutex_lock(&u->reply_mutex); rc = queue_reply(&u->read_buffers, &msg, sizeof(msg.hdr) + msg.hdr.len); -- GitLab From 5f4bf078e779927200b246d05f569dbe75543ace Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 27 Mar 2018 14:30:44 +0100 Subject: [PATCH 0505/1299] ASoC: topology: Check widget kcontrols before deref. [ Upstream commit 05bdcf12905533b8628627b6634608cd3b57c607 ] Validate the topology input before we dereference the pointer. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- sound/soc/soc-topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index b64d128ecdac..30cdad2eab7f 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -510,7 +510,7 @@ static void remove_widget(struct snd_soc_component *comp, */ if (dobj->widget.kcontrol_type == SND_SOC_TPLG_TYPE_ENUM) { /* enumerated widget mixer */ - for (i = 0; i < w->num_kcontrols; i++) { + for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) { struct snd_kcontrol *kcontrol = w->kcontrols[i]; struct soc_enum *se = (struct soc_enum *)kcontrol->private_value; @@ -528,7 +528,7 @@ static void remove_widget(struct snd_soc_component *comp, kfree(w->kcontrol_news); } else { /* volume mixer or bytes controls */ - for (i = 0; i < w->num_kcontrols; i++) { + for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) { struct snd_kcontrol *kcontrol = w->kcontrols[i]; if (dobj->widget.kcontrol_type -- GitLab From c5b6316c3f5139cbc1d9a37cd6b86bb7be3802bf Mon Sep 17 00:00:00 2001 From: sxauwsk Date: Tue, 17 Apr 2018 04:01:27 +0800 Subject: [PATCH 0506/1299] spi: cadence: Add usleep_range() for cdns_spi_fill_tx_fifo() [ Upstream commit 49530e6411789c1b9ea3ebc58e520c19d1c3752f ] In case of xspi work in busy condition, may send bytes failed. once something wrong, spi controller did't work any more My test found this situation appear in both of read/write process. so when TX FIFO is full, add one byte delay before send data; Signed-off-by: sxauwsk Signed-off-by: Mark Brown Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/spi/spi-cadence.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 5c9516ae4942..4a001634023e 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -313,6 +313,14 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) while ((trans_cnt < CDNS_SPI_FIFO_DEPTH) && (xspi->tx_bytes > 0)) { + + /* When xspi in busy condition, bytes may send failed, + * then spi control did't work thoroughly, add one byte delay + */ + if (cdns_spi_read(xspi, CDNS_SPI_ISR) & + CDNS_SPI_IXR_TXFULL) + usleep_range(10, 20); + if (xspi->txbuf) cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); else -- GitLab From 9d5e2d69705fed4ab527f5a283b90ae602f4e0fd Mon Sep 17 00:00:00 2001 From: Jiang Biao Date: Wed, 18 Apr 2018 08:37:18 -0600 Subject: [PATCH 0507/1299] blkcg: don't hold blkcg lock when deactivating policy [ Upstream commit 946b81da114b8ba5c74bb01e57c0c6eca2bdc801 ] As described in the comment of blkcg_activate_policy(), *Update of each blkg is protected by both queue and blkcg locks so that holding either lock and testing blkcg_policy_enabled() is always enough for dereferencing policy data.* with queue lock held, there is no need to hold blkcg lock in blkcg_deactivate_policy(). Similar case is in blkcg_activate_policy(), which has removed holding of blkcg lock in commit 4c55f4f9ad3001ac1fefdd8d8ca7641d18558e23. Signed-off-by: Jiang Biao Signed-off-by: Wen Yang CC: Tejun Heo Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- block/blk-cgroup.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index d3f56baee936..00b133c44474 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -1374,17 +1374,12 @@ void blkcg_deactivate_policy(struct request_queue *q, __clear_bit(pol->plid, q->blkcg_pols); list_for_each_entry(blkg, &q->blkg_list, q_node) { - /* grab blkcg lock too while removing @pd from @blkg */ - spin_lock(&blkg->blkcg->lock); - if (blkg->pd[pol->plid]) { if (pol->pd_offline_fn) pol->pd_offline_fn(blkg->pd[pol->plid]); pol->pd_free_fn(blkg->pd[pol->plid]); blkg->pd[pol->plid] = NULL; } - - spin_unlock(&blkg->blkcg->lock); } spin_unlock_irq(q->queue_lock); -- GitLab From 3f64c0c502ef050846c6dc1b56a9510afee53328 Mon Sep 17 00:00:00 2001 From: Tung Nguyen Date: Tue, 17 Apr 2018 21:58:27 +0200 Subject: [PATCH 0508/1299] tipc: fix infinite loop when dumping link monitor summary [ Upstream commit 36a50a989ee8267588de520b8704b85f045a3220 ] When configuring the number of used bearers to MAX_BEARER and issuing command "tipc link monitor summary", the command enters infinite loop in user space. This issue happens because function tipc_nl_node_dump_monitor() returns the wrong 'prev_bearer' value when all potential monitors have been scanned. The correct behavior is to always try to scan all monitors until either the netlink message is full, in which case we return the bearer identity of the affected monitor, or we continue through the whole bearer array until we can return MAX_BEARERS. This solution also caters for the case where there may be gaps in the bearer array. Signed-off-by: Tung Nguyen Signed-off-by: Jon Maloy Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/tipc/monitor.c | 2 +- net/tipc/node.c | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/net/tipc/monitor.c b/net/tipc/monitor.c index 0fcfb3916dcf..254ddc2c3914 100644 --- a/net/tipc/monitor.c +++ b/net/tipc/monitor.c @@ -768,7 +768,7 @@ int __tipc_nl_add_monitor(struct net *net, struct tipc_nl_msg *msg, ret = tipc_bearer_get_name(net, bearer_name, bearer_id); if (ret || !mon) - return -EINVAL; + return 0; hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, NLM_F_MULTI, TIPC_NL_MON_GET); diff --git a/net/tipc/node.c b/net/tipc/node.c index f6c5743c170e..0d97395d60d5 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -2113,8 +2113,8 @@ int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb) struct net *net = sock_net(skb->sk); u32 prev_bearer = cb->args[0]; struct tipc_nl_msg msg; + int bearer_id; int err; - int i; if (prev_bearer == MAX_BEARERS) return 0; @@ -2124,16 +2124,13 @@ int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb) msg.seq = cb->nlh->nlmsg_seq; rtnl_lock(); - for (i = prev_bearer; i < MAX_BEARERS; i++) { - prev_bearer = i; + for (bearer_id = prev_bearer; bearer_id < MAX_BEARERS; bearer_id++) { err = __tipc_nl_add_monitor(net, &msg, prev_bearer); if (err) - goto out; + break; } - -out: rtnl_unlock(); - cb->args[0] = prev_bearer; + cb->args[0] = bearer_id; return skb->len; } -- GitLab From af2cc1d2e75c50ce0dbbd3455608790c4fe07fbd Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Mon, 9 Apr 2018 15:15:28 -0700 Subject: [PATCH 0509/1299] scsi: iscsi: respond to netlink with unicast when appropriate [ Upstream commit af17092810a887178195276255b7b31f8fbe7dbe ] Instead of always multicasting responses, send a unicast netlink message directed at the correct pid. This will be needed if we ever want to support multiple userspace processes interacting with the kernel over iSCSI netlink simultaneously. Limitations can currently be seen if you attempt to run multiple iscsistart commands in parallel. We've fixed up the userspace issues in iscsistart that prevented multiple instances from running, so now attempts to speed up booting by bringing up multiple iscsi sessions at once in the initramfs are just running into misrouted responses that this fixes. Signed-off-by: Chris Leech Reviewed-by: Lee Duncan Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_transport_iscsi.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 7404d26895f5..f6542c159ed6 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2322,6 +2322,12 @@ iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp) return nlmsg_multicast(nls, skb, 0, group, gfp); } +static int +iscsi_unicast_skb(struct sk_buff *skb, u32 portid) +{ + return nlmsg_unicast(nls, skb, portid); +} + int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size) { @@ -2524,14 +2530,11 @@ void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport, EXPORT_SYMBOL_GPL(iscsi_ping_comp_event); static int -iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi, - void *payload, int size) +iscsi_if_send_reply(u32 portid, int type, void *payload, int size) { struct sk_buff *skb; struct nlmsghdr *nlh; int len = nlmsg_total_size(size); - int flags = multi ? NLM_F_MULTI : 0; - int t = done ? NLMSG_DONE : type; skb = alloc_skb(len, GFP_ATOMIC); if (!skb) { @@ -2539,10 +2542,9 @@ iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi, return -ENOMEM; } - nlh = __nlmsg_put(skb, 0, 0, t, (len - sizeof(*nlh)), 0); - nlh->nlmsg_flags = flags; + nlh = __nlmsg_put(skb, 0, 0, type, (len - sizeof(*nlh)), 0); memcpy(nlmsg_data(nlh), payload, size); - return iscsi_multicast_skb(skb, group, GFP_ATOMIC); + return iscsi_unicast_skb(skb, portid); } static int @@ -3470,6 +3472,7 @@ static int iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) { int err = 0; + u32 portid; struct iscsi_uevent *ev = nlmsg_data(nlh); struct iscsi_transport *transport = NULL; struct iscsi_internal *priv; @@ -3490,10 +3493,12 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) if (!try_module_get(transport->owner)) return -EINVAL; + portid = NETLINK_CB(skb).portid; + switch (nlh->nlmsg_type) { case ISCSI_UEVENT_CREATE_SESSION: err = iscsi_if_create_session(priv, ep, ev, - NETLINK_CB(skb).portid, + portid, ev->u.c_session.initial_cmdsn, ev->u.c_session.cmds_max, ev->u.c_session.queue_depth); @@ -3506,7 +3511,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) } err = iscsi_if_create_session(priv, ep, ev, - NETLINK_CB(skb).portid, + portid, ev->u.c_bound_session.initial_cmdsn, ev->u.c_bound_session.cmds_max, ev->u.c_bound_session.queue_depth); @@ -3664,6 +3669,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) static void iscsi_if_rx(struct sk_buff *skb) { + u32 portid = NETLINK_CB(skb).portid; + mutex_lock(&rx_queue_mutex); while (skb->len >= NLMSG_HDRLEN) { int err; @@ -3699,8 +3706,8 @@ iscsi_if_rx(struct sk_buff *skb) break; if (ev->type == ISCSI_UEVENT_GET_CHAP && !err) break; - err = iscsi_if_send_reply(group, nlh->nlmsg_seq, - nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); + err = iscsi_if_send_reply(portid, nlh->nlmsg_type, + ev, sizeof(*ev)); } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH); skb_pull(skb, rlen); } -- GitLab From 4fb7926bba584ed7045551f8a40d0a4b0a89d2fd Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Wed, 21 Mar 2018 21:04:12 +0000 Subject: [PATCH 0510/1299] scsi: megaraid_sas: Do not log an error if FW successfully initializes. [ Upstream commit fb1633d56b0025233ed3dc49b44544748d509d9d ] Fixes: 2d2c2331673c ("scsi: megaraid_sas: modified few prints in OCR and IOC INIT path") Signed-off-by: Vinson Lee Acked-by: Shivasharan S Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 4bf406df051b..72a919179d06 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -903,7 +903,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) goto fail_fw_init; } - ret = 0; + return 0; fail_fw_init: megasas_return_cmd(instance, cmd); @@ -913,8 +913,8 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) IOCInitMessage, ioc_init_handle); fail_get_cmd: dev_err(&instance->pdev->dev, - "Init cmd return status %s for SCSI host %d\n", - ret ? "FAILED" : "SUCCESS", instance->host->host_no); + "Init cmd return status FAILED for SCSI host %d\n", + instance->host->host_no); return ret; } -- GitLab From 348288a2699c046a524aac1a43a1fa1d508945ba Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Mon, 16 Apr 2018 17:48:41 +0800 Subject: [PATCH 0511/1299] scsi: target: fix crash with iscsi target and dvd [ Upstream commit 8e1ceafe50ec4d1bcfae154dd70e7cb6946a6177 ] When the current page can't be added to bio, one new bio should be created for adding this page again, instead of ignoring this page. This patch fixes kernel crash with iscsi target and dvd, as reported by Wakko. Cc: Wakko Warner Cc: Bart Van Assche Cc: target-devel@vger.kernel.org Cc: linux-scsi@vger.kernel.org Cc: "Nicholas A. Bellinger" Cc: Christoph Hellwig Fixes: 84c8590646d5b35804 ("target: avoid accessing .bi_vcnt directly") Signed-off-by: Ming Lei Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_pscsi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 0d99b242e82e..6cb933ecc084 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -890,6 +890,7 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, bytes = min(bytes, data_len); if (!bio) { +new_bio: nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages); nr_pages -= nr_vecs; /* @@ -931,6 +932,7 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, * be allocated with pscsi_get_bio() above. */ bio = NULL; + goto new_bio; } data_len -= bytes; -- GitLab From d11b04c348940a0331689551385858298e7e1a84 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 18 Apr 2018 12:23:39 +0200 Subject: [PATCH 0512/1299] netfilter: nf_tables: NAT chain and extensions require NF_TABLES [ Upstream commit 39f2ff0816e5421476c2bc538b68b4bb0708a78e ] Move these options inside the scope of the 'if' NF_TABLES and NF_TABLES_IPV6 dependencies. This patch fixes: net/ipv6/netfilter/nft_chain_nat_ipv6.o: In function `nft_nat_do_chain': >> net/ipv6/netfilter/nft_chain_nat_ipv6.c:37: undefined reference to `nft_do_chain' net/ipv6/netfilter/nft_chain_nat_ipv6.o: In function `nft_chain_nat_ipv6_exit': >> net/ipv6/netfilter/nft_chain_nat_ipv6.c:94: undefined reference to `nft_unregister_chain_type' net/ipv6/netfilter/nft_chain_nat_ipv6.o: In function `nft_chain_nat_ipv6_init': >> net/ipv6/netfilter/nft_chain_nat_ipv6.c:87: undefined reference to `nft_register_chain_type' that happens with: CONFIG_NF_TABLES=m CONFIG_NFT_CHAIN_NAT_IPV6=y Fixes: 02c7b25e5f54 ("netfilter: nf_tables: build-in filter chain type") Reported-by: kbuild test robot Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/ipv6/netfilter/Kconfig | 55 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 6acb2eecd986..c764c2a77d94 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -48,6 +48,34 @@ config NFT_CHAIN_ROUTE_IPV6 fields such as the source, destination, flowlabel, hop-limit and the packet mark. +if NF_NAT_IPV6 + +config NFT_CHAIN_NAT_IPV6 + tristate "IPv6 nf_tables nat chain support" + help + This option enables the "nat" chain for IPv6 in nf_tables. This + chain type is used to perform Network Address Translation (NAT) + packet transformations such as the source, destination address and + source and destination ports. + +config NFT_MASQ_IPV6 + tristate "IPv6 masquerade support for nf_tables" + depends on NFT_MASQ + select NF_NAT_MASQUERADE_IPV6 + help + This is the expression that provides IPv4 masquerading support for + nf_tables. + +config NFT_REDIR_IPV6 + tristate "IPv6 redirect support for nf_tables" + depends on NFT_REDIR + select NF_NAT_REDIRECT + help + This is the expression that provides IPv4 redirect support for + nf_tables. + +endif # NF_NAT_IPV6 + config NFT_REJECT_IPV6 select NF_REJECT_IPV6 default NFT_REJECT @@ -99,39 +127,12 @@ config NF_NAT_IPV6 if NF_NAT_IPV6 -config NFT_CHAIN_NAT_IPV6 - depends on NF_TABLES_IPV6 - tristate "IPv6 nf_tables nat chain support" - help - This option enables the "nat" chain for IPv6 in nf_tables. This - chain type is used to perform Network Address Translation (NAT) - packet transformations such as the source, destination address and - source and destination ports. - config NF_NAT_MASQUERADE_IPV6 tristate "IPv6 masquerade support" help This is the kernel functionality to provide NAT in the masquerade flavour (automatic source address selection) for IPv6. -config NFT_MASQ_IPV6 - tristate "IPv6 masquerade support for nf_tables" - depends on NF_TABLES_IPV6 - depends on NFT_MASQ - select NF_NAT_MASQUERADE_IPV6 - help - This is the expression that provides IPv4 masquerading support for - nf_tables. - -config NFT_REDIR_IPV6 - tristate "IPv6 redirect support for nf_tables" - depends on NF_TABLES_IPV6 - depends on NFT_REDIR - select NF_NAT_REDIRECT - help - This is the expression that provides IPv4 redirect support for - nf_tables. - endif # NF_NAT_IPV6 config IP6_NF_IPTABLES -- GitLab From 705fd605237b384051cf64b1bfeb223f6478d6cb Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Wed, 18 Apr 2018 23:35:34 +0900 Subject: [PATCH 0513/1299] netfilter: nf_tables: fix out-of-bounds in nft_chain_commit_update [ Upstream commit d71efb599ad42ef1e564c652d8084252bdc85edf ] When chain name is changed, nft_chain_commit_update is called. In the nft_chain_commit_update, trans->ctx.chain->name has old chain name and nft_trans_chain_name(trans) has new chain name. If new chain name is longer than old chain name, KASAN warns slab-out-of-bounds. [ 175.015012] BUG: KASAN: slab-out-of-bounds in strcpy+0x9e/0xb0 [ 175.022735] Write of size 1 at addr ffff880114e022da by task iptables-compat/1458 [ 175.031353] CPU: 0 PID: 1458 Comm: iptables-compat Not tainted 4.16.0-rc7+ #146 [ 175.031353] Hardware name: To be filled by O.E.M. To be filled by O.E.M./Aptio CRB, BIOS 5.6.5 07/08/2015 [ 175.031353] Call Trace: [ 175.031353] dump_stack+0x68/0xa0 [ 175.031353] print_address_description+0xd0/0x260 [ 175.031353] ? strcpy+0x9e/0xb0 [ 175.031353] kasan_report+0x234/0x350 [ 175.031353] __asan_report_store1_noabort+0x1c/0x20 [ 175.031353] strcpy+0x9e/0xb0 [ 175.031353] nf_tables_commit+0x1ccc/0x2990 [ 175.031353] nfnetlink_rcv+0x141e/0x16c0 [ 175.031353] ? nfnetlink_net_init+0x150/0x150 [ 175.031353] ? lock_acquire+0x370/0x370 [ 175.031353] ? lock_acquire+0x370/0x370 [ 175.031353] netlink_unicast+0x444/0x640 [ 175.031353] ? netlink_attachskb+0x700/0x700 [ 175.031353] ? _copy_from_iter_full+0x180/0x740 [ 175.031353] ? kasan_check_write+0x14/0x20 [ 175.031353] ? _copy_from_user+0x9b/0xd0 [ 175.031353] netlink_sendmsg+0x845/0xc70 [ ... ] Steps to reproduce: iptables-compat -N 1 iptables-compat -E 1 aaaaaaaaa Signed-off-by: Taehee Yoo Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_tables_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 689e9c0570ba..cf30c440f7a7 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -4977,7 +4977,7 @@ static void nft_chain_commit_update(struct nft_trans *trans) struct nft_base_chain *basechain; if (nft_trans_chain_name(trans)) - strcpy(trans->ctx.chain->name, nft_trans_chain_name(trans)); + swap(trans->ctx.chain->name, nft_trans_chain_name(trans)); if (!nft_is_base_chain(trans->ctx.chain)) return; -- GitLab From 625b5b8c76d42afdf5ebcd7fa8da9fa2fcebfd67 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 18 Apr 2018 18:46:37 +0100 Subject: [PATCH 0514/1299] ASoC: msm8916-wcd-analog: use threaded context for mbhc events [ Upstream commit a8419a0cd98ddf628a9e38a92110af7cc650dde7 ] As snd_soc_jack_report() can sleep, move handling of mbhc events to a thread context rather than in interrupt context. Fixes: de66b3455023 ('ASoC: codecs: msm8916-wcd-analog: add MBHC support') Reported-by: Bjorn Andersson Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/msm8916-wcd-analog.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 8c7063e1aa46..0b9b014b4bb6 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -1184,7 +1184,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) return irq; } - ret = devm_request_irq(dev, irq, pm8916_mbhc_switch_irq_handler, + ret = devm_request_threaded_irq(dev, irq, NULL, + pm8916_mbhc_switch_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "mbhc switch irq", priv); @@ -1198,7 +1199,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) return irq; } - ret = devm_request_irq(dev, irq, mbhc_btn_press_irq_handler, + ret = devm_request_threaded_irq(dev, irq, NULL, + mbhc_btn_press_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "mbhc btn press irq", priv); @@ -1211,7 +1213,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) return irq; } - ret = devm_request_irq(dev, irq, mbhc_btn_release_irq_handler, + ret = devm_request_threaded_irq(dev, irq, NULL, + mbhc_btn_release_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "mbhc btn release irq", priv); -- GitLab From be04f7301d8dc92a0c54392da26bd9b474ed7a2b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 3 Apr 2018 23:38:45 +0100 Subject: [PATCH 0515/1299] drm/msm: Fix possible null dereference on failure of get_pages() [ Upstream commit 3976626ea3d2011f8fd3f3a47070a8b792018253 ] Commit 62e3a3e342af changed get_pages() to initialise msm_gem_object::pages before trying to initialise msm_gem_object::sgt, so that put_pages() would properly clean up pages in the failure case. However, this means that put_pages() now needs to check that msm_gem_object::sgt is not null before trying to clean it up, and this check was only applied to part of the cleanup code. Move it all into the conditional block. (Strictly speaking we don't need to make the kfree() conditional, but since we can't avoid checking for null ourselves we may as well do so.) Fixes: 62e3a3e342af ("drm/msm: fix leak in failed get_pages") Signed-off-by: Ben Hutchings Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/msm/msm_gem.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 6e0fb50d0de4..f2df718af370 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -132,17 +132,19 @@ static void put_pages(struct drm_gem_object *obj) struct msm_gem_object *msm_obj = to_msm_bo(obj); if (msm_obj->pages) { - /* For non-cached buffers, ensure the new pages are clean - * because display controller, GPU, etc. are not coherent: - */ - if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) - dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); + if (msm_obj->sgt) { + /* For non-cached buffers, ensure the new + * pages are clean because display controller, + * GPU, etc. are not coherent: + */ + if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) + dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, + msm_obj->sgt->nents, + DMA_BIDIRECTIONAL); - if (msm_obj->sgt) sg_free_table(msm_obj->sgt); - - kfree(msm_obj->sgt); + kfree(msm_obj->sgt); + } if (use_pages(obj)) drm_gem_put_pages(obj, msm_obj->pages, true, false); -- GitLab From 5151a0c8d730509cc92ac2d1a2697dd0fe48be59 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 19 Mar 2018 22:26:32 +0100 Subject: [PATCH 0516/1299] drm/msm/dsi: use correct enum in dsi_get_cmd_fmt [ Upstream commit a4af89286f8fc382459308764ea05935dc477cdc ] The function dsi_get_cmd_fmt returns enum dsi_cmd_dst_format, use the correct enum value also for MIPI_DSI_FMT_RGB666/_PACKED. This has been discovered using clang: drivers/gpu/drm/msm/dsi/dsi_host.c:743:35: warning: implicit conversion from enumeration type 'enum dsi_vid_dst_format' to different enumeration type 'enum dsi_cmd_dst_format' [-Wenum-conversion] case MIPI_DSI_FMT_RGB666: return VID_DST_FORMAT_RGB666; ~~~~~~ ^~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Stefan Agner Reviewed-by: Archit Taneja Signed-off-by: Rob Clark Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index deaf869374ea..a9a0b56f1fbc 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -740,7 +740,7 @@ static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt( switch (mipi_fmt) { case MIPI_DSI_FMT_RGB888: return CMD_DST_FORMAT_RGB888; case MIPI_DSI_FMT_RGB666_PACKED: - case MIPI_DSI_FMT_RGB666: return VID_DST_FORMAT_RGB666; + case MIPI_DSI_FMT_RGB666: return CMD_DST_FORMAT_RGB666; case MIPI_DSI_FMT_RGB565: return CMD_DST_FORMAT_RGB565; default: return CMD_DST_FORMAT_RGB888; } -- GitLab From b6126afd64d069384e41605779e8e27288185359 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Wed, 28 Mar 2018 17:22:16 +0100 Subject: [PATCH 0517/1299] drm/msm: don't deref error pointer in the msm_fbdev_create error path [ Upstream commit 789d4c300e10eb2096ee83c3497118e67ccc951e ] Currently the error pointer returned by msm_alloc_stolen_fb gets passed to drm_framebuffer_remove. The latter handles only NULL pointers, thus a nasty crash will occur. Drop the unnecessary fail label and the associated checks - both err and fb will be set at this stage. Cc: Rob Clark Cc: linux-arm-msm@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: freedreno@lists.freedesktop.org Signed-off-by: Emil Velikov Signed-off-by: Rob Clark Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/msm/msm_fbdev.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index c178563fcd4d..456622b46335 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -92,8 +92,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, if (IS_ERR(fb)) { dev_err(dev->dev, "failed to allocate fb\n"); - ret = PTR_ERR(fb); - goto fail; + return PTR_ERR(fb); } bo = msm_framebuffer_bo(fb, 0); @@ -151,13 +150,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, fail_unlock: mutex_unlock(&dev->struct_mutex); -fail: - - if (ret) { - if (fb) - drm_framebuffer_remove(fb); - } - + drm_framebuffer_remove(fb); return ret; } -- GitLab From ea7246c258922565a53319ddc54684d081d1b4c8 Mon Sep 17 00:00:00 2001 From: Jiang Biao Date: Thu, 19 Apr 2018 12:06:09 +0800 Subject: [PATCH 0518/1299] blkcg: init root blkcg_gq under lock [ Upstream commit 901932a3f9b2b80352896be946c6d577c0a9652c ] The initializing of q->root_blkg is currently outside of queue lock and rcu, so the blkg may be destroied before the initializing, which may cause dangling/null references. On the other side, the destroys of blkg are protected by queue lock or rcu. Put the initializing inside the queue lock and rcu to make it safer. Signed-off-by: Jiang Biao Signed-off-by: Wen Yang CC: Tejun Heo CC: Jens Axboe Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- block/blk-cgroup.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 00b133c44474..3dc7c0b4adcb 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -1149,18 +1149,16 @@ int blkcg_init_queue(struct request_queue *q) rcu_read_lock(); spin_lock_irq(q->queue_lock); blkg = blkg_create(&blkcg_root, q, new_blkg); + if (IS_ERR(blkg)) + goto err_unlock; + q->root_blkg = blkg; + q->root_rl.blkg = blkg; spin_unlock_irq(q->queue_lock); rcu_read_unlock(); if (preloaded) radix_tree_preload_end(); - if (IS_ERR(blkg)) - return PTR_ERR(blkg); - - q->root_blkg = blkg; - q->root_rl.blkg = blkg; - ret = blk_throtl_init(q); if (ret) { spin_lock_irq(q->queue_lock); @@ -1168,6 +1166,13 @@ int blkcg_init_queue(struct request_queue *q) spin_unlock_irq(q->queue_lock); } return ret; + +err_unlock: + spin_unlock_irq(q->queue_lock); + rcu_read_unlock(); + if (preloaded) + radix_tree_preload_end(); + return PTR_ERR(blkg); } /** -- GitLab From bd595dbfcbd640e8270e8fdfe8b91226a80242ac Mon Sep 17 00:00:00 2001 From: dann frazier Date: Wed, 18 Apr 2018 21:55:41 -0600 Subject: [PATCH 0519/1299] net: hns: Avoid action name truncation [ Upstream commit f4ea89110df237da6fbcaab76af431e85f07d904 ] When longer interface names are used, the action names exposed in /proc/interrupts and /proc/irq/* maybe truncated. For example, when using the predictable name algorithm in systemd on a HiSilicon D05, I see: ubuntu@d05-3:~$ grep enahisic2i0-tx /proc/interrupts | sed 's/.* //' enahisic2i0-tx0 enahisic2i0-tx1 [...] enahisic2i0-tx8 enahisic2i0-tx9 enahisic2i0-tx1 enahisic2i0-tx1 enahisic2i0-tx1 enahisic2i0-tx1 enahisic2i0-tx1 enahisic2i0-tx1 Increase the max ring name length to allow for an interface name of IFNAMSIZE. After this change, I now see: $ grep enahisic2i0-tx /proc/interrupts | sed 's/.* //' enahisic2i0-tx0 enahisic2i0-tx1 enahisic2i0-tx2 [...] enahisic2i0-tx8 enahisic2i0-tx9 enahisic2i0-tx10 enahisic2i0-tx11 enahisic2i0-tx12 enahisic2i0-tx13 enahisic2i0-tx14 enahisic2i0-tx15 Signed-off-by: dann frazier Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/hisilicon/hns/hnae.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index 3e62692af011..fa5b30f547f6 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -87,7 +87,7 @@ do { \ #define HNAE_AE_REGISTER 0x1 -#define RCB_RING_NAME_LEN 16 +#define RCB_RING_NAME_LEN (IFNAMSIZ + 4) #define HNAE_LOWEST_LATENCY_COAL_PARAM 30 #define HNAE_LOW_LATENCY_COAL_PARAM 80 -- GitLab From 6bf379f26a549f06a6b38a9594a06b1b213e18de Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 20 Apr 2018 13:35:02 +0100 Subject: [PATCH 0520/1299] vfs: Undo an overly zealous MS_RDONLY -> SB_RDONLY conversion [ Upstream commit a9e5b73288cf1595ac2e05cf1acd1924ceea05fa ] In do_mount() when the MS_* flags are being converted to MNT_* flags, MS_RDONLY got accidentally convered to SB_RDONLY. Undo this change. Fixes: e462ec50cb5f ("VFS: Differentiate mount flags (MS_*) from internal superblock flags") Signed-off-by: David Howells Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index 62b17aff1908..1eb3bfd8be5a 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2810,7 +2810,7 @@ long do_mount(const char *dev_name, const char __user *dir_name, mnt_flags |= MNT_NODIRATIME; if (flags & MS_STRICTATIME) mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME); - if (flags & SB_RDONLY) + if (flags & MS_RDONLY) mnt_flags |= MNT_READONLY; /* The default atime for remount is preservation */ -- GitLab From fc0d99fde0d2439ac7802efcb2f390013198db3b Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 19 Apr 2018 14:51:03 +0800 Subject: [PATCH 0521/1299] parisc: time: Convert read_persistent_clock() to read_persistent_clock64() [ Upstream commit f76cdd00ef0e39d880139b074e3b247594dff95a ] The read_persistent_clock() uses a timespec, which is not year 2038 safe on 32bit systems. On parisc architecture, we have implemented generic RTC drivers that can be used to compensate the system suspend time, but the RTC time can not represent the nanosecond resolution, so this patch just converts to read_persistent_clock64() with timespec64. Signed-off-by: Baolin Wang Acked-by: Arnd Bergmann Signed-off-by: Helge Deller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index f7e684560186..42a873226a04 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -205,7 +205,7 @@ static int __init rtc_init(void) device_initcall(rtc_init); #endif -void read_persistent_clock(struct timespec *ts) +void read_persistent_clock64(struct timespec64 *ts) { static struct pdc_tod tod_data; if (pdc_tod_read(&tod_data) == 0) { -- GitLab From 12f9bb1a273e29c0b51b5894803f8076dc5e4a8e Mon Sep 17 00:00:00 2001 From: Long Li Date: Thu, 22 Mar 2018 14:47:18 -0700 Subject: [PATCH 0522/1299] scsi: storvsc: Set up correct queue depth values for IDE devices [ Upstream commit f286299c1d0ba5e2ca0377610307b370fe178767 ] Unlike SCSI and FC, we don't use multiple channels for IDE. Also fix the calculation for sub-channels. Signed-off-by: Long Li Reviewed-by: Michael Kelley Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/storvsc_drv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index c44de0b4a995..beb585ddc07d 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1725,11 +1725,14 @@ static int storvsc_probe(struct hv_device *device, max_targets = STORVSC_MAX_TARGETS; max_channels = STORVSC_MAX_CHANNELS; /* - * On Windows8 and above, we support sub-channels for storage. + * On Windows8 and above, we support sub-channels for storage + * on SCSI and FC controllers. * The number of sub-channels offerred is based on the number of * VCPUs in the guest. */ - max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel); + if (!dev_is_ide) + max_sub_channels = + (num_cpus - 1) / storvsc_vcpus_per_sub_channel; } scsi_driver.can_queue = (max_outstanding_req_per_channel * -- GitLab From 6385f2da8b3bda687ae5e9f7c60655cfeb16632a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 20 Apr 2018 10:57:16 +0100 Subject: [PATCH 0523/1299] scsi: isci: Fix infinite loop in while loop [ Upstream commit 4bc83b3f272fe8f36450f9c003df49cf07ffe5fd ] In the case when the phy_mask is bitwise anded with the phy_index bit is zero the continue statement currently jumps to the next iteration of the while loop and phy_index is never actually incremented, potentially causing an infinite loop if phy_index is less than SCI_MAX_PHS. Fix this by turning the while loop into a for loop. Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/isci/port_config.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index ac879745ef80..18a409bb9e0c 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -291,7 +291,7 @@ sci_mpc_agent_validate_phy_configuration(struct isci_host *ihost, * Note: We have not moved the current phy_index so we will actually * compare the startting phy with itself. * This is expected and required to add the phy to the port. */ - while (phy_index < SCI_MAX_PHYS) { + for (; phy_index < SCI_MAX_PHYS; phy_index++) { if ((phy_mask & (1 << phy_index)) == 0) continue; sci_phy_get_sas_address(&ihost->phys[phy_index], @@ -311,7 +311,6 @@ sci_mpc_agent_validate_phy_configuration(struct isci_host *ihost, &ihost->phys[phy_index]); assigned_phy_mask |= (1 << phy_index); - phy_index++; } } -- GitLab From a20600762300154bb6ed99eea6b16abd1163dbea Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Fri, 20 Apr 2018 14:55:38 -0700 Subject: [PATCH 0524/1299] mm, pagemap: fix swap offset value for PMD migration entry [ Upstream commit 88c28f2469151b031f8cea9b28ed5be1b74a4172 ] The swap offset reported by /proc//pagemap may be not correct for PMD migration entries. If addr passed into pagemap_pmd_range() isn't aligned with PMD start address, the swap offset reported doesn't reflect this. And in the loop to report information of each sub-page, the swap offset isn't increased accordingly as that for PFN. This may happen after opening /proc//pagemap and seeking to a page whose address doesn't align with a PMD start address. I have verified this with a simple test program. BTW: migration swap entries have PFN information, do we need to restrict whether to show them? [akpm@linux-foundation.org: fix typo, per Huang, Ying] Link: http://lkml.kernel.org/r/20180408033737.10897-1-ying.huang@intel.com Signed-off-by: "Huang, Ying" Cc: Michal Hocko Cc: "Kirill A. Shutemov" Cc: Andrei Vagin Cc: Dan Williams Cc: "Jerome Glisse" Cc: Daniel Colascione Cc: Zi Yan Cc: Naoya Horiguchi Cc: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/proc/task_mmu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 6744bd706ecf..4cd8328e4039 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1327,9 +1327,11 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end, #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION else if (is_swap_pmd(pmd)) { swp_entry_t entry = pmd_to_swp_entry(pmd); + unsigned long offset = swp_offset(entry); + offset += (addr & ~PMD_MASK) >> PAGE_SHIFT; frame = swp_type(entry) | - (swp_offset(entry) << MAX_SWAPFILES_SHIFT); + (offset << MAX_SWAPFILES_SHIFT); flags |= PM_SWAP; if (pmd_swp_soft_dirty(pmd)) flags |= PM_SOFT_DIRTY; @@ -1349,6 +1351,8 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end, break; if (pm->show_pfn && (flags & PM_PRESENT)) frame++; + else if (flags & PM_SWAP) + frame += (1 << MAX_SWAPFILES_SHIFT); } spin_unlock(ptl); return err; -- GitLab From d497efd805fe5e2c2bd77f98bcc0f1700f090f0b Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 20 Apr 2018 14:56:03 -0700 Subject: [PATCH 0525/1299] proc: revalidate kernel thread inodes to root:root [ Upstream commit 2e0ad552f5f8cd0fda02bc45fcd2b89821c62fd1 ] task_dump_owner() has the following code: mm = task->mm; if (mm) { if (get_dumpable(mm) != SUID_DUMP_USER) { uid = ... } } Check for ->mm is buggy -- kernel thread might be borrowing mm and inode will go to some random uid:gid pair. Link: http://lkml.kernel.org/r/20180412220109.GA20978@avx2 Signed-off-by: Alexey Dobriyan Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/proc/base.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/proc/base.c b/fs/proc/base.c index dd9d4d3a2e39..c5c42f3e33d1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1694,6 +1694,12 @@ void task_dump_owner(struct task_struct *task, mode_t mode, kuid_t uid; kgid_t gid; + if (unlikely(task->flags & PF_KTHREAD)) { + *ruid = GLOBAL_ROOT_UID; + *rgid = GLOBAL_ROOT_GID; + return; + } + /* Default to the tasks effective ownership */ rcu_read_lock(); cred = __task_cred(task); -- GitLab From cd2cc6d131709b28032e026f81baa2f9a0d9b88d Mon Sep 17 00:00:00 2001 From: Dave Young Date: Fri, 20 Apr 2018 14:56:10 -0700 Subject: [PATCH 0526/1299] kexec_file: do not add extra alignment to efi memmap [ Upstream commit a841aa83dff0af75c88aa846ba610a8af4c5ee21 ] Chun-Yi reported a kernel warning message below: WARNING: CPU: 0 PID: 0 at ../mm/early_ioremap.c:182 early_iounmap+0x4f/0x12c() early_iounmap(ffffffffff200180, 00000118) [0] size not consistent 00000120 The problem is x86 kexec_file_load adds extra alignment to the efi memmap: in bzImage64_load(): efi_map_sz = efi_get_runtime_map_size(); efi_map_sz = ALIGN(efi_map_sz, 16); And __efi_memmap_init maps with the size including the alignment bytes but efi_memmap_unmap use nr_maps * desc_size which does not include the extra bytes. The alignment in kexec code is only needed for the kexec buffer internal use Actually kexec should pass exact size of the efi memmap to 2nd kernel. Link: http://lkml.kernel.org/r/20180417083600.GA1972@dhcp-128-65.nay.redhat.com Signed-off-by: Dave Young Reported-by: joeyli Tested-by: Randy Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/kexec-bzimage64.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c index fb095ba0c02f..f24cd9f1799a 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c @@ -398,11 +398,10 @@ static void *bzImage64_load(struct kimage *image, char *kernel, * little bit simple */ efi_map_sz = efi_get_runtime_map_size(); - efi_map_sz = ALIGN(efi_map_sz, 16); params_cmdline_sz = sizeof(struct boot_params) + cmdline_len + MAX_ELFCOREHDR_STR_LEN; params_cmdline_sz = ALIGN(params_cmdline_sz, 16); - kbuf.bufsz = params_cmdline_sz + efi_map_sz + + kbuf.bufsz = params_cmdline_sz + ALIGN(efi_map_sz, 16) + sizeof(struct setup_data) + sizeof(struct efi_setup_data); @@ -410,7 +409,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel, if (!params) return ERR_PTR(-ENOMEM); efi_map_offset = params_cmdline_sz; - efi_setup_data_offset = efi_map_offset + efi_map_sz; + efi_setup_data_offset = efi_map_offset + ALIGN(efi_map_sz, 16); /* Copy setup header onto bootparams. Documentation/x86/boot.txt */ setup_header_size = 0x0202 + kernel[0x0201] - setup_hdr_offset; -- GitLab From 6d2707f26892a07c19286c9472e2e32bd441f55e Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Fri, 20 Apr 2018 14:56:17 -0700 Subject: [PATCH 0527/1299] mm: memcg: add __GFP_NOWARN in __memcg_schedule_kmem_cache_create() [ Upstream commit c892fd82cc0632d425ae011a4dd75eb59e9f84ee ] If there is heavy memory pressure, page allocation with __GFP_NOWAIT fails easily although it's order-0 request. I got below warning 9 times for normal boot. : page allocation failure: order:0, mode:0x2200000(GFP_NOWAIT|__GFP_NOTRACK) .. snip .. Call trace: dump_backtrace+0x0/0x4 dump_stack+0xa4/0xc0 warn_alloc+0xd4/0x15c __alloc_pages_nodemask+0xf88/0x10fc alloc_slab_page+0x40/0x18c new_slab+0x2b8/0x2e0 ___slab_alloc+0x25c/0x464 __kmalloc+0x394/0x498 memcg_kmem_get_cache+0x114/0x2b8 kmem_cache_alloc+0x98/0x3e8 mmap_region+0x3bc/0x8c0 do_mmap+0x40c/0x43c vm_mmap_pgoff+0x15c/0x1e4 sys_mmap+0xb0/0xc8 el0_svc_naked+0x24/0x28 Mem-Info: active_anon:17124 inactive_anon:193 isolated_anon:0 active_file:7898 inactive_file:712955 isolated_file:55 unevictable:0 dirty:27 writeback:18 unstable:0 slab_reclaimable:12250 slab_unreclaimable:23334 mapped:19310 shmem:212 pagetables:816 bounce:0 free:36561 free_pcp:1205 free_cma:35615 Node 0 active_anon:68496kB inactive_anon:772kB active_file:31592kB inactive_file:2851820kB unevictable:0kB isolated(anon):0kB isolated(file):220kB mapped:77240kB dirty:108kB writeback:72kB shmem:848kB writeback_tmp:0kB unstable:0kB all_unreclaimable? no DMA free:142188kB min:3056kB low:3820kB high:4584kB active_anon:10052kB inactive_anon:12kB active_file:312kB inactive_file:1412620kB unevictable:0kB writepending:0kB present:1781412kB managed:1604728kB mlocked:0kB slab_reclaimable:3592kB slab_unreclaimable:876kB kernel_stack:400kB pagetables:52kB bounce:0kB free_pcp:1436kB local_pcp:124kB free_cma:142492kB lowmem_reserve[]: 0 1842 1842 Normal free:4056kB min:4172kB low:5212kB high:6252kB active_anon:58376kB inactive_anon:760kB active_file:31348kB inactive_file:1439040kB unevictable:0kB writepending:180kB present:2000636kB managed:1923688kB mlocked:0kB slab_reclaimable:45408kB slab_unreclaimable:92460kB kernel_stack:9680kB pagetables:3212kB bounce:0kB free_pcp:3392kB local_pcp:688kB free_cma:0kB lowmem_reserve[]: 0 0 0 DMA: 0*4kB 0*8kB 1*16kB (C) 0*32kB 0*64kB 0*128kB 1*256kB (C) 1*512kB (C) 0*1024kB 1*2048kB (C) 34*4096kB (C) = 142096kB Normal: 228*4kB (UMEH) 172*8kB (UMH) 23*16kB (UH) 24*32kB (H) 5*64kB (H) 1*128kB (H) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 3872kB 721350 total pagecache pages 0 pages in swap cache Swap cache stats: add 0, delete 0, find 0/0 Free swap = 0kB Total swap = 0kB 945512 pages RAM 0 pages HighMem/MovableOnly 63408 pages reserved 51200 pages cma reserved __memcg_schedule_kmem_cache_create() tries to create a shadow slab cache and the worker allocation failure is not really critical because we will retry on the next kmem charge. We might miss some charges but that shouldn't be critical. The excessive allocation failure report is not very helpful. [mhocko@kernel.org: changelog update] Link: http://lkml.kernel.org/r/20180418022912.248417-1-minchan@kernel.org Signed-off-by: Minchan Kim Acked-by: Johannes Weiner Reviewed-by: Andrew Morton Cc: Michal Hocko Cc: Vladimir Davydov Cc: Minchan Kim Cc: Matthew Wilcox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- mm/memcontrol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 546cd481a2ca..942d9342b63b 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2205,7 +2205,7 @@ static void __memcg_schedule_kmem_cache_create(struct mem_cgroup *memcg, { struct memcg_kmem_cache_create_work *cw; - cw = kmalloc(sizeof(*cw), GFP_NOWAIT); + cw = kmalloc(sizeof(*cw), GFP_NOWAIT | __GFP_NOWARN); if (!cw) return; -- GitLab From d3bd4954286b95471c676722f21964ab36cec4d7 Mon Sep 17 00:00:00 2001 From: Tobias Regnery Date: Tue, 10 Apr 2018 10:38:06 +0200 Subject: [PATCH 0528/1299] usb: typec: ucsi: fix tracepoint related build error [ Upstream commit 2f860691c2d2e3af1404ffeb2d22dd5c3dbca811 ] There is the following build error with CONFIG_TYPEC_UCSI=m, CONFIG_FTRACE=y and CONFIG_TRACING=n: ERROR: "__tracepoint_ucsi_command" [drivers/usb/typec/ucsi/typec_ucsi.ko] undefined! ERROR: "__tracepoint_ucsi_register_port" [drivers/usb/typec/ucsi/typec_ucsi.ko] undefined! ERROR: "__tracepoint_ucsi_notify" [drivers/usb/typec/ucsi/typec_ucsi.ko] undefined! ERROR: "__tracepoint_ucsi_reset_ppm" [drivers/usb/typec/ucsi/typec_ucsi.ko] undefined! ERROR: "__tracepoint_ucsi_run_command" [drivers/usb/typec/ucsi/typec_ucsi.ko] undefined! ERROR: "__tracepoint_ucsi_ack" [drivers/usb/typec/ucsi/typec_ucsi.ko] undefined! ERROR: "__tracepoint_ucsi_connector_change" [drivers/usb/typec/ucsi/typec_ucsi.ko] undefined! This compination is quite hard to create because CONFIG_TRACING gets selected only in rare cases without CONFIG_FTRACE. The build failure is caused by conditionally compiling trace.c depending on the wrong option CONFIG_FTRACE. Change this to depend on CONFIG_TRACING like other users of tracepoints do. Fixes: c1b0bc2dabfa ("usb: typec: Add support for UCSI interface") Signed-off-by: Tobias Regnery Acked-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile index b57891c1fd31..7afbea512207 100644 --- a/drivers/usb/typec/ucsi/Makefile +++ b/drivers/usb/typec/ucsi/Makefile @@ -5,6 +5,6 @@ obj-$(CONFIG_TYPEC_UCSI) += typec_ucsi.o typec_ucsi-y := ucsi.o -typec_ucsi-$(CONFIG_FTRACE) += trace.o +typec_ucsi-$(CONFIG_TRACING) += trace.o obj-$(CONFIG_UCSI_ACPI) += ucsi_acpi.o -- GitLab From 71c8e7432a2e2ed11bb78dd524bc1cbe0fbea1d6 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Tue, 10 Apr 2018 23:07:51 +0800 Subject: [PATCH 0529/1299] ACPI / PM: Blacklist Low Power S0 Idle _DSM for ThinkPad X1 Tablet(2016) [ Upstream commit 855c1c2fce8bdbd796cba1d1456ca8f0e876c2f1 ] ThinkPad X1 Tablet(2016) is reported to have issues with the Low Power S0 Idle _DSM interface and since this machine model generally can do ACPI S3 just fine, and user would like to use S3 as default sleep model, add a blacklist entry to disable that interface for ThinkPad X1 Tablet(2016). Link: https://bugzilla.kernel.org/show_bug.cgi?id=199057 Reported-and-tested-by: Robin Lee Signed-off-by: Chen Yu Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/sleep.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 8082871b409a..2ef0ad6a33d6 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -364,6 +364,19 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"), }, }, + /* + * ThinkPad X1 Tablet(2016) cannot do suspend-to-idle using + * the Low Power S0 Idle firmware interface (see + * https://bugzilla.kernel.org/show_bug.cgi?id=199057). + */ + { + .callback = init_no_lps0, + .ident = "ThinkPad X1 Tablet(2016)", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20GGA00L00"), + }, + }, {}, }; -- GitLab From a4fa9189d6084067a7faa384ae1a405267caa48e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 23 Apr 2018 09:32:40 +0200 Subject: [PATCH 0530/1299] dt-bindings: meson-uart: DT fix s/clocks-names/clock-names/ [ Upstream commit 34df2466b48dfe258e14fe2a7bc4641416575ade ] Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/amlogic,meson-uart.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/serial/amlogic,meson-uart.txt b/Documentation/devicetree/bindings/serial/amlogic,meson-uart.txt index 8ff65fa632fd..c06c045126fc 100644 --- a/Documentation/devicetree/bindings/serial/amlogic,meson-uart.txt +++ b/Documentation/devicetree/bindings/serial/amlogic,meson-uart.txt @@ -21,7 +21,7 @@ Required properties: - interrupts : identifier to the device interrupt - clocks : a list of phandle + clock-specifier pairs, one for each entry in clock names. -- clocks-names : +- clock-names : * "xtal" for external xtal clock identifier * "pclk" for the bus core clock, either the clk81 clock or the gate clock * "baud" for the source of the baudrate generator, can be either the xtal -- GitLab From b0471926ceb538d1bd75576a853dbb19722eff25 Mon Sep 17 00:00:00 2001 From: Balbir Singh Date: Fri, 6 Apr 2018 15:24:24 +1000 Subject: [PATCH 0531/1299] powerpc/powernv/memtrace: Let the arch hotunplug code flush cache [ Upstream commit 7fd6641de28fe9b5bce0c38d2adee0a72a72619e ] Don't do this via custom code, instead now that we have support in the arch hotplug/hotunplug code, rely on those routines to do the right thing. The existing flush doesn't work because it uses ppc64_caches.l1d.size instead of ppc64_caches.l1d.line_size. Fixes: 9d5171a8f248 ("powerpc/powernv: Enable removal of memory for in memory tracing") Signed-off-by: Balbir Singh Reviewed-by: Rashmica Gupta Signed-off-by: Michael Ellerman Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/powernv/memtrace.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c index de470caf0784..fc222a0c2ac4 100644 --- a/arch/powerpc/platforms/powernv/memtrace.c +++ b/arch/powerpc/platforms/powernv/memtrace.c @@ -82,19 +82,6 @@ static const struct file_operations memtrace_fops = { .open = simple_open, }; -static void flush_memory_region(u64 base, u64 size) -{ - unsigned long line_size = ppc64_caches.l1d.size; - u64 end = base + size; - u64 addr; - - base = round_down(base, line_size); - end = round_up(end, line_size); - - for (addr = base; addr < end; addr += line_size) - asm volatile("dcbf 0,%0" : "=r" (addr) :: "memory"); -} - static int check_memblock_online(struct memory_block *mem, void *arg) { if (mem->state != MEM_ONLINE) @@ -132,10 +119,6 @@ static bool memtrace_offline_pages(u32 nid, u64 start_pfn, u64 nr_pages) walk_memory_range(start_pfn, end_pfn, (void *)MEM_OFFLINE, change_memblock_state); - /* RCU grace period? */ - flush_memory_region((u64)__va(start_pfn << PAGE_SHIFT), - nr_pages << PAGE_SHIFT); - lock_device_hotplug(); remove_memory(nid, start_pfn << PAGE_SHIFT, nr_pages << PAGE_SHIFT); unlock_device_hotplug(); -- GitLab From 9148e21d7624fd4d6b69383c8988978c7ec84ef8 Mon Sep 17 00:00:00 2001 From: Jingju Hou Date: Mon, 23 Apr 2018 15:22:49 +0800 Subject: [PATCH 0532/1299] net: phy: marvell: clear wol event before setting it [ Upstream commit b6a930fa88083b41d26ddf1cab95cbd740936c22 ] If WOL event happened once, the LED[2] interrupt pin will not be cleared unless we read the CSISR register. If interrupts are in use, the normal interrupt handling will clear the WOL event. Let's clear the WOL event before enabling it if !phy_interrupt_is_valid(). Signed-off-by: Jingju Hou Signed-off-by: Jisheng Zhang Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/net/phy/marvell.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index a3f456b91c99..e9e67c22c8bb 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -1409,6 +1409,15 @@ static int m88e1318_set_wol(struct phy_device *phydev, if (err < 0) return err; + /* If WOL event happened once, the LED[2] interrupt pin + * will not be cleared unless we reading the interrupt status + * register. If interrupts are in use, the normal interrupt + * handling will clear the WOL event. Clear the WOL event + * before enabling it if !phy_interrupt_is_valid() + */ + if (!phy_interrupt_is_valid(phydev)) + phy_read(phydev, MII_M1011_IEVENT); + /* Enable the WOL interrupt */ temp = phy_read(phydev, MII_88E1318S_PHY_CSIER); temp |= MII_88E1318S_PHY_CSIER_WOL_EIE; -- GitLab From 00a85086e51fc213d66d15d5693dc4ff29ab68bd Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 17 Apr 2018 18:06:00 +0530 Subject: [PATCH 0533/1299] ARM: dts: da850: fix W=1 warnings with pinmux node [ Upstream commit 94a82284ad4711b7f9fd78981fdc7a1cb645030b ] Remove unused #address-cells and #size-cells from pinmux node. This fixes W=1 warnings of the type: arch/arm/boot/dts/da850-lcdk.dtb: Warning (avoid_unnecessary_addr_size): /soc@1c00000/pinmux@14120: unnecessary #address-cells/#size-cells without "ranges" or child "reg" property Tested on DA850 LCDK by checking output of: /sys/kernel/debug/pinctrl/1c14120.pinmux-pinctrl-single/pins before and after the change. Reviewed-by: David Lechner Signed-off-by: Sekhar Nori Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/da850.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index af68ef7b0caa..8a15f7193c82 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -34,8 +34,6 @@ pmx_core: pinmux@14120 { compatible = "pinctrl-single"; reg = <0x14120 0x50>; - #address-cells = <1>; - #size-cells = <0>; #pinctrl-cells = <2>; pinctrl-single,bit-per-mux; pinctrl-single,register-width = <32>; -- GitLab From 73ea96beb771e7a1670eeb9d945a00d6bf1855d5 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 23 Apr 2018 14:16:03 +0300 Subject: [PATCH 0534/1299] ACPI / watchdog: Prefer iTCO_wdt on Lenovo Z50-70 [ Upstream commit a0a37862a4e1844793d39aca9ccb8fecbdcb8659 ] WDAT table on Lenovo Z50-70 is using RTC SRAM (ports 0x70 and 0x71) to store state of the timer. This conflicts with Linux RTC driver (rtc-cmos.c) who fails to reserve those ports for itself preventing RTC from functioning. In addition the WDAT table seems not to be fully functional because it does not reset the system when the watchdog times out. On this system iTCO_wdt works just fine so we simply prefer to use it instead of WDAT. This makes RTC working again and also results working watchdog via iTCO_wdt. Reported-by: Peter Milley Link: https://bugzilla.kernel.org/show_bug.cgi?id=199033 Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/acpi_watchdog.c | 59 ++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/acpi_watchdog.c b/drivers/acpi/acpi_watchdog.c index ebb626ffb5fa..4bde16fb97d8 100644 --- a/drivers/acpi/acpi_watchdog.c +++ b/drivers/acpi/acpi_watchdog.c @@ -12,23 +12,64 @@ #define pr_fmt(fmt) "ACPI: watchdog: " fmt #include +#include #include #include #include "internal.h" +static const struct dmi_system_id acpi_watchdog_skip[] = { + { + /* + * On Lenovo Z50-70 there are two issues with the WDAT + * table. First some of the instructions use RTC SRAM + * to store persistent information. This does not work well + * with Linux RTC driver. Second, more important thing is + * that the instructions do not actually reset the system. + * + * On this particular system iTCO_wdt seems to work just + * fine so we prefer that over WDAT for now. + * + * See also https://bugzilla.kernel.org/show_bug.cgi?id=199033. + */ + .ident = "Lenovo Z50-70", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20354"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Z50-70"), + }, + }, + {} +}; + +static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void) +{ + const struct acpi_table_wdat *wdat = NULL; + acpi_status status; + + if (acpi_disabled) + return NULL; + + if (dmi_check_system(acpi_watchdog_skip)) + return NULL; + + status = acpi_get_table(ACPI_SIG_WDAT, 0, + (struct acpi_table_header **)&wdat); + if (ACPI_FAILURE(status)) { + /* It is fine if there is no WDAT */ + return NULL; + } + + return wdat; +} + /** * Returns true if this system should prefer ACPI based watchdog instead of * the native one (which are typically the same hardware). */ bool acpi_has_watchdog(void) { - struct acpi_table_header hdr; - - if (acpi_disabled) - return false; - - return ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_WDAT, 0, &hdr)); + return !!acpi_watchdog_get_wdat(); } EXPORT_SYMBOL_GPL(acpi_has_watchdog); @@ -41,12 +82,10 @@ void __init acpi_watchdog_init(void) struct platform_device *pdev; struct resource *resources; size_t nresources = 0; - acpi_status status; int i; - status = acpi_get_table(ACPI_SIG_WDAT, 0, - (struct acpi_table_header **)&wdat); - if (ACPI_FAILURE(status)) { + wdat = acpi_watchdog_get_wdat(); + if (!wdat) { /* It is fine if there is no WDAT */ return; } -- GitLab From 56dfe52e04a287eb8c1d25d8fcfaef9e32fcd2e8 Mon Sep 17 00:00:00 2001 From: Andres Rodriguez Date: Tue, 10 Apr 2018 17:32:33 -0400 Subject: [PATCH 0535/1299] drm/amdkfd: fix clock counter retrieval for node without GPU [ Upstream commit 1cf6cc74bbeb85bb87c3ca3f3df97a283c3aa737 ] Currently if a user requests clock counters for a node without a GPU resource we will always return EINVAL. Instead if no GPU resource is attached, fill the gpu_clock_counter argument with zeroes so that we may proceed and return valid CPU counters. Signed-off-by: Andres Rodriguez Signed-off-by: Felix Kuehling Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 660b3fbade41..8a05efa7edf0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -716,12 +716,13 @@ static int kfd_ioctl_get_clock_counters(struct file *filep, struct timespec64 time; dev = kfd_device_by_id(args->gpu_id); - if (dev == NULL) - return -EINVAL; - - /* Reading GPU clock counter from KGD */ - args->gpu_clock_counter = - dev->kfd2kgd->get_gpu_clock_counter(dev->kgd); + if (dev) + /* Reading GPU clock counter from KGD */ + args->gpu_clock_counter = + dev->kfd2kgd->get_gpu_clock_counter(dev->kgd); + else + /* Node without GPU resource */ + args->gpu_clock_counter = 0; /* No access to rdtsc. Using raw monotonic time */ getrawmonotonic64(&time); -- GitLab From b1d0907c6feddcfe13f26b901d7e28c22d6650c0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 22 Apr 2018 19:56:17 +0200 Subject: [PATCH 0536/1299] thermal: int3403_thermal: Fix NULL pointer deref on module load / probe [ Upstream commit 13b86f50eaaddaea4bdd2fe476fd12e6a0951add ] Starting with kernel 4.17 thermal_cooling_device_register() will call the get_max_state() op during register. Since we deref priv->priv in int3403_get_max_state() this means we must set priv->priv before calling thermal_cooling_device_register(). Signed-off-by: Hans de Goede Signed-off-by: Zhang Rui Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/thermal/int340x_thermal/int3403_thermal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/thermal/int340x_thermal/int3403_thermal.c b/drivers/thermal/int340x_thermal/int3403_thermal.c index 8a7f24dd9315..0c19fcd56a0d 100644 --- a/drivers/thermal/int340x_thermal/int3403_thermal.c +++ b/drivers/thermal/int340x_thermal/int3403_thermal.c @@ -194,6 +194,7 @@ static int int3403_cdev_add(struct int3403_priv *priv) return -EFAULT; } + priv->priv = obj; obj->max_state = p->package.count - 1; obj->cdev = thermal_cooling_device_register(acpi_device_bid(priv->adev), @@ -201,8 +202,6 @@ static int int3403_cdev_add(struct int3403_priv *priv) if (IS_ERR(obj->cdev)) result = PTR_ERR(obj->cdev); - priv->priv = obj; - kfree(buf.pointer); /* TODO: add ACPI notification support */ -- GitLab From ef0fa5e6f52b5850440bd3cf144220b688af8b3a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 23 Apr 2018 15:51:38 -0700 Subject: [PATCH 0537/1299] net: ethtool: Add missing kernel doc for FEC parameters [ Upstream commit d805c5209350ae725e3a1ee0204ba27d9e75ce3e ] While adding support for ethtool::get_fecparam and set_fecparam, kernel doc for these functions was missed, add those. Fixes: 1a5f3da20bd9 ("net: ethtool: add support for forward error correction modes") Signed-off-by: Florian Fainelli Acked-by: Roopa Prabhu Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- include/linux/ethtool.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 0c0146e7e274..59fbe005f204 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -300,6 +300,8 @@ bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, * fields should be ignored (use %__ETHTOOL_LINK_MODE_MASK_NBITS * instead of the latter), any change to them will be overwritten * by kernel. Returns a negative error code or zero. + * @get_fecparam: Get the network device Forward Error Correction parameters. + * @set_fecparam: Set the network device Forward Error Correction parameters. * * All operations are optional (i.e. the function pointer may be set * to %NULL) and callers must take this into account. Callers must -- GitLab From e6ec885f5f4ce93f5fb446c52131ac159e7e63f6 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 24 Apr 2018 13:11:22 +0100 Subject: [PATCH 0538/1299] arm64: ptrace: remove addr_limit manipulation [ Upstream commit 59275a0c037ed6fabd6354730f1e3104264ab719 ] We transiently switch to KERNEL_DS in compat_ptrace_gethbpregs() and compat_ptrace_sethbpregs(), but in either case this is pointless as we don't perform any uaccess during this window. let's rip out the redundant addr_limit manipulation. Acked-by: Catalin Marinas Signed-off-by: Mark Rutland Cc: Will Deacon Signed-off-by: Will Deacon Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/ptrace.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 9cbb6123208f..85e80a473130 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -1194,9 +1194,7 @@ static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num, { int ret; u32 kdata; - mm_segment_t old_fs = get_fs(); - set_fs(KERNEL_DS); /* Watchpoint */ if (num < 0) { ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata); @@ -1207,7 +1205,6 @@ static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num, } else { ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata); } - set_fs(old_fs); if (!ret) ret = put_user(kdata, data); @@ -1220,7 +1217,6 @@ static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num, { int ret; u32 kdata = 0; - mm_segment_t old_fs = get_fs(); if (num == 0) return 0; @@ -1229,12 +1225,10 @@ static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num, if (ret) return ret; - set_fs(KERNEL_DS); if (num < 0) ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata); else ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata); - set_fs(old_fs); return ret; } -- GitLab From 2f3ca3908fc06af250172cf08210778cfecb66aa Mon Sep 17 00:00:00 2001 From: pgzh Date: Thu, 12 Apr 2018 19:36:47 +0200 Subject: [PATCH 0539/1299] HID: lenovo: Add support for IBM/Lenovo Scrollpoint mice [ Upstream commit a230cd52b8a2be39cd6e9a13b3e62af57f21372a ] The IBM/Lenovo Scrollpoint mice feature a trackpoint-like stick instead of a scrolling wheel capable of 2-D (vertical+horizontal) scrolling. hid-generic does only expose 1-D (vertical) scrolling functionality for these mice. This patch adds support for horizontal scrolling for the IBM/Lenovo Scrollpoint mice to hid-lenovo. [jkosina@suse.cz: remove change versioning from git changelog] Signed-off-by: Peter Ganzhorn Reviewed-by: Benjamin Tissoires Signed-off-by: Peter De Wachter Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/hid/Kconfig | 7 ++++--- drivers/hid/hid-ids.h | 8 ++++++++ drivers/hid/hid-lenovo.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 8c7a0ce147a1..eca4c9d97110 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -436,10 +436,11 @@ config HID_LENOVO select NEW_LEDS select LEDS_CLASS ---help--- - Support for Lenovo devices that are not fully compliant with HID standard. + Support for IBM/Lenovo devices that are not fully compliant with HID standard. - Say Y if you want support for the non-compliant features of the Lenovo - Thinkpad standalone keyboards, e.g: + Say Y if you want support for horizontal scrolling of the IBM/Lenovo + Scrollpoint mice or the non-compliant features of the Lenovo Thinkpad + standalone keyboards, e.g: - ThinkPad USB Keyboard with TrackPoint (supports extra LEDs and trackpoint configuration) - ThinkPad Compact Bluetooth Keyboard with TrackPoint (supports Fn keys) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index ff539c0b4637..9e478f03e845 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -532,6 +532,13 @@ #define USB_VENDOR_ID_HUION 0x256c #define USB_DEVICE_ID_HUION_TABLET 0x006e +#define USB_VENDOR_ID_IBM 0x04b3 +#define USB_DEVICE_ID_IBM_SCROLLPOINT_III 0x3100 +#define USB_DEVICE_ID_IBM_SCROLLPOINT_PRO 0x3103 +#define USB_DEVICE_ID_IBM_SCROLLPOINT_OPTICAL 0x3105 +#define USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL 0x3108 +#define USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO 0x3109 + #define USB_VENDOR_ID_IDEACOM 0x1cb6 #define USB_DEVICE_ID_IDEACOM_IDC6650 0x6650 #define USB_DEVICE_ID_IDEACOM_IDC6651 0x6651 @@ -664,6 +671,7 @@ #define USB_DEVICE_ID_LENOVO_TPKBD 0x6009 #define USB_DEVICE_ID_LENOVO_CUSBKBD 0x6047 #define USB_DEVICE_ID_LENOVO_CBTKBD 0x6048 +#define USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL 0x6049 #define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067 #define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085 #define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3 diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index 1ac4ff4d57a6..643b6eb54442 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c @@ -6,6 +6,17 @@ * * Copyright (c) 2012 Bernhard Seibold * Copyright (c) 2014 Jamie Lentin + * + * Linux IBM/Lenovo Scrollpoint mouse driver: + * - IBM Scrollpoint III + * - IBM Scrollpoint Pro + * - IBM Scrollpoint Optical + * - IBM Scrollpoint Optical 800dpi + * - IBM Scrollpoint Optical 800dpi Pro + * - Lenovo Scrollpoint Optical + * + * Copyright (c) 2012 Peter De Wachter + * Copyright (c) 2018 Peter Ganzhorn */ /* @@ -160,6 +171,17 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, return 0; } +static int lenovo_input_mapping_scrollpoint(struct hid_device *hdev, + struct hid_input *hi, struct hid_field *field, + struct hid_usage *usage, unsigned long **bit, int *max) +{ + if (usage->hid == HID_GD_Z) { + hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL); + return 1; + } + return 0; +} + static int lenovo_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) @@ -172,6 +194,14 @@ static int lenovo_input_mapping(struct hid_device *hdev, case USB_DEVICE_ID_LENOVO_CBTKBD: return lenovo_input_mapping_cptkbd(hdev, hi, field, usage, bit, max); + case USB_DEVICE_ID_IBM_SCROLLPOINT_III: + case USB_DEVICE_ID_IBM_SCROLLPOINT_PRO: + case USB_DEVICE_ID_IBM_SCROLLPOINT_OPTICAL: + case USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL: + case USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO: + case USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL: + return lenovo_input_mapping_scrollpoint(hdev, hi, field, + usage, bit, max); default: return 0; } @@ -883,6 +913,12 @@ static const struct hid_device_id lenovo_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_III) }, + { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_PRO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_OPTICAL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL) }, { } }; -- GitLab From 27e13b330dd2dae63b41855640d2b70517bd67e1 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Tue, 24 Apr 2018 13:33:03 +0530 Subject: [PATCH 0540/1299] HID: wacom: Release device resource data obtained by devres_alloc() [ Upstream commit 097b8f62dd793e08f1732fc74dbb64596c7fbff9 ] Free device resource data, if __wacom_devm_sysfs_create_group is not successful. Signed-off-by: Arvind Yadav Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/hid/wacom_sys.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 4c337585479e..69afd7968d9c 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1102,8 +1102,10 @@ static int __wacom_devm_sysfs_create_group(struct wacom *wacom, devres->root = root; error = sysfs_create_group(devres->root, group); - if (error) + if (error) { + devres_free(devres); return error; + } devres_add(&wacom->hdev->dev, devres); -- GitLab From 9079946f612b25f4db25c9fbb074c2cb60c0c31d Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 5 Apr 2018 18:29:12 +0900 Subject: [PATCH 0541/1299] selftests: ftrace: Add a testcase for multiple actions on trigger [ Upstream commit 25aa50e0ca397a5e5d4d6fcecefa8107877d1dd0 ] Add a testcase for multiple actions with different parameters on an event trigger, which has been fixed by commit 192c283e93bd ("tracing: Add action comparisons when testing matching hist triggers"). Link: http://lkml.kernel.org/r/152292055227.15769.6327959816123227152.stgit@devbox Reviewed-by: Tom Zanussi Tested-by: Tom Zanussi Signed-off-by: Masami Hiramatsu Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- .../trigger-multi-actions-accept.tc | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc new file mode 100644 index 000000000000..c193dce611a2 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc @@ -0,0 +1,44 @@ +#!/bin/sh +# description: event trigger - test multiple actions on hist trigger + + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic event is not supported" + exit_unsupported +fi + +clear_synthetic_events +reset_tracer +do_reset + +echo "Test multiple actions on hist trigger" +echo 'wakeup_latency u64 lat; pid_t pid' >> synthetic_events +TRIGGER1=events/sched/sched_wakeup/trigger +TRIGGER2=events/sched/sched_switch/trigger + +echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="cyclictest"' > $TRIGGER1 +echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0 if next_comm=="cyclictest"' >> $TRIGGER2 +echo 'hist:keys=next_pid:onmatch(sched.sched_wakeup).wakeup_latency(sched.sched_switch.$wakeup_lat,next_pid) if next_comm=="cyclictest"' >> $TRIGGER2 +echo 'hist:keys=next_pid:onmatch(sched.sched_wakeup).wakeup_latency(sched.sched_switch.$wakeup_lat,prev_pid) if next_comm=="cyclictest"' >> $TRIGGER2 +echo 'hist:keys=next_pid if next_comm=="cyclictest"' >> $TRIGGER2 + +do_reset + +exit 0 -- GitLab From 3958294c661e35e8454147c7fc7df60c35d989c2 Mon Sep 17 00:00:00 2001 From: Dag Moxnes Date: Wed, 25 Apr 2018 13:22:01 +0200 Subject: [PATCH 0542/1299] rds: ib: Fix missing call to rds_ib_dev_put in rds_ib_setup_qp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 91a825290ca4eae88603bc811bf74a45f94a3f46 ] The function rds_ib_setup_qp is calling rds_ib_get_client_data and should correspondingly call rds_ib_dev_put. This call was lost in the non-error path with the introduction of error handling done in commit 3b12f73a5c29 ("rds: ib: add error handle") Signed-off-by: Dag Moxnes Reviewed-by: Håkon Bugge Acked-by: Santosh Shilimkar Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/rds/ib_cm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 80fb6f63e768..6e721c449c4b 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c @@ -546,7 +546,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) rdsdebug("conn %p pd %p cq %p %p\n", conn, ic->i_pd, ic->i_send_cq, ic->i_recv_cq); - return ret; + goto out; sends_out: vfree(ic->i_sends); @@ -571,6 +571,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) ic->i_send_cq = NULL; rds_ibdev_out: rds_ib_remove_conn(rds_ibdev, conn); +out: rds_ib_dev_put(rds_ibdev); return ret; -- GitLab From af22d1b7705a130ccf917d806a139ea9ff1e9703 Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Wed, 25 Apr 2018 14:57:17 -0400 Subject: [PATCH 0543/1299] perf/x86/intel: Don't enable freeze-on-smi for PerfMon V1 [ Upstream commit 4e949e9b9d1e3edcdab3b54656c5851bd9e49c67 ] The SMM freeze feature was introduced since PerfMon V2. But the current code unconditionally enables the feature for all platforms. It can generate #GP exception, if the related FREEZE_WHILE_SMM bit is set for the machine with PerfMon V1. To disable the feature for PerfMon V1, perf needs to - Remove the freeze_on_smi sysfs entry by moving intel_pmu_attrs to intel_pmu, which is only applied to PerfMon V2 and later. - Check the PerfMon version before flipping the SMM bit when starting CPU Fixes: 6089327f5424 ("perf/x86: Add sysfs entry to freeze counters on SMI") Signed-off-by: Kan Liang Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Cc: ak@linux.intel.com Cc: eranian@google.com Cc: acme@redhat.com Link: https://lkml.kernel.org/r/1524682637-63219-1-git-send-email-kan.liang@linux.intel.com Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/x86/events/intel/core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 6965ee8c4b8a..228732654cfe 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -3331,7 +3331,8 @@ static void intel_pmu_cpu_starting(int cpu) cpuc->lbr_sel = NULL; - flip_smm_bit(&x86_pmu.attr_freeze_on_smi); + if (x86_pmu.version > 1) + flip_smm_bit(&x86_pmu.attr_freeze_on_smi); if (!cpuc->shared_regs) return; @@ -3494,6 +3495,8 @@ static __initconst const struct x86_pmu core_pmu = { .cpu_dying = intel_pmu_cpu_dying, }; +static struct attribute *intel_pmu_attrs[]; + static __initconst const struct x86_pmu intel_pmu = { .name = "Intel", .handle_irq = intel_pmu_handle_irq, @@ -3524,6 +3527,8 @@ static __initconst const struct x86_pmu intel_pmu = { .format_attrs = intel_arch3_formats_attr, .events_sysfs_show = intel_event_sysfs_show, + .attrs = intel_pmu_attrs, + .cpu_prepare = intel_pmu_cpu_prepare, .cpu_starting = intel_pmu_cpu_starting, .cpu_dying = intel_pmu_cpu_dying, @@ -3902,8 +3907,6 @@ __init int intel_pmu_init(void) x86_pmu.max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, x86_pmu.num_counters); - - x86_pmu.attrs = intel_pmu_attrs; /* * Quirk: v2 perfmon does not report fixed-purpose events, so * assume at least 3 events, when not running in a hypervisor: -- GitLab From bb7894391aad325ffe83e84b412022324ce345ef Mon Sep 17 00:00:00 2001 From: Tobias Jordan Date: Thu, 15 Feb 2018 16:12:55 +0100 Subject: [PATCH 0544/1299] remoteproc: qcom: Fix potential device node leaks [ Upstream commit 278d744c46fd4f1925aec77752d18a0e4a9cbec3 ] Add missing of_node_put()s at two places for device nodes returned by of_parse_phandle(). Fixes: 051fb70fd4ea ("remoteproc: qcom: Driver for the self-authenticating Hexagon v5") Signed-off-by: Tobias Jordan Signed-off-by: Bjorn Andersson Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/remoteproc/qcom_q6v5_pil.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 2d3d5ac92c06..81ec9b6805fc 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -915,6 +915,7 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc) dev_err(qproc->dev, "unable to resolve mba region\n"); return ret; } + of_node_put(node); qproc->mba_phys = r.start; qproc->mba_size = resource_size(&r); @@ -932,6 +933,7 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc) dev_err(qproc->dev, "unable to resolve mpss region\n"); return ret; } + of_node_put(node); qproc->mpss_phys = qproc->mpss_reloc = r.start; qproc->mpss_size = resource_size(&r); -- GitLab From d803d94a3fcde7f317c40cc846d7c585532119f0 Mon Sep 17 00:00:00 2001 From: Ramon Fried Date: Fri, 23 Mar 2018 00:09:12 -0400 Subject: [PATCH 0545/1299] rpmsg: added MODULE_ALIAS for rpmsg_char [ Upstream commit 93dd4e73c0d9cc32f835d76a54257020b0bfc75a ] Added "rpmsg:rpmsg_chrdev" MODULE_ALIAS to autoload rpmg_chrdev module automatically. Signed-off-by: Ramon Fried Signed-off-by: Bjorn Andersson Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/rpmsg/rpmsg_char.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index e0996fce3963..6a5b5b16145e 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -581,4 +581,6 @@ static void rpmsg_chrdev_exit(void) unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX); } module_exit(rpmsg_chrdev_exit); + +MODULE_ALIAS("rpmsg:rpmsg_chrdev"); MODULE_LICENSE("GPL v2"); -- GitLab From 11ac08bd73ebfda3bb0c7b748d0306bdb658e6fe Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Fri, 30 Mar 2018 16:56:10 +0530 Subject: [PATCH 0546/1299] HID: intel-ish-hid: use put_device() instead of kfree() [ Upstream commit a4eb490a41a0da3b1275fc7427084cf9ae2c3c1c ] Never directly free @dev after calling device_register(), even if it returned an error. Always use put_device() to give up the reference initialized. Signed-off-by: Arvind Yadav Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/hid/intel-ish-hid/ishtp/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c index f272cdd9bd55..2623a567ffba 100644 --- a/drivers/hid/intel-ish-hid/ishtp/bus.c +++ b/drivers/hid/intel-ish-hid/ishtp/bus.c @@ -418,7 +418,7 @@ static struct ishtp_cl_device *ishtp_bus_add_device(struct ishtp_device *dev, list_del(&device->device_link); spin_unlock_irqrestore(&dev->device_list_lock, flags); dev_err(dev->devc, "Failed to register ISHTP client device\n"); - kfree(device); + put_device(&device->dev); return NULL; } -- GitLab From 06beec8716407961d6c4a74f1feaecd72013fa8b Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Thu, 26 Apr 2018 00:21:59 -0700 Subject: [PATCH 0547/1299] blk-mq: fix sysfs inflight counter [ Upstream commit bf0ddaba65ddbb2715af97041da8e7a45b2d8628 ] When the blk-mq inflight implementation was added, /proc/diskstats was converted to use it, but /sys/block/$dev/inflight was not. Fix it by adding another helper to count in-flight requests by data direction. Fixes: f299b7c7a9de ("blk-mq: provide internal in-flight variant") Signed-off-by: Omar Sandoval Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- block/blk-mq.c | 19 +++++++++++++++++++ block/blk-mq.h | 4 +++- block/genhd.c | 12 ++++++++++++ block/partition-generic.c | 10 ++++++---- include/linux/genhd.h | 4 +++- 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 007f96611364..74c35513ada5 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -118,6 +118,25 @@ void blk_mq_in_flight(struct request_queue *q, struct hd_struct *part, blk_mq_queue_tag_busy_iter(q, blk_mq_check_inflight, &mi); } +static void blk_mq_check_inflight_rw(struct blk_mq_hw_ctx *hctx, + struct request *rq, void *priv, + bool reserved) +{ + struct mq_inflight *mi = priv; + + if (rq->part == mi->part) + mi->inflight[rq_data_dir(rq)]++; +} + +void blk_mq_in_flight_rw(struct request_queue *q, struct hd_struct *part, + unsigned int inflight[2]) +{ + struct mq_inflight mi = { .part = part, .inflight = inflight, }; + + inflight[0] = inflight[1] = 0; + blk_mq_queue_tag_busy_iter(q, blk_mq_check_inflight_rw, &mi); +} + void blk_freeze_queue_start(struct request_queue *q) { int freeze_depth; diff --git a/block/blk-mq.h b/block/blk-mq.h index 4933af9d61f7..877237e09083 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -136,6 +136,8 @@ static inline bool blk_mq_hw_queue_mapped(struct blk_mq_hw_ctx *hctx) } void blk_mq_in_flight(struct request_queue *q, struct hd_struct *part, - unsigned int inflight[2]); + unsigned int inflight[2]); +void blk_mq_in_flight_rw(struct request_queue *q, struct hd_struct *part, + unsigned int inflight[2]); #endif diff --git a/block/genhd.c b/block/genhd.c index dd305c65ffb0..449ef56bba70 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -82,6 +82,18 @@ void part_in_flight(struct request_queue *q, struct hd_struct *part, } } +void part_in_flight_rw(struct request_queue *q, struct hd_struct *part, + unsigned int inflight[2]) +{ + if (q->mq_ops) { + blk_mq_in_flight_rw(q, part, inflight); + return; + } + + inflight[0] = atomic_read(&part->in_flight[0]); + inflight[1] = atomic_read(&part->in_flight[1]); +} + struct hd_struct *__disk_get_part(struct gendisk *disk, int partno) { struct disk_part_tbl *ptbl = rcu_dereference(disk->part_tbl); diff --git a/block/partition-generic.c b/block/partition-generic.c index 08dabcd8b6ae..db57cced9b98 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -145,13 +145,15 @@ ssize_t part_stat_show(struct device *dev, jiffies_to_msecs(part_stat_read(p, time_in_queue))); } -ssize_t part_inflight_show(struct device *dev, - struct device_attribute *attr, char *buf) +ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct hd_struct *p = dev_to_part(dev); + struct request_queue *q = part_to_disk(p)->queue; + unsigned int inflight[2]; - return sprintf(buf, "%8u %8u\n", atomic_read(&p->in_flight[0]), - atomic_read(&p->in_flight[1])); + part_in_flight_rw(q, p, inflight); + return sprintf(buf, "%8u %8u\n", inflight[0], inflight[1]); } #ifdef CONFIG_FAIL_MAKE_REQUEST diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 5ade8f2a6987..550fa358893a 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -365,7 +365,9 @@ static inline void free_part_stats(struct hd_struct *part) part_stat_add(cpu, gendiskp, field, -subnd) void part_in_flight(struct request_queue *q, struct hd_struct *part, - unsigned int inflight[2]); + unsigned int inflight[2]); +void part_in_flight_rw(struct request_queue *q, struct hd_struct *part, + unsigned int inflight[2]); void part_dec_in_flight(struct request_queue *q, struct hd_struct *part, int rw); void part_inc_in_flight(struct request_queue *q, struct hd_struct *part, -- GitLab From e3d1002e14cede45fc543c82b469dd21c5ba027f Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 25 Apr 2018 17:13:40 +0100 Subject: [PATCH 0548/1299] arm64: fix possible spectre-v1 in ptrace_hbp_get_event() [ Upstream commit 19791a7ca674fb3009bb068260e852a2f05b605c ] It's possible for userspace to control idx. Sanitize idx when using it as an array index. Found by smatch. Signed-off-by: Mark Rutland Cc: Catalin Marinas Cc: Will Deacon Signed-off-by: Will Deacon Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/ptrace.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 85e80a473130..edaf346d13d5 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -247,15 +248,20 @@ static struct perf_event *ptrace_hbp_get_event(unsigned int note_type, switch (note_type) { case NT_ARM_HW_BREAK: - if (idx < ARM_MAX_BRP) - bp = tsk->thread.debug.hbp_break[idx]; + if (idx >= ARM_MAX_BRP) + goto out; + idx = array_index_nospec(idx, ARM_MAX_BRP); + bp = tsk->thread.debug.hbp_break[idx]; break; case NT_ARM_HW_WATCH: - if (idx < ARM_MAX_WRP) - bp = tsk->thread.debug.hbp_watch[idx]; + if (idx >= ARM_MAX_WRP) + goto out; + idx = array_index_nospec(idx, ARM_MAX_WRP); + bp = tsk->thread.debug.hbp_watch[idx]; break; } +out: return bp; } -- GitLab From 81d27c6ed637d5088901de01f0f5c7a624dad119 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 25 Apr 2018 17:13:42 +0100 Subject: [PATCH 0549/1299] KVM: arm/arm64: vgic: fix possible spectre-v1 in vgic_mmio_read_apr() [ Upstream commit 5e1ca5e23b167987d5b6d8b08f2d5b7dd2d13f49 ] It's possible for userspace to control n. Sanitize n when using it as an array index. Note that while it appears that n must be bound to the interval [0,3] due to the way it is extracted from addr, we cannot guarantee that compiler transformations (and/or future refactoring) will ensure this is the case, and given this is a slow path it's better to always perform the masking. Found by smatch. Signed-off-by: Mark Rutland Acked-by: Christoffer Dall Acked-by: Marc Zyngier Cc: kvmarm@lists.cs.columbia.edu Signed-off-by: Will Deacon Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- virt/kvm/arm/vgic/vgic-mmio-v2.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c index b3d4a10f09a1..af003268bf3e 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c @@ -14,6 +14,8 @@ #include #include #include +#include + #include #include @@ -320,6 +322,9 @@ static unsigned long vgic_mmio_read_apr(struct kvm_vcpu *vcpu, if (n > vgic_v3_max_apr_idx(vcpu)) return 0; + + n = array_index_nospec(n, 4); + /* GICv3 only uses ICH_AP1Rn for memory mapped (GICv2) guests */ return vgicv3->vgic_ap1r[n]; } -- GitLab From 48c0bf9af16115adda818dcff78871f547643a1b Mon Sep 17 00:00:00 2001 From: Evan Wang Date: Fri, 13 Apr 2018 12:32:30 +0800 Subject: [PATCH 0550/1299] libahci: Allow drivers to override stop_engine [ Upstream commit fa89f53bd7288d6aa7a982841119e7123faf5a53 ] Marvell armada37xx, armada7k and armada8k share the same AHCI sata controller IP, and currently there is an issue (Errata Ref#226)that the SATA can not be detected via SATA Port-MultiPlayer(PMP). After debugging, the reason is found that the value of Port-x FIS-based Switching Control (PxFBS@0x40) became wrong. According to design, the bits[11:8, 0] of register PxFBS are cleared when Port Command and Status (0x18) bit[0] changes its value from 1 to 0, i.e. falling edge of Port Command and Status bit[0] sends PULSE that resets PxFBS bits[11:8; 0]. So it needs save the port PxFBS register before PxCMD ST write and restore the port PxFBS register afterwards in ahci_stop_engine(). This commit allows drivers to override ahci_stop_engine behavior for use by the Marvell AHCI driver(and potentially other drivers in the future). Signed-off-by: Evan Wang Cc: Ofer Heifetz Cc: Tejun Heo Cc: Thomas Petazzoni Signed-off-by: Tejun Heo Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.c | 6 +++--- drivers/ata/ahci.h | 7 +++++++ drivers/ata/ahci_qoriq.c | 2 +- drivers/ata/ahci_xgene.c | 4 ++-- drivers/ata/libahci.c | 20 ++++++++++++-------- drivers/ata/sata_highbank.c | 2 +- 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 18391d0c0cd7..75eb50041c99 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -686,7 +686,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, DPRINTK("ENTER\n"); - ahci_stop_engine(ap); + hpriv->stop_engine(ap); rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), deadline, &online, NULL); @@ -712,7 +712,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, bool online; int rc; - ahci_stop_engine(ap); + hpriv->stop_engine(ap); /* clear D2H reception area to properly wait for D2H FIS */ ata_tf_init(link->device, &tf); @@ -776,7 +776,7 @@ static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, DPRINTK("ENTER\n"); - ahci_stop_engine(ap); + hpriv->stop_engine(ap); for (i = 0; i < 2; i++) { u16 val; diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 8b61123d2c3c..781b898e5785 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -361,6 +361,13 @@ struct ahci_host_priv { * be overridden anytime before the host is activated. */ void (*start_engine)(struct ata_port *ap); + /* + * Optional ahci_stop_engine override, if not set this gets set to the + * default ahci_stop_engine during ahci_save_initial_config, this can + * be overridden anytime before the host is activated. + */ + int (*stop_engine)(struct ata_port *ap); + irqreturn_t (*irq_handler)(int irq, void *dev_instance); /* only required for per-port MSI(-X) support */ diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c index b6b0bf76dfc7..ab5ac103bfb8 100644 --- a/drivers/ata/ahci_qoriq.c +++ b/drivers/ata/ahci_qoriq.c @@ -94,7 +94,7 @@ static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class, DPRINTK("ENTER\n"); - ahci_stop_engine(ap); + hpriv->stop_engine(ap); /* * There is a errata on ls1021a Rev1.0 and Rev2.0 which is: diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c index c2b5941d9184..ad58da7c9aff 100644 --- a/drivers/ata/ahci_xgene.c +++ b/drivers/ata/ahci_xgene.c @@ -165,7 +165,7 @@ static int xgene_ahci_restart_engine(struct ata_port *ap) PORT_CMD_ISSUE, 0x0, 1, 100)) return -EBUSY; - ahci_stop_engine(ap); + hpriv->stop_engine(ap); ahci_start_fis_rx(ap); /* @@ -421,7 +421,7 @@ static int xgene_ahci_hardreset(struct ata_link *link, unsigned int *class, portrxfis_saved = readl(port_mmio + PORT_FIS_ADDR); portrxfishi_saved = readl(port_mmio + PORT_FIS_ADDR_HI); - ahci_stop_engine(ap); + hpriv->stop_engine(ap); rc = xgene_ahci_do_hardreset(link, deadline, &online); diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 3e286d86ab42..5ae268b8514e 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -560,6 +560,9 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv) if (!hpriv->start_engine) hpriv->start_engine = ahci_start_engine; + if (!hpriv->stop_engine) + hpriv->stop_engine = ahci_stop_engine; + if (!hpriv->irq_handler) hpriv->irq_handler = ahci_single_level_irq_intr; } @@ -887,9 +890,10 @@ static void ahci_start_port(struct ata_port *ap) static int ahci_deinit_port(struct ata_port *ap, const char **emsg) { int rc; + struct ahci_host_priv *hpriv = ap->host->private_data; /* disable DMA */ - rc = ahci_stop_engine(ap); + rc = hpriv->stop_engine(ap); if (rc) { *emsg = "failed to stop engine"; return rc; @@ -1299,7 +1303,7 @@ int ahci_kick_engine(struct ata_port *ap) int busy, rc; /* stop engine */ - rc = ahci_stop_engine(ap); + rc = hpriv->stop_engine(ap); if (rc) goto out_restart; @@ -1538,7 +1542,7 @@ int ahci_do_hardreset(struct ata_link *link, unsigned int *class, DPRINTK("ENTER\n"); - ahci_stop_engine(ap); + hpriv->stop_engine(ap); /* clear D2H reception area to properly wait for D2H FIS */ ata_tf_init(link->device, &tf); @@ -2064,14 +2068,14 @@ void ahci_error_handler(struct ata_port *ap) if (!(ap->pflags & ATA_PFLAG_FROZEN)) { /* restart engine */ - ahci_stop_engine(ap); + hpriv->stop_engine(ap); hpriv->start_engine(ap); } sata_pmp_error_handler(ap); if (!ata_dev_enabled(ap->link.device)) - ahci_stop_engine(ap); + hpriv->stop_engine(ap); } EXPORT_SYMBOL_GPL(ahci_error_handler); @@ -2118,7 +2122,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) return; /* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */ - rc = ahci_stop_engine(ap); + rc = hpriv->stop_engine(ap); if (rc) return; @@ -2178,7 +2182,7 @@ static void ahci_enable_fbs(struct ata_port *ap) return; } - rc = ahci_stop_engine(ap); + rc = hpriv->stop_engine(ap); if (rc) return; @@ -2211,7 +2215,7 @@ static void ahci_disable_fbs(struct ata_port *ap) return; } - rc = ahci_stop_engine(ap); + rc = hpriv->stop_engine(ap); if (rc) return; diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c index aafb8cc03523..e67815b896fc 100644 --- a/drivers/ata/sata_highbank.c +++ b/drivers/ata/sata_highbank.c @@ -410,7 +410,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, int rc; int retry = 100; - ahci_stop_engine(ap); + hpriv->stop_engine(ap); /* clear D2H reception area to properly wait for D2H FIS */ ata_tf_init(link->device, &tf); -- GitLab From 75b0436b24d6806c10108c4743c1c816aa026289 Mon Sep 17 00:00:00 2001 From: Evan Wang Date: Fri, 13 Apr 2018 12:32:31 +0800 Subject: [PATCH 0551/1299] ata: ahci: mvebu: override ahci_stop_engine for mvebu AHCI [ Upstream commit daa2e3bdbb0b3e691cf20a042350817310cb8cb5 ] There is an issue(Errata Ref#226) that the SATA can not be detected via SATA Port-MultiPlayer(PMP) with following error log: ata1.15: PMP product ID mismatch ata1.15: SATA link up 6.0 Gbps (SStatus 133 SControl 300) ata1.15: Port Multiplier vendor mismatch '0x1b4b'!='0x0' ata1.15: PMP revalidation failed (errno=-19) After debugging, the reason is found that the value Port-x FIS-based Switching Control(PxFBS@0x40) become wrong. According to design, the bits[11:8, 0] of register PxFBS are cleared when Port Command and Status (0x18) bit[0] changes its value from 1 to 0, i.e. falling edge of Port Command and Status bit[0] sends PULSE that resets PxFBS bits[11:8; 0]. So it needs a mvebu SATA WA to save the port PxFBS register before PxCMD ST write and restore it afterwards. This patch implements the WA in a separate function of ahci_mvebu_stop_engine to override ahci_stop_gngine. Signed-off-by: Evan Wang Cc: Ofer Heifetz Cc: Tejun Heo Cc: Thomas Petazzoni Signed-off-by: Tejun Heo Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci_mvebu.c | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c index de7128d81e9c..0045dacd814b 100644 --- a/drivers/ata/ahci_mvebu.c +++ b/drivers/ata/ahci_mvebu.c @@ -62,6 +62,60 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv) writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA); } +/** + * ahci_mvebu_stop_engine + * + * @ap: Target ata port + * + * Errata Ref#226 - SATA Disk HOT swap issue when connected through + * Port Multiplier in FIS-based Switching mode. + * + * To avoid the issue, according to design, the bits[11:8, 0] of + * register PxFBS are cleared when Port Command and Status (0x18) bit[0] + * changes its value from 1 to 0, i.e. falling edge of Port + * Command and Status bit[0] sends PULSE that resets PxFBS + * bits[11:8; 0]. + * + * This function is used to override function of "ahci_stop_engine" + * from libahci.c by adding the mvebu work around(WA) to save PxFBS + * value before the PxCMD ST write of 0, then restore PxFBS value. + * + * Return: 0 on success; Error code otherwise. + */ +int ahci_mvebu_stop_engine(struct ata_port *ap) +{ + void __iomem *port_mmio = ahci_port_base(ap); + u32 tmp, port_fbs; + + tmp = readl(port_mmio + PORT_CMD); + + /* check if the HBA is idle */ + if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0) + return 0; + + /* save the port PxFBS register for later restore */ + port_fbs = readl(port_mmio + PORT_FBS); + + /* setting HBA to idle */ + tmp &= ~PORT_CMD_START; + writel(tmp, port_mmio + PORT_CMD); + + /* + * bit #15 PxCMD signal doesn't clear PxFBS, + * restore the PxFBS register right after clearing the PxCMD ST, + * no need to wait for the PxCMD bit #15. + */ + writel(port_fbs, port_mmio + PORT_FBS); + + /* wait for engine to stop. This could be as long as 500 msec */ + tmp = ata_wait_register(ap, port_mmio + PORT_CMD, + PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500); + if (tmp & PORT_CMD_LIST_ON) + return -EIO; + + return 0; +} + #ifdef CONFIG_PM_SLEEP static int ahci_mvebu_suspend(struct platform_device *pdev, pm_message_t state) { @@ -112,6 +166,8 @@ static int ahci_mvebu_probe(struct platform_device *pdev) if (rc) return rc; + hpriv->stop_engine = ahci_mvebu_stop_engine; + if (of_device_is_compatible(pdev->dev.of_node, "marvell,armada-380-ahci")) { dram = mv_mbus_dram_info(); -- GitLab From 09daf2df8db88672ae8060eee7802d93a371f244 Mon Sep 17 00:00:00 2001 From: "jacek.tomaka@poczta.fm" Date: Tue, 24 Apr 2018 00:14:25 +0800 Subject: [PATCH 0552/1299] x86/cpu/intel: Add missing TLB cpuid values [ Upstream commit b837913fc2d9061bf9b8c0dd6bf2d24e2f98b84a ] Make kernel print the correct number of TLB entries on Intel Xeon Phi 7210 (and others) Before: [ 0.320005] Last level dTLB entries: 4KB 0, 2MB 0, 4MB 0, 1GB 0 After: [ 0.320005] Last level dTLB entries: 4KB 256, 2MB 128, 4MB 128, 1GB 16 The entries do exist in the official Intel SMD but the type column there is incorrect (states "Cache" where it should read "TLB"), but the entries for the values 0x6B, 0x6C and 0x6D are correctly described as 'Data TLB'. Signed-off-by: Jacek Tomaka Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20180423161425.24366-1-jacekt@dugeo.com Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/intel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index c895f38a7a5e..0b2330e19169 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -751,6 +751,9 @@ static const struct _tlb_table intel_tlb_table[] = { { 0x5d, TLB_DATA_4K_4M, 256, " TLB_DATA 4 KByte and 4 MByte pages" }, { 0x61, TLB_INST_4K, 48, " TLB_INST 4 KByte pages, full associative" }, { 0x63, TLB_DATA_1G, 4, " TLB_DATA 1 GByte pages, 4-way set associative" }, + { 0x6b, TLB_DATA_4K, 256, " TLB_DATA 4 KByte pages, 8-way associative" }, + { 0x6c, TLB_DATA_2M_4M, 128, " TLB_DATA 2 MByte or 4 MByte pages, 8-way associative" }, + { 0x6d, TLB_DATA_1G, 16, " TLB_DATA 1 GByte pages, fully associative" }, { 0x76, TLB_INST_2M_4M, 8, " TLB_INST 2-MByte or 4-MByte pages, fully associative" }, { 0xb0, TLB_INST_4K, 128, " TLB_INST 4 KByte pages, 4-way set associative" }, { 0xb1, TLB_INST_2M_4M, 4, " TLB_INST 2M pages, 4-way, 8 entries or 4M pages, 4-way entries" }, -- GitLab From 40d526e672125a75342b779a9305b64f8792e1b0 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Wed, 25 Apr 2018 15:08:53 -0700 Subject: [PATCH 0553/1299] bpf: fix uninitialized variable in bpf tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 815425567dea6c54494e85050631d6bdda907c5d ] Here the variable cont is used as the saved_pointer for a call to strtok_r(). It is safe to use the value uninitialized in this context however and the later reference is only ever used if the strtok_r is successful. But, 'gcc-5' at least doesn't have all this knowledge so initialize cont to NULL. Additionally, do the natural NULL check before accessing just for completness. The warning is the following: ./bpf/tools/bpf/bpf_dbg.c: In function ‘cmd_load’: ./bpf/tools/bpf/bpf_dbg.c:1077:13: warning: ‘cont’ may be used uninitialized in this function [-Wmaybe-uninitialized] } else if (matches(subcmd, "pcap") == 0) { Fixes: fd981e3c321a "filter: bpf_dbg: add minimal bpf debugger" Signed-off-by: John Fastabend Signed-off-by: Daniel Borkmann Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/net/bpf_dbg.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/net/bpf_dbg.c b/tools/net/bpf_dbg.c index 4f254bcc4423..61b9aa5d6415 100644 --- a/tools/net/bpf_dbg.c +++ b/tools/net/bpf_dbg.c @@ -1063,7 +1063,7 @@ static int cmd_load_pcap(char *file) static int cmd_load(char *arg) { - char *subcmd, *cont, *tmp = strdup(arg); + char *subcmd, *cont = NULL, *tmp = strdup(arg); int ret = CMD_OK; subcmd = strtok_r(tmp, " ", &cont); @@ -1073,7 +1073,10 @@ static int cmd_load(char *arg) bpf_reset(); bpf_reset_breakpoints(); - ret = cmd_load_bpf(cont); + if (!cont) + ret = CMD_ERR; + else + ret = cmd_load_bpf(cont); } else if (matches(subcmd, "pcap") == 0) { ret = cmd_load_pcap(cont); } else { -- GitLab From 201dc1345bfe7228d74830767f2a8de7be9b9723 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 9 Apr 2018 14:40:54 +0800 Subject: [PATCH 0554/1299] i2c: sprd: Prevent i2c accesses after suspend is called [ Upstream commit da33aa03fa34c918faf2c371ebda0dd961d7ccb2 ] Add one flag to indicate if the i2c controller has been in suspend state, which can prevent i2c accesses after i2c controller is suspended following system suspend. Signed-off-by: Baolin Wang Signed-off-by: Wolfram Sang Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-sprd.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index 25fcc3c1e32b..2fdad63a23a1 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -86,6 +86,7 @@ struct sprd_i2c { u32 count; int irq; int err; + bool is_suspended; }; static void sprd_i2c_set_count(struct sprd_i2c *i2c_dev, u32 count) @@ -283,6 +284,9 @@ static int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct sprd_i2c *i2c_dev = i2c_adap->algo_data; int im, ret; + if (i2c_dev->is_suspended) + return -EBUSY; + ret = pm_runtime_get_sync(i2c_dev->dev); if (ret < 0) return ret; @@ -586,11 +590,23 @@ static int sprd_i2c_remove(struct platform_device *pdev) static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev) { + struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); + + i2c_lock_adapter(&i2c_dev->adap); + i2c_dev->is_suspended = true; + i2c_unlock_adapter(&i2c_dev->adap); + return pm_runtime_force_suspend(pdev); } static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev) { + struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); + + i2c_lock_adapter(&i2c_dev->adap); + i2c_dev->is_suspended = false; + i2c_unlock_adapter(&i2c_dev->adap); + return pm_runtime_force_resume(pdev); } -- GitLab From f1e5bbe86ec13618fc39d2b01ad166cfa335b488 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 9 Apr 2018 14:40:55 +0800 Subject: [PATCH 0555/1299] i2c: sprd: Fix the i2c count issue [ Upstream commit 2a010461207cc96bee5ab81748325dec1972976f ] We found the I2C controller count register is unreliable sometimes, that will cause I2C to lose data. Thus we can read the data count from 'i2c_dev->count' instead of the I2C controller count register. Signed-off-by: Baolin Wang Signed-off-by: Wolfram Sang Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-sprd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index 2fdad63a23a1..4053259bccb8 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -368,13 +368,12 @@ static irqreturn_t sprd_i2c_isr_thread(int irq, void *dev_id) struct sprd_i2c *i2c_dev = dev_id; struct i2c_msg *msg = i2c_dev->msg; bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK); - u32 i2c_count = readl(i2c_dev->base + I2C_COUNT); u32 i2c_tran; if (msg->flags & I2C_M_RD) i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD; else - i2c_tran = i2c_count; + i2c_tran = i2c_dev->count; /* * If we got one ACK from slave when writing data, and we did not @@ -412,14 +411,13 @@ static irqreturn_t sprd_i2c_isr(int irq, void *dev_id) { struct sprd_i2c *i2c_dev = dev_id; struct i2c_msg *msg = i2c_dev->msg; - u32 i2c_count = readl(i2c_dev->base + I2C_COUNT); bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK); u32 i2c_tran; if (msg->flags & I2C_M_RD) i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD; else - i2c_tran = i2c_count; + i2c_tran = i2c_dev->count; /* * If we did not get one ACK from slave when writing data, then we -- GitLab From 5d33c9d0fbd8a5a5f2dfc4affb7f9f97cb86afd0 Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Wed, 25 Apr 2018 18:29:25 +0200 Subject: [PATCH 0556/1299] tipc: fix bug in function tipc_nl_node_dump_monitor [ Upstream commit 7dbc73e6124ce4d0cfbdd6166de388e9367c47ad ] Commit 36a50a989ee8 ("tipc: fix infinite loop when dumping link monitor summary") intended to fix a problem with user tool looping when max number of bearers are enabled. Unfortunately, the wrong version of the commit was posted, so the problem was not solved at all. This commit adds the missing part. Fixes: 36a50a989ee8 ("tipc: fix infinite loop when dumping link monitor summary") Signed-off-by: Jon Maloy Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/tipc/node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tipc/node.c b/net/tipc/node.c index 0d97395d60d5..47c67e5b5793 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -2125,7 +2125,7 @@ int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb) rtnl_lock(); for (bearer_id = prev_bearer; bearer_id < MAX_BEARERS; bearer_id++) { - err = __tipc_nl_add_monitor(net, &msg, prev_bearer); + err = __tipc_nl_add_monitor(net, &msg, bearer_id); if (err) break; } -- GitLab From 8e6dba9166ed125f52287354541a753b6a532f9c Mon Sep 17 00:00:00 2001 From: Greg Thelen Date: Thu, 26 Apr 2018 11:19:30 -0700 Subject: [PATCH 0557/1299] nvme: depend on INFINIBAND_ADDR_TRANS [ Upstream commit 3af7a156bdc356946098e13180be66b6420619bf ] NVME_RDMA code depends on INFINIBAND_ADDR_TRANS provided symbols. So declare the kconfig dependency. This is necessary to allow for enabling INFINIBAND without INFINIBAND_ADDR_TRANS. Signed-off-by: Greg Thelen Cc: Tarick Bedeir Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/nvme/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig index 46d6cb1e03bd..8f845de8a8a2 100644 --- a/drivers/nvme/host/Kconfig +++ b/drivers/nvme/host/Kconfig @@ -18,7 +18,7 @@ config NVME_FABRICS config NVME_RDMA tristate "NVM Express over Fabrics RDMA host driver" - depends on INFINIBAND && BLOCK + depends on INFINIBAND && INFINIBAND_ADDR_TRANS && BLOCK select NVME_CORE select NVME_FABRICS select SG_POOL -- GitLab From 4e2b7d1687c4c4aeeed55e8cb9ff040a68cbf90e Mon Sep 17 00:00:00 2001 From: Greg Thelen Date: Thu, 26 Apr 2018 11:19:31 -0700 Subject: [PATCH 0558/1299] nvmet-rdma: depend on INFINIBAND_ADDR_TRANS [ Upstream commit d6fc6a22fc7d3df987666725496ed5dd2dd30f23 ] NVME_TARGET_RDMA code depends on INFINIBAND_ADDR_TRANS provided symbols. So declare the kconfig dependency. This is necessary to allow for enabling INFINIBAND without INFINIBAND_ADDR_TRANS. Signed-off-by: Greg Thelen Cc: Tarick Bedeir Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/nvme/target/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/target/Kconfig b/drivers/nvme/target/Kconfig index 03e4ab65fe77..48d20c2c1256 100644 --- a/drivers/nvme/target/Kconfig +++ b/drivers/nvme/target/Kconfig @@ -27,7 +27,7 @@ config NVME_TARGET_LOOP config NVME_TARGET_RDMA tristate "NVMe over Fabrics RDMA target support" - depends on INFINIBAND + depends on INFINIBAND && INFINIBAND_ADDR_TRANS depends on NVME_TARGET help This enables the NVMe RDMA target support, which allows exporting NVMe -- GitLab From 08088b8a079331d80ca4e6f54892a9801c0eef32 Mon Sep 17 00:00:00 2001 From: Greg Thelen Date: Thu, 26 Apr 2018 11:19:32 -0700 Subject: [PATCH 0559/1299] ib_srpt: depend on INFINIBAND_ADDR_TRANS [ Upstream commit 346a47b65d10e450778ec0d21e4a9409f25daaa8 ] INFINIBAND_SRPT code depends on INFINIBAND_ADDR_TRANS provided symbols. So declare the kconfig dependency. This is necessary to allow for enabling INFINIBAND without INFINIBAND_ADDR_TRANS. Signed-off-by: Greg Thelen Cc: Tarick Bedeir Reviewed-by: Bart Van Assche Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/srpt/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/srpt/Kconfig b/drivers/infiniband/ulp/srpt/Kconfig index 31ee83d528d9..fb8b7182f05e 100644 --- a/drivers/infiniband/ulp/srpt/Kconfig +++ b/drivers/infiniband/ulp/srpt/Kconfig @@ -1,6 +1,6 @@ config INFINIBAND_SRPT tristate "InfiniBand SCSI RDMA Protocol target support" - depends on INFINIBAND && TARGET_CORE + depends on INFINIBAND && INFINIBAND_ADDR_TRANS && TARGET_CORE ---help--- Support for the SCSI RDMA Protocol (SRP) Target driver. The -- GitLab From b8500e6e8eb538c520136d92d35d0e8894210dcb Mon Sep 17 00:00:00 2001 From: Greg Thelen Date: Thu, 26 Apr 2018 11:19:34 -0700 Subject: [PATCH 0560/1299] ib_srp: depend on INFINIBAND_ADDR_TRANS [ Upstream commit 5a3bc8a4abbd2d553430218d3a320400dce811b7 ] INFINIBAND_SRP code depends on INFINIBAND_ADDR_TRANS provided symbols. So declare the kconfig dependency. This is necessary to allow for enabling INFINIBAND without INFINIBAND_ADDR_TRANS. Signed-off-by: Greg Thelen Cc: Tarick Bedeir Reviewed-by: Bart Van Assche Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/srp/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/srp/Kconfig b/drivers/infiniband/ulp/srp/Kconfig index c74ee9633041..99db8fe5173a 100644 --- a/drivers/infiniband/ulp/srp/Kconfig +++ b/drivers/infiniband/ulp/srp/Kconfig @@ -1,6 +1,6 @@ config INFINIBAND_SRP tristate "InfiniBand SCSI RDMA Protocol" - depends on SCSI + depends on SCSI && INFINIBAND_ADDR_TRANS select SCSI_SRP_ATTRS ---help--- Support for the SCSI RDMA Protocol over InfiniBand. This -- GitLab From fb019834bf8e717a0fc0c67f4a61d4455e3cfec1 Mon Sep 17 00:00:00 2001 From: Greg Thelen Date: Thu, 26 Apr 2018 11:19:35 -0700 Subject: [PATCH 0561/1299] IB: make INFINIBAND_ADDR_TRANS configurable [ Upstream commit f7cb7b85be55a4906b4b4b30596db1043dae6335 ] Allow INFINIBAND without INFINIBAND_ADDR_TRANS because fuzzing has been finding fair number of CM bugs. So provide option to disable it. Signed-off-by: Greg Thelen Cc: Tarick Bedeir Reviewed-by: Bart Van Assche Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig index 3726205c8704..7507cc641de3 100644 --- a/drivers/infiniband/Kconfig +++ b/drivers/infiniband/Kconfig @@ -60,9 +60,12 @@ config INFINIBAND_ON_DEMAND_PAGING pages on demand instead. config INFINIBAND_ADDR_TRANS - bool + bool "RDMA/CM" depends on INFINIBAND default y + ---help--- + Support for RDMA communication manager (CM). + This allows for a generic connection abstraction over RDMA. config INFINIBAND_ADDR_TRANS_CONFIGFS bool -- GitLab From 84f66378da20a4efc07f6d7b35f31cd3327639f1 Mon Sep 17 00:00:00 2001 From: Matan Barak Date: Tue, 24 Apr 2018 08:15:20 +0000 Subject: [PATCH 0562/1299] IB/uverbs: Fix validating mandatory attributes [ Upstream commit f604db645a66b7ba4f21c426fe73253928dada41 ] Previously, if a method contained mandatory attributes in a namespace that wasn't given by the user, these attributes weren't validated. Fixing this by iterating over all specification namespaces. Fixes: fac9658cabb9 ("IB/core: Add new ioctl interface") Signed-off-by: Matan Barak Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/uverbs_ioctl.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c index 5e9f72ea4579..5feb8bbeff18 100644 --- a/drivers/infiniband/core/uverbs_ioctl.c +++ b/drivers/infiniband/core/uverbs_ioctl.c @@ -191,6 +191,15 @@ static int uverbs_validate_kernel_mandatory(const struct uverbs_method_spec *met return -EINVAL; } + for (; i < method_spec->num_buckets; i++) { + struct uverbs_attr_spec_hash *attr_spec_bucket = + method_spec->attr_buckets[i]; + + if (!bitmap_empty(attr_spec_bucket->mandatory_attrs_bitmask, + attr_spec_bucket->num_attrs)) + return -EINVAL; + } + return 0; } -- GitLab From 019ce25a4ee05e14a879289881e9883d4583beb8 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Tue, 24 Apr 2018 20:13:45 +0300 Subject: [PATCH 0563/1299] RDMA/cma: Fix use after destroy access to net namespace for IPoIB [ Upstream commit 2918c1a900252b4a0c730715ec205437c7daf79d ] There are few issues with validation of netdevice and listen id lookup for IB (IPoIB) while processing incoming CM request as below. 1. While performing lookup of bind_list in cma_ps_find(), net namespace of the netdevice can get deleted in cma_exit_net(), resulting in use after free access of idr and/or net namespace structures. This lookup occurs from the workqueue context (and not userspace context where net namespace is always valid). CPU0 CPU1 ==== ==== bind_list = cma_ps_find(); move netdevice to new namespace delete net namespace cma_exit_net() idr_destroy(idr); [..] cma_find_listener(bind_list, ..); 2. While netdevice is validated for IP address in given net namespace, netdevice's net namespace and/or ifindex can change in cma_get_net_dev() and cma_match_net_dev(). Above issues are overcome by using rcu lock along with netdevice UP/DOWN state as described below. When a net namespace is getting deleted, netdevice is closed and shutdown before moving it back to init_net namespace. change_net_namespace() synchronizes with any existing use of netdevice before changing the netdev properties such as net or ifindex. Once netdevice IFF_UP flags is cleared, such fields are not guaranteed to be valid. Therefore, rcu lock along with netdevice state check ensures that, while route lookup and cm_id lookup is in progress, netdevice of interest won't migrate to any other net namespace. This ensures that associated net namespace of netdevice won't get deleted while rcu lock is held for netdevice which is in IFF_UP state. Fixes: fa20105e09e9 ("IB/cma: Add support for network namespaces") Fixes: 4be74b42a6d0 ("IB/cma: Separate port allocation to network namespaces") Fixes: f887f2ac87c2 ("IB/cma: Validate routing of incoming requests") Signed-off-by: Parav Pandit Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/cma.c | 53 ++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 6c725c435f5d..509d318b50d6 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -420,6 +420,8 @@ struct cma_hdr { #define CMA_VERSION 0x00 struct cma_req_info { + struct sockaddr_storage listen_addr_storage; + struct sockaddr_storage src_addr_storage; struct ib_device *device; int port; union ib_gid local_gid; @@ -1372,11 +1374,11 @@ static bool validate_net_dev(struct net_device *net_dev, } static struct net_device *cma_get_net_dev(struct ib_cm_event *ib_event, - const struct cma_req_info *req) + struct cma_req_info *req) { - struct sockaddr_storage listen_addr_storage, src_addr_storage; - struct sockaddr *listen_addr = (struct sockaddr *)&listen_addr_storage, - *src_addr = (struct sockaddr *)&src_addr_storage; + struct sockaddr *listen_addr = + (struct sockaddr *)&req->listen_addr_storage; + struct sockaddr *src_addr = (struct sockaddr *)&req->src_addr_storage; struct net_device *net_dev; const union ib_gid *gid = req->has_gid ? &req->local_gid : NULL; int err; @@ -1391,11 +1393,6 @@ static struct net_device *cma_get_net_dev(struct ib_cm_event *ib_event, if (!net_dev) return ERR_PTR(-ENODEV); - if (!validate_net_dev(net_dev, listen_addr, src_addr)) { - dev_put(net_dev); - return ERR_PTR(-EHOSTUNREACH); - } - return net_dev; } @@ -1531,15 +1528,51 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id, } } + /* + * Net namespace might be getting deleted while route lookup, + * cm_id lookup is in progress. Therefore, perform netdevice + * validation, cm_id lookup under rcu lock. + * RCU lock along with netdevice state check, synchronizes with + * netdevice migrating to different net namespace and also avoids + * case where net namespace doesn't get deleted while lookup is in + * progress. + * If the device state is not IFF_UP, its properties such as ifindex + * and nd_net cannot be trusted to remain valid without rcu lock. + * net/core/dev.c change_net_namespace() ensures to synchronize with + * ongoing operations on net device after device is closed using + * synchronize_net(). + */ + rcu_read_lock(); + if (*net_dev) { + /* + * If netdevice is down, it is likely that it is administratively + * down or it might be migrating to different namespace. + * In that case avoid further processing, as the net namespace + * or ifindex may change. + */ + if (((*net_dev)->flags & IFF_UP) == 0) { + id_priv = ERR_PTR(-EHOSTUNREACH); + goto err; + } + + if (!validate_net_dev(*net_dev, + (struct sockaddr *)&req.listen_addr_storage, + (struct sockaddr *)&req.src_addr_storage)) { + id_priv = ERR_PTR(-EHOSTUNREACH); + goto err; + } + } + bind_list = cma_ps_find(*net_dev ? dev_net(*net_dev) : &init_net, rdma_ps_from_service_id(req.service_id), cma_port_from_service_id(req.service_id)); id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev); +err: + rcu_read_unlock(); if (IS_ERR(id_priv) && *net_dev) { dev_put(*net_dev); *net_dev = NULL; } - return id_priv; } -- GitLab From d2be557eef15dad24e1acef1f4179a5e207cf2ef Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 25 Apr 2018 17:24:04 +0100 Subject: [PATCH 0564/1299] RDMA/iwpm: fix memory leak on map_info [ Upstream commit f96416cea7bce9afe619c15e87fced70f93f9098 ] In the cases where iwpm_hash_bucket is NULL and where function get_mapinfo_hash_bucket returns NULL then the map_info is never added to hash_bucket_head and hence there is a leak of map_info. Fix this by nullifying hash_bucket_head and if that is null we know that that map_info was not added to hash_bucket_head and hence map_info should be free'd. Detected by CoverityScan, CID#1222481 ("Resource Leak") Fixes: 30dc5e63d6a5 ("RDMA/core: Add support for iWARP Port Mapper user space service") Signed-off-by: Colin Ian King Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/iwpm_util.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c index 81528f64061a..cb0fecc958b5 100644 --- a/drivers/infiniband/core/iwpm_util.c +++ b/drivers/infiniband/core/iwpm_util.c @@ -114,7 +114,7 @@ int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr, struct sockaddr_storage *mapped_sockaddr, u8 nl_client) { - struct hlist_head *hash_bucket_head; + struct hlist_head *hash_bucket_head = NULL; struct iwpm_mapping_info *map_info; unsigned long flags; int ret = -EINVAL; @@ -142,6 +142,9 @@ int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr, } } spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); + + if (!hash_bucket_head) + kfree(map_info); return ret; } -- GitLab From b4f6e28c801ac69406ecf1a2d5e27b03dc4644c2 Mon Sep 17 00:00:00 2001 From: Jianchao Wang Date: Thu, 26 Apr 2018 11:52:39 +0800 Subject: [PATCH 0565/1299] IB/rxe: add RXE_START_MASK for rxe_opcode IB_OPCODE_RC_SEND_ONLY_INV [ Upstream commit 2da36d44a9d54a2c6e1f8da1f7ccc26b0bc6cfec ] w/o RXE_START_MASK, the last_psn of IB_OPCODE_RC_SEND_ONLY_INV will not be updated in update_wqe_psn, and the corresponding wqe will not be acked in rxe_completer due to its last_psn is zero. Finally, the other wqe will also not be able to be acked, because the wqe of IB_OPCODE_RC_SEND_ONLY_INV with last_psn 0 is still there. This causes large amount of io timeout when nvmeof is over rxe. Add RXE_START_MASK for IB_OPCODE_RC_SEND_ONLY_INV to fix this. Signed-off-by: Jianchao Wang Reviewed-by: Zhu Yanjun Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/sw/rxe/rxe_opcode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/sw/rxe/rxe_opcode.c b/drivers/infiniband/sw/rxe/rxe_opcode.c index 61927c165b59..4cf11063e0b5 100644 --- a/drivers/infiniband/sw/rxe/rxe_opcode.c +++ b/drivers/infiniband/sw/rxe/rxe_opcode.c @@ -390,7 +390,7 @@ struct rxe_opcode_info rxe_opcode[RXE_NUM_OPCODE] = { .name = "IB_OPCODE_RC_SEND_ONLY_INV", .mask = RXE_IETH_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_COMP_MASK | RXE_RWR_MASK | RXE_SEND_MASK - | RXE_END_MASK, + | RXE_END_MASK | RXE_START_MASK, .length = RXE_BTH_BYTES + RXE_IETH_BYTES, .offset = { [RXE_BTH] = 0, -- GitLab From 3fbbdb44cead49ab5e0913e3db143954979f6174 Mon Sep 17 00:00:00 2001 From: Zhu Yanjun Date: Thu, 26 Apr 2018 00:41:10 -0400 Subject: [PATCH 0566/1299] IB/rxe: avoid double kfree_skb [ Upstream commit 9fd4350ba8953804f05215999e11a6cfb7b41f2b ] When skb is sent, it will pass the following functions in soft roce. rxe_send [rdma_rxe] ip_local_out __ip_local_out ip_output ip_finish_output ip_finish_output2 dev_queue_xmit __dev_queue_xmit dev_hard_start_xmit In the above functions, if error occurs in the above functions or iptables rules drop skb after ip_local_out, kfree_skb will be called. So it is not necessary to call kfree_skb in soft roce module again. Or else crash will occur. The steps to reproduce: server client --------- --------- |1.1.1.1|<----rxe-channel--->|1.1.1.2| --------- --------- On server: rping -s -a 1.1.1.1 -v -C 10000 -S 512 On client: rping -c -a 1.1.1.1 -v -C 10000 -S 512 The kernel configs CONFIG_DEBUG_KMEMLEAK and CONFIG_DEBUG_OBJECTS are enabled on both server and client. When rping runs, run the following command in server: iptables -I OUTPUT -p udp --dport 4791 -j DROP Without this patch, crash will occur. CC: Srinivas Eeda CC: Junxiao Bi Signed-off-by: Zhu Yanjun Reviewed-by: Yuval Shaia Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/sw/rxe/rxe_req.c | 1 - drivers/infiniband/sw/rxe/rxe_resp.c | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c index 44b838ec9420..54cc9cb1e3b7 100644 --- a/drivers/infiniband/sw/rxe/rxe_req.c +++ b/drivers/infiniband/sw/rxe/rxe_req.c @@ -728,7 +728,6 @@ int rxe_requester(void *arg) rollback_state(wqe, qp, &rollback_wqe, rollback_psn); if (ret == -EAGAIN) { - kfree_skb(skb); rxe_run_task(&qp->req.task, 1); goto exit; } diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c index 01f926fd9029..bd43c1c7a42f 100644 --- a/drivers/infiniband/sw/rxe/rxe_resp.c +++ b/drivers/infiniband/sw/rxe/rxe_resp.c @@ -742,7 +742,6 @@ static enum resp_states read_reply(struct rxe_qp *qp, err = rxe_xmit_packet(rxe, qp, &ack_pkt, skb); if (err) { pr_err("Failed sending RDMA reply.\n"); - kfree_skb(skb); return RESPST_ERR_RNR; } @@ -955,10 +954,8 @@ static int send_ack(struct rxe_qp *qp, struct rxe_pkt_info *pkt, } err = rxe_xmit_packet(rxe, qp, &ack_pkt, skb); - if (err) { + if (err) pr_err_ratelimited("Failed sending ack\n"); - kfree_skb(skb); - } err1: return err; @@ -1151,7 +1148,6 @@ static enum resp_states duplicate_request(struct rxe_qp *qp, if (rc) { pr_err("Failed resending result. This flow is not handled - skb ignored\n"); rxe_drop_ref(qp); - kfree_skb(skb_copy); rc = RESPST_CLEANUP; goto out; } -- GitLab From 5cb0ba254fee3c3ef61a3c02892e010851bbf54f Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Mon, 5 Feb 2018 19:32:18 +0200 Subject: [PATCH 0567/1299] : fix end_name_hash() for 64bit long [ Upstream commit 19b9ad67310ed2f685062a00aec602bec33835f0 ] The comment claims that this helper will try not to loose bits, but for 64bit long it looses the high bits before hashing 64bit long into 32bit int. Use the helper hash_long() to do the right thing for 64bit long. For 32bit long, there is no change. All the callers of end_name_hash() either assign the result to qstr->hash, which is u32 or return the result as an int value (e.g. full_name_hash()). Change the helper return type to int to conform to its users. [ It took me a while to apply this, because my initial reaction to it was - incorrectly - that it could make for slower code. After having looked more at it, I take back all my complaints about the patch, Amir was right and I was mis-reading things or just being stupid. I also don't worry too much about the possible performance impact of this on 64-bit, since most architectures that actually care about performance end up not using this very much (the dcache code is the most performance-critical, but the word-at-a-time case uses its own hashing anyway). So this ends up being mostly used for filesystems that do their own degraded hashing (usually because they want a case-insensitive comparison function). A _tiny_ worry remains, in that not everybody uses DCACHE_WORD_ACCESS, and then this potentially makes things more expensive on 64-bit architectures with slow or lacking multipliers even for the normal case. That said, realistically the only such architecture I can think of is PA-RISC. Nobody really cares about performance on that, it's more of a "look ma, I've got warts^W an odd machine" platform. So the patch is fine, and all my initial worries were just misplaced from not looking at this properly. - Linus ] Signed-off-by: Amir Goldstein Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- include/linux/stringhash.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/stringhash.h b/include/linux/stringhash.h index e8f0f852968f..c0c5c5b73dc0 100644 --- a/include/linux/stringhash.h +++ b/include/linux/stringhash.h @@ -50,9 +50,9 @@ partial_name_hash(unsigned long c, unsigned long prevhash) * losing bits). This also has the property (wanted by the dcache) * that the msbits make a good hash table index. */ -static inline unsigned long end_name_hash(unsigned long hash) +static inline unsigned int end_name_hash(unsigned long hash) { - return __hash_32((unsigned int)hash); + return hash_long(hash, 32); } /* -- GitLab From 13e4a2083d2b5286ecfecfe98aa1bace6eee7a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Bugge?= Date: Wed, 18 Apr 2018 16:24:50 +0200 Subject: [PATCH 0568/1299] IB/core: Make ib_mad_client_id atomic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit db82476f37413eaeff5f836a9d8b022d6544accf ] Currently, the kernel protects access to the agent ID allocator on a per port basis using a spinlock, so it is impossible for two apps/threads on the same port to get the same TID, but it is entirely possible for two threads on different ports to end up with the same TID. As this can be confusing (regardless of it being legal according to the IB Spec 1.3, C13-18.1.1, in section 13.4.6.4 - TransactionID usage), and as the rdma-core user space API for /dev/umad devices implies unique TIDs even across ports, make the TID an atomic type so that no two allocations, regardless of port number, will be the same. Signed-off-by: Håkon Bugge Reviewed-by: Jack Morgenstein Reviewed-by: Ira Weiny Reviewed-by: Zhu Yanjun Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/mad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index cb91245e9163..d8efdc191c27 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -60,7 +60,7 @@ module_param_named(recv_queue_size, mad_recvq_size, int, 0444); MODULE_PARM_DESC(recv_queue_size, "Size of receive queue in number of work requests"); static struct list_head ib_mad_port_list; -static u32 ib_mad_client_id = 0; +static atomic_t ib_mad_client_id = ATOMIC_INIT(0); /* Port list lock */ static DEFINE_SPINLOCK(ib_mad_port_list_lock); @@ -378,7 +378,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, } spin_lock_irqsave(&port_priv->reg_lock, flags); - mad_agent_priv->agent.hi_tid = ++ib_mad_client_id; + mad_agent_priv->agent.hi_tid = atomic_inc_return(&ib_mad_client_id); /* * Make sure MAD registration (if supplied) -- GitLab From 38ffd4d581ff5448926dc72fc25e1cecb817de27 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 24 Apr 2018 20:05:03 +0530 Subject: [PATCH 0569/1299] ARM: davinci: board-da830-evm: fix GPIO lookup for MMC/SD [ Upstream commit 51e9f12163223546bd3aa9f7af6817931f980da8 ] The GPIO chip is called davinci_gpio.0 in legacy mode. Fix it, so that mmc can correctly lookup the wp and cp gpios. Also fix the GPIO numbers as they are not offsets within a bank. Note that it is the gpio-davinci driver that sets the gpiochip label to davinci_gpio.0. Fixes: b5e1438cf98a ("ARM: davinci: da830-evm: use gpio descriptor for mmc pins") Reported-by: David Lechner Reviewed-by: David Lechner Signed-off-by: Sekhar Nori Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-davinci/board-da830-evm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index f673cd7a6766..fb7c44cdadcb 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -205,12 +205,17 @@ static const short da830_evm_mmc_sd_pins[] = { -1 }; +#define DA830_MMCSD_WP_PIN GPIO_TO_PIN(2, 1) +#define DA830_MMCSD_CD_PIN GPIO_TO_PIN(2, 2) + static struct gpiod_lookup_table mmc_gpios_table = { .dev_id = "da830-mmc.0", .table = { /* gpio chip 1 contains gpio range 32-63 */ - GPIO_LOOKUP("davinci_gpio.1", 2, "cd", GPIO_ACTIVE_LOW), - GPIO_LOOKUP("davinci_gpio.1", 1, "wp", GPIO_ACTIVE_LOW), + GPIO_LOOKUP("davinci_gpio.0", DA830_MMCSD_CD_PIN, "cd", + GPIO_ACTIVE_LOW), + GPIO_LOOKUP("davinci_gpio.0", DA830_MMCSD_WP_PIN, "wp", + GPIO_ACTIVE_LOW), }, }; -- GitLab From 0bf4a2db29648e1a7df776de41b1177aa7a037f2 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 24 Apr 2018 20:05:04 +0530 Subject: [PATCH 0570/1299] ARM: davinci: board-da850-evm: fix GPIO lookup for MMC/SD [ Upstream commit 67c6b6ff221f807180aea6dd597246f87e1dd98a ] The GPIO chip is called davinci_gpio.0 in legacy mode. Fix it, so that mmc can correctly lookup the wp and cp gpios. Also fix the GPIO numbers as they are not offsets within a bank. Note that it is the gpio-davinci driver that sets the gpiochip label to davinci_gpio.0. Fixes: bdf0e8364fd3 ("ARM: davinci: da850-evm: use gpio descriptor for mmc pins") Reviewed-by: David Lechner Signed-off-by: Sekhar Nori Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-davinci/board-da850-evm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index cbde0030c092..25f12118c364 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -763,12 +763,17 @@ static const short da850_evm_mcasp_pins[] __initconst = { -1 }; +#define DA850_MMCSD_CD_PIN GPIO_TO_PIN(4, 0) +#define DA850_MMCSD_WP_PIN GPIO_TO_PIN(4, 1) + static struct gpiod_lookup_table mmc_gpios_table = { .dev_id = "da830-mmc.0", .table = { /* gpio chip 2 contains gpio range 64-95 */ - GPIO_LOOKUP("davinci_gpio.2", 0, "cd", GPIO_ACTIVE_LOW), - GPIO_LOOKUP("davinci_gpio.2", 1, "wp", GPIO_ACTIVE_LOW), + GPIO_LOOKUP("davinci_gpio.0", DA850_MMCSD_CD_PIN, "cd", + GPIO_ACTIVE_LOW), + GPIO_LOOKUP("davinci_gpio.0", DA850_MMCSD_WP_PIN, "wp", + GPIO_ACTIVE_LOW), }, }; -- GitLab From 034a9e9b235efa6ab98b67cd0bac57496d702589 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 24 Apr 2018 20:05:06 +0530 Subject: [PATCH 0571/1299] ARM: davinci: board-omapl138-hawk: fix GPIO numbers for MMC/SD lookup [ Upstream commit d45622c0eaa5992a1a2248cbe93e1ff7a2da7be4 ] commit c4dc56be7e26 ("ARM: davinci: fix the GPIO lookup for omapl138-hawk") fixed the GPIO chip name for look-up of MMC/SD CD and WP pins, but forgot to change the GPIO numbers passed. The GPIO numbers are not offsets from within a 32 GPIO bank. Fix the GPIO numbers as well as remove the misleading comment. Fixes: c4dc56be7e26 ("ARM: davinci: fix the GPIO lookup for omapl138-hawk") Reviewed-by: David Lechner Signed-off-by: Sekhar Nori Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-davinci/board-omapl138-hawk.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index 62eb7d668890..10a027253250 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -123,12 +123,16 @@ static const short hawk_mmcsd0_pins[] = { -1 }; +#define DA850_HAWK_MMCSD_CD_PIN GPIO_TO_PIN(3, 12) +#define DA850_HAWK_MMCSD_WP_PIN GPIO_TO_PIN(3, 13) + static struct gpiod_lookup_table mmc_gpios_table = { .dev_id = "da830-mmc.0", .table = { - /* CD: gpio3_12: gpio60: chip 1 contains gpio range 32-63*/ - GPIO_LOOKUP("davinci_gpio.0", 28, "cd", GPIO_ACTIVE_LOW), - GPIO_LOOKUP("davinci_gpio.0", 29, "wp", GPIO_ACTIVE_LOW), + GPIO_LOOKUP("davinci_gpio.0", DA850_HAWK_MMCSD_CD_PIN, "cd", + GPIO_ACTIVE_LOW), + GPIO_LOOKUP("davinci_gpio.0", DA850_HAWK_MMCSD_WP_PIN, "wp", + GPIO_ACTIVE_LOW), }, }; -- GitLab From b1ac1ca7352dc59d1710fa14468e36b73ba454e0 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Wed, 25 Apr 2018 14:53:23 +0530 Subject: [PATCH 0572/1299] ARM: davinci: board-dm355-evm: fix broken networking [ Upstream commit 5c054de228dd6d97bf8e38962bd118953b66e5a0 ] Since commit 09f3756bb9a8 ("dm9000: Return an ERR_PTR() in all error conditions of dm9000_parse_dt()"), passing either non-NULL platform data or device-tree for dm9000 driver to probe is mandatory. DM335 board was using none, so networking failed to initialize. Fix it by passing non-NULL (but empty) platform data. Fixes: 09f3756bb9a8 ("dm9000: Return an ERR_PTR() in all error conditions of dm9000_parse_dt()") Signed-off-by: Sekhar Nori Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-davinci/board-dm355-evm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c index 62e7bc3018f0..8e64685b1941 100644 --- a/arch/arm/mach-davinci/board-dm355-evm.c +++ b/arch/arm/mach-davinci/board-dm355-evm.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -168,11 +169,16 @@ static struct resource dm355evm_dm9000_rsrc[] = { }, }; +static struct dm9000_plat_data dm335evm_dm9000_platdata; + static struct platform_device dm355evm_dm9000 = { .name = "dm9000", .id = -1, .resource = dm355evm_dm9000_rsrc, .num_resources = ARRAY_SIZE(dm355evm_dm9000_rsrc), + .dev = { + .platform_data = &dm335evm_dm9000_platdata, + }, }; static struct tvp514x_platform_data tvp5146_pdata = { -- GitLab From 061a560f3293e06c72f4c36219e5bd4153c8cc6a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 25 Apr 2018 09:49:38 +0200 Subject: [PATCH 0573/1299] dt-bindings: panel: lvds: Fix path to display timing bindings [ Upstream commit f130307054a59ca21d2396f386be77ebd2e8ca96 ] Fixes: 14da3ed8dd08c581 ("devicetree/bindings: display: Document common panel properties") Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Rob Herring Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- .../devicetree/bindings/display/panel/panel-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.txt b/Documentation/devicetree/bindings/display/panel/panel-common.txt index ec52c472c845..0603af877155 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-common.txt +++ b/Documentation/devicetree/bindings/display/panel/panel-common.txt @@ -38,7 +38,7 @@ Display Timings require specific display timings. The panel-timing subnode expresses those timings as specified in the timing subnode section of the display timing bindings defined in - Documentation/devicetree/bindings/display/display-timing.txt. + Documentation/devicetree/bindings/display/panel/display-timing.txt. Connectivity -- GitLab From 691f0a6b3b098511e98e7f4df30f8fa0d26b2868 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 9 Mar 2018 11:50:20 +0200 Subject: [PATCH 0574/1299] ARM: OMAP2+: powerdomain: use raw_smp_processor_id() for trace [ Upstream commit 33e9572483031a79ad0a4468064675144d9269ec ] smp_processor_id() checks preemption if CONFIG_DEBUG_PREEMPT is enabled, causing a warning dump during boot: [ 5.042377] BUG: using smp_processor_id() in preemptible [00000000] code: swapper/0/1 [ 5.050281] caller is pwrdm_set_next_pwrst+0x48/0x88 [ 5.055330] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.14.24-g57341df0b4 #1 Use the raw_smp_processor_id() for the trace instead, this value does not need to be perfectly correct. The alternative of disabling preempt is too heavy weight operation to be applied in PM hot path for just tracing purposes. Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/powerdomain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 76eb6ec5f157..1e6a967cd2d5 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -188,7 +188,7 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) ((prev & OMAP_POWERSTATE_MASK) << 0)); trace_power_domain_target_rcuidle(pwrdm->name, trace_state, - smp_processor_id()); + raw_smp_processor_id()); } break; default: @@ -518,7 +518,7 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) { /* Trace the pwrdm desired target state */ trace_power_domain_target_rcuidle(pwrdm->name, pwrst, - smp_processor_id()); + raw_smp_processor_id()); /* Program the pwrdm desired target state */ ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst); } -- GitLab From 8c4511032ac1d3087906415a770beb75ad198493 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Mon, 30 Apr 2018 18:24:34 -0500 Subject: [PATCH 0575/1299] ARM: dts: logicpd-som-lv: Fix WL127x Startup Issues [ Upstream commit 189822cbcbf3ea37c26a15612d8f922c440bc0e0 ] The VAUX3 rail from the PMIC powers a clock driver which clocks the WL127x. This corrects a bug which did not correctly associate the vin-supply with the proper power rail. This also fixes a typo in the pinmuxing to properly configure the interrupt pin. Fixes: ab8dd3aed011 ("ARM: DTS: Add minimal Support for Logic PD DM3730 SOM-LV") Signed-off-by: Adam Ford Signed-off-by: Tony Lindgren Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/logicpd-som-lv.dtsi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/logicpd-som-lv.dtsi b/arch/arm/boot/dts/logicpd-som-lv.dtsi index e262fa9ef334..d300149fbf1f 100644 --- a/arch/arm/boot/dts/logicpd-som-lv.dtsi +++ b/arch/arm/boot/dts/logicpd-som-lv.dtsi @@ -26,7 +26,7 @@ gpio = <&gpio1 3 0>; /* gpio_3 */ startup-delay-us = <70000>; enable-active-high; - vin-supply = <&vmmc2>; + vin-supply = <&vaux3>; }; /* HS USB Host PHY on PORT 1 */ @@ -235,7 +235,7 @@ }; wl127x_gpio: pinmux_wl127x_gpio_pin { pinctrl-single,pins = < - OMAP3_WKUP_IOPAD(0x2a0c, PIN_INPUT | MUX_MODE4) /* sys_boot0.gpio_2 */ + OMAP3_WKUP_IOPAD(0x2a0a, PIN_INPUT | MUX_MODE4) /* sys_boot0.gpio_2 */ OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE4) /* sys_boot1.gpio_3 */ >; }; @@ -270,6 +270,11 @@ #include "twl4030.dtsi" #include "twl4030_omap3.dtsi" +&vaux3 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; +}; + &twl { twl_power: power { compatible = "ti,twl4030-power-idle-osc-off", "ti,twl4030-power-idle"; -- GitLab From f8d7147cb60ffafe2363592cca2daee75a6a8530 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Tue, 1 May 2018 08:58:53 -0500 Subject: [PATCH 0576/1299] ARM: dts: logicpd-som-lv: Fix Audio Mute [ Upstream commit 95e59fc3c3fa3187a07a75f40b21637deb4bd12d ] The Audio has worked, but the mute pin has a weak pulldown which alows some of the audio signal to pass very quietly. This patch fixes that so the mute pin is actively driven high for mute or low for normal operation. Fixes: ab8dd3aed011 ("ARM: DTS: Add minimal Support for Logic PD DM3730 SOM-LV") Signed-off-by: Adam Ford Signed-off-by: Tony Lindgren Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/logicpd-som-lv.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/logicpd-som-lv.dtsi b/arch/arm/boot/dts/logicpd-som-lv.dtsi index d300149fbf1f..c335b923753a 100644 --- a/arch/arm/boot/dts/logicpd-som-lv.dtsi +++ b/arch/arm/boot/dts/logicpd-som-lv.dtsi @@ -108,6 +108,7 @@ twl_audio: audio { compatible = "ti,twl4030-audio"; codec { + ti,hs_extmute_gpio = <&gpio2 25 GPIO_ACTIVE_HIGH>; }; }; }; @@ -221,6 +222,7 @@ pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ + OMAP3_CORE1_IOPAD(0x20ba, PIN_OUTPUT | MUX_MODE4) /* gpmc_ncs6.gpio_57 */ >; }; }; -- GitLab From 960fe000b1d3228394f930a824eeb1a401c2cdd9 Mon Sep 17 00:00:00 2001 From: Nick Dyer Date: Tue, 1 May 2018 11:40:18 -0700 Subject: [PATCH 0577/1299] Input: atmel_mxt_ts - fix the firmware update [ Upstream commit 068bdb67ef74df0ad1627b7247a163e3e252ac11 ] The automatic update mechanism will trigger an update if the info block CRCs are different between maxtouch configuration file (maxtouch.cfg) and chip. The driver compared the CRCs without retrieving the chip CRC, resulting always in a failure and firmware flashing action triggered. Fix this issue by retrieving the chip info block CRC before the check. Note that this solution has the benefit that by reading the information block and the object table into a contiguous region of memory, we can verify the checksum at probe time. This means we make sure that we are indeed talking to a chip that supports object protocol correctly. Using this patch on a kevin chromebook, the touchscreen and touchpad drivers are able to match the CRC: atmel_mxt_ts 3-004b: Family: 164 Variant: 14 Firmware V2.3.AA Objects: 40 atmel_mxt_ts 5-004a: Family: 164 Variant: 17 Firmware V2.0.AA Objects: 31 atmel_mxt_ts 3-004b: Resetting device atmel_mxt_ts 5-004a: Resetting device atmel_mxt_ts 3-004b: Config CRC 0x573E89: OK atmel_mxt_ts 3-004b: Touchscreen size X4095Y2729 input: Atmel maXTouch Touchscreen as /devices/platform/ff130000.i2c/i2c-3/3-004b/input/input5 atmel_mxt_ts 5-004a: Config CRC 0x0AF6BA: OK atmel_mxt_ts 5-004a: Touchscreen size X1920Y1080 input: Atmel maXTouch Touchpad as /devices/platform/ff140000.i2c/i2c-5/5-004a/input/input6 Signed-off-by: Nick Dyer Acked-by: Benson Leung [Ezequiel: minor patch massage] Signed-off-by: Ezequiel Garcia Tested-by: Sebastian Reichel Signed-off-by: Dmitry Torokhov Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/input/touchscreen/atmel_mxt_ts.c | 186 ++++++++++++++--------- 1 file changed, 110 insertions(+), 76 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 429b694405c7..fc149ea64be7 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -275,7 +275,8 @@ struct mxt_data { char phys[64]; /* device physical location */ const struct mxt_platform_data *pdata; struct mxt_object *object_table; - struct mxt_info info; + struct mxt_info *info; + void *raw_info_block; unsigned int irq; unsigned int max_x; unsigned int max_y; @@ -450,12 +451,13 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) { u8 appmode = data->client->addr; u8 bootloader; + u8 family_id = data->info ? data->info->family_id : 0; switch (appmode) { case 0x4a: case 0x4b: /* Chips after 1664S use different scheme */ - if (retry || data->info.family_id >= 0xa2) { + if (retry || family_id >= 0xa2) { bootloader = appmode - 0x24; break; } @@ -682,7 +684,7 @@ mxt_get_object(struct mxt_data *data, u8 type) struct mxt_object *object; int i; - for (i = 0; i < data->info.object_num; i++) { + for (i = 0; i < data->info->object_num; i++) { object = data->object_table + i; if (object->type == type) return object; @@ -1453,12 +1455,12 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) data_pos += offset; } - if (cfg_info.family_id != data->info.family_id) { + if (cfg_info.family_id != data->info->family_id) { dev_err(dev, "Family ID mismatch!\n"); return -EINVAL; } - if (cfg_info.variant_id != data->info.variant_id) { + if (cfg_info.variant_id != data->info->variant_id) { dev_err(dev, "Variant ID mismatch!\n"); return -EINVAL; } @@ -1503,7 +1505,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) /* Malloc memory to store configuration */ cfg_start_ofs = MXT_OBJECT_START + - data->info.object_num * sizeof(struct mxt_object) + + data->info->object_num * sizeof(struct mxt_object) + MXT_INFO_CHECKSUM_SIZE; config_mem_size = data->mem_size - cfg_start_ofs; config_mem = kzalloc(config_mem_size, GFP_KERNEL); @@ -1554,20 +1556,6 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) return ret; } -static int mxt_get_info(struct mxt_data *data) -{ - struct i2c_client *client = data->client; - struct mxt_info *info = &data->info; - int error; - - /* Read 7-byte info block starting at address 0 */ - error = __mxt_read_reg(client, 0, sizeof(*info), info); - if (error) - return error; - - return 0; -} - static void mxt_free_input_device(struct mxt_data *data) { if (data->input_dev) { @@ -1582,9 +1570,10 @@ static void mxt_free_object_table(struct mxt_data *data) video_unregister_device(&data->dbg.vdev); v4l2_device_unregister(&data->dbg.v4l2); #endif - - kfree(data->object_table); data->object_table = NULL; + data->info = NULL; + kfree(data->raw_info_block); + data->raw_info_block = NULL; kfree(data->msg_buf); data->msg_buf = NULL; data->T5_address = 0; @@ -1600,34 +1589,18 @@ static void mxt_free_object_table(struct mxt_data *data) data->max_reportid = 0; } -static int mxt_get_object_table(struct mxt_data *data) +static int mxt_parse_object_table(struct mxt_data *data, + struct mxt_object *object_table) { struct i2c_client *client = data->client; - size_t table_size; - struct mxt_object *object_table; - int error; int i; u8 reportid; u16 end_address; - table_size = data->info.object_num * sizeof(struct mxt_object); - object_table = kzalloc(table_size, GFP_KERNEL); - if (!object_table) { - dev_err(&data->client->dev, "Failed to allocate memory\n"); - return -ENOMEM; - } - - error = __mxt_read_reg(client, MXT_OBJECT_START, table_size, - object_table); - if (error) { - kfree(object_table); - return error; - } - /* Valid Report IDs start counting from 1 */ reportid = 1; data->mem_size = 0; - for (i = 0; i < data->info.object_num; i++) { + for (i = 0; i < data->info->object_num; i++) { struct mxt_object *object = object_table + i; u8 min_id, max_id; @@ -1651,8 +1624,8 @@ static int mxt_get_object_table(struct mxt_data *data) switch (object->type) { case MXT_GEN_MESSAGE_T5: - if (data->info.family_id == 0x80 && - data->info.version < 0x20) { + if (data->info->family_id == 0x80 && + data->info->version < 0x20) { /* * On mXT224 firmware versions prior to V2.0 * read and discard unused CRC byte otherwise @@ -1707,24 +1680,102 @@ static int mxt_get_object_table(struct mxt_data *data) /* If T44 exists, T5 position has to be directly after */ if (data->T44_address && (data->T5_address != data->T44_address + 1)) { dev_err(&client->dev, "Invalid T44 position\n"); - error = -EINVAL; - goto free_object_table; + return -EINVAL; } data->msg_buf = kcalloc(data->max_reportid, data->T5_msg_size, GFP_KERNEL); - if (!data->msg_buf) { - dev_err(&client->dev, "Failed to allocate message buffer\n"); + if (!data->msg_buf) + return -ENOMEM; + + return 0; +} + +static int mxt_read_info_block(struct mxt_data *data) +{ + struct i2c_client *client = data->client; + int error; + size_t size; + void *id_buf, *buf; + uint8_t num_objects; + u32 calculated_crc; + u8 *crc_ptr; + + /* If info block already allocated, free it */ + if (data->raw_info_block) + mxt_free_object_table(data); + + /* Read 7-byte ID information block starting at address 0 */ + size = sizeof(struct mxt_info); + id_buf = kzalloc(size, GFP_KERNEL); + if (!id_buf) + return -ENOMEM; + + error = __mxt_read_reg(client, 0, size, id_buf); + if (error) + goto err_free_mem; + + /* Resize buffer to give space for rest of info block */ + num_objects = ((struct mxt_info *)id_buf)->object_num; + size += (num_objects * sizeof(struct mxt_object)) + + MXT_INFO_CHECKSUM_SIZE; + + buf = krealloc(id_buf, size, GFP_KERNEL); + if (!buf) { error = -ENOMEM; - goto free_object_table; + goto err_free_mem; + } + id_buf = buf; + + /* Read rest of info block */ + error = __mxt_read_reg(client, MXT_OBJECT_START, + size - MXT_OBJECT_START, + id_buf + MXT_OBJECT_START); + if (error) + goto err_free_mem; + + /* Extract & calculate checksum */ + crc_ptr = id_buf + size - MXT_INFO_CHECKSUM_SIZE; + data->info_crc = crc_ptr[0] | (crc_ptr[1] << 8) | (crc_ptr[2] << 16); + + calculated_crc = mxt_calculate_crc(id_buf, 0, + size - MXT_INFO_CHECKSUM_SIZE); + + /* + * CRC mismatch can be caused by data corruption due to I2C comms + * issue or else device is not using Object Based Protocol (eg i2c-hid) + */ + if ((data->info_crc == 0) || (data->info_crc != calculated_crc)) { + dev_err(&client->dev, + "Info Block CRC error calculated=0x%06X read=0x%06X\n", + calculated_crc, data->info_crc); + error = -EIO; + goto err_free_mem; + } + + data->raw_info_block = id_buf; + data->info = (struct mxt_info *)id_buf; + + dev_info(&client->dev, + "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", + data->info->family_id, data->info->variant_id, + data->info->version >> 4, data->info->version & 0xf, + data->info->build, data->info->object_num); + + /* Parse object table information */ + error = mxt_parse_object_table(data, id_buf + MXT_OBJECT_START); + if (error) { + dev_err(&client->dev, "Error %d parsing object table\n", error); + mxt_free_object_table(data); + goto err_free_mem; } - data->object_table = object_table; + data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START); return 0; -free_object_table: - mxt_free_object_table(data); +err_free_mem: + kfree(id_buf); return error; } @@ -2039,7 +2090,7 @@ static int mxt_initialize(struct mxt_data *data) int error; while (1) { - error = mxt_get_info(data); + error = mxt_read_info_block(data); if (!error) break; @@ -2070,16 +2121,9 @@ static int mxt_initialize(struct mxt_data *data) msleep(MXT_FW_RESET_TIME); } - /* Get object table information */ - error = mxt_get_object_table(data); - if (error) { - dev_err(&client->dev, "Error %d reading object table\n", error); - return error; - } - error = mxt_acquire_irq(data); if (error) - goto err_free_object_table; + return error; error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, &client->dev, GFP_KERNEL, data, @@ -2087,14 +2131,10 @@ static int mxt_initialize(struct mxt_data *data) if (error) { dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", error); - goto err_free_object_table; + return error; } return 0; - -err_free_object_table: - mxt_free_object_table(data); - return error; } static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) @@ -2155,7 +2195,7 @@ static int mxt_init_t7_power_cfg(struct mxt_data *data) static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x, unsigned int y) { - struct mxt_info *info = &data->info; + struct mxt_info *info = data->info; struct mxt_dbg *dbg = &data->dbg; unsigned int ofs, page; unsigned int col = 0; @@ -2483,7 +2523,7 @@ static const struct video_device mxt_video_device = { static void mxt_debug_init(struct mxt_data *data) { - struct mxt_info *info = &data->info; + struct mxt_info *info = data->info; struct mxt_dbg *dbg = &data->dbg; struct mxt_object *object; int error; @@ -2569,7 +2609,6 @@ static int mxt_configure_objects(struct mxt_data *data, const struct firmware *cfg) { struct device *dev = &data->client->dev; - struct mxt_info *info = &data->info; int error; error = mxt_init_t7_power_cfg(data); @@ -2594,11 +2633,6 @@ static int mxt_configure_objects(struct mxt_data *data, mxt_debug_init(data); - dev_info(dev, - "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", - info->family_id, info->variant_id, info->version >> 4, - info->version & 0xf, info->build, info->object_num); - return 0; } @@ -2607,7 +2641,7 @@ static ssize_t mxt_fw_version_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mxt_data *data = dev_get_drvdata(dev); - struct mxt_info *info = &data->info; + struct mxt_info *info = data->info; return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n", info->version >> 4, info->version & 0xf, info->build); } @@ -2617,7 +2651,7 @@ static ssize_t mxt_hw_version_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mxt_data *data = dev_get_drvdata(dev); - struct mxt_info *info = &data->info; + struct mxt_info *info = data->info; return scnprintf(buf, PAGE_SIZE, "%u.%u\n", info->family_id, info->variant_id); } @@ -2656,7 +2690,7 @@ static ssize_t mxt_object_show(struct device *dev, return -ENOMEM; error = 0; - for (i = 0; i < data->info.object_num; i++) { + for (i = 0; i < data->info->object_num; i++) { object = data->object_table + i; if (!mxt_object_readable(object->type)) -- GitLab From 8794fff6f4d9d48c6638b05f8de6bda8919b1748 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 6 Apr 2018 16:28:22 +0200 Subject: [PATCH 0578/1299] hexagon: add memset_io() helper [ Upstream commit a57ab96ef9dde231d4d46edba4d5f73720edc16a ] We already have memcpy_toio(), but not memset_io(), so let's add the obvious version to allow building an allmodconfig kernel without errors like drivers/gpu/drm/ttm/ttm_bo_util.c: In function 'ttm_bo_move_memcpy': drivers/gpu/drm/ttm/ttm_bo_util.c:390:3: error: implicit declaration of function 'memset_io' [-Werror=implicit-function-declaration] Signed-off-by: Arnd Bergmann Signed-off-by: Richard Kuo Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/hexagon/include/asm/io.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h index 66f5e9a61efc..7288e31d3713 100644 --- a/arch/hexagon/include/asm/io.h +++ b/arch/hexagon/include/asm/io.h @@ -216,6 +216,12 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src, memcpy((void *) dst, src, count); } +static inline void memset_io(volatile void __iomem *addr, int value, + size_t size) +{ + memset((void __force *)addr, value, size); +} + #define PCI_IO_ADDR (volatile void __iomem *) /* -- GitLab From 09e12b91d12c03c31fee65ab7e4052b7f14e006b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 6 Apr 2018 16:28:23 +0200 Subject: [PATCH 0579/1299] hexagon: export csum_partial_copy_nocheck [ Upstream commit 330e261c35dfb969c48f996dbbc8b334b5ee8d9d ] This is needed to link ipv6 as a loadable module, which in turn happens in allmodconfig. Signed-off-by: Arnd Bergmann Signed-off-by: Richard Kuo Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/hexagon/lib/checksum.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/hexagon/lib/checksum.c b/arch/hexagon/lib/checksum.c index 617506d1a559..7cd0a2259269 100644 --- a/arch/hexagon/lib/checksum.c +++ b/arch/hexagon/lib/checksum.c @@ -199,3 +199,4 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) memcpy(dst, src, len); return csum_partial(dst, len, sum); } +EXPORT_SYMBOL(csum_partial_copy_nocheck); -- GitLab From 666776d5f45d478ef97b087ebc9ca0f52e55fdc5 Mon Sep 17 00:00:00 2001 From: Jim Gill Date: Fri, 20 Apr 2018 19:04:47 -0700 Subject: [PATCH 0580/1299] scsi: vmw-pvscsi: return DID_BUS_BUSY for adapter-initated aborts [ Upstream commit f4b024271ae3e9786e5d6f1c05b01b57a74e1d6d ] The vmw_pvscsi driver returns DID_ABORT for commands aborted internally by the adapter, leading to the filesystem going read-only. Change the result to DID_BUS_BUSY, causing the kernel to retry the command. Signed-off-by: Jim Gill Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/vmw_pvscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index c374e3b5c678..777e5f1e52d1 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c @@ -609,7 +609,7 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter, break; case BTSTAT_ABORTQUEUE: - cmd->result = (DID_ABORT << 16); + cmd->result = (DID_BUS_BUSY << 16); break; case BTSTAT_SCSIPARITY: -- GitLab From 609377d79e7578fc977ef02381febcc71a7a810a Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 2 May 2018 20:12:22 +0200 Subject: [PATCH 0581/1299] bpf, x64: fix memleak when not converging after image [ Upstream commit 3aab8884c9eb99189a3569ac4e6b205371c9ac0b ] While reviewing x64 JIT code, I noticed that we leak the prior allocated JIT image in the case where proglen != oldproglen during the JIT passes. Prior to the commit e0ee9c12157d ("x86: bpf_jit: fix two bugs in eBPF JIT compiler") we would just break out of the loop, and using the image as the JITed prog since it could only shrink in size anyway. After e0ee9c12157d, we would bail out to out_addrs label where we free addrs and jit_data but not the image coming from bpf_jit_binary_alloc(). Fixes: e0ee9c12157d ("x86: bpf_jit: fix two bugs in eBPF JIT compiler") Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Acked-by: David S. Miller Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/x86/net/bpf_jit_comp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index bb77606d04e0..a9deb2b0397d 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -1159,6 +1159,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) for (pass = 0; pass < 20 || image; pass++) { proglen = do_jit(prog, addrs, image, oldproglen, &ctx); if (proglen <= 0) { +out_image: image = NULL; if (header) bpf_jit_binary_free(header); @@ -1169,8 +1170,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) if (proglen != oldproglen) { pr_err("bpf_jit: proglen=%d != oldproglen=%d\n", proglen, oldproglen); - prog = orig_prog; - goto out_addrs; + goto out_image; } break; } -- GitLab From a814d1101042d117069de12ba6a0ba152ac3f79a Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 20 Apr 2018 23:19:17 +0200 Subject: [PATCH 0582/1299] parisc: drivers.c: Fix section mismatches [ Upstream commit b819439fea305a0bfd6ca23a7994fd1a8847c0d8 ] Fix two section mismatches in drivers.c: 1) Section mismatch in reference from the function alloc_tree_node() to the function .init.text:create_tree_node(). 2) Section mismatch in reference from the function walk_native_bus() to the function .init.text:alloc_pa_dev(). Signed-off-by: Helge Deller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/drivers.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 513826a43efd..6a71d3151a23 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -448,7 +448,8 @@ static int match_by_id(struct device * dev, void * data) * Checks all the children of @parent for a matching @id. If none * found, it allocates a new device and returns it. */ -static struct parisc_device * alloc_tree_node(struct device *parent, char id) +static struct parisc_device * __init alloc_tree_node( + struct device *parent, char id) { struct match_id_data d = { .id = id, @@ -825,8 +826,8 @@ void walk_lower_bus(struct parisc_device *dev) * devices which are not physically connected (such as extra serial & * keyboard ports). This problem is not yet solved. */ -static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, - struct device *parent) +static void __init walk_native_bus(unsigned long io_io_low, + unsigned long io_io_high, struct device *parent) { int i, devices_found = 0; unsigned long hpa = io_io_low; -- GitLab From e7a65e899d521eba676a1e652f9bf48d67722a18 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 20 Apr 2018 11:50:05 +0200 Subject: [PATCH 0583/1299] stop_machine, sched: Fix migrate_swap() vs. active_balance() deadlock [ Upstream commit 0b26351b910fb8fe6a056f8a1bbccabe50c0e19f ] Matt reported the following deadlock: CPU0 CPU1 schedule(.prev=migrate/0) pick_next_task() ... idle_balance() migrate_swap() active_balance() stop_two_cpus() spin_lock(stopper0->lock) spin_lock(stopper1->lock) ttwu(migrate/0) smp_cond_load_acquire() -- waits for schedule() stop_one_cpu(1) spin_lock(stopper1->lock) -- waits for stopper lock Fix this deadlock by taking the wakeups out from under stopper->lock. This allows the active_balance() to queue the stop work and finish the context switch, which in turn allows the wakeup from migrate_swap() to observe the context and complete the wakeup. Signed-off-by: Peter Zijlstra (Intel) Reported-by: Matt Fleming Signed-off-by: Peter Zijlstra (Intel) Acked-by: Matt Fleming Cc: Linus Torvalds Cc: Michal Hocko Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20180420095005.GH4064@hirez.programming.kicks-ass.net Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- kernel/stop_machine.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index b7591261652d..64c0291b579c 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -21,6 +21,7 @@ #include #include #include +#include /* * Structure to determine completion condition and record errors. May @@ -65,27 +66,31 @@ static void cpu_stop_signal_done(struct cpu_stop_done *done) } static void __cpu_stop_queue_work(struct cpu_stopper *stopper, - struct cpu_stop_work *work) + struct cpu_stop_work *work, + struct wake_q_head *wakeq) { list_add_tail(&work->list, &stopper->works); - wake_up_process(stopper->thread); + wake_q_add(wakeq, stopper->thread); } /* queue @work to @stopper. if offline, @work is completed immediately */ static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work) { struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); + DEFINE_WAKE_Q(wakeq); unsigned long flags; bool enabled; spin_lock_irqsave(&stopper->lock, flags); enabled = stopper->enabled; if (enabled) - __cpu_stop_queue_work(stopper, work); + __cpu_stop_queue_work(stopper, work, &wakeq); else if (work->done) cpu_stop_signal_done(work->done); spin_unlock_irqrestore(&stopper->lock, flags); + wake_up_q(&wakeq); + return enabled; } @@ -229,6 +234,7 @@ static int cpu_stop_queue_two_works(int cpu1, struct cpu_stop_work *work1, { struct cpu_stopper *stopper1 = per_cpu_ptr(&cpu_stopper, cpu1); struct cpu_stopper *stopper2 = per_cpu_ptr(&cpu_stopper, cpu2); + DEFINE_WAKE_Q(wakeq); int err; retry: spin_lock_irq(&stopper1->lock); @@ -252,8 +258,8 @@ static int cpu_stop_queue_two_works(int cpu1, struct cpu_stop_work *work1, goto unlock; err = 0; - __cpu_stop_queue_work(stopper1, work1); - __cpu_stop_queue_work(stopper2, work2); + __cpu_stop_queue_work(stopper1, work1, &wakeq); + __cpu_stop_queue_work(stopper2, work2, &wakeq); unlock: spin_unlock(&stopper2->lock); spin_unlock_irq(&stopper1->lock); @@ -263,6 +269,9 @@ static int cpu_stop_queue_two_works(int cpu1, struct cpu_stop_work *work1, cpu_relax(); goto retry; } + + wake_up_q(&wakeq); + return err; } /** -- GitLab From 61ca60932d52536944d56880032fc7a9ca305557 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 30 Apr 2018 14:50:22 +0200 Subject: [PATCH 0584/1299] kthread, sched/wait: Fix kthread_parkme() wait-loop [ Upstream commit 741a76b350897604c48fb12beff1c9b77724dc96 ] Gaurav reported a problem with __kthread_parkme() where a concurrent try_to_wake_up() could result in competing stores to ->state which, when the TASK_PARKED store got lost bad things would happen. The comment near set_current_state() actually mentions this competing store, but only mentions the case against TASK_RUNNING. This same store, with different timing, can happen against a subsequent !RUNNING store. This normally is not a problem, because as per that same comment, the !RUNNING state store is inside a condition based wait-loop: for (;;) { set_current_state(TASK_UNINTERRUPTIBLE); if (!need_sleep) break; schedule(); } __set_current_state(TASK_RUNNING); If we loose the (first) TASK_UNINTERRUPTIBLE store to a previous (concurrent) wakeup, the schedule() will NO-OP and we'll go around the loop once more. The problem here is that the TASK_PARKED store is not inside the KTHREAD_SHOULD_PARK condition wait-loop. There is a genuine issue with sleeps that do not have a condition; this is addressed in a subsequent patch. Reported-by: Gaurav Kohli Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Oleg Nesterov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- kernel/kthread.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/kthread.c b/kernel/kthread.c index 1c19edf82427..1ef8f3a5b072 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -169,12 +169,13 @@ void *kthread_probe_data(struct task_struct *task) static void __kthread_parkme(struct kthread *self) { - __set_current_state(TASK_PARKED); - while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) { + for (;;) { + set_current_state(TASK_PARKED); + if (!test_bit(KTHREAD_SHOULD_PARK, &self->flags)) + break; if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags)) complete(&self->parked); schedule(); - __set_current_state(TASK_PARKED); } clear_bit(KTHREAD_IS_PARKED, &self->flags); __set_current_state(TASK_RUNNING); -- GitLab From d98905c00c4c348eae88a5c195c611e2e1f23fc5 Mon Sep 17 00:00:00 2001 From: Bhadram Varka Date: Wed, 2 May 2018 20:44:40 +0530 Subject: [PATCH 0585/1299] arm64: tegra: Make BCM89610 PHY interrupt as active low [ Upstream commit 9df50ba76ac1485b844beffa1f3f5d9659d9cdaf ] Need to configure PHY interrupt as active low for P3310 Tegra186 platform otherwise it results in spurious interrupts. This issue wasn't seen before because the generic PHY driver without interrupt support was used. Signed-off-by: Bhadram Varka Signed-off-by: Thierry Reding Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi index 54f418d05e15..2306b1a0c09a 100644 --- a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi @@ -46,7 +46,7 @@ compatible = "ethernet-phy-ieee802.3-c22"; reg = <0x0>; interrupt-parent = <&gpio>; - interrupts = ; + interrupts = ; }; }; }; -- GitLab From 665d3c7f1e506ed9310e3038ab0966520fa5749a Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Fri, 20 Apr 2018 13:29:55 +0800 Subject: [PATCH 0586/1299] iommu/vt-d: fix shift-out-of-bounds in bug checking [ Upstream commit 0dfc0c792d691f8056f38b5c30789f504be0e467 ] It allows to flush more than 4GB of device TLBs. So the mask should be 64bit wide. UBSAN captured this fault as below. [ 3.760024] ================================================================================ [ 3.768440] UBSAN: Undefined behaviour in drivers/iommu/dmar.c:1348:3 [ 3.774864] shift exponent 64 is too large for 32-bit type 'int' [ 3.780853] CPU: 2 PID: 0 Comm: swapper/2 Tainted: G U 4.17.0-rc1+ #89 [ 3.788661] Hardware name: Dell Inc. OptiPlex 7040/0Y7WYT, BIOS 1.2.8 01/26/2016 [ 3.796034] Call Trace: [ 3.798472] [ 3.800479] dump_stack+0x90/0xfb [ 3.803787] ubsan_epilogue+0x9/0x40 [ 3.807353] __ubsan_handle_shift_out_of_bounds+0x10e/0x170 [ 3.812916] ? qi_flush_dev_iotlb+0x124/0x180 [ 3.817261] qi_flush_dev_iotlb+0x124/0x180 [ 3.821437] iommu_flush_dev_iotlb+0x94/0xf0 [ 3.825698] iommu_flush_iova+0x10b/0x1c0 [ 3.829699] ? fq_ring_free+0x1d0/0x1d0 [ 3.833527] iova_domain_flush+0x25/0x40 [ 3.837448] fq_flush_timeout+0x55/0x160 [ 3.841368] ? fq_ring_free+0x1d0/0x1d0 [ 3.845200] ? fq_ring_free+0x1d0/0x1d0 [ 3.849034] call_timer_fn+0xbe/0x310 [ 3.852696] ? fq_ring_free+0x1d0/0x1d0 [ 3.856530] run_timer_softirq+0x223/0x6e0 [ 3.860625] ? sched_clock+0x5/0x10 [ 3.864108] ? sched_clock+0x5/0x10 [ 3.867594] __do_softirq+0x1b5/0x6f5 [ 3.871250] irq_exit+0xd4/0x130 [ 3.874470] smp_apic_timer_interrupt+0xb8/0x2f0 [ 3.879075] apic_timer_interrupt+0xf/0x20 [ 3.883159] [ 3.885255] RIP: 0010:poll_idle+0x60/0xe7 [ 3.889252] RSP: 0018:ffffb1b201943e30 EFLAGS: 00000246 ORIG_RAX: ffffffffffffff13 [ 3.896802] RAX: 0000000080200000 RBX: 000000000000008e RCX: 000000000000001f [ 3.903918] RDX: 0000000000000000 RSI: 000000002819aa06 RDI: 0000000000000000 [ 3.911031] RBP: ffff9e93c6b33280 R08: 00000010f717d567 R09: 000000000010d205 [ 3.918146] R10: ffffb1b201943df8 R11: 0000000000000001 R12: 00000000e01b169d [ 3.925260] R13: 0000000000000000 R14: ffffffffb12aa400 R15: 0000000000000000 [ 3.932382] cpuidle_enter_state+0xb4/0x470 [ 3.936558] do_idle+0x222/0x310 [ 3.939779] cpu_startup_entry+0x78/0x90 [ 3.943693] start_secondary+0x205/0x2e0 [ 3.947607] secondary_startup_64+0xa5/0xb0 [ 3.951783] ================================================================================ Signed-off-by: Changbin Du Signed-off-by: Joerg Roedel Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/dmar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 57c920c1372d..e3dbb6101b4a 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1342,7 +1342,7 @@ void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep, struct qi_desc desc; if (mask) { - BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1)); + BUG_ON(addr & ((1ULL << (VTD_PAGE_SHIFT + mask)) - 1)); addr |= (1ULL << (VTD_PAGE_SHIFT + mask - 1)) - 1; desc.high = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE; } else -- GitLab From b19122a48f01544456f4b4efe423b9aa7c21be6d Mon Sep 17 00:00:00 2001 From: Chengguang Xu Date: Sat, 14 Apr 2018 20:06:19 +0800 Subject: [PATCH 0587/1299] nvme: fix potential memory leak in option parsing [ Upstream commit 59a2f3f00fd744dbad22593f47552037d3154ca6 ] When specifying same string type option several times, current option parsing may cause memory leak. Hence, call kfree for previous one in this case. Signed-off-by: Chengguang Xu Reviewed-by: Christoph Hellwig Reviewed-by: Sagi Grimberg Signed-off-by: Keith Busch Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/nvme/host/fabrics.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c index 740aae51e1c6..33d060c524e6 100644 --- a/drivers/nvme/host/fabrics.c +++ b/drivers/nvme/host/fabrics.c @@ -587,6 +587,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, ret = -ENOMEM; goto out; } + kfree(opts->transport); opts->transport = p; break; case NVMF_OPT_NQN: @@ -595,6 +596,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, ret = -ENOMEM; goto out; } + kfree(opts->subsysnqn); opts->subsysnqn = p; nqnlen = strlen(opts->subsysnqn); if (nqnlen >= NVMF_NQN_SIZE) { @@ -617,6 +619,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, ret = -ENOMEM; goto out; } + kfree(opts->traddr); opts->traddr = p; break; case NVMF_OPT_TRSVCID: @@ -625,6 +628,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, ret = -ENOMEM; goto out; } + kfree(opts->trsvcid); opts->trsvcid = p; break; case NVMF_OPT_QUEUE_SIZE: @@ -706,6 +710,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, ret = -EINVAL; goto out; } + nvmf_host_put(opts->host); opts->host = nvmf_host_add(p); kfree(p); if (!opts->host) { @@ -731,6 +736,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, ret = -ENOMEM; goto out; } + kfree(opts->host_traddr); opts->host_traddr = p; break; case NVMF_OPT_HOST_ID: -- GitLab From ac5e86401fea34255dcc65f791d927bf8f84673b Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Tue, 17 Apr 2018 14:42:44 -0600 Subject: [PATCH 0588/1299] nvme: Set integrity flag for user passthrough commands [ Upstream commit f31a21103c03bb62846409fdc60cc9faf2398cfb ] If the command a separate metadata buffer attached, the request needs to have the integrity flag set so the driver knows to map it. Signed-off-by: Keith Busch Reviewed-by: Martin K. Petersen Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/nvme/host/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index dd956311a85a..38c128f230e7 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -665,6 +665,7 @@ static int nvme_submit_user_cmd(struct request_queue *q, ret = PTR_ERR(meta); goto out_unmap; } + req->cmd_flags |= REQ_INTEGRITY; } } -- GitLab From 9c0f528f6bf0abcea8291d620117b8b49fb48ab5 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 2 May 2018 20:32:03 +0200 Subject: [PATCH 0589/1299] ARM: OMAP1: ams-delta: fix deferred_fiq handler [ Upstream commit baf64250b4a513bf4ac226fd938692dc1836f4f6 ] The deferred_fiq handler used to limit hardware operations to IRQ unmask only, relying on gpio-omap assigned handler performing the ACKs. Since commit 80ac93c27441 ("gpio: omap: Fix lost edge interrupts") this is no longer the case as handle_edge_irq() has been replaced with handle_simmple_irq() which doesn't touch the hardware. Add single ACK operation per each active IRQ pin to the handler. While being at it, move unmask operation out of irq_counter loop so it is also called only once for each active IRQ pin. Fixes: 80ac93c27441 ("gpio: omap: Fix lost edge interrupts") Signed-off-by: Janusz Krzysztofik Signed-off-by: Tony Lindgren Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap1/ams-delta-fiq.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c index 793a24a53c52..d7ca9e2b40d2 100644 --- a/arch/arm/mach-omap1/ams-delta-fiq.c +++ b/arch/arm/mach-omap1/ams-delta-fiq.c @@ -58,22 +58,24 @@ static irqreturn_t deferred_fiq(int irq, void *dev_id) irq_num = gpio_to_irq(gpio); fiq_count = fiq_buffer[FIQ_CNT_INT_00 + gpio]; - while (irq_counter[gpio] < fiq_count) { - if (gpio != AMS_DELTA_GPIO_PIN_KEYBRD_CLK) { - struct irq_data *d = irq_get_irq_data(irq_num); - - /* - * It looks like handle_edge_irq() that - * OMAP GPIO edge interrupts default to, - * expects interrupt already unmasked. - */ - if (irq_chip && irq_chip->irq_unmask) + if (irq_counter[gpio] < fiq_count && + gpio != AMS_DELTA_GPIO_PIN_KEYBRD_CLK) { + struct irq_data *d = irq_get_irq_data(irq_num); + + /* + * handle_simple_irq() that OMAP GPIO edge + * interrupts default to since commit 80ac93c27441 + * requires interrupt already acked and unmasked. + */ + if (irq_chip) { + if (irq_chip->irq_ack) + irq_chip->irq_ack(d); + if (irq_chip->irq_unmask) irq_chip->irq_unmask(d); } - generic_handle_irq(irq_num); - - irq_counter[gpio]++; } + for (; irq_counter[gpio] < fiq_count; irq_counter[gpio]++) + generic_handle_irq(irq_num); } return IRQ_HANDLED; } -- GitLab From 194feed06bcea86a804d2a547f34f1033faa728f Mon Sep 17 00:00:00 2001 From: Stefan Raspl Date: Thu, 3 May 2018 17:57:39 +0200 Subject: [PATCH 0590/1299] smc: fix sendpage() call [ Upstream commit bda27ff5c4526f80a7620a94ecfe8dca153e3696 ] The sendpage() call grabs the sock lock before calling the default implementation - which tries to grab it once again. Signed-off-by: Stefan Raspl Signed-off-by: Ursula Braun < Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/smc/af_smc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index f9c289e05707..654a81238406 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -1264,8 +1264,11 @@ static ssize_t smc_sendpage(struct socket *sock, struct page *page, smc = smc_sk(sk); lock_sock(sk); - if (sk->sk_state != SMC_ACTIVE) + if (sk->sk_state != SMC_ACTIVE) { + release_sock(sk); goto out; + } + release_sock(sk); if (smc->use_fallback) rc = kernel_sendpage(smc->clcsock, page, offset, size, flags); @@ -1273,7 +1276,6 @@ static ssize_t smc_sendpage(struct socket *sock, struct page *page, rc = sock_no_sendpage(sock, page, offset, size, flags); out: - release_sock(sk); return rc; } -- GitLab From 77662d35b8c5e95ad498c253d434c37e137a2eda Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Tue, 1 May 2018 05:35:43 -0700 Subject: [PATCH 0591/1299] IB/hfi1 Use correct type for num_user_context [ Upstream commit 5da9e742be44d9b7c68b1bf6e1aaf46a1aa7a52b ] The module parameter num_user_context is defined as 'int' and defaults to -1. The module_param_named() says that it is uint. Correct module_param_named() type information and update the modinfo text to reflect the default value. Reviewed-by: Dennis Dalessandro Signed-off-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/hfi1/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index d5c6ff843fc6..918dbd350c71 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c @@ -88,9 +88,9 @@ * pio buffers per ctxt, etc.) Zero means use one user context per CPU. */ int num_user_contexts = -1; -module_param_named(num_user_contexts, num_user_contexts, uint, S_IRUGO); +module_param_named(num_user_contexts, num_user_contexts, int, 0444); MODULE_PARM_DESC( - num_user_contexts, "Set max number of user contexts to use"); + num_user_contexts, "Set max number of user contexts to use (default: -1 will use the real (non-HT) CPU count)"); uint krcvqs[RXE_NUM_DATA_VL]; int krcvqsset; -- GitLab From 3c54e919bd4f41417b601448b73fa2c0aafb47d0 Mon Sep 17 00:00:00 2001 From: Sebastian Sanchez Date: Tue, 1 May 2018 05:36:13 -0700 Subject: [PATCH 0592/1299] IB/hfi1: Fix memory leak in exception path in get_irq_affinity() [ Upstream commit 59482a14918b282ca2a98f38c69da5ebeb1107d2 ] When IRQ affinity is set and the interrupt type is unknown, a cpu mask allocated within the function is never freed. Fix this memory leak by allocating memory within the scope where it is used. Reviewed-by: Mike Marciniszyn Reviewed-by: Michael J. Ruhl Signed-off-by: Sebastian Sanchez Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/hfi1/affinity.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c index a97055dd4fbd..b5fab55cc275 100644 --- a/drivers/infiniband/hw/hfi1/affinity.c +++ b/drivers/infiniband/hw/hfi1/affinity.c @@ -412,7 +412,6 @@ static void hfi1_cleanup_sdma_notifier(struct hfi1_msix_entry *msix) static int get_irq_affinity(struct hfi1_devdata *dd, struct hfi1_msix_entry *msix) { - int ret; cpumask_var_t diff; struct hfi1_affinity_node *entry; struct cpu_mask_set *set = NULL; @@ -424,10 +423,6 @@ static int get_irq_affinity(struct hfi1_devdata *dd, extra[0] = '\0'; cpumask_clear(&msix->mask); - ret = zalloc_cpumask_var(&diff, GFP_KERNEL); - if (!ret) - return -ENOMEM; - entry = node_affinity_lookup(dd->node); switch (msix->type) { @@ -458,6 +453,9 @@ static int get_irq_affinity(struct hfi1_devdata *dd, * finds its CPU here. */ if (cpu == -1 && set) { + if (!zalloc_cpumask_var(&diff, GFP_KERNEL)) + return -ENOMEM; + if (cpumask_equal(&set->mask, &set->used)) { /* * We've used up all the CPUs, bump up the generation @@ -469,6 +467,8 @@ static int get_irq_affinity(struct hfi1_devdata *dd, cpumask_andnot(diff, &set->mask, &set->used); cpu = cpumask_first(diff); cpumask_set_cpu(cpu, &set->used); + + free_cpumask_var(diff); } cpumask_set_cpu(cpu, &msix->mask); @@ -482,7 +482,6 @@ static int get_irq_affinity(struct hfi1_devdata *dd, hfi1_setup_sdma_notifier(msix); } - free_cpumask_var(diff); return 0; } -- GitLab From 373a625cb3c49d72800ac7b2ac00f1d66ba7457f Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Wed, 2 May 2018 13:18:59 +0300 Subject: [PATCH 0593/1299] RDMA/cma: Do not query GID during QP state transition to RTR [ Upstream commit 9aa169213d1166d30ae357a44abbeae93459339d ] When commit [1] was added, SGID was queried to derive the SMAC address. Then, later on during a refactor [2], SMAC was no longer needed. However, the now useless GID query remained. Then during additional code changes later on, the GID query was being done in such a way that it caused iWARP queries to start breaking. Remove the useless GID query and resolve the iWARP breakage at the same time. This is discussed in [3]. [1] commit dd5f03beb4f7 ("IB/core: Ethernet L2 attributes in verbs/cm structures") [2] commit 5c266b2304fb ("IB/cm: Remove the usage of smac and vid of qp_attr and cm_av") [3] https://www.spinics.net/lists/linux-rdma/msg63951.html Suggested-by: Shiraz Saleem Signed-off-by: Parav Pandit Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/cma.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 509d318b50d6..79843a3ca9dc 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -900,7 +900,6 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv, { struct ib_qp_attr qp_attr; int qp_attr_mask, ret; - union ib_gid sgid; mutex_lock(&id_priv->qp_mutex); if (!id_priv->id.qp) { @@ -923,12 +922,6 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv, if (ret) goto out; - ret = ib_query_gid(id_priv->id.device, id_priv->id.port_num, - rdma_ah_read_grh(&qp_attr.ah_attr)->sgid_index, - &sgid, NULL); - if (ret) - goto out; - BUG_ON(id_priv->cma_dev->device != id_priv->id.device); if (conn_param) -- GitLab From a614eaa465f78767cfe6c5580c9741d73a228964 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 3 May 2018 13:09:44 -0500 Subject: [PATCH 0594/1299] spi: bcm2835aux: ensure interrupts are enabled for shared handler [ Upstream commit bc519d9574618e47a0c788000fb78da95e18d953 ] The BCM2835 AUX SPI has a shared interrupt line (with AUX UART). Downstream fixes this with an AUX irqchip to demux the IRQ sources and a DT change which breaks compatibility with older kernels. The AUX irqchip was already rejected for upstream[1] and the DT change would break working systems if the DTB is updated to a newer one. The latter issue was brought to my attention by Alex Graf. The root cause however is a bug in the shared handler. Shared handlers must check that interrupts are actually enabled before servicing the interrupt. Add a check that the TXEMPTY or IDLE interrupts are enabled. [1] https://patchwork.kernel.org/patch/9781221/ Cc: Alexander Graf Cc: Marc Zyngier Cc: Mark Brown Cc: Eric Anholt Cc: Stefan Wahren Cc: Florian Fainelli Cc: Ray Jui Cc: Scott Branden Cc: bcm-kernel-feedback-list@broadcom.com Cc: linux-spi@vger.kernel.org Cc: linux-rpi-kernel@lists.infradead.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Rob Herring Reviewed-by: Eric Anholt Signed-off-by: Mark Brown Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/spi/spi-bcm2835aux.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 7428091d3f5b..bd00b7cc8b78 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -184,6 +184,11 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) struct bcm2835aux_spi *bs = spi_master_get_devdata(master); irqreturn_t ret = IRQ_NONE; + /* IRQ may be shared, so return if our interrupts are disabled */ + if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) & + (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE))) + return ret; + /* check if we have data to read */ while (bs->rx_len && (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & -- GitLab From 0742396317a0a0e41ab47e9de10cd6f16317f049 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 30 Apr 2018 14:51:01 +0200 Subject: [PATCH 0595/1299] sched/core: Introduce set_special_state() [ Upstream commit b5bf9a90bbebffba888c9144c5a8a10317b04064 ] Gaurav reported a perceived problem with TASK_PARKED, which turned out to be a broken wait-loop pattern in __kthread_parkme(), but the reported issue can (and does) in fact happen for states that do not do condition based sleeps. When the 'current->state = TASK_RUNNING' store of a previous (concurrent) try_to_wake_up() collides with the setting of a 'special' sleep state, we can loose the sleep state. Normal condition based wait-loops are immune to this problem, but for sleep states that are not condition based are subject to this problem. There already is a fix for TASK_DEAD. Abstract that and also apply it to TASK_STOPPED and TASK_TRACED, both of which are also without condition based wait-loop. Reported-by: Gaurav Kohli Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Oleg Nesterov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 50 ++++++++++++++++++++++++++++++++---- include/linux/sched/signal.h | 2 +- kernel/sched/core.c | 17 +----------- kernel/signal.c | 17 ++++++++++-- 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 2c9790b43881..e04919aa8201 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -113,17 +113,36 @@ struct task_group; #ifdef CONFIG_DEBUG_ATOMIC_SLEEP +/* + * Special states are those that do not use the normal wait-loop pattern. See + * the comment with set_special_state(). + */ +#define is_special_task_state(state) \ + ((state) & (__TASK_STOPPED | __TASK_TRACED | TASK_DEAD)) + #define __set_current_state(state_value) \ do { \ + WARN_ON_ONCE(is_special_task_state(state_value));\ current->task_state_change = _THIS_IP_; \ current->state = (state_value); \ } while (0) + #define set_current_state(state_value) \ do { \ + WARN_ON_ONCE(is_special_task_state(state_value));\ current->task_state_change = _THIS_IP_; \ smp_store_mb(current->state, (state_value)); \ } while (0) +#define set_special_state(state_value) \ + do { \ + unsigned long flags; /* may shadow */ \ + WARN_ON_ONCE(!is_special_task_state(state_value)); \ + raw_spin_lock_irqsave(¤t->pi_lock, flags); \ + current->task_state_change = _THIS_IP_; \ + current->state = (state_value); \ + raw_spin_unlock_irqrestore(¤t->pi_lock, flags); \ + } while (0) #else /* * set_current_state() includes a barrier so that the write of current->state @@ -145,8 +164,8 @@ struct task_group; * * The above is typically ordered against the wakeup, which does: * - * need_sleep = false; - * wake_up_state(p, TASK_UNINTERRUPTIBLE); + * need_sleep = false; + * wake_up_state(p, TASK_UNINTERRUPTIBLE); * * Where wake_up_state() (and all other wakeup primitives) imply enough * barriers to order the store of the variable against wakeup. @@ -155,12 +174,33 @@ struct task_group; * once it observes the TASK_UNINTERRUPTIBLE store the waking CPU can issue a * TASK_RUNNING store which can collide with __set_current_state(TASK_RUNNING). * - * This is obviously fine, since they both store the exact same value. + * However, with slightly different timing the wakeup TASK_RUNNING store can + * also collide with the TASK_UNINTERRUPTIBLE store. Loosing that store is not + * a problem either because that will result in one extra go around the loop + * and our @cond test will save the day. * * Also see the comments of try_to_wake_up(). */ -#define __set_current_state(state_value) do { current->state = (state_value); } while (0) -#define set_current_state(state_value) smp_store_mb(current->state, (state_value)) +#define __set_current_state(state_value) \ + current->state = (state_value) + +#define set_current_state(state_value) \ + smp_store_mb(current->state, (state_value)) + +/* + * set_special_state() should be used for those states when the blocking task + * can not use the regular condition based wait-loop. In that case we must + * serialize against wakeups such that any possible in-flight TASK_RUNNING stores + * will not collide with our state change. + */ +#define set_special_state(state_value) \ + do { \ + unsigned long flags; /* may shadow */ \ + raw_spin_lock_irqsave(¤t->pi_lock, flags); \ + current->state = (state_value); \ + raw_spin_unlock_irqrestore(¤t->pi_lock, flags); \ + } while (0) + #endif /* Task command name length: */ diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 0aa4548fb492..fbf86ecd149d 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -280,7 +280,7 @@ static inline void kernel_signal_stop(void) { spin_lock_irq(¤t->sighand->siglock); if (current->jobctl & JOBCTL_STOP_DEQUEUED) - __set_current_state(TASK_STOPPED); + set_special_state(TASK_STOPPED); spin_unlock_irq(¤t->sighand->siglock); schedule(); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8cf36b30a006..f287dcbe8cb2 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3374,23 +3374,8 @@ static void __sched notrace __schedule(bool preempt) void __noreturn do_task_dead(void) { - /* - * The setting of TASK_RUNNING by try_to_wake_up() may be delayed - * when the following two conditions become true. - * - There is race condition of mmap_sem (It is acquired by - * exit_mm()), and - * - SMI occurs before setting TASK_RUNINNG. - * (or hypervisor of virtual machine switches to other guest) - * As a result, we may become TASK_RUNNING after becoming TASK_DEAD - * - * To avoid it, we have to wait for releasing tsk->pi_lock which - * is held by try_to_wake_up() - */ - raw_spin_lock_irq(¤t->pi_lock); - raw_spin_unlock_irq(¤t->pi_lock); - /* Causes final put_task_struct in finish_task_switch(): */ - __set_current_state(TASK_DEAD); + set_special_state(TASK_DEAD); /* Tell freezer to ignore us: */ current->flags |= PF_NOFREEZE; diff --git a/kernel/signal.c b/kernel/signal.c index 6895f6bb98a7..4439ba9dc5d9 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1828,14 +1828,27 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) return; } + set_special_state(TASK_TRACED); + /* * We're committing to trapping. TRACED should be visible before * TRAPPING is cleared; otherwise, the tracer might fail do_wait(). * Also, transition to TRACED and updates to ->jobctl should be * atomic with respect to siglock and should be done after the arch * hook as siglock is released and regrabbed across it. + * + * TRACER TRACEE + * + * ptrace_attach() + * [L] wait_on_bit(JOBCTL_TRAPPING) [S] set_special_state(TRACED) + * do_wait() + * set_current_state() smp_wmb(); + * ptrace_do_wait() + * wait_task_stopped() + * task_stopped_code() + * [L] task_is_traced() [S] task_clear_jobctl_trapping(); */ - set_current_state(TASK_TRACED); + smp_wmb(); current->last_siginfo = info; current->exit_code = exit_code; @@ -2043,7 +2056,7 @@ static bool do_signal_stop(int signr) if (task_participate_group_stop(current)) notify = CLD_STOPPED; - __set_current_state(TASK_STOPPED); + set_special_state(TASK_STOPPED); spin_unlock_irq(¤t->sighand->siglock); /* -- GitLab From d40e177f29ab6fd3cc4ddd261d785c3e5b1a2918 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 5 May 2018 16:40:23 -0400 Subject: [PATCH 0596/1299] sh: fix build failure for J2 cpu with SMP disabled [ Upstream commit 6cb465972c4eb6741b3094a58a65e527fc63c100 ] The sh asm/smp.h defines a fallback hard_smp_processor_id macro for the !SMP case, but linux/smp.h never includes asm/smp.h in the !SMP case. Signed-off-by: Rich Felker Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/sh/kernel/cpu/sh2/probe.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index 4205f6d42b69..a5bd03642678 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -43,7 +43,11 @@ void __ref cpu_probe(void) #endif #if defined(CONFIG_CPU_J2) +#if defined(CONFIG_SMP) unsigned cpu = hard_smp_processor_id(); +#else + unsigned cpu = 0; +#endif if (cpu == 0) of_scan_flat_dt(scan_cache, NULL); if (j2_ccr_base) __raw_writel(0x80000303, j2_ccr_base + 4*cpu); if (cpu != 0) return; -- GitLab From 46d6ee12fa9dc094193b06be3d4db236cfa564a9 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Sun, 29 Apr 2018 14:22:29 +0200 Subject: [PATCH 0597/1299] tee: check shm references are consistent in offset/size [ Upstream commit ab9d3db5b320a052452b9cd035599ee3c84bbee9 ] This change prevents userland from referencing TEE shared memory outside the area initially allocated by its owner. Prior this change an application could not reference or access memory it did not own but it could reference memory not explicitly allocated by owner but still allocated to the owner due to the memory allocation granule. Reported-by: Alexandre Jutras Signed-off-by: Etienne Carriere Signed-off-by: Jens Wiklander Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/tee/tee_core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 58a5009eacc3..a548c3695797 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -181,6 +181,17 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params, if (IS_ERR(shm)) return PTR_ERR(shm); + /* + * Ensure offset + size does not overflow offset + * and does not overflow the size of the referred + * shared memory object. + */ + if ((ip.a + ip.b) < ip.a || + (ip.a + ip.b) > shm->size) { + tee_shm_put(shm); + return -EINVAL; + } + params[n].u.memref.shm_offs = ip.a; params[n].u.memref.size = ip.b; params[n].u.memref.shm = shm; -- GitLab From 6ad69952d50d719ec9fbf3062e50d47b3e314231 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Fri, 20 Apr 2018 13:49:20 +0300 Subject: [PATCH 0598/1299] mac80211: Adjust SAE authentication timeout [ Upstream commit 407879b690ba3a6bf29be896d02dad63463bd1c0 ] The IEEE P802.11-REVmd D1.0 specification updated the SAE authentication timeout to be 2000 milliseconds (see dot11RSNASAERetransPeriod). Update the SAE timeout setting accordingly. While at it, reduce some code duplication in the timeout configuration. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mlme.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9115cc52ce83..052dbd4fa366 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -35,6 +35,7 @@ #define IEEE80211_AUTH_TIMEOUT (HZ / 5) #define IEEE80211_AUTH_TIMEOUT_LONG (HZ / 2) #define IEEE80211_AUTH_TIMEOUT_SHORT (HZ / 10) +#define IEEE80211_AUTH_TIMEOUT_SAE (HZ * 2) #define IEEE80211_AUTH_MAX_TRIES 3 #define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) @@ -3798,16 +3799,19 @@ static int ieee80211_auth(struct ieee80211_sub_if_data *sdata) tx_flags); if (tx_flags == 0) { - auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; - auth_data->timeout_started = true; - run_again(sdata, auth_data->timeout); + if (auth_data->algorithm == WLAN_AUTH_SAE) + auth_data->timeout = jiffies + + IEEE80211_AUTH_TIMEOUT_SAE; + else + auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; } else { auth_data->timeout = round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG); - auth_data->timeout_started = true; - run_again(sdata, auth_data->timeout); } + auth_data->timeout_started = true; + run_again(sdata, auth_data->timeout); + return 0; } @@ -3878,8 +3882,15 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) ifmgd->status_received = false; if (ifmgd->auth_data && ieee80211_is_auth(fc)) { if (status_acked) { - ifmgd->auth_data->timeout = - jiffies + IEEE80211_AUTH_TIMEOUT_SHORT; + if (ifmgd->auth_data->algorithm == + WLAN_AUTH_SAE) + ifmgd->auth_data->timeout = + jiffies + + IEEE80211_AUTH_TIMEOUT_SAE; + else + ifmgd->auth_data->timeout = + jiffies + + IEEE80211_AUTH_TIMEOUT_SHORT; run_again(sdata, ifmgd->auth_data->timeout); } else { ifmgd->auth_data->timeout = jiffies - 1; -- GitLab From ca3c09a74945bfa9db326cee60601f60237e5606 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 18 Apr 2018 17:29:37 +0300 Subject: [PATCH 0599/1299] drm/omap: silence unititialized variable warning [ Upstream commit 4a9fbfcab19d3f71ad2bf0bcb653c4ee84e69c7f ] Smatch complains that "area_free" could be used without being initialized. This code is several years old and premusably works fine so this can't be a very serious bug. But it's easy enough to silence the warning. If "area_free" is false at the end of the function then we return -ENOMEM. Signed-off-by: Dan Carpenter Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20180418142937.GA13828@mwanda Signed-off-by: Sean Paul Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/omapdrm/tcm-sita.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/omapdrm/tcm-sita.c b/drivers/gpu/drm/omapdrm/tcm-sita.c index c10fdfc0930f..1cd39507b634 100644 --- a/drivers/gpu/drm/omapdrm/tcm-sita.c +++ b/drivers/gpu/drm/omapdrm/tcm-sita.c @@ -92,7 +92,7 @@ static int l2r_t2b(uint16_t w, uint16_t h, uint16_t a, int16_t offset, { int i; unsigned long index; - bool area_free; + bool area_free = false; unsigned long slots_per_band = PAGE_SIZE / slot_bytes; unsigned long bit_offset = (offset > 0) ? offset / slot_bytes : 0; unsigned long curr_bit = bit_offset; -- GitLab From 9631f32b61dcdaf4f52976f3706364f470cfcca0 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 29 Mar 2018 13:40:36 +0300 Subject: [PATCH 0600/1299] drm/omap: fix uninitialized ret variable [ Upstream commit 77eeac24b10fc84d3ffd5b11a897dff88dde244d ] audio_config function for both HDMI4 and HDMI5 return uninitialized value as the error code if the display is not currently enabled. For some reason this has not caused any issues. Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20180329104038.29154-1-tomi.valkeinen@ti.com Reviewed-by: Emil Velikov Reviewed-by: Laurent Pinchart Signed-off-by: Sean Paul Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 2 +- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index f169348da377..ef3731d2f2e7 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -634,7 +634,7 @@ static int hdmi_audio_config(struct device *dev, struct omap_dss_audio *dss_audio) { struct omap_hdmi *hd = dev_get_drvdata(dev); - int ret; + int ret = 0; mutex_lock(&hd->lock); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index b3221ca5bcd8..26db0ce7a085 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -660,7 +660,7 @@ static int hdmi_audio_config(struct device *dev, struct omap_dss_audio *dss_audio) { struct omap_hdmi *hd = dev_get_drvdata(dev); - int ret; + int ret = 0; mutex_lock(&hd->lock); -- GitLab From a490d0570df2d7fe7ffe40e4049c7846677aa078 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 29 Mar 2018 13:40:37 +0300 Subject: [PATCH 0601/1299] drm/omap: fix possible NULL ref issue in tiler_reserve_2d [ Upstream commit 6a0f0c55619f0b82a677cab72e77c3444a5eee58 ] tiler_reserve_2d allocates memory but does not check if it got the memory. Add the check and return ENOMEM on failure. Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20180329104038.29154-2-tomi.valkeinen@ti.com Reviewed-by: Emil Velikov Reviewed-by: Laurent Pinchart Signed-off-by: Sean Paul Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index fd05f7e9f43f..df05fe53c399 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c @@ -389,12 +389,16 @@ int tiler_unpin(struct tiler_block *block) struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w, uint16_t h, uint16_t align) { - struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL); + struct tiler_block *block; u32 min_align = 128; int ret; unsigned long flags; u32 slot_bytes; + block = kzalloc(sizeof(*block), GFP_KERNEL); + if (!block) + return ERR_PTR(-ENOMEM); + BUG_ON(!validfmt(fmt)); /* convert width/height to slots */ -- GitLab From 771f573cc158884bae8cf22d1a5627c396aa868f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 May 2018 12:11:56 +0300 Subject: [PATCH 0602/1299] drm/omap: check return value from soc_device_match [ Upstream commit 4d6cb5e2fee52af17001e92950f0894304706ee4 ] soc_device_match() can return NULL, so add a check and fail if soc_device_match() fails. Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20180502091159.7071-2-tomi.valkeinen@ti.com Reviewed-by: Benoit Parrot Reviewed-by: Peter Ujfalusi Signed-off-by: Sean Paul Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c index c3453f3bd603..1359bf50598f 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c @@ -926,8 +926,13 @@ int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core) { const struct hdmi4_features *features; struct resource *res; + const struct soc_device_attribute *soc; - features = soc_device_match(hdmi4_soc_devices)->data; + soc = soc_device_match(hdmi4_soc_devices); + if (!soc) + return -ENODEV; + + features = soc->data; core->cts_swmode = features->cts_swmode; core->audio_use_mclk = features->audio_use_mclk; -- GitLab From bc707b2d950b549b6071f39fe269291ec6031d5a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 May 2018 12:11:59 +0300 Subject: [PATCH 0603/1299] drm/omap: handle alloc failures in omap_connector [ Upstream commit 47aaaec818dfd1009d1358974a2931f05dd57203 ] Handle memory allocation failures in omap_connector to avoid NULL derefs. Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20180502091159.7071-5-tomi.valkeinen@ti.com Reviewed-by: Benoit Parrot Reviewed-by: Peter Ujfalusi Signed-off-by: Sean Paul Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/omapdrm/omap_connector.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index aa5ba9ae2191..556335ecb2b7 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -123,6 +123,9 @@ static int omap_connector_get_modes(struct drm_connector *connector) if (dssdrv->read_edid) { void *edid = kzalloc(MAX_EDID, GFP_KERNEL); + if (!edid) + return 0; + if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) && drm_edid_is_valid(edid)) { drm_mode_connector_update_edid_property( @@ -141,6 +144,9 @@ static int omap_connector_get_modes(struct drm_connector *connector) struct drm_display_mode *mode = drm_mode_create(dev); struct videomode vm = {0}; + if (!mode) + return 0; + dssdrv->get_timings(dssdev, &vm); drm_display_mode_from_videomode(&vm, mode); @@ -196,6 +202,10 @@ static int omap_connector_mode_valid(struct drm_connector *connector, if (!r) { /* check if vrefresh is still valid */ new_mode = drm_mode_duplicate(dev, mode); + + if (!new_mode) + return MODE_BAD; + new_mode->clock = vm.pixelclock / 1000; new_mode->vrefresh = 0; if (mode->vrefresh == drm_mode_vrefresh(new_mode)) -- GitLab From 36166445a922a50343bec7f193f243390e9e0680 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Sat, 5 May 2018 22:00:37 +0200 Subject: [PATCH 0604/1299] driver core: add __printf verification to __ata_ehi_pushv_desc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 0d74d872c3f8b9cb3d096fb932a063b43b37f188 ] __printf is useful to verify format and arguments. Remove the following warning (with W=1): drivers/ata/libata-eh.c:183:10: warning: function might be possible candidate for ‘gnu_printf’ format attribute [-Wsuggest-attribute=format] Signed-off-by: Mathieu Malaterre Signed-off-by: Tejun Heo Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-eh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ea20e0eb4d5a..711dd91b5e2c 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -175,8 +175,8 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) { } #endif /* CONFIG_PM */ -static void __ata_ehi_pushv_desc(struct ata_eh_info *ehi, const char *fmt, - va_list args) +static __printf(2, 0) void __ata_ehi_pushv_desc(struct ata_eh_info *ehi, + const char *fmt, va_list args) { ehi->desc_len += vscnprintf(ehi->desc + ehi->desc_len, ATA_EH_DESC_LEN - ehi->desc_len, -- GitLab From e4bd54eb87c820b3e2da9a9701896d6ac1bae6f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Thu, 3 May 2018 17:32:07 +0200 Subject: [PATCH 0605/1299] ARM: dts: cygnus: fix irq type for arm global timer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 675c7215aacf54242b2e8bc64bab698abbe764db ] As per ARM documentation PPI(0) ID27 - global timer interrupt is rising-edge sensitive. set IRQ triggering type to IRQ_TYPE_EDGE_RISING for ARM Global timers. Fixes: c9ad7bc5fe3 ("ARM: dts: Enable Broadcom Cygnus SoC") Signed-off-by: Clément Péron Signed-off-by: Florian Fainelli Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/bcm-cygnus.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi index 7c957ea06c66..9a9902974b1b 100644 --- a/arch/arm/boot/dts/bcm-cygnus.dtsi +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi @@ -69,7 +69,7 @@ timer@20200 { compatible = "arm,cortex-a9-global-timer"; reg = <0x20200 0x100>; - interrupts = ; + interrupts = ; clocks = <&periph_clk>; }; -- GitLab From ba29f3738e86f4e69cc8470a60a62e21d492475d Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Fri, 20 Apr 2018 13:49:19 +0300 Subject: [PATCH 0606/1299] mac80211: use timeout from the AddBA response instead of the request [ Upstream commit 914eac248d876f9c00cd1792ffec3d182c863f13 ] 2016 spec, section 10.24.2 specifies that the block ack timeout in the ADD BA request is advisory. That means we should check the value in the response and act upon it (same as buffer size). Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/mac80211/agg-tx.c | 4 ++++ net/mac80211/tx.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index bef516ec47f9..197947a07f83 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -8,6 +8,7 @@ * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation * Copyright(c) 2015-2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -987,6 +988,9 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, sta->ampdu_mlme.addba_req_num[tid] = 0; + tid_tx->timeout = + le16_to_cpu(mgmt->u.action.u.addba_resp.timeout); + if (tid_tx->timeout) { mod_timer(&tid_tx->session_timer, TU_TO_EXP_TIME(tid_tx->timeout)); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 73429841f115..ccb65f18df5d 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -4,6 +4,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -1138,7 +1139,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, } /* reset session timer */ - if (reset_agg_timer && tid_tx->timeout) + if (reset_agg_timer) tid_tx->last_tx = jiffies; return queued; -- GitLab From a951cf4da8964e4f8797b48e9c805abac4c7b1d9 Mon Sep 17 00:00:00 2001 From: "van der Linden, Frank" Date: Fri, 4 May 2018 16:11:00 -0400 Subject: [PATCH 0607/1299] x86/xen: Reset VCPU0 info pointer after shared_info remap [ Upstream commit d1ecfa9d1f402366b1776fbf84e635678a51414f ] This patch fixes crashes during boot for HVM guests on older (pre HVM vector callback) Xen versions. Without this, current kernels will always fail to boot on those Xen versions. Sample stack trace: BUG: unable to handle kernel paging request at ffffffffff200000 IP: __xen_evtchn_do_upcall+0x1e/0x80 PGD 1e0e067 P4D 1e0e067 PUD 1e10067 PMD 235c067 PTE 0 Oops: 0002 [#1] SMP PTI Modules linked in: CPU: 0 PID: 512 Comm: kworker/u2:0 Not tainted 4.14.33-52.13.amzn1.x86_64 #1 Hardware name: Xen HVM domU, BIOS 3.4.3.amazon 11/11/2016 task: ffff88002531d700 task.stack: ffffc90000480000 RIP: 0010:__xen_evtchn_do_upcall+0x1e/0x80 RSP: 0000:ffff880025403ef0 EFLAGS: 00010046 RAX: ffffffff813cc760 RBX: ffffffffff200000 RCX: ffffc90000483ef0 RDX: ffff880020540a00 RSI: ffff880023c78000 RDI: 000000000000001c RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 R13: ffff880025403f5c R14: 0000000000000000 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff880025400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffff200000 CR3: 0000000001e0a000 CR4: 00000000000006f0 Call Trace: do_hvm_evtchn_intr+0xa/0x10 __handle_irq_event_percpu+0x43/0x1a0 handle_irq_event_percpu+0x20/0x50 handle_irq_event+0x39/0x60 handle_fasteoi_irq+0x80/0x140 handle_irq+0xaf/0x120 do_IRQ+0x41/0xd0 common_interrupt+0x7d/0x7d During boot, the HYPERVISOR_shared_info page gets remapped to make it work with KASLR. This means that any pointer derived from it needs to be adjusted. The only value that this applies to is the vcpu_info pointer for VCPU 0. For PV and HVM with the callback vector feature, this gets done via the smp_ops prepare_boot_cpu callback. Older Xen versions do not support the HVM callback vector, so there is no Xen-specific smp_ops set up in that scenario. So, the vcpu_info pointer for VCPU 0 never gets set to the proper value, and the first reference of it will be bad. Fix this by resetting it immediately after the remap. Signed-off-by: Frank van der Linden Reviewed-by: Eduardo Valentin Reviewed-by: Alakesh Haloi Reviewed-by: Vallish Vaidyeshwara Reviewed-by: Boris Ostrovsky Cc: Juergen Gross Cc: Boris Ostrovsky Cc: xen-devel@lists.xenproject.org Signed-off-by: Boris Ostrovsky Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten_hvm.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c index 754d5391d9fa..854508b00bbb 100644 --- a/arch/x86/xen/enlighten_hvm.c +++ b/arch/x86/xen/enlighten_hvm.c @@ -64,6 +64,19 @@ static void __init xen_hvm_init_mem_mapping(void) { early_memunmap(HYPERVISOR_shared_info, PAGE_SIZE); HYPERVISOR_shared_info = __va(PFN_PHYS(shared_info_pfn)); + + /* + * The virtual address of the shared_info page has changed, so + * the vcpu_info pointer for VCPU 0 is now stale. + * + * The prepare_boot_cpu callback will re-initialize it via + * xen_vcpu_setup, but we can't rely on that to be called for + * old Xen versions (xen_have_vector_callback == 0). + * + * It is, in any case, bad to have a stale vcpu_info pointer + * so reset it now. + */ + xen_vcpu_info_reset(0); } static void __init init_hvm_pv_info(void) -- GitLab From 4dc2437cdd6b6c6a745500ac647dc3cd66a0e2ee Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Mon, 7 May 2018 16:10:38 +0300 Subject: [PATCH 0608/1299] net: aquantia: driver should correctly declare vlan_features bits [ Upstream commit 8c61ab7f111a2b29d051348b9cb9a39804ebf1f8 ] In particular, not reporting SG forced skbs to be linear for vlan interfaces over atlantic NIC. With this fix it is possible to enable SG feature on device and therefore optimize performance. Reported-by: Ma Yuying Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index c93e5613d4cc..cc658a29cc33 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -310,6 +310,8 @@ int aq_nic_ndev_init(struct aq_nic_s *self) self->ndev->hw_features |= aq_hw_caps->hw_features; self->ndev->features = aq_hw_caps->hw_features; + self->ndev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM | + NETIF_F_RXHASH | NETIF_F_SG | NETIF_F_LRO; self->ndev->priv_flags = aq_hw_caps->hw_priv_flags; self->ndev->mtu = aq_nic_cfg->mtu - ETH_HLEN; self->ndev->max_mtu = self->aq_hw_caps.mtu - ETH_FCS_LEN - ETH_HLEN; -- GitLab From 56068475a7f02f7fb7afdb941cc6e6b53d6f3a91 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 18 Apr 2018 16:10:03 +0200 Subject: [PATCH 0609/1299] can: dev: increase bus-off message severity [ Upstream commit 71c23a821c6bcacba71a094efe49ee689605906b ] bus-off is usually caused by hardware malfunction or configuration error (baud rate mismatch) and causes a complete loss of communication. Increase the "bus-off" message's severity from netdev_dbg() to netdev_info() to make it visible to the user. A can interface going into bus-off is similar in severity to ethernet's "Link is Down" message, which is also printed at info level. It is debatable whether the the "restarted" message should also be changed to netdev_info() to make the interface state changes comprehensible from the kernel log. I have chosen to keep the "restarted" message at dbg for now as the "bus-off" message should be enough for the user to notice and investigate the problem. Signed-off-by: Jakob Unterwurzacher Cc: linux-can@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Marc Kleine-Budde Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 365a8cc62405..b6a681bce400 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -604,7 +604,7 @@ void can_bus_off(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); - netdev_dbg(dev, "bus-off\n"); + netdev_info(dev, "bus-off\n"); netif_carrier_off(dev); -- GitLab From fcc0315abc95076062cfe59b9933d08fdcad2781 Mon Sep 17 00:00:00 2001 From: David Gilhooley Date: Tue, 8 May 2018 15:49:42 -0700 Subject: [PATCH 0610/1299] arm64: Add MIDR encoding for NVIDIA CPUs [ Upstream commit 1b06bd8dd95f7a19ab33fdf0f477c94950822ab3 ] This patch adds the MIDR encodings for NVIDIA as well as the Denver and Carmel CPUs used in Tegra SoCs. Signed-off-by: David Gilhooley Signed-off-by: Will Deacon Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/cputype.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 30da0918d046..04569aa267fd 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -75,6 +75,7 @@ #define ARM_CPU_IMP_CAVIUM 0x43 #define ARM_CPU_IMP_BRCM 0x42 #define ARM_CPU_IMP_QCOM 0x51 +#define ARM_CPU_IMP_NVIDIA 0x4E #define ARM_CPU_PART_AEM_V8 0xD0F #define ARM_CPU_PART_FOUNDATION 0xD00 @@ -98,6 +99,9 @@ #define QCOM_CPU_PART_FALKOR 0xC00 #define QCOM_CPU_PART_KRYO 0x200 +#define NVIDIA_CPU_PART_DENVER 0x003 +#define NVIDIA_CPU_PART_CARMEL 0x004 + #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) #define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55) #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) @@ -112,6 +116,8 @@ #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1) #define MIDR_QCOM_FALKOR MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR) #define MIDR_QCOM_KRYO MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO) +#define MIDR_NVIDIA_DENVER MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_DENVER) +#define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL) #ifndef __ASSEMBLY__ -- GitLab From 8223298c5075c9fb0ae4b10274124c35cd6ea120 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Fri, 4 May 2018 11:25:26 -0300 Subject: [PATCH 0611/1299] cifs: smb2ops: Fix listxattr() when there are no EAs [ Upstream commit ae2cd7fb478b8da707906ee1706ae1379968a8f9 ] As per listxattr(2): On success, a nonnegative number is returned indicating the size of the extended attribute name list. On failure, -1 is returned and errno is set appropriately. In SMB1, when the server returns an empty EA list through a listxattr(), it will correctly return 0 as there are no EAs for the given file. However, in SMB2+, it returns -ENODATA in listxattr() which is wrong since the request and response were sent successfully, although there's no actual EA for the given file. This patch fixes listxattr() for SMB2+ by returning 0 in cifs_listxattr() when the server returns an empty list of EAs. Signed-off-by: Paulo Alcantara Reviewed-by: Aurelien Aptel Signed-off-by: Steve French Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/cifs/smb2ops.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index eef875da7c0b..839327f75e3d 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -570,9 +570,15 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); + /* + * If ea_name is NULL (listxattr) and there are no EAs, return 0 as it's + * not an error. Otherwise, the specified ea_name was not found. + */ if (!rc) rc = move_smb2_ea_to_cifs(ea_data, buf_size, smb2_data, SMB2_MAX_EA_BUF, ea_name); + else if (!ea_name && rc == -ENODATA) + rc = 0; kfree(smb2_data); return rc; -- GitLab From 6ca2fa569d65a7a4b0fbc1aada8fd373cd4a0790 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Sat, 5 May 2018 21:54:05 +0200 Subject: [PATCH 0612/1299] agp: uninorth: make two functions static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit dec60f3a9b7251f2657d743d96ba9a83dca02351 ] Both ‘uninorth_remove_memory’ and ‘null_cache_flush’ can be made static. So make them. Silence the following gcc warning (W=1): drivers/char/agp/uninorth-agp.c:198:5: warning: no previous prototype for ‘uninorth_remove_memory’ [-Wmissing-prototypes] and drivers/char/agp/uninorth-agp.c:473:6: warning: no previous prototype for ‘null_cache_flush’ [-Wmissing-prototypes] Signed-off-by: Mathieu Malaterre Signed-off-by: Dave Airlie Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/uninorth-agp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index c381c8e396fc..79d8c84693a1 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -195,7 +195,7 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int ty return 0; } -int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type) +static int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { size_t i; u32 *gp; @@ -470,7 +470,7 @@ static int uninorth_free_gatt_table(struct agp_bridge_data *bridge) return 0; } -void null_cache_flush(void) +static void null_cache_flush(void) { mb(); } -- GitLab From dc5af7b0de98ce376fb7d34035749e71c081a7ff Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Tue, 8 May 2018 21:44:06 +0800 Subject: [PATCH 0613/1299] tipc: eliminate KMSAN uninit-value in strcmp complaint [ Upstream commit 94f6a80c0c11828cb7b3d79294459dd8d761ca89 ] When we get link properties through netlink interface with tipc_nl_node_get_link(), we don't validate TIPC_NLA_LINK_NAME attribute at all, instead we directly use it. As a consequence, KMSAN detected the TIPC_NLA_LINK_NAME attribute was an uninitialized value, and then posted the following complaint: ================================================================== BUG: KMSAN: uninit-value in strcmp+0xf7/0x160 lib/string.c:329 CPU: 1 PID: 4527 Comm: syz-executor655 Not tainted 4.16.0+ #87 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:17 [inline] dump_stack+0x185/0x1d0 lib/dump_stack.c:53 kmsan_report+0x142/0x240 mm/kmsan/kmsan.c:1067 __msan_warning_32+0x6c/0xb0 mm/kmsan/kmsan_instr.c:683 strcmp+0xf7/0x160 lib/string.c:329 tipc_nl_node_get_link+0x220/0x6f0 net/tipc/node.c:1881 genl_family_rcv_msg net/netlink/genetlink.c:599 [inline] genl_rcv_msg+0x1686/0x1810 net/netlink/genetlink.c:624 netlink_rcv_skb+0x378/0x600 net/netlink/af_netlink.c:2447 genl_rcv+0x63/0x80 net/netlink/genetlink.c:635 netlink_unicast_kernel net/netlink/af_netlink.c:1311 [inline] netlink_unicast+0x166b/0x1740 net/netlink/af_netlink.c:1337 netlink_sendmsg+0x1048/0x1310 net/netlink/af_netlink.c:1900 sock_sendmsg_nosec net/socket.c:630 [inline] sock_sendmsg net/socket.c:640 [inline] ___sys_sendmsg+0xec0/0x1310 net/socket.c:2046 __sys_sendmsg net/socket.c:2080 [inline] SYSC_sendmsg+0x2a3/0x3d0 net/socket.c:2091 SyS_sendmsg+0x54/0x80 net/socket.c:2087 do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x3d/0xa2 RIP: 0033:0x445589 RSP: 002b:00007fb7ee66cdb8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00000000006dac24 RCX: 0000000000445589 RDX: 0000000000000000 RSI: 0000000020023000 RDI: 0000000000000003 RBP: 00000000006dac20 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 00007fffa2bf3f3f R14: 00007fb7ee66d9c0 R15: 0000000000000001 Uninit was created at: kmsan_save_stack_with_flags mm/kmsan/kmsan.c:278 [inline] kmsan_internal_poison_shadow+0xb8/0x1b0 mm/kmsan/kmsan.c:188 kmsan_kmalloc+0x94/0x100 mm/kmsan/kmsan.c:314 kmsan_slab_alloc+0x11/0x20 mm/kmsan/kmsan.c:321 slab_post_alloc_hook mm/slab.h:445 [inline] slab_alloc_node mm/slub.c:2737 [inline] __kmalloc_node_track_caller+0xaed/0x11c0 mm/slub.c:4369 __kmalloc_reserve net/core/skbuff.c:138 [inline] __alloc_skb+0x2cf/0x9f0 net/core/skbuff.c:206 alloc_skb include/linux/skbuff.h:984 [inline] netlink_alloc_large_skb net/netlink/af_netlink.c:1183 [inline] netlink_sendmsg+0x9a6/0x1310 net/netlink/af_netlink.c:1875 sock_sendmsg_nosec net/socket.c:630 [inline] sock_sendmsg net/socket.c:640 [inline] ___sys_sendmsg+0xec0/0x1310 net/socket.c:2046 __sys_sendmsg net/socket.c:2080 [inline] SYSC_sendmsg+0x2a3/0x3d0 net/socket.c:2091 SyS_sendmsg+0x54/0x80 net/socket.c:2087 do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x3d/0xa2 ================================================================== To quiet the complaint, TIPC_NLA_LINK_NAME attribute has been validated in tipc_nl_node_get_link() before it's used. Reported-by: syzbot+df0257c92ffd4fcc58cd@syzkaller.appspotmail.com Signed-off-by: Ying Xue Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/tipc/node.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/net/tipc/node.c b/net/tipc/node.c index 47c67e5b5793..42e9bdcc4bb6 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1831,6 +1831,7 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info) int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); + struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; struct tipc_nl_msg msg; char *name; int err; @@ -1838,9 +1839,19 @@ int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info) msg.portid = info->snd_portid; msg.seq = info->snd_seq; - if (!info->attrs[TIPC_NLA_LINK_NAME]) + if (!info->attrs[TIPC_NLA_LINK]) return -EINVAL; - name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]); + + err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX, + info->attrs[TIPC_NLA_LINK], + tipc_nl_link_policy, info->extack); + if (err) + return err; + + if (!attrs[TIPC_NLA_LINK_NAME]) + return -EINVAL; + + name = nla_data(attrs[TIPC_NLA_LINK_NAME]); msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg.skb) -- GitLab From 6618d064bacad3bef642825263eb4e8edcc55142 Mon Sep 17 00:00:00 2001 From: Michal Kalderon Date: Tue, 8 May 2018 21:29:18 +0300 Subject: [PATCH 0614/1299] qed: Fix l2 initializations over iWARP personality [ Upstream commit af6858ee423a309d93054c361c61099b8eb12bbf ] If qede driver was loaded on a device configured for iWARP the l2 mutex wouldn't be allocated, and some l2 related resources wouldn't be freed. fixes: c851a9dc4359 ("qed: Introduce iWARP personality") Signed-off-by: Michal Kalderon Signed-off-by: Sudarsana Kalluru Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/qlogic/qed/qed_l2.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 085338990f49..c5452b445c37 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -115,8 +115,7 @@ int qed_l2_alloc(struct qed_hwfn *p_hwfn) void qed_l2_setup(struct qed_hwfn *p_hwfn) { - if (p_hwfn->hw_info.personality != QED_PCI_ETH && - p_hwfn->hw_info.personality != QED_PCI_ETH_ROCE) + if (!QED_IS_L2_PERSONALITY(p_hwfn)) return; mutex_init(&p_hwfn->p_l2_info->lock); @@ -126,8 +125,7 @@ void qed_l2_free(struct qed_hwfn *p_hwfn) { u32 i; - if (p_hwfn->hw_info.personality != QED_PCI_ETH && - p_hwfn->hw_info.personality != QED_PCI_ETH_ROCE) + if (!QED_IS_L2_PERSONALITY(p_hwfn)) return; if (!p_hwfn->p_l2_info) -- GitLab From b5b3188098b3c438534c083243777bc685bb0627 Mon Sep 17 00:00:00 2001 From: Michal Kalderon Date: Tue, 8 May 2018 21:29:19 +0300 Subject: [PATCH 0615/1299] qede: Fix gfp flags sent to rdma event node allocation [ Upstream commit 090477e4acb31c5dd674940c7c01d4f16bd1ac41 ] A previous commit 4609adc27175 ("qede: Fix qedr link update") added a flow that could allocate rdma event objects from an interrupt path (link notification). Therefore the kzalloc call should be done with GFP_ATOMIC. fixes: 4609adc27175 ("qede: Fix qedr link update") Signed-off-by: Michal Kalderon Signed-off-by: Sudarsana Kalluru Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/qlogic/qede/qede_rdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qede/qede_rdma.c b/drivers/net/ethernet/qlogic/qede/qede_rdma.c index 50b142fad6b8..1900bf7e67d1 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_rdma.c +++ b/drivers/net/ethernet/qlogic/qede/qede_rdma.c @@ -238,7 +238,7 @@ qede_rdma_get_free_event_node(struct qede_dev *edev) } if (!found) { - event_node = kzalloc(sizeof(*event_node), GFP_KERNEL); + event_node = kzalloc(sizeof(*event_node), GFP_ATOMIC); if (!event_node) { DP_NOTICE(edev, "qedr: Could not allocate memory for rdma work\n"); -- GitLab From b2abd2b98afccb8dfa9d0e51ab8f77e574ad7756 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 10 May 2018 23:26:00 +0100 Subject: [PATCH 0616/1299] rxrpc: Fix error reception on AF_INET6 sockets [ Upstream commit f2aeed3a591ff29a82495eeaa92ac4780bad7487 ] AF_RXRPC tries to turn on IP_RECVERR and IP_MTU_DISCOVER on the UDP socket it just opened for communications with the outside world, regardless of the type of socket. Unfortunately, this doesn't work with an AF_INET6 socket. Fix this by turning on IPV6_RECVERR and IPV6_MTU_DISCOVER instead if the socket is of the AF_INET6 family. Without this, kAFS server and address rotation doesn't work correctly because the algorithm doesn't detect received network errors. Fixes: 75b54cb57ca3 ("rxrpc: Add IPv6 support") Signed-off-by: David Howells Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/rxrpc/local_object.c | 57 +++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c index 38b99db30e54..2af42c7d5b82 100644 --- a/net/rxrpc/local_object.c +++ b/net/rxrpc/local_object.c @@ -133,22 +133,49 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net) } } - /* we want to receive ICMP errors */ - opt = 1; - ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR, - (char *) &opt, sizeof(opt)); - if (ret < 0) { - _debug("setsockopt failed"); - goto error; - } + switch (local->srx.transport.family) { + case AF_INET: + /* we want to receive ICMP errors */ + opt = 1; + ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR, + (char *) &opt, sizeof(opt)); + if (ret < 0) { + _debug("setsockopt failed"); + goto error; + } - /* we want to set the don't fragment bit */ - opt = IP_PMTUDISC_DO; - ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER, - (char *) &opt, sizeof(opt)); - if (ret < 0) { - _debug("setsockopt failed"); - goto error; + /* we want to set the don't fragment bit */ + opt = IP_PMTUDISC_DO; + ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER, + (char *) &opt, sizeof(opt)); + if (ret < 0) { + _debug("setsockopt failed"); + goto error; + } + break; + + case AF_INET6: + /* we want to receive ICMP errors */ + opt = 1; + ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_RECVERR, + (char *) &opt, sizeof(opt)); + if (ret < 0) { + _debug("setsockopt failed"); + goto error; + } + + /* we want to set the don't fragment bit */ + opt = IPV6_PMTUDISC_DO; + ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_MTU_DISCOVER, + (char *) &opt, sizeof(opt)); + if (ret < 0) { + _debug("setsockopt failed"); + goto error; + } + break; + + default: + BUG(); } /* set the socket up */ -- GitLab From 29475c404b56f4ff03d99e35b9258dc6dbf8f4b1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 10 May 2018 23:26:01 +0100 Subject: [PATCH 0617/1299] rxrpc: Fix the min security level for kernel calls [ Upstream commit 93864fc3ffcc4bf70e96cfb5cc6e941630419ad0 ] Fix the kernel call initiation to set the minimum security level for kernel initiated calls (such as from kAFS) from the sockopt value. Fixes: 19ffa01c9c45 ("rxrpc: Use structs to hold connection params and protocol info") Signed-off-by: David Howells Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/rxrpc/af_rxrpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 7c1cb08874d5..2a32f60652d8 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -302,7 +302,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, memset(&cp, 0, sizeof(cp)); cp.local = rx->local; cp.key = key; - cp.security_level = 0; + cp.security_level = rx->min_sec_level; cp.exclusive = false; cp.service_id = srx->srx_service; call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, tx_total_len, -- GitLab From ce44a4d5db630728a5a20cf833afeafe1dce88f6 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 26 Apr 2018 17:55:03 -0700 Subject: [PATCH 0618/1299] KVM: Extend MAX_IRQ_ROUTES to 4096 for all archs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit ddc9cfb79c1096a0855839631c091aa7e9602052 ] Our virtual machines make use of device assignment by configuring 12 NVMe disks for high I/O performance. Each NVMe device has 129 MSI-X Table entries: Capabilities: [50] MSI-X: Enable+ Count=129 Masked-Vector table: BAR=0 offset=00002000 The windows virtual machines fail to boot since they will map the number of MSI-table entries that the NVMe hardware reported to the bus to msi routing table, this will exceed the 1024. This patch extends MAX_IRQ_ROUTES to 4096 for all archs, in the future this might be extended again if needed. Reviewed-by: Cornelia Huck Cc: Paolo Bonzini Cc: Radim KrÄmář Cc: Cornelia Huck Cc: Christian Borntraeger Signed-off-by: Wanpeng Li Signed-off-by: Tonny Lu Signed-off-by: Paolo Bonzini Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- include/linux/kvm_host.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 39f0489eb137..b81d458ad4fb 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -1044,13 +1044,7 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq) #ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -#ifdef CONFIG_S390 -#define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that... -#elif defined(CONFIG_ARM64) -#define KVM_MAX_IRQ_ROUTES 4096 -#else -#define KVM_MAX_IRQ_ROUTES 1024 -#endif +#define KVM_MAX_IRQ_ROUTES 4096 /* might need extension/rework in the future */ bool kvm_arch_can_set_irq_routing(struct kvm *kvm); int kvm_set_irq_routing(struct kvm *kvm, -- GitLab From 33d1c29e935ef72dbcaf0eeeb67b6cb0788fa045 Mon Sep 17 00:00:00 2001 From: Marian Rotariu Date: Mon, 30 Apr 2018 12:23:01 +0300 Subject: [PATCH 0619/1299] x86: Delay skip of emulated hypercall instruction [ Upstream commit 6356ee0c9602004e0a3b4b2dad68ee2ee9385b17 ] The IP increment should be done after the hypercall emulation, after calling the various handlers. In this way, these handlers can accurately identify the the IP of the VMCALL if they need it. This patch keeps the same functionality for the Hyper-V handler which does not use the return code of the standard kvm_skip_emulated_instruction() call. Signed-off-by: Marian Rotariu [Hyper-V hypercalls also need kvm_skip_emulated_instruction() - Paolo] Signed-off-by: Paolo Bonzini Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/hyperv.c | 2 +- arch/x86/kvm/x86.c | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index dc97f2544b6f..5d13abecb384 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1223,7 +1223,7 @@ static int kvm_hv_hypercall_complete_userspace(struct kvm_vcpu *vcpu) struct kvm_run *run = vcpu->run; kvm_hv_hypercall_set_result(vcpu, run->hyperv.u.hcall.result); - return 1; + return kvm_skip_emulated_instruction(vcpu); } int kvm_hv_hypercall(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b62328cd4cb0..2f3fe25639b3 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6297,12 +6297,13 @@ void kvm_vcpu_deactivate_apicv(struct kvm_vcpu *vcpu) int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) { unsigned long nr, a0, a1, a2, a3, ret; - int op_64_bit, r; + int op_64_bit; - r = kvm_skip_emulated_instruction(vcpu); - - if (kvm_hv_hypercall_enabled(vcpu->kvm)) - return kvm_hv_hypercall(vcpu); + if (kvm_hv_hypercall_enabled(vcpu->kvm)) { + if (!kvm_hv_hypercall(vcpu)) + return 0; + goto out; + } nr = kvm_register_read(vcpu, VCPU_REGS_RAX); a0 = kvm_register_read(vcpu, VCPU_REGS_RBX); @@ -6323,7 +6324,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) if (kvm_x86_ops->get_cpl(vcpu) != 0) { ret = -KVM_EPERM; - goto out; + goto out_error; } switch (nr) { @@ -6343,12 +6344,14 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) ret = -KVM_ENOSYS; break; } -out: +out_error: if (!op_64_bit) ret = (u32)ret; kvm_register_write(vcpu, VCPU_REGS_RAX, ret); + +out: ++vcpu->stat.hypercalls; - return r; + return kvm_skip_emulated_instruction(vcpu); } EXPORT_SYMBOL_GPL(kvm_emulate_hypercall); -- GitLab From 55e95f9ad712f43756393bfc1369ddade995ef26 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 19 Apr 2018 17:06:57 -0700 Subject: [PATCH 0620/1299] ixgbe: return error on unsupported SFP module when resetting [ Upstream commit bbb2707623f3ccc48695da2433f06d7c38193451 ] Add check for unsupported module and return the error code. This fixes a Coverity hit due to unused return status from setup_sfp. Signed-off-by: Emil Tantilov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 8a85217845ae..cf6a245db6d5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -3413,6 +3413,9 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) hw->phy.sfp_setup_needed = false; } + if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) + return status; + /* Reset PHY */ if (!hw->phy.reset_disable && hw->phy.ops.reset) hw->phy.ops.reset(hw); -- GitLab From 86900754306e7e4eafbd050e4405f292cf4458f3 Mon Sep 17 00:00:00 2001 From: Roman Mashak Date: Fri, 11 May 2018 10:55:09 -0400 Subject: [PATCH 0621/1299] net sched actions: fix invalid pointer dereferencing if skbedit flags missing [ Upstream commit af5d01842fe1fbfb9f5e1c1d957ba02ab6f4569a ] When application fails to pass flags in netlink TLV for a new skbedit action, the kernel results in the following oops: [ 8.307732] BUG: unable to handle kernel paging request at 0000000000021130 [ 8.309167] PGD 80000000193d1067 P4D 80000000193d1067 PUD 180e0067 PMD 0 [ 8.310595] Oops: 0000 [#1] SMP PTI [ 8.311334] Modules linked in: kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcbc aesni_intel aes_x86_64 crypto_simd cryptd glue_helper serio_raw [ 8.314190] CPU: 1 PID: 397 Comm: tc Not tainted 4.17.0-rc3+ #357 [ 8.315252] RIP: 0010:__tcf_idr_release+0x33/0x140 [ 8.316203] RSP: 0018:ffffa0718038f840 EFLAGS: 00010246 [ 8.317123] RAX: 0000000000000001 RBX: 0000000000021100 RCX: 0000000000000000 [ 8.319831] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000021100 [ 8.321181] RBP: 0000000000000000 R08: 000000000004adf8 R09: 0000000000000122 [ 8.322645] R10: 0000000000000000 R11: ffffffff9e5b01ed R12: 0000000000000000 [ 8.324157] R13: ffffffff9e0d3cc0 R14: 0000000000000000 R15: 0000000000000000 [ 8.325590] FS: 00007f591292e700(0000) GS:ffff8fcf5bc40000(0000) knlGS:0000000000000000 [ 8.327001] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 8.327987] CR2: 0000000000021130 CR3: 00000000180e6004 CR4: 00000000001606a0 [ 8.329289] Call Trace: [ 8.329735] tcf_skbedit_init+0xa7/0xb0 [ 8.330423] tcf_action_init_1+0x362/0x410 [ 8.331139] ? try_to_wake_up+0x44/0x430 [ 8.331817] tcf_action_init+0x103/0x190 [ 8.332511] tc_ctl_action+0x11a/0x220 [ 8.333174] rtnetlink_rcv_msg+0x23d/0x2e0 [ 8.333902] ? _cond_resched+0x16/0x40 [ 8.334569] ? __kmalloc_node_track_caller+0x5b/0x2c0 [ 8.335440] ? rtnl_calcit.isra.31+0xf0/0xf0 [ 8.336178] netlink_rcv_skb+0xdb/0x110 [ 8.336855] netlink_unicast+0x167/0x220 [ 8.337550] netlink_sendmsg+0x2a7/0x390 [ 8.338258] sock_sendmsg+0x30/0x40 [ 8.338865] ___sys_sendmsg+0x2c5/0x2e0 [ 8.339531] ? pagecache_get_page+0x27/0x210 [ 8.340271] ? filemap_fault+0xa2/0x630 [ 8.340943] ? page_add_file_rmap+0x108/0x200 [ 8.341732] ? alloc_set_pte+0x2aa/0x530 [ 8.342573] ? finish_fault+0x4e/0x70 [ 8.343332] ? __handle_mm_fault+0xbc1/0x10d0 [ 8.344337] ? __sys_sendmsg+0x53/0x80 [ 8.345040] __sys_sendmsg+0x53/0x80 [ 8.345678] do_syscall_64+0x4f/0x100 [ 8.346339] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 8.347206] RIP: 0033:0x7f591191da67 [ 8.347831] RSP: 002b:00007fff745abd48 EFLAGS: 00000246 ORIG_RAX: 000000000000002e [ 8.349179] RAX: ffffffffffffffda RBX: 00007fff745abe70 RCX: 00007f591191da67 [ 8.350431] RDX: 0000000000000000 RSI: 00007fff745abdc0 RDI: 0000000000000003 [ 8.351659] RBP: 000000005af35251 R08: 0000000000000001 R09: 0000000000000000 [ 8.352922] R10: 00000000000005f1 R11: 0000000000000246 R12: 0000000000000000 [ 8.354183] R13: 00007fff745afed0 R14: 0000000000000001 R15: 00000000006767c0 [ 8.355400] Code: 41 89 d4 53 89 f5 48 89 fb e8 aa 20 fd ff 85 c0 0f 84 ed 00 00 00 48 85 db 0f 84 cf 00 00 00 40 84 ed 0f 85 cd 00 00 00 45 84 e4 <8b> 53 30 74 0d 85 d2 b8 ff ff ff ff 0f 8f b3 00 00 00 8b 43 2c [ 8.358699] RIP: __tcf_idr_release+0x33/0x140 RSP: ffffa0718038f840 [ 8.359770] CR2: 0000000000021130 [ 8.360438] ---[ end trace 60c66be45dfc14f0 ]--- The caller calls action's ->init() and passes pointer to "struct tc_action *a", which later may be initialized to point at the existing action, otherwise "struct tc_action *a" is still invalid, and therefore dereferencing it is an error as happens in tcf_idr_release, where refcnt is decremented. So in case of missing flags tcf_idr_release must be called only for existing actions. v2: - prepare patch for net tree Fixes: 5e1567aeb7fe ("net sched: skbedit action fix late binding") Signed-off-by: Roman Mashak Acked-by: Cong Wang Signed-off-by: David S. Miller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/sched/act_skbedit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index 59949d61f20d..6e749497009e 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c @@ -121,7 +121,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, return 0; if (!flags) { - tcf_idr_release(*a, bind); + if (exists) + tcf_idr_release(*a, bind); return -EINVAL; } -- GitLab From 20e557fb26cae647f13b4973c47293d691ff5666 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Fri, 11 May 2018 16:01:42 -0700 Subject: [PATCH 0622/1299] init: fix false positives in W+X checking [ Upstream commit ae646f0b9ca135b87bc73ff606ef996c3029780a ] load_module() creates W+X mappings via __vmalloc_node_range() (from layout_and_allocate()->move_module()->module_alloc()) by using PAGE_KERNEL_EXEC. These mappings are later cleaned up via "call_rcu_sched(&freeinit->rcu, do_free_init)" from do_init_module(). This is a problem because call_rcu_sched() queues work, which can be run after debug_checkwx() is run, resulting in a race condition. If hit, the race results in a nasty splat about insecure W+X mappings, which results in a poor user experience as these are not the mappings that debug_checkwx() is intended to catch. This issue is observed on multiple arm64 platforms, and has been artificially triggered on an x86 platform. Address the race by flushing the queued work before running the arch-defined mark_rodata_ro() which then calls debug_checkwx(). Link: http://lkml.kernel.org/r/1525103946-29526-1-git-send-email-jhugo@codeaurora.org Fixes: e1a58320a38d ("x86/mm: Warn on W^X mappings") Signed-off-by: Jeffrey Hugo Reported-by: Timur Tabi Reported-by: Jan Glauber Acked-by: Kees Cook Acked-by: Ingo Molnar Acked-by: Will Deacon Acked-by: Laura Abbott Cc: Mark Rutland Cc: Ard Biesheuvel Cc: Catalin Marinas Cc: Stephen Smalley Cc: Thomas Gleixner Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- init/main.c | 7 +++++++ kernel/module.c | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/init/main.c b/init/main.c index 2d355a61dfc5..0d88f37febcb 100644 --- a/init/main.c +++ b/init/main.c @@ -974,6 +974,13 @@ __setup("rodata=", set_debug_rodata); static void mark_readonly(void) { if (rodata_enabled) { + /* + * load_module() results in W+X mappings, which are cleaned up + * with call_rcu_sched(). Let's make sure that queued work is + * flushed so that we don't hit false positives looking for + * insecure pages which are W+X. + */ + rcu_barrier_sched(); mark_rodata_ro(); rodata_test(); } else diff --git a/kernel/module.c b/kernel/module.c index 690c0651c40f..321b0b1f87e7 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3506,6 +3506,11 @@ static noinline int do_init_module(struct module *mod) * walking this with preempt disabled. In all the failure paths, we * call synchronize_sched(), but we don't want to slow down the success * path, so use actual RCU here. + * Note that module_alloc() on most architectures creates W+X page + * mappings which won't be cleaned up until do_free_init() runs. Any + * code such as mark_rodata_ro() which depends on those mappings to + * be cleaned up needs to sync with the queued work - ie + * rcu_barrier_sched() */ call_rcu_sched(&freeinit->rcu, do_free_init); mutex_unlock(&module_mutex); -- GitLab From 553495752c8241ef0a4a2c2fc3a5c8298899ec81 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Fri, 11 May 2018 16:01:57 -0700 Subject: [PATCH 0623/1299] proc/kcore: don't bounds check against address 0 [ Upstream commit 3955333df9a50e8783d115613a397ae55d905080 ] The existing kcore code checks for bad addresses against __va(0) with the assumption that this is the lowest address on the system. This may not hold true on some systems (e.g. arm64) and produce overflows and crashes. Switch to using other functions to validate the address range. It's currently only seen on arm64 and it's not clear if anyone wants to use that particular combination on a stable release. So this is not urgent for stable. Link: http://lkml.kernel.org/r/20180501201143.15121-1-labbott@redhat.com Signed-off-by: Laura Abbott Tested-by: Dave Anderson Cc: Kees Cook Cc: Ard Biesheuvel Cc: Ingo Molnar Cc: Andi Kleen Cc: Alexey Dobriyan a Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/proc/kcore.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index d1e82761de81..e64ecb9f2720 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c @@ -209,25 +209,34 @@ kclist_add_private(unsigned long pfn, unsigned long nr_pages, void *arg) { struct list_head *head = (struct list_head *)arg; struct kcore_list *ent; + struct page *p; + + if (!pfn_valid(pfn)) + return 1; + + p = pfn_to_page(pfn); + if (!memmap_valid_within(pfn, p, page_zone(p))) + return 1; ent = kmalloc(sizeof(*ent), GFP_KERNEL); if (!ent) return -ENOMEM; - ent->addr = (unsigned long)__va((pfn << PAGE_SHIFT)); + ent->addr = (unsigned long)page_to_virt(p); ent->size = nr_pages << PAGE_SHIFT; - /* Sanity check: Can happen in 32bit arch...maybe */ - if (ent->addr < (unsigned long) __va(0)) + if (!virt_addr_valid(ent->addr)) goto free_out; /* cut not-mapped area. ....from ppc-32 code. */ if (ULONG_MAX - ent->addr < ent->size) ent->size = ULONG_MAX - ent->addr; - /* cut when vmalloc() area is higher than direct-map area */ - if (VMALLOC_START > (unsigned long)__va(0)) { - if (ent->addr > VMALLOC_START) - goto free_out; + /* + * We've already checked virt_addr_valid so we know this address + * is a valid pointer, therefore we can check against it to determine + * if we need to trim + */ + if (VMALLOC_START > ent->addr) { if (VMALLOC_START - ent->addr < ent->size) ent->size = VMALLOC_START - ent->addr; } -- GitLab From 12ddc2639e31d96f5b136a84baf7d2b312db5519 Mon Sep 17 00:00:00 2001 From: Ashish Samant Date: Fri, 11 May 2018 16:02:07 -0700 Subject: [PATCH 0624/1299] ocfs2: take inode cluster lock before moving reflinked inode from orphan dir [ Upstream commit e4383029201470523c3ffe339bd7d57e9b4a7d65 ] While reflinking an inode, we create a new inode in orphan directory, then take EX lock on it, reflink the original inode to orphan inode and release EX lock. Once the lock is released another node could request it in EX mode from ocfs2_recover_orphans() which causes downconvert of the lock, on this node, to NL mode. Later we attempt to initialize security acl for the orphan inode and move it to the reflink destination. However, while doing this we dont take EX lock on the inode. This could potentially cause problems because we could be starting transaction, accessing journal and modifying metadata of the inode while holding NL lock and with another node holding EX lock on the inode. Fix this by taking orphan inode cluster lock in EX mode before initializing security and moving orphan inode to reflink destination. Use the __tracker variant while taking inode lock to avoid recursive locking in the ocfs2_init_security_and_acl() call chain. Link: http://lkml.kernel.org/r/1523475107-7639-1-git-send-email-ashish.samant@oracle.com Signed-off-by: Ashish Samant Reviewed-by: Joseph Qi Reviewed-by: Junxiao Bi Acked-by: Jun Piao Cc: Mark Fasheh Cc: Joel Becker Cc: Changwei Ge Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/refcounttree.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index ab156e35ec00..1b1283f07941 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -4250,10 +4250,11 @@ static int __ocfs2_reflink(struct dentry *old_dentry, static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, bool preserve) { - int error; + int error, had_lock; struct inode *inode = d_inode(old_dentry); struct buffer_head *old_bh = NULL; struct inode *new_orphan_inode = NULL; + struct ocfs2_lock_holder oh; if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) return -EOPNOTSUPP; @@ -4295,6 +4296,14 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir, goto out; } + had_lock = ocfs2_inode_lock_tracker(new_orphan_inode, NULL, 1, + &oh); + if (had_lock < 0) { + error = had_lock; + mlog_errno(error); + goto out; + } + /* If the security isn't preserved, we need to re-initialize them. */ if (!preserve) { error = ocfs2_init_security_and_acl(dir, new_orphan_inode, @@ -4302,14 +4311,15 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir, if (error) mlog_errno(error); } -out: if (!error) { error = ocfs2_mv_orphaned_inode_to_new(dir, new_orphan_inode, new_dentry); if (error) mlog_errno(error); } + ocfs2_inode_unlock_tracker(new_orphan_inode, 1, &oh, had_lock); +out: if (new_orphan_inode) { /* * We need to open_unlock the inode no matter whether we -- GitLab From ba202cd5a1f045609c43058b2aeddd6fb341f236 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 9 May 2018 21:58:15 +0900 Subject: [PATCH 0625/1299] kprobes/x86: Prohibit probing on exception masking instructions [ Upstream commit ee6a7354a3629f9b65bc18dbe393503e9440d6f5 ] Since MOV SS and POP SS instructions will delay the exceptions until the next instruction is executed, single-stepping on it by kprobes must be prohibited. However, kprobes usually executes those instructions directly on trampoline buffer (a.k.a. kprobe-booster), except for the kprobes which has post_handler. Thus if kprobe user probes MOV SS with post_handler, it will do single-stepping on the MOV SS. This means it is safe that if it is used via ftrace or perf/bpf since those don't use the post_handler. Anyway, since the stack switching is a rare case, it is safer just rejecting kprobes on such instructions. Signed-off-by: Masami Hiramatsu Signed-off-by: Thomas Gleixner Cc: Ricardo Neri Cc: Francis Deslauriers Cc: Oleg Nesterov Cc: Alexei Starovoitov Cc: Steven Rostedt Cc: Andy Lutomirski Cc: "H . Peter Anvin" Cc: Yonghong Song Cc: Borislav Petkov Cc: Linus Torvalds Cc: "David S . Miller" Link: https://lkml.kernel.org/r/152587069574.17316.3311695234863248641.stgit@devbox Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/insn.h | 18 ++++++++++++++++++ arch/x86/kernel/kprobes/core.c | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/arch/x86/include/asm/insn.h b/arch/x86/include/asm/insn.h index b3e32b010ab1..c2c01f84df75 100644 --- a/arch/x86/include/asm/insn.h +++ b/arch/x86/include/asm/insn.h @@ -208,4 +208,22 @@ static inline int insn_offset_immediate(struct insn *insn) return insn_offset_displacement(insn) + insn->displacement.nbytes; } +#define POP_SS_OPCODE 0x1f +#define MOV_SREG_OPCODE 0x8e + +/* + * Intel SDM Vol.3A 6.8.3 states; + * "Any single-step trap that would be delivered following the MOV to SS + * instruction or POP to SS instruction (because EFLAGS.TF is 1) is + * suppressed." + * This function returns true if @insn is MOV SS or POP SS. On these + * instructions, single stepping is suppressed. + */ +static inline int insn_masking_exception(struct insn *insn) +{ + return insn->opcode.bytes[0] == POP_SS_OPCODE || + (insn->opcode.bytes[0] == MOV_SREG_OPCODE && + X86_MODRM_REG(insn->modrm.bytes[0]) == 2); +} + #endif /* _ASM_X86_INSN_H */ diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index ce06ec9c2323..f1030c522e06 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -369,6 +369,10 @@ int __copy_instruction(u8 *dest, u8 *src, struct insn *insn) if (insn->opcode.bytes[0] == BREAKPOINT_INSTRUCTION) return 0; + /* We should not singlestep on the exception masking instructions */ + if (insn_masking_exception(insn)) + return 0; + #ifdef CONFIG_X86_64 /* Only x86_64 has RIP relative instructions */ if (insn_rip_relative(insn)) { -- GitLab From 5aaee3e9ef32913ed77eb8fe4e9b51b5ace32a67 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 9 May 2018 21:58:45 +0900 Subject: [PATCH 0626/1299] uprobes/x86: Prohibit probing on MOV SS instruction [ Upstream commit 13ebe18c94f5b0665c01ae7fad2717ae959f4212 ] Since MOV SS and POP SS instructions will delay the exceptions until the next instruction is executed, single-stepping on it by uprobes must be prohibited. uprobe already rejects probing on POP SS (0x1f), but allows probing on MOV SS (0x8e and reg == 2). This checks the target instruction and if it is MOV SS or POP SS, returns -ENOTSUPP to reject probing. Signed-off-by: Masami Hiramatsu Signed-off-by: Thomas Gleixner Acked-by: Oleg Nesterov Cc: Ricardo Neri Cc: Francis Deslauriers Cc: Alexei Starovoitov Cc: Steven Rostedt Cc: Andy Lutomirski Cc: "H . Peter Anvin" Cc: Yonghong Song Cc: Borislav Petkov Cc: Linus Torvalds Cc: "David S . Miller" Link: https://lkml.kernel.org/r/152587072544.17316.5950935243917346341.stgit@devbox Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/uprobes.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 495c776de4b4..e1ea13ae53b9 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -296,6 +296,10 @@ static int uprobe_init_insn(struct arch_uprobe *auprobe, struct insn *insn, bool if (is_prefix_bad(insn)) return -ENOTSUPP; + /* We should not singlestep on the exception masking instructions */ + if (insn_masking_exception(insn)) + return -ENOTSUPP; + if (x86_64) good_insns = good_insns_64; else -- GitLab From 847f0cacf21eb0f575acbf06e7314466347be841 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 14 May 2018 10:15:54 +0200 Subject: [PATCH 0627/1299] objtool, kprobes/x86: Sync the latest header with tools/objtool/arch/x86/include/asm/insn.h [ Upstream commit 4fe875e4bd3cae85ae6f6eaf77f63fabe613b66e ] The following commit: ee6a7354a362: kprobes/x86: Prohibit probing on exception masking instructions Modified , adding the insn_masking_exception() function. Sync the tooling version of the header to it, to fix this warning: Warning: synced file at 'tools/objtool/arch/x86/include/asm/insn.h' differs from latest kernel version at 'arch/x86/include/asm/insn.h' Cc: Peter Zijlstra Cc: Josh Poimboeuf Cc: Masami Hiramatsu Cc: Thomas Gleixner Cc: Ricardo Neri Cc: Francis Deslauriers Cc: Oleg Nesterov Cc: Alexei Starovoitov Cc: Steven Rostedt Cc: Andy Lutomirski Cc: "H . Peter Anvin" Cc: Yonghong Song Cc: Borislav Petkov Cc: Linus Torvalds Cc: "David S . Miller" Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/objtool/arch/x86/include/asm/insn.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tools/objtool/arch/x86/include/asm/insn.h b/tools/objtool/arch/x86/include/asm/insn.h index b3e32b010ab1..c2c01f84df75 100644 --- a/tools/objtool/arch/x86/include/asm/insn.h +++ b/tools/objtool/arch/x86/include/asm/insn.h @@ -208,4 +208,22 @@ static inline int insn_offset_immediate(struct insn *insn) return insn_offset_displacement(insn) + insn->displacement.nbytes; } +#define POP_SS_OPCODE 0x1f +#define MOV_SREG_OPCODE 0x8e + +/* + * Intel SDM Vol.3A 6.8.3 states; + * "Any single-step trap that would be delivered following the MOV to SS + * instruction or POP to SS instruction (because EFLAGS.TF is 1) is + * suppressed." + * This function returns true if @insn is MOV SS or POP SS. On these + * instructions, single stepping is suppressed. + */ +static inline int insn_masking_exception(struct insn *insn) +{ + return insn->opcode.bytes[0] == POP_SS_OPCODE || + (insn->opcode.bytes[0] == MOV_SREG_OPCODE && + X86_MODRM_REG(insn->modrm.bytes[0]) == 2); +} + #endif /* _ASM_X86_INSN_H */ -- GitLab From 2361f1f4fff26781386536379d117aa1c0218ad5 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 14 May 2018 10:56:23 +0200 Subject: [PATCH 0628/1299] x86/pkeys/selftests: Adjust the self-test to fresh distros that export the pkeys ABI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 0fb96620dce351608aa82eed5942e2f58b07beda ] Ubuntu 18.04 started exporting pkeys details in header files, resulting in build failures and warnings in the pkeys self-tests: protection_keys.c:232:0: warning: "SEGV_BNDERR" redefined protection_keys.c:387:5: error: conflicting types for ‘pkey_get’ protection_keys.c:409:5: error: conflicting types for ‘pkey_set’ ... Fix these namespace conflicts and double definitions, plus also clean up the ABI definitions to make it all a bit more readable ... Cc: Dave Hansen Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: akpm@linux-foundation.org Cc: dave.hansen@intel.com Cc: linux-mm@kvack.org Cc: linuxram@us.ibm.com Cc: mpe@ellerman.id.au Cc: shakeelb@google.com Cc: shuah@kernel.org Link: http://lkml.kernel.org/r/20180514085623.GB7094@gmail.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 67 ++++++++++++------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index f15aa5a76fe3..bbe80a5c31c7 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -191,26 +191,30 @@ void lots_o_noops_around_write(int *write_to_me) #ifdef __i386__ #ifndef SYS_mprotect_key -# define SYS_mprotect_key 380 +# define SYS_mprotect_key 380 #endif + #ifndef SYS_pkey_alloc -# define SYS_pkey_alloc 381 -# define SYS_pkey_free 382 +# define SYS_pkey_alloc 381 +# define SYS_pkey_free 382 #endif -#define REG_IP_IDX REG_EIP -#define si_pkey_offset 0x14 + +#define REG_IP_IDX REG_EIP +#define si_pkey_offset 0x14 #else #ifndef SYS_mprotect_key -# define SYS_mprotect_key 329 +# define SYS_mprotect_key 329 #endif + #ifndef SYS_pkey_alloc -# define SYS_pkey_alloc 330 -# define SYS_pkey_free 331 +# define SYS_pkey_alloc 330 +# define SYS_pkey_free 331 #endif -#define REG_IP_IDX REG_RIP -#define si_pkey_offset 0x20 + +#define REG_IP_IDX REG_RIP +#define si_pkey_offset 0x20 #endif @@ -225,8 +229,14 @@ void dump_mem(void *dumpme, int len_bytes) } } -#define SEGV_BNDERR 3 /* failed address bound checks */ -#define SEGV_PKUERR 4 +/* Failed address bound checks: */ +#ifndef SEGV_BNDERR +# define SEGV_BNDERR 3 +#endif + +#ifndef SEGV_PKUERR +# define SEGV_PKUERR 4 +#endif static char *si_code_str(int si_code) { @@ -393,10 +403,15 @@ pid_t fork_lazy_child(void) return forkret; } -#define PKEY_DISABLE_ACCESS 0x1 -#define PKEY_DISABLE_WRITE 0x2 +#ifndef PKEY_DISABLE_ACCESS +# define PKEY_DISABLE_ACCESS 0x1 +#endif + +#ifndef PKEY_DISABLE_WRITE +# define PKEY_DISABLE_WRITE 0x2 +#endif -u32 pkey_get(int pkey, unsigned long flags) +static u32 hw_pkey_get(int pkey, unsigned long flags) { u32 mask = (PKEY_DISABLE_ACCESS|PKEY_DISABLE_WRITE); u32 pkru = __rdpkru(); @@ -418,7 +433,7 @@ u32 pkey_get(int pkey, unsigned long flags) return masked_pkru; } -int pkey_set(int pkey, unsigned long rights, unsigned long flags) +static int hw_pkey_set(int pkey, unsigned long rights, unsigned long flags) { u32 mask = (PKEY_DISABLE_ACCESS|PKEY_DISABLE_WRITE); u32 old_pkru = __rdpkru(); @@ -452,15 +467,15 @@ void pkey_disable_set(int pkey, int flags) pkey, flags); pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)); - pkey_rights = pkey_get(pkey, syscall_flags); + pkey_rights = hw_pkey_get(pkey, syscall_flags); - dprintf1("%s(%d) pkey_get(%d): %x\n", __func__, + dprintf1("%s(%d) hw_pkey_get(%d): %x\n", __func__, pkey, pkey, pkey_rights); pkey_assert(pkey_rights >= 0); pkey_rights |= flags; - ret = pkey_set(pkey, pkey_rights, syscall_flags); + ret = hw_pkey_set(pkey, pkey_rights, syscall_flags); assert(!ret); /*pkru and flags have the same format */ shadow_pkru |= flags << (pkey * 2); @@ -468,8 +483,8 @@ void pkey_disable_set(int pkey, int flags) pkey_assert(ret >= 0); - pkey_rights = pkey_get(pkey, syscall_flags); - dprintf1("%s(%d) pkey_get(%d): %x\n", __func__, + pkey_rights = hw_pkey_get(pkey, syscall_flags); + dprintf1("%s(%d) hw_pkey_get(%d): %x\n", __func__, pkey, pkey, pkey_rights); dprintf1("%s(%d) pkru: 0x%x\n", __func__, pkey, rdpkru()); @@ -483,24 +498,24 @@ void pkey_disable_clear(int pkey, int flags) { unsigned long syscall_flags = 0; int ret; - int pkey_rights = pkey_get(pkey, syscall_flags); + int pkey_rights = hw_pkey_get(pkey, syscall_flags); u32 orig_pkru = rdpkru(); pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)); - dprintf1("%s(%d) pkey_get(%d): %x\n", __func__, + dprintf1("%s(%d) hw_pkey_get(%d): %x\n", __func__, pkey, pkey, pkey_rights); pkey_assert(pkey_rights >= 0); pkey_rights |= flags; - ret = pkey_set(pkey, pkey_rights, 0); + ret = hw_pkey_set(pkey, pkey_rights, 0); /* pkru and flags have the same format */ shadow_pkru &= ~(flags << (pkey * 2)); pkey_assert(ret >= 0); - pkey_rights = pkey_get(pkey, syscall_flags); - dprintf1("%s(%d) pkey_get(%d): %x\n", __func__, + pkey_rights = hw_pkey_get(pkey, syscall_flags); + dprintf1("%s(%d) hw_pkey_get(%d): %x\n", __func__, pkey, pkey, pkey_rights); dprintf1("%s(%d) pkru: 0x%x\n", __func__, pkey, rdpkru()); -- GitLab From c25b160c8da6f3c20a5eed95f98f76bf2c26c55e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 14 May 2018 10:59:08 +0200 Subject: [PATCH 0629/1299] x86/mpx/selftests: Adjust the self-test to fresh distros that export the MPX ABI [ Upstream commit 73bb4d6cd192b8629c5125aaada9892d9fc986b6 ] Fix this warning: mpx-mini-test.c:422:0: warning: "SEGV_BNDERR" redefined Cc: Dave Hansen Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: akpm@linux-foundation.org Cc: dave.hansen@intel.com Cc: linux-mm@kvack.org Cc: linuxram@us.ibm.com Cc: mpe@ellerman.id.au Cc: shakeelb@google.com Cc: shuah@kernel.org Link: http://lkml.kernel.org/r/20180514085908.GA12798@gmail.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/mpx-mini-test.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c index 9c0325e1ea68..50f7e9272481 100644 --- a/tools/testing/selftests/x86/mpx-mini-test.c +++ b/tools/testing/selftests/x86/mpx-mini-test.c @@ -368,6 +368,11 @@ static int expected_bnd_index = -1; uint64_t shadow_plb[NR_MPX_BOUNDS_REGISTERS][2]; /* shadow MPX bound registers */ unsigned long shadow_map[NR_MPX_BOUNDS_REGISTERS]; +/* Failed address bound checks: */ +#ifndef SEGV_BNDERR +# define SEGV_BNDERR 3 +#endif + /* * The kernel is supposed to provide some information about the bounds * exception in the siginfo. It should match what we have in the bounds @@ -419,8 +424,6 @@ void handler(int signum, siginfo_t *si, void *vucontext) br_count++; dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count); -#define SEGV_BNDERR 3 /* failed address bound checks */ - dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n", status, ip, br_reason); dprintf2("si_signo: %d\n", si->si_signo); -- GitLab From 4824a6473b8553a503af02376157b099f03ef8e8 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 8 May 2018 10:28:35 -0700 Subject: [PATCH 0630/1299] x86/selftests: Add mov_to_ss test [ Upstream commit 59c2a7226fc5130032021c99f05ad5c0a56551cd ] This exercises a nasty corner case of the x86 ISA. Signed-off-by: Andy Lutomirski Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/67e08b69817171da8026e0eb3af0214b06b4d74f.1525800455.git.luto@kernel.org Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/Makefile | 2 +- tools/testing/selftests/x86/mov_ss_trap.c | 285 ++++++++++++++++++++++ 2 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/x86/mov_ss_trap.c diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index aa6e2d7f6a1f..903980921d9e 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -11,7 +11,7 @@ CAN_BUILD_X86_64 := $(shell ./check_cc.sh $(CC) trivial_64bit_program.c) TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \ check_initial_reg_state sigreturn iopl mpx-mini-test ioperm \ - protection_keys test_vdso test_vsyscall + protection_keys test_vdso test_vsyscall mov_ss_trap TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ vdso_restorer diff --git a/tools/testing/selftests/x86/mov_ss_trap.c b/tools/testing/selftests/x86/mov_ss_trap.c new file mode 100644 index 000000000000..3c3a022654f3 --- /dev/null +++ b/tools/testing/selftests/x86/mov_ss_trap.c @@ -0,0 +1,285 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mov_ss_trap.c: Exercise the bizarre side effects of a watchpoint on MOV SS + * + * This does MOV SS from a watchpointed address followed by various + * types of kernel entries. A MOV SS that hits a watchpoint will queue + * up a #DB trap but will not actually deliver that trap. The trap + * will be delivered after the next instruction instead. The CPU's logic + * seems to be: + * + * - Any fault: drop the pending #DB trap. + * - INT $N, INT3, INTO, SYSCALL, SYSENTER: enter the kernel and then + * deliver #DB. + * - ICEBP: enter the kernel but do not deliver the watchpoint trap + * - breakpoint: only one #DB is delivered (phew!) + * + * There are plenty of ways for a kernel to handle this incorrectly. This + * test tries to exercise all the cases. + * + * This should mostly cover CVE-2018-1087 and CVE-2018-8897. + */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define X86_EFLAGS_RF (1UL << 16) + +#if __x86_64__ +# define REG_IP REG_RIP +#else +# define REG_IP REG_EIP +#endif + +unsigned short ss; +extern unsigned char breakpoint_insn[]; +sigjmp_buf jmpbuf; +static unsigned char altstack_data[SIGSTKSZ]; + +static void enable_watchpoint(void) +{ + pid_t parent = getpid(); + int status; + + pid_t child = fork(); + if (child < 0) + err(1, "fork"); + + if (child) { + if (waitpid(child, &status, 0) != child) + err(1, "waitpid for child"); + } else { + unsigned long dr0, dr1, dr7; + + dr0 = (unsigned long)&ss; + dr1 = (unsigned long)breakpoint_insn; + dr7 = ((1UL << 1) | /* G0 */ + (3UL << 16) | /* RW0 = read or write */ + (1UL << 18) | /* LEN0 = 2 bytes */ + (1UL << 3)); /* G1, RW1 = insn */ + + if (ptrace(PTRACE_ATTACH, parent, NULL, NULL) != 0) + err(1, "PTRACE_ATTACH"); + + if (waitpid(parent, &status, 0) != parent) + err(1, "waitpid for child"); + + if (ptrace(PTRACE_POKEUSER, parent, (void *)offsetof(struct user, u_debugreg[0]), dr0) != 0) + err(1, "PTRACE_POKEUSER DR0"); + + if (ptrace(PTRACE_POKEUSER, parent, (void *)offsetof(struct user, u_debugreg[1]), dr1) != 0) + err(1, "PTRACE_POKEUSER DR1"); + + if (ptrace(PTRACE_POKEUSER, parent, (void *)offsetof(struct user, u_debugreg[7]), dr7) != 0) + err(1, "PTRACE_POKEUSER DR7"); + + printf("\tDR0 = %lx, DR1 = %lx, DR7 = %lx\n", dr0, dr1, dr7); + + if (ptrace(PTRACE_DETACH, parent, NULL, NULL) != 0) + err(1, "PTRACE_DETACH"); + + exit(0); + } +} + +static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), + int flags) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO | flags; + sigemptyset(&sa.sa_mask); + if (sigaction(sig, &sa, 0)) + err(1, "sigaction"); +} + +static char const * const signames[] = { + [SIGSEGV] = "SIGSEGV", + [SIGBUS] = "SIBGUS", + [SIGTRAP] = "SIGTRAP", + [SIGILL] = "SIGILL", +}; + +static void sigtrap(int sig, siginfo_t *si, void *ctx_void) +{ + ucontext_t *ctx = ctx_void; + + printf("\tGot SIGTRAP with RIP=%lx, EFLAGS.RF=%d\n", + (unsigned long)ctx->uc_mcontext.gregs[REG_IP], + !!(ctx->uc_mcontext.gregs[REG_EFL] & X86_EFLAGS_RF)); +} + +static void handle_and_return(int sig, siginfo_t *si, void *ctx_void) +{ + ucontext_t *ctx = ctx_void; + + printf("\tGot %s with RIP=%lx\n", signames[sig], + (unsigned long)ctx->uc_mcontext.gregs[REG_IP]); +} + +static void handle_and_longjmp(int sig, siginfo_t *si, void *ctx_void) +{ + ucontext_t *ctx = ctx_void; + + printf("\tGot %s with RIP=%lx\n", signames[sig], + (unsigned long)ctx->uc_mcontext.gregs[REG_IP]); + + siglongjmp(jmpbuf, 1); +} + +int main() +{ + unsigned long nr; + + asm volatile ("mov %%ss, %[ss]" : [ss] "=m" (ss)); + printf("\tSS = 0x%hx, &SS = 0x%p\n", ss, &ss); + + if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0) == 0) + printf("\tPR_SET_PTRACER_ANY succeeded\n"); + + printf("\tSet up a watchpoint\n"); + sethandler(SIGTRAP, sigtrap, 0); + enable_watchpoint(); + + printf("[RUN]\tRead from watched memory (should get SIGTRAP)\n"); + asm volatile ("mov %[ss], %[tmp]" : [tmp] "=r" (nr) : [ss] "m" (ss)); + + printf("[RUN]\tMOV SS; INT3\n"); + asm volatile ("mov %[ss], %%ss; int3" :: [ss] "m" (ss)); + + printf("[RUN]\tMOV SS; INT 3\n"); + asm volatile ("mov %[ss], %%ss; .byte 0xcd, 0x3" :: [ss] "m" (ss)); + + printf("[RUN]\tMOV SS; CS CS INT3\n"); + asm volatile ("mov %[ss], %%ss; .byte 0x2e, 0x2e; int3" :: [ss] "m" (ss)); + + printf("[RUN]\tMOV SS; CSx14 INT3\n"); + asm volatile ("mov %[ss], %%ss; .fill 14,1,0x2e; int3" :: [ss] "m" (ss)); + + printf("[RUN]\tMOV SS; INT 4\n"); + sethandler(SIGSEGV, handle_and_return, SA_RESETHAND); + asm volatile ("mov %[ss], %%ss; int $4" :: [ss] "m" (ss)); + +#ifdef __i386__ + printf("[RUN]\tMOV SS; INTO\n"); + sethandler(SIGSEGV, handle_and_return, SA_RESETHAND); + nr = -1; + asm volatile ("add $1, %[tmp]; mov %[ss], %%ss; into" + : [tmp] "+r" (nr) : [ss] "m" (ss)); +#endif + + if (sigsetjmp(jmpbuf, 1) == 0) { + printf("[RUN]\tMOV SS; ICEBP\n"); + + /* Some emulators (e.g. QEMU TCG) don't emulate ICEBP. */ + sethandler(SIGILL, handle_and_longjmp, SA_RESETHAND); + + asm volatile ("mov %[ss], %%ss; .byte 0xf1" :: [ss] "m" (ss)); + } + + if (sigsetjmp(jmpbuf, 1) == 0) { + printf("[RUN]\tMOV SS; CLI\n"); + sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND); + asm volatile ("mov %[ss], %%ss; cli" :: [ss] "m" (ss)); + } + + if (sigsetjmp(jmpbuf, 1) == 0) { + printf("[RUN]\tMOV SS; #PF\n"); + sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND); + asm volatile ("mov %[ss], %%ss; mov (-1), %[tmp]" + : [tmp] "=r" (nr) : [ss] "m" (ss)); + } + + /* + * INT $1: if #DB has DPL=3 and there isn't special handling, + * then the kernel will die. + */ + if (sigsetjmp(jmpbuf, 1) == 0) { + printf("[RUN]\tMOV SS; INT 1\n"); + sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND); + asm volatile ("mov %[ss], %%ss; int $1" :: [ss] "m" (ss)); + } + +#ifdef __x86_64__ + /* + * In principle, we should test 32-bit SYSCALL as well, but + * the calling convention is so unpredictable that it's + * not obviously worth the effort. + */ + if (sigsetjmp(jmpbuf, 1) == 0) { + printf("[RUN]\tMOV SS; SYSCALL\n"); + sethandler(SIGILL, handle_and_longjmp, SA_RESETHAND); + nr = SYS_getpid; + /* + * Toggle the high bit of RSP to make it noncanonical to + * strengthen this test on non-SMAP systems. + */ + asm volatile ("btc $63, %%rsp\n\t" + "mov %[ss], %%ss; syscall\n\t" + "btc $63, %%rsp" + : "+a" (nr) : [ss] "m" (ss) + : "rcx" +#ifdef __x86_64__ + , "r11" +#endif + ); + } +#endif + + printf("[RUN]\tMOV SS; breakpointed NOP\n"); + asm volatile ("mov %[ss], %%ss; breakpoint_insn: nop" :: [ss] "m" (ss)); + + /* + * Invoking SYSENTER directly breaks all the rules. Just handle + * the SIGSEGV. + */ + if (sigsetjmp(jmpbuf, 1) == 0) { + printf("[RUN]\tMOV SS; SYSENTER\n"); + stack_t stack = { + .ss_sp = altstack_data, + .ss_size = SIGSTKSZ, + }; + if (sigaltstack(&stack, NULL) != 0) + err(1, "sigaltstack"); + sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND | SA_ONSTACK); + nr = SYS_getpid; + asm volatile ("mov %[ss], %%ss; SYSENTER" : "+a" (nr) + : [ss] "m" (ss) : "flags", "rcx" +#ifdef __x86_64__ + , "r11" +#endif + ); + + /* We're unreachable here. SYSENTER forgets RIP. */ + } + + if (sigsetjmp(jmpbuf, 1) == 0) { + printf("[RUN]\tMOV SS; INT $0x80\n"); + sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND); + nr = 20; /* compat getpid */ + asm volatile ("mov %[ss], %%ss; int $0x80" + : "+a" (nr) : [ss] "m" (ss) + : "flags" +#ifdef __x86_64__ + , "r8", "r9", "r10", "r11" +#endif + ); + } + + printf("[OK]\tI aten't dead\n"); + return 0; +} -- GitLab From 477c024fb33ab5fd9bc139495fe6323191e513df Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 9 May 2018 10:13:38 -0700 Subject: [PATCH 0631/1299] x86/pkeys/selftests: Give better unexpected fault error messages [ Upstream commit 55556b0b2016806b2e16a20b62d143383983a34a ] do_not_expect_pk_fault() is a helper that we call when we do not expect a PK fault to have occurred. But, it is a function, which means that it obscures the line numbers from pkey_assert(). It also gives no details. Replace it with an implementation that gives nice line numbers and also lets callers pass in a more descriptive message about what happened that caused the unexpected fault. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Dave Hansen Cc: Linus Torvalds Cc: Michael Ellermen Cc: Peter Zijlstra Cc: Ram Pai Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20180509171338.55D13B64@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index bbe80a5c31c7..a0f0a732784b 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -954,10 +954,11 @@ void expected_pk_fault(int pkey) last_si_pkey = -1; } -void do_not_expect_pk_fault(void) -{ - pkey_assert(last_pkru_faults == pkru_faults); -} +#define do_not_expect_pk_fault(msg) do { \ + if (last_pkru_faults != pkru_faults) \ + dprintf0("unexpected PK fault: %s\n", msg); \ + pkey_assert(last_pkru_faults == pkru_faults); \ +} while (0) int test_fds[10] = { -1 }; int nr_test_fds; @@ -1243,7 +1244,7 @@ void test_ptrace_of_child(int *ptr, u16 pkey) pkey_assert(ret != -1); /* Now access from the current task, and expect NO exception: */ peek_result = read_ptr(plain_ptr); - do_not_expect_pk_fault(); + do_not_expect_pk_fault("read plain pointer after ptrace"); ret = ptrace(PTRACE_DETACH, child_pid, ignored, 0); pkey_assert(ret != -1); @@ -1287,7 +1288,7 @@ void test_executing_on_unreadable_memory(int *ptr, u16 pkey) */ madvise(p1, PAGE_SIZE, MADV_DONTNEED); lots_o_noops_around_write(&scratch); - do_not_expect_pk_fault(); + do_not_expect_pk_fault("executing on PROT_EXEC memory"); ptr_contents = read_ptr(p1); dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents); expected_pk_fault(pkey); -- GitLab From 8b9f3a7404d79ebcdf2a8491ea37d5b1b851ac6a Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 9 May 2018 10:13:40 -0700 Subject: [PATCH 0632/1299] x86/pkeys/selftests: Stop using assert() [ Upstream commit 86b9eea230edf4c67d4d4a70fba9b74505867a25 ] If we use assert(), the program "crashes". That can be scary to users, so stop doing it. Just exit with a >0 exit code instead. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Dave Hansen Cc: Linus Torvalds Cc: Michael Ellermen Cc: Peter Zijlstra Cc: Ram Pai Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20180509171340.E63EF7DA@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index a0f0a732784b..8537a7cfe1cc 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -72,10 +72,9 @@ extern void abort_hooks(void); test_nr, iteration_nr); \ dprintf0("errno at assert: %d", errno); \ abort_hooks(); \ - assert(condition); \ + exit(__LINE__); \ } \ } while (0) -#define raw_assert(cond) assert(cond) void cat_into_file(char *str, char *file) { @@ -87,12 +86,17 @@ void cat_into_file(char *str, char *file) * these need to be raw because they are called under * pkey_assert() */ - raw_assert(fd >= 0); + if (fd < 0) { + fprintf(stderr, "error opening '%s'\n", str); + perror("error: "); + exit(__LINE__); + } + ret = write(fd, str, strlen(str)); if (ret != strlen(str)) { perror("write to file failed"); fprintf(stderr, "filename: '%s' str: '%s'\n", file, str); - raw_assert(0); + exit(__LINE__); } close(fd); } -- GitLab From 9545530701c9031ac5431f388ad82b28acc3fc75 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 9 May 2018 10:13:42 -0700 Subject: [PATCH 0633/1299] x86/pkeys/selftests: Remove dead debugging code, fix dprint_in_signal [ Upstream commit a50093d60464dd51d1ae0c2267b0abe9e1de77f3 ] There is some noisy debug code at the end of the signal handler. It was disabled by an early, unconditional "return". However, that return also hid a dprint_in_signal=0, which kept dprint_in_signal=1 and effectively locked us into permanent dprint_in_signal=1 behavior. Remove the return and the dead code, fixing dprint_in_signal. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Dave Hansen Cc: Linus Torvalds Cc: Michael Ellermen Cc: Peter Zijlstra Cc: Ram Pai Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20180509171342.846B9B2E@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index 8537a7cfe1cc..5f5aedb80e7b 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -325,22 +325,6 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext) dprintf1("WARNING: set PRKU=0 to allow faulting instruction to continue\n"); pkru_faults++; dprintf1("<<<<==================================================\n"); - return; - if (trapno == 14) { - fprintf(stderr, - "ERROR: In signal handler, page fault, trapno = %d, ip = %016lx\n", - trapno, ip); - fprintf(stderr, "si_addr %p\n", si->si_addr); - fprintf(stderr, "REG_ERR: %lx\n", - (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]); - exit(1); - } else { - fprintf(stderr, "unexpected trap %d! at 0x%lx\n", trapno, ip); - fprintf(stderr, "si_addr %p\n", si->si_addr); - fprintf(stderr, "REG_ERR: %lx\n", - (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]); - exit(2); - } dprint_in_signal = 0; } -- GitLab From 777d513aaaf620dab38bbbbb32d4191e18714c89 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 9 May 2018 10:13:46 -0700 Subject: [PATCH 0634/1299] x86/pkeys/selftests: Allow faults on unknown keys [ Upstream commit 7e7fd67ca39335a49619729821efb7cbdd674eb0 ] The exec-only pkey is allocated inside the kernel and userspace is not told what it is. So, allow PK faults to occur that have an unknown key. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Dave Hansen Cc: Linus Torvalds Cc: Michael Ellermen Cc: Peter Zijlstra Cc: Ram Pai Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20180509171345.7FC7DA00@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index 5f5aedb80e7b..7d95acd2aec3 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -921,13 +921,21 @@ void *malloc_pkey(long size, int prot, u16 pkey) } int last_pkru_faults; +#define UNKNOWN_PKEY -2 void expected_pk_fault(int pkey) { dprintf2("%s(): last_pkru_faults: %d pkru_faults: %d\n", __func__, last_pkru_faults, pkru_faults); dprintf2("%s(%d): last_si_pkey: %d\n", __func__, pkey, last_si_pkey); pkey_assert(last_pkru_faults + 1 == pkru_faults); - pkey_assert(last_si_pkey == pkey); + + /* + * For exec-only memory, we do not know the pkey in + * advance, so skip this check. + */ + if (pkey != UNKNOWN_PKEY) + pkey_assert(last_si_pkey == pkey); + /* * The signal handler shold have cleared out PKRU to let the * test program continue. We now have to restore it. -- GitLab From 1fcd226878b3f8eb838dab7bef6d423cdec6035c Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 9 May 2018 10:13:47 -0700 Subject: [PATCH 0635/1299] x86/pkeys/selftests: Factor out "instruction page" [ Upstream commit 3fcd2b2d928904cbf30b01e2c5e4f1dd2f9ab262 ] We currently have an execute-only test, but it is for the explicit mprotect_pkey() interface. We will soon add a test for the implicit mprotect(PROT_EXEC) enterface. We need this code in both tests. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Dave Hansen Cc: Linus Torvalds Cc: Michael Ellermen Cc: Peter Zijlstra Cc: Ram Pai Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20180509171347.C64AB733@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index 7d95acd2aec3..083ebd51b44e 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -1253,12 +1253,9 @@ void test_ptrace_of_child(int *ptr, u16 pkey) free(plain_ptr_unaligned); } -void test_executing_on_unreadable_memory(int *ptr, u16 pkey) +void *get_pointer_to_instructions(void) { void *p1; - int scratch; - int ptr_contents; - int ret; p1 = ALIGN_PTR_UP(&lots_o_noops_around_write, PAGE_SIZE); dprintf3("&lots_o_noops: %p\n", &lots_o_noops_around_write); @@ -1268,7 +1265,23 @@ void test_executing_on_unreadable_memory(int *ptr, u16 pkey) /* Point 'p1' at the *second* page of the function: */ p1 += PAGE_SIZE; + /* + * Try to ensure we fault this in on next touch to ensure + * we get an instruction fault as opposed to a data one + */ madvise(p1, PAGE_SIZE, MADV_DONTNEED); + + return p1; +} + +void test_executing_on_unreadable_memory(int *ptr, u16 pkey) +{ + void *p1; + int scratch; + int ptr_contents; + int ret; + + p1 = get_pointer_to_instructions(); lots_o_noops_around_write(&scratch); ptr_contents = read_ptr(p1); dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents); -- GitLab From 63bdea73bd5283ee66df1a3aa1cebd34a2dc181f Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 9 May 2018 10:13:48 -0700 Subject: [PATCH 0636/1299] x86/pkeys/selftests: Add PROT_EXEC test [ Upstream commit 6af17cf89e99b64cf1f660bf848755442ab2f047 ] Under the covers, implement executable-only memory with protection keys when userspace calls mprotect(PROT_EXEC). But, we did not have a selftest for that. Now we do. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Dave Hansen Cc: Linus Torvalds Cc: Michael Ellermen Cc: Peter Zijlstra Cc: Ram Pai Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20180509171348.9EEE4BEF@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index 083ebd51b44e..8cb4fe58f381 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -1303,6 +1303,49 @@ void test_executing_on_unreadable_memory(int *ptr, u16 pkey) expected_pk_fault(pkey); } +void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey) +{ + void *p1; + int scratch; + int ptr_contents; + int ret; + + dprintf1("%s() start\n", __func__); + + p1 = get_pointer_to_instructions(); + lots_o_noops_around_write(&scratch); + ptr_contents = read_ptr(p1); + dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents); + + /* Use a *normal* mprotect(), not mprotect_pkey(): */ + ret = mprotect(p1, PAGE_SIZE, PROT_EXEC); + pkey_assert(!ret); + + dprintf2("pkru: %x\n", rdpkru()); + + /* Make sure this is an *instruction* fault */ + madvise(p1, PAGE_SIZE, MADV_DONTNEED); + lots_o_noops_around_write(&scratch); + do_not_expect_pk_fault("executing on PROT_EXEC memory"); + ptr_contents = read_ptr(p1); + dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents); + expected_pk_fault(UNKNOWN_PKEY); + + /* + * Put the memory back to non-PROT_EXEC. Should clear the + * exec-only pkey off the VMA and allow it to be readable + * again. Go to PROT_NONE first to check for a kernel bug + * that did not clear the pkey when doing PROT_NONE. + */ + ret = mprotect(p1, PAGE_SIZE, PROT_NONE); + pkey_assert(!ret); + + ret = mprotect(p1, PAGE_SIZE, PROT_READ|PROT_EXEC); + pkey_assert(!ret); + ptr_contents = read_ptr(p1); + do_not_expect_pk_fault("plain read on recently PROT_EXEC area"); +} + void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey) { int size = PAGE_SIZE; @@ -1327,6 +1370,7 @@ void (*pkey_tests[])(int *ptr, u16 pkey) = { test_kernel_gup_of_access_disabled_region, test_kernel_gup_write_to_write_disabled_region, test_executing_on_unreadable_memory, + test_implicit_mprotect_exec_only_memory, test_ptrace_of_child, test_pkey_syscalls_on_non_allocated_pkey, test_pkey_syscalls_bad_args, -- GitLab From 2dd0e5d62a6b167cc3889d05da37b293bc21f2f0 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 9 May 2018 10:13:50 -0700 Subject: [PATCH 0637/1299] x86/pkeys/selftests: Fix pkey exhaustion test off-by-one [ Upstream commit f50b4878329ab61d8e05796f655adeb6f5fb57c6 ] In our "exhaust all pkeys" test, we make sure that there is the expected number available. Turns out that the test did not cover the execute-only key, but discussed it anyway. It did *not* discuss the test-allocated key. Now that we have a test for the mprotect(PROT_EXEC) case, this off-by-one issue showed itself. Correct the off-by- one and add the explanation for the case we missed. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Dave Hansen Cc: Linus Torvalds Cc: Michael Ellermen Cc: Peter Zijlstra Cc: Ram Pai Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20180509171350.E1656B95@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index 8cb4fe58f381..55a4e349a45e 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -1163,12 +1163,15 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey) pkey_assert(i < NR_PKEYS*2); /* - * There are 16 pkeys supported in hardware. One is taken - * up for the default (0) and another can be taken up by - * an execute-only mapping. Ensure that we can allocate - * at least 14 (16-2). + * There are 16 pkeys supported in hardware. Three are + * allocated by the time we get here: + * 1. The default key (0) + * 2. One possibly consumed by an execute-only mapping. + * 3. One allocated by the test code and passed in via + * 'pkey' to this function. + * Ensure that we can allocate at least another 13 (16-3). */ - pkey_assert(i >= NR_PKEYS-2); + pkey_assert(i >= NR_PKEYS-3); for (i = 0; i < nr_allocated_pkeys; i++) { err = sys_pkey_free(allocated_pkeys[i]); -- GitLab From cdfdffcaa8f99139f4b5e49790b4465a64a85839 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 9 May 2018 10:13:52 -0700 Subject: [PATCH 0638/1299] x86/pkeys/selftests: Fix pointer math [ Upstream commit 3d64f4ed15c3c53dba4c514bf59c334464dee373 ] We dump out the entire area of the siginfo where the si_pkey_ptr is supposed to be. But, we do some math on the poitner, which is a u32. We intended to do byte math, not u32 math on the pointer. Cast it over to a u8* so it works. Also, move this block of code to below th si_code check. It doesn't hurt anything, but the si_pkey field is gibberish for other signal types. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Dave Hansen Cc: Linus Torvalds Cc: Michael Ellermen Cc: Peter Zijlstra Cc: Ram Pai Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20180509171352.9BE09819@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index 55a4e349a45e..ee8176358d12 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -303,13 +303,6 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext) dump_mem(pkru_ptr - 128, 256); pkey_assert(*pkru_ptr); - si_pkey_ptr = (u32 *)(((u8 *)si) + si_pkey_offset); - dprintf1("si_pkey_ptr: %p\n", si_pkey_ptr); - dump_mem(si_pkey_ptr - 8, 24); - siginfo_pkey = *si_pkey_ptr; - pkey_assert(siginfo_pkey < NR_PKEYS); - last_si_pkey = siginfo_pkey; - if ((si->si_code == SEGV_MAPERR) || (si->si_code == SEGV_ACCERR) || (si->si_code == SEGV_BNDERR)) { @@ -317,6 +310,13 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext) exit(4); } + si_pkey_ptr = (u32 *)(((u8 *)si) + si_pkey_offset); + dprintf1("si_pkey_ptr: %p\n", si_pkey_ptr); + dump_mem((u8 *)si_pkey_ptr - 8, 24); + siginfo_pkey = *si_pkey_ptr; + pkey_assert(siginfo_pkey < NR_PKEYS); + last_si_pkey = siginfo_pkey; + dprintf1("signal pkru from xsave: %08x\n", *pkru_ptr); /* need __rdpkru() version so we do not do shadow_pkru checking */ dprintf1("signal pkru from pkru: %08x\n", __rdpkru()); -- GitLab From b1f192a9e0cd3591142841731e01e5d9eb1c793d Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 9 May 2018 10:13:54 -0700 Subject: [PATCH 0639/1299] x86/pkeys/selftests: Save off 'prot' for allocations [ Upstream commit acb25d761d6f2f64e785ccefc71e54f244f1eda4 ] This makes it possible to to tell what 'prot' a given allocation is supposed to have. That way, if we want to change just the pkey, we know what 'prot' to pass to mprotect_pkey(). Also, keep a record of the most recent allocation so the tests can easily find it. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Dave Hansen Cc: Linus Torvalds Cc: Michael Ellermen Cc: Peter Zijlstra Cc: Ram Pai Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20180509171354.AA23E228@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index ee8176358d12..986ed38a2b25 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -677,10 +677,12 @@ int mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot, struct pkey_malloc_record { void *ptr; long size; + int prot; }; struct pkey_malloc_record *pkey_malloc_records; +struct pkey_malloc_record *pkey_last_malloc_record; long nr_pkey_malloc_records; -void record_pkey_malloc(void *ptr, long size) +void record_pkey_malloc(void *ptr, long size, int prot) { long i; struct pkey_malloc_record *rec = NULL; @@ -712,6 +714,8 @@ void record_pkey_malloc(void *ptr, long size) (int)(rec - pkey_malloc_records), rec, ptr, size); rec->ptr = ptr; rec->size = size; + rec->prot = prot; + pkey_last_malloc_record = rec; nr_pkey_malloc_records++; } @@ -756,7 +760,7 @@ void *malloc_pkey_with_mprotect(long size, int prot, u16 pkey) pkey_assert(ptr != (void *)-1); ret = mprotect_pkey((void *)ptr, PAGE_SIZE, prot, pkey); pkey_assert(!ret); - record_pkey_malloc(ptr, size); + record_pkey_malloc(ptr, size, prot); rdpkru(); dprintf1("%s() for pkey %d @ %p\n", __func__, pkey, ptr); @@ -777,7 +781,7 @@ void *malloc_pkey_anon_huge(long size, int prot, u16 pkey) size = ALIGN_UP(size, HPAGE_SIZE * 2); ptr = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); pkey_assert(ptr != (void *)-1); - record_pkey_malloc(ptr, size); + record_pkey_malloc(ptr, size, prot); mprotect_pkey(ptr, size, prot, pkey); dprintf1("unaligned ptr: %p\n", ptr); @@ -850,7 +854,7 @@ void *malloc_pkey_hugetlb(long size, int prot, u16 pkey) pkey_assert(ptr != (void *)-1); mprotect_pkey(ptr, size, prot, pkey); - record_pkey_malloc(ptr, size); + record_pkey_malloc(ptr, size, prot); dprintf1("mmap()'d hugetlbfs for pkey %d @ %p\n", pkey, ptr); return ptr; @@ -872,7 +876,7 @@ void *malloc_pkey_mmap_dax(long size, int prot, u16 pkey) mprotect_pkey(ptr, size, prot, pkey); - record_pkey_malloc(ptr, size); + record_pkey_malloc(ptr, size, prot); dprintf1("mmap()'d for pkey %d @ %p\n", pkey, ptr); close(fd); -- GitLab From 9b9ac282bad9a0463a9dbc7cd4c9de30c03ca5f9 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 9 May 2018 10:13:56 -0700 Subject: [PATCH 0640/1299] x86/pkeys/selftests: Add a test for pkey 0 [ Upstream commit 3488a600d90bcaf061b104dbcfbdc8d99b398312 ] Protection key 0 is the default key for all memory and will not normally come back from pkey_alloc(). But, you might still want pass it to mprotect_pkey(). This check ensures that you can use pkey 0. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Dave Hansen Cc: Linus Torvalds Cc: Michael Ellermen Cc: Peter Zijlstra Cc: Ram Pai Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20180509171356.9E40B254@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/x86/protection_keys.c | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index 986ed38a2b25..460b4bdf4c1e 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -1184,6 +1184,35 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey) } } +/* + * pkey 0 is special. It is allocated by default, so you do not + * have to call pkey_alloc() to use it first. Make sure that it + * is usable. + */ +void test_mprotect_with_pkey_0(int *ptr, u16 pkey) +{ + long size; + int prot; + + assert(pkey_last_malloc_record); + size = pkey_last_malloc_record->size; + /* + * This is a bit of a hack. But mprotect() requires + * huge-page-aligned sizes when operating on hugetlbfs. + * So, make sure that we use something that's a multiple + * of a huge page when we can. + */ + if (size >= HPAGE_SIZE) + size = HPAGE_SIZE; + prot = pkey_last_malloc_record->prot; + + /* Use pkey 0 */ + mprotect_pkey(ptr, size, prot, 0); + + /* Make sure that we can set it back to the original pkey. */ + mprotect_pkey(ptr, size, prot, pkey); +} + void test_ptrace_of_child(int *ptr, u16 pkey) { __attribute__((__unused__)) int peek_result; @@ -1378,6 +1407,7 @@ void (*pkey_tests[])(int *ptr, u16 pkey) = { test_kernel_gup_write_to_write_disabled_region, test_executing_on_unreadable_memory, test_implicit_mprotect_exec_only_memory, + test_mprotect_with_pkey_0, test_ptrace_of_child, test_pkey_syscalls_on_non_allocated_pkey, test_pkey_syscalls_bad_args, -- GitLab From a92a286361572e65988e37ac7c5da91a04e26a01 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 10 May 2018 19:20:54 +0100 Subject: [PATCH 0641/1299] mtd: Fix comparison in map_word_andequal() [ Upstream commit ea739a287f4f16d6250bea779a1026ead79695f2 ] Commit 9e343e87d2c4 ("mtd: cfi: convert inline functions to macros") changed map_word_andequal() into a macro, but also changed the right hand side of the comparison from val3 to val2. Change it back to use val3 on the right hand side. Thankfully this did not cause a regression because all callers currently pass the same argument for val2 and val3. Fixes: 9e343e87d2c4 ("mtd: cfi: convert inline functions to macros") Signed-off-by: Ben Hutchings Signed-off-by: Boris Brezillon Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- include/linux/mtd/map.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index b5b43f94f311..01b990e4b228 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -312,7 +312,7 @@ void map_destroy(struct mtd_info *mtd); ({ \ int i, ret = 1; \ for (i = 0; i < map_words(map); i++) { \ - if (((val1).x[i] & (val2).x[i]) != (val2).x[i]) { \ + if (((val1).x[i] & (val2).x[i]) != (val3).x[i]) { \ ret = 0; \ break; \ } \ -- GitLab From 634b9e0aabd92d2b6f0df7580b60fd0921b1c578 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 10 May 2018 23:10:40 +0100 Subject: [PATCH 0642/1299] afs: Fix the non-encryption of calls [ Upstream commit 4776cab43fd3111618112737a257dc3ef368eddd ] Some AFS servers refuse to accept unencrypted traffic, so can't be accessed with kAFS. Set the AF_RXRPC security level to encrypt client calls to deal with this. Note that incoming service calls are set by the remote client and so aren't affected by this. This requires an AF_RXRPC patch to pass the value set by setsockopt to calls begun by the kernel. Signed-off-by: David Howells Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/afs/rxrpc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 9f715c3edcf9..ccc9c708a860 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -55,6 +55,7 @@ int afs_open_socket(void) { struct sockaddr_rxrpc srx; struct socket *socket; + unsigned int min_level; int ret; _enter(""); @@ -80,6 +81,12 @@ int afs_open_socket(void) memset(&srx.transport.sin.sin_addr, 0, sizeof(srx.transport.sin.sin_addr)); + min_level = RXRPC_SECURITY_ENCRYPT; + ret = kernel_setsockopt(socket, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL, + (void *)&min_level, sizeof(min_level)); + if (ret < 0) + goto error_2; + ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx)); if (ret < 0) goto error_2; -- GitLab From a187b9c72d0cc71d30abfc6e2a5e692a897177bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= Date: Mon, 14 May 2018 09:40:05 -0500 Subject: [PATCH 0643/1299] usb: musb: fix remote wakeup racing with suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit ebc3dd688cd988754a304147753b13e58de1b5a1 ] It has been observed that writing 0xF2 to the power register while it reads as 0xF4 results in the register having the value 0xF0, i.e. clearing RESUME and setting SUSPENDM in one go does not work. It might also violate the USB spec to transition directly from resume to suspend, especially when not taking T_DRSMDN into account. But this is what happens when a remote wakeup occurs between SetPortFeature USB_PORT_FEAT_SUSPEND on the root hub and musb_bus_suspend being called. This commit returns -EBUSY when musb_bus_suspend is called while remote wakeup is signalled and thus avoids to reset the RESUME bit. Ignoring this error when musb_port_suspend is called from musb_hub_control is ok. Signed-off-by: Daniel Glöckner Signed-off-by: Bin Liu Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 5 ++++- drivers/usb/musb/musb_host.h | 7 +++++-- drivers/usb/musb/musb_virthub.c | 25 +++++++++++++++---------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 5a6dca01a1d0..802388bb42ba 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2560,8 +2560,11 @@ static int musb_bus_suspend(struct usb_hcd *hcd) { struct musb *musb = hcd_to_musb(hcd); u8 devctl; + int ret; - musb_port_suspend(musb, true); + ret = musb_port_suspend(musb, true); + if (ret) + return ret; if (!is_host_active(musb)) return 0; diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index 7bbf01bf4bb0..54d02ed032df 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h @@ -92,7 +92,7 @@ extern void musb_host_rx(struct musb *, u8); extern void musb_root_disconnect(struct musb *musb); extern void musb_host_resume_root_hub(struct musb *musb); extern void musb_host_poke_root_hub(struct musb *musb); -extern void musb_port_suspend(struct musb *musb, bool do_suspend); +extern int musb_port_suspend(struct musb *musb, bool do_suspend); extern void musb_port_reset(struct musb *musb, bool do_reset); extern void musb_host_finish_resume(struct work_struct *work); #else @@ -124,7 +124,10 @@ static inline void musb_root_disconnect(struct musb *musb) {} static inline void musb_host_resume_root_hub(struct musb *musb) {} static inline void musb_host_poll_rh_status(struct musb *musb) {} static inline void musb_host_poke_root_hub(struct musb *musb) {} -static inline void musb_port_suspend(struct musb *musb, bool do_suspend) {} +static inline int musb_port_suspend(struct musb *musb, bool do_suspend) +{ + return 0; +} static inline void musb_port_reset(struct musb *musb, bool do_reset) {} static inline void musb_host_finish_resume(struct work_struct *work) {} #endif diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 0b4595439d51..5eca5d2d5e00 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -73,14 +73,14 @@ void musb_host_finish_resume(struct work_struct *work) spin_unlock_irqrestore(&musb->lock, flags); } -void musb_port_suspend(struct musb *musb, bool do_suspend) +int musb_port_suspend(struct musb *musb, bool do_suspend) { struct usb_otg *otg = musb->xceiv->otg; u8 power; void __iomem *mbase = musb->mregs; if (!is_host_active(musb)) - return; + return 0; /* NOTE: this doesn't necessarily put PHY into low power mode, * turning off its clock; that's a function of PHY integration and @@ -91,16 +91,20 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) if (do_suspend) { int retries = 10000; - power &= ~MUSB_POWER_RESUME; - power |= MUSB_POWER_SUSPENDM; - musb_writeb(mbase, MUSB_POWER, power); + if (power & MUSB_POWER_RESUME) + return -EBUSY; - /* Needed for OPT A tests */ - power = musb_readb(mbase, MUSB_POWER); - while (power & MUSB_POWER_SUSPENDM) { + if (!(power & MUSB_POWER_SUSPENDM)) { + power |= MUSB_POWER_SUSPENDM; + musb_writeb(mbase, MUSB_POWER, power); + + /* Needed for OPT A tests */ power = musb_readb(mbase, MUSB_POWER); - if (retries-- < 1) - break; + while (power & MUSB_POWER_SUSPENDM) { + power = musb_readb(mbase, MUSB_POWER); + if (retries-- < 1) + break; + } } musb_dbg(musb, "Root port suspended, power %02x", power); @@ -136,6 +140,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) schedule_delayed_work(&musb->finish_resume_work, msecs_to_jiffies(USB_RESUME_TIMEOUT)); } + return 0; } void musb_port_reset(struct musb *musb, bool do_reset) -- GitLab From 7416dd78ad9a5c1e254d293cf5e3fee8656665cc Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 10 May 2018 14:24:20 +0100 Subject: [PATCH 0644/1299] ARM: keystone: fix platform_domain_notifier array overrun [ Upstream commit 9954b80b8c0e8abc98e17bba0fccd9876211ceaa ] platform_domain_notifier contains a variable sized array, which the pm_clk_notify() notifier treats as a NULL terminated array: for (con_id = clknb->con_ids; *con_id; con_id++) pm_clk_add(dev, *con_id); Omitting the initialiser for con_ids means that the array is zero sized, and there is no NULL terminator. This leads to pm_clk_notify() overrunning into what ever structure follows, which may not be NULL. This leads to an oops: Unable to handle kernel NULL pointer dereference at virtual address 0000008c pgd = c0003000 [0000008c] *pgd=80000800004003c, *pmd=00000000c Internal error: Oops: 206 [#1] PREEMPT SMP ARM Modules linked in:c CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.16.0+ #9 Hardware name: Keystone PC is at strlen+0x0/0x34 LR is at kstrdup+0x18/0x54 pc : [] lr : [] psr: 20000013 sp : eec73dc0 ip : eed780c0 fp : 00000001 r10: 00000000 r9 : 00000000 r8 : eed71e10 r7 : 0000008c r6 : 0000008c r5 : 014000c0 r4 : c03a6ff4 r3 : c09445d0 r2 : 00000000 r1 : 014000c0 r0 : 0000008c Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 30c5387d Table: 00003000 DAC: fffffffd Process swapper/0 (pid: 1, stack limit = 0xeec72210) Stack: (0xeec73dc0 to 0xeec74000) ... [] (strlen) from [] (kstrdup+0x18/0x54) [] (kstrdup) from [] (__pm_clk_add+0x58/0x120) [] (__pm_clk_add) from [] (pm_clk_notify+0x64/0xa8) [] (pm_clk_notify) from [] (notifier_call_chain+0x44/0x84) [] (notifier_call_chain) from [] (__blocking_notifier_call_chain+0x48/0x60) [] (__blocking_notifier_call_chain) from [] (blocking_notifier_call_chain+0x18/0x20) [] (blocking_notifier_call_chain) from [] (device_add+0x36c/0x534) [] (device_add) from [] (of_platform_device_create_pdata+0x70/0xa4) [] (of_platform_device_create_pdata) from [] (of_platform_bus_create+0xf0/0x1ec) [] (of_platform_bus_create) from [] (of_platform_populate+0x5c/0xac) [] (of_platform_populate) from [] (of_platform_default_populate_init+0x8c/0xa8) [] (of_platform_default_populate_init) from [] (do_one_initcall+0x3c/0x164) [] (do_one_initcall) from [] (kernel_init_freeable+0x10c/0x1d0) [] (kernel_init_freeable) from [] (kernel_init+0x8/0xf0) [] (kernel_init) from [] (ret_from_fork+0x14/0x3c) Exception stack(0xeec73fb0 to 0xeec73ff8) 3fa0: 00000000 00000000 00000000 00000000 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000 Code: e3520000 1afffff7 e12fff1e c0801730 (e5d02000) ---[ end trace cafa8f148e262e80 ]--- Fix this by adding the necessary initialiser. Fixes: fc20ffe1213b ("ARM: keystone: add PM domain support for clock management") Signed-off-by: Russell King Acked-by: Santosh Shilimkar Signed-off-by: Olof Johansson Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-keystone/pm_domain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-keystone/pm_domain.c b/arch/arm/mach-keystone/pm_domain.c index fe57e2692629..abca83d22ff3 100644 --- a/arch/arm/mach-keystone/pm_domain.c +++ b/arch/arm/mach-keystone/pm_domain.c @@ -29,6 +29,7 @@ static struct dev_pm_domain keystone_pm_domain = { static struct pm_clk_notifier_block platform_domain_notifier = { .pm_domain = &keystone_pm_domain, + .con_ids = { NULL }, }; static const struct of_device_id of_keystone_table[] = { -- GitLab From 0c1885743a9bdd554d20c368d775142224abdff9 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 9 May 2018 21:46:29 +0200 Subject: [PATCH 0645/1299] i2c: pmcmsp: return message count on master_xfer success [ Upstream commit de9a8634f1cb4560a35696d472cc7f1383d9b866 ] Returning zero is wrong in this case. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang Fixes: 1b144df1d7d6 ("i2c: New PMC MSP71xx TWI bus driver") Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-pmcmsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index 2aa0e83174c5..ec27e27e8d06 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -567,7 +567,7 @@ static int pmcmsptwi_master_xfer(struct i2c_adapter *adap, return -1; } - return 0; + return num; } static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter) -- GitLab From cbfe697cdba95c055830f4e04cb4d30a4fdd6be1 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 9 May 2018 21:46:30 +0200 Subject: [PATCH 0646/1299] i2c: pmcmsp: fix error return from master_xfer [ Upstream commit 12d9bbc5a7f347eaa65ff2a9d34995cadc05eb1b ] Returning -1 (-EPERM) is not appropriate here, go with -EIO. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang Fixes: 1b144df1d7d6 ("i2c: New PMC MSP71xx TWI bus driver") Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-pmcmsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index ec27e27e8d06..dae8ac618a52 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -564,7 +564,7 @@ static int pmcmsptwi_master_xfer(struct i2c_adapter *adap, * TODO: We could potentially loop and retry in the case * of MSP_TWI_XFER_TIMEOUT. */ - return -1; + return -EIO; } return num; -- GitLab From daf6bdb29d55325d49bb00bacda154e91b374975 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 9 May 2018 21:47:48 +0200 Subject: [PATCH 0647/1299] i2c: viperboard: return message count on master_xfer success [ Upstream commit 35cd67a0caf767aba472452865dcb4471fcce2b1 ] Returning zero is wrong in this case. Signed-off-by: Peter Rosin Signed-off-by: Wolfram Sang Fixes: 174a13aa8669 ("i2c: Add viperboard i2c master driver") Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-viperboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c index e4be86b3de9a..7235c7302bb7 100644 --- a/drivers/i2c/busses/i2c-viperboard.c +++ b/drivers/i2c/busses/i2c-viperboard.c @@ -337,7 +337,7 @@ static int vprbrd_i2c_xfer(struct i2c_adapter *i2c, struct i2c_msg *msgs, } mutex_unlock(&vb->lock); } - return 0; + return num; error: mutex_unlock(&vb->lock); return error; -- GitLab From ae7418dd09f9879b21fb7b8c8ddb2e3ce8d4523d Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Fri, 11 May 2018 20:51:34 +0530 Subject: [PATCH 0648/1299] ARM: davinci: dm646x: fix timer interrupt generation [ Upstream commit 73d4337ed9ceddef4b2f0e226634d5f985aa2d1c ] commit b38434145b34 ("ARM: davinci: irqs: Correct McASP1 TX interrupt definition for DM646x") inadvertently removed priority setting for timer0_12 (bottom half of timer0). This timer is used as clockevent. When INTPRIn register setting for an interrupt is left at 0, it is mapped to FIQ by the AINTC causing the timer interrupt to not get generated. Fix it by including an entry for timer0_12 in interrupt priority map array. While at it, move the clockevent comment to the right place. Fixes: b38434145b34 ("ARM: davinci: irqs: Correct McASP1 TX interrupt definition for DM646x") Signed-off-by: Sekhar Nori Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-davinci/dm646x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index da21353cac45..d869369ca2bc 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -495,7 +495,8 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = { [IRQ_DM646X_MCASP0TXINT] = 7, [IRQ_DM646X_MCASP0RXINT] = 7, [IRQ_DM646X_RESERVED_3] = 7, - [IRQ_DM646X_MCASP1TXINT] = 7, /* clockevent */ + [IRQ_DM646X_MCASP1TXINT] = 7, + [IRQ_TINT0_TINT12] = 7, /* clockevent */ [IRQ_TINT0_TINT34] = 7, /* clocksource */ [IRQ_TINT1_TINT12] = 7, /* DSP timer */ [IRQ_TINT1_TINT34] = 7, /* system tick */ -- GitLab From eb6b0d6987fc58c5dc79abba8a82e1fe999ef602 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Fri, 11 May 2018 20:51:35 +0530 Subject: [PATCH 0649/1299] ARM: davinci: board-dm646x-evm: pass correct I2C adapter id for VPIF [ Upstream commit 7d46899d57f8b61eb28701d9a4043b71e3392c26 ] commit a16cb91ad9c4 ("[media] media: vpif: use a configurable i2c_adapter_id for vpif display") removed hardcoded I2C adaptor setting in VPIF driver, but missed updating platform data passed from DM646x board. Fix it. Fixes: a16cb91ad9c4 ("[media] media: vpif: use a configurable i2c_adapter_id for vpif display") Signed-off-by: Sekhar Nori Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-davinci/board-dm646x-evm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index cb0a41e83582..6cb9fe3a6990 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -534,6 +534,7 @@ static struct vpif_display_config dm646x_vpif_display_config = { .set_clock = set_vpif_clock, .subdevinfo = dm646x_vpif_subdev, .subdev_count = ARRAY_SIZE(dm646x_vpif_subdev), + .i2c_adapter_id = 1, .chan_config[0] = { .outputs = dm6467_ch0_outputs, .output_count = ARRAY_SIZE(dm6467_ch0_outputs), @@ -676,6 +677,7 @@ static struct vpif_capture_config dm646x_vpif_capture_cfg = { .setup_input_channel_mode = setup_vpif_input_channel_mode, .subdev_info = vpif_capture_sdev_info, .subdev_count = ARRAY_SIZE(vpif_capture_sdev_info), + .i2c_adapter_id = 1, .chan_config[0] = { .inputs = dm6467_ch0_inputs, .input_count = ARRAY_SIZE(dm6467_ch0_inputs), -- GitLab From 0c5dfa51caf77461da90b3af1f1ec28490255bc0 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Fri, 11 May 2018 20:51:36 +0530 Subject: [PATCH 0650/1299] ARM: davinci: board-dm646x-evm: set VPIF capture card name [ Upstream commit bb7298a7e87cf3430eb62be8746e5d7a07ca9d7c ] VPIF capture driver expects card name to be set since it uses it without checking for NULL. The commit which introduced VPIF display and capture support added card name only for display, not for capture. Set it in platform data to probe driver successfully. While at it, also fix the display card name to something more appropriate. Fixes: 85609c1ccda6 ("DaVinci: DM646x - platform changes for vpif capture and display drivers") Signed-off-by: Sekhar Nori Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-davinci/board-dm646x-evm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 6cb9fe3a6990..4c458f714101 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -539,7 +539,7 @@ static struct vpif_display_config dm646x_vpif_display_config = { .outputs = dm6467_ch0_outputs, .output_count = ARRAY_SIZE(dm6467_ch0_outputs), }, - .card_name = "DM646x EVM", + .card_name = "DM646x EVM Video Display", }; /** @@ -698,6 +698,7 @@ static struct vpif_capture_config dm646x_vpif_capture_cfg = { .fid_pol = 0, }, }, + .card_name = "DM646x EVM Video Capture", }; static void __init evm_init_video(void) -- GitLab From c5746752bdbe4e7c6512d581dce5cc4ebc45ae75 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 18 Apr 2018 14:49:08 +0200 Subject: [PATCH 0651/1299] clk: imx6ull: use OSC clock during AXI rate change [ Upstream commit 2e5be528ab0182ad4b42b9feea3b80f85f37179b ] On i.MX6 ULL using PLL3 seems to cause a freeze when setting the parent to IMX6UL_CLK_PLL3_USB_OTG. This only seems to appear since commit 6f9575e55632 ("clk: imx: Add CLK_IS_CRITICAL flag for busy divider and busy mux"), probably because the clock is now forced to be on. Fixes: 6f9575e55632("clk: imx: Add CLK_IS_CRITICAL flag for busy divider and busy mux") Signed-off-by: Stefan Agner Signed-off-by: Stephen Boyd Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/clk/imx/clk-imx6ul.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index 5e8c18afce9a..41c08fc892b9 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -461,7 +461,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) clk_set_rate(clks[IMX6UL_CLK_AHB], 99000000); /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */ - clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]); + clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_OSC]); clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_CLK2]); clk_set_parent(clks[IMX6UL_CLK_PERIPH_PRE], clks[IMX6UL_CLK_PLL2_BUS]); clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_PRE]); -- GitLab From b3f84e48786d5696153917f7d93a0e3a5c21b294 Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Tue, 15 May 2018 17:49:50 -0400 Subject: [PATCH 0652/1299] locking/rwsem: Add a new RWSEM_ANONYMOUSLY_OWNED flag [ Upstream commit d7d760efad70c7a030725499bf9f342f04af24dd ] There are use cases where a rwsem can be acquired by one task, but released by another task. In thess cases, optimistic spinning may need to be disabled. One example will be the filesystem freeze/thaw code where the task that freezes the filesystem will acquire a write lock on a rwsem and then un-owns it before returning to userspace. Later on, another task will come along, acquire the ownership, thaw the filesystem and release the rwsem. Bit 0 of the owner field was used to designate that it is a reader owned rwsem. It is now repurposed to mean that the owner of the rwsem is not known. If only bit 0 is set, the rwsem is reader owned. If bit 0 and other bits are set, it is writer owned with an unknown owner. One such value for the latter case is (-1L). So we can set owner to 1 for reader-owned, -1 for writer-owned. The owner is unknown in both cases. To handle transfer of rwsem ownership, the higher level code should set the owner field to -1 to indicate a write-locked rwsem with unknown owner. Optimistic spinning will be disabled in this case. Once the higher level code figures who the new owner is, it can then set the owner field accordingly. Tested-by: Amir Goldstein Signed-off-by: Waiman Long Acked-by: Peter Zijlstra Cc: Andrew Morton Cc: Davidlohr Bueso Cc: Jan Kara Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Oleg Nesterov Cc: Paul E. McKenney Cc: Theodore Y. Ts'o Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-fsdevel@vger.kernel.org Link: http://lkml.kernel.org/r/1526420991-21213-2-git-send-email-longman@redhat.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- kernel/locking/rwsem-xadd.c | 17 +++++++---------- kernel/locking/rwsem.c | 2 -- kernel/locking/rwsem.h | 30 +++++++++++++++++++++--------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index e795908f3607..604d247ea8c3 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -357,11 +357,8 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem) rcu_read_lock(); owner = READ_ONCE(sem->owner); - if (!rwsem_owner_is_writer(owner)) { - /* - * Don't spin if the rwsem is readers owned. - */ - ret = !rwsem_owner_is_reader(owner); + if (!owner || !is_rwsem_owner_spinnable(owner)) { + ret = !owner; /* !owner is spinnable */ goto done; } @@ -382,11 +379,11 @@ static noinline bool rwsem_spin_on_owner(struct rw_semaphore *sem) { struct task_struct *owner = READ_ONCE(sem->owner); - if (!rwsem_owner_is_writer(owner)) - goto out; + if (!is_rwsem_owner_spinnable(owner)) + return false; rcu_read_lock(); - while (sem->owner == owner) { + while (owner && (READ_ONCE(sem->owner) == owner)) { /* * Ensure we emit the owner->on_cpu, dereference _after_ * checking sem->owner still matches owner, if that fails, @@ -408,12 +405,12 @@ static noinline bool rwsem_spin_on_owner(struct rw_semaphore *sem) cpu_relax(); } rcu_read_unlock(); -out: + /* * If there is a new owner or the owner is not set, we continue * spinning. */ - return !rwsem_owner_is_reader(READ_ONCE(sem->owner)); + return is_rwsem_owner_spinnable(READ_ONCE(sem->owner)); } static bool rwsem_optimistic_spin(struct rw_semaphore *sem) diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c index a6c76a4832b4..22bd01a7dcaa 100644 --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c @@ -201,5 +201,3 @@ void up_read_non_owner(struct rw_semaphore *sem) EXPORT_SYMBOL(up_read_non_owner); #endif - - diff --git a/kernel/locking/rwsem.h b/kernel/locking/rwsem.h index a883b8f1fdc6..410ee7b9ac2c 100644 --- a/kernel/locking/rwsem.h +++ b/kernel/locking/rwsem.h @@ -1,20 +1,24 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * The owner field of the rw_semaphore structure will be set to - * RWSEM_READ_OWNED when a reader grabs the lock. A writer will clear + * RWSEM_READER_OWNED when a reader grabs the lock. A writer will clear * the owner field when it unlocks. A reader, on the other hand, will * not touch the owner field when it unlocks. * - * In essence, the owner field now has the following 3 states: + * In essence, the owner field now has the following 4 states: * 1) 0 * - lock is free or the owner hasn't set the field yet * 2) RWSEM_READER_OWNED * - lock is currently or previously owned by readers (lock is free * or not set by owner yet) - * 3) Other non-zero value - * - a writer owns the lock + * 3) RWSEM_ANONYMOUSLY_OWNED bit set with some other bits set as well + * - lock is owned by an anonymous writer, so spinning on the lock + * owner should be disabled. + * 4) Other non-zero value + * - a writer owns the lock and other writers can spin on the lock owner. */ -#define RWSEM_READER_OWNED ((struct task_struct *)1UL) +#define RWSEM_ANONYMOUSLY_OWNED (1UL << 0) +#define RWSEM_READER_OWNED ((struct task_struct *)RWSEM_ANONYMOUSLY_OWNED) #ifdef CONFIG_RWSEM_SPIN_ON_OWNER /* @@ -45,14 +49,22 @@ static inline void rwsem_set_reader_owned(struct rw_semaphore *sem) WRITE_ONCE(sem->owner, RWSEM_READER_OWNED); } -static inline bool rwsem_owner_is_writer(struct task_struct *owner) +/* + * Return true if the a rwsem waiter can spin on the rwsem's owner + * and steal the lock, i.e. the lock is not anonymously owned. + * N.B. !owner is considered spinnable. + */ +static inline bool is_rwsem_owner_spinnable(struct task_struct *owner) { - return owner && owner != RWSEM_READER_OWNED; + return !((unsigned long)owner & RWSEM_ANONYMOUSLY_OWNED); } -static inline bool rwsem_owner_is_reader(struct task_struct *owner) +/* + * Return true if rwsem is owned by an anonymous writer or readers. + */ +static inline bool rwsem_has_anonymous_owner(struct task_struct *owner) { - return owner == RWSEM_READER_OWNED; + return (unsigned long)owner & RWSEM_ANONYMOUSLY_OWNED; } #else static inline void rwsem_set_owner(struct rw_semaphore *sem) -- GitLab From 77a60e752ec8d2b0b507d55f7a5aa36e6c8c15e7 Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Tue, 15 May 2018 17:49:51 -0400 Subject: [PATCH 0653/1299] locking/percpu-rwsem: Annotate rwsem ownership transfer by setting RWSEM_OWNER_UNKNOWN [ Upstream commit 5a817641f68a6399a5fac8b7d2da67a73698ffed ] The filesystem freezing code needs to transfer ownership of a rwsem embedded in a percpu-rwsem from the task that does the freezing to another one that does the thawing by calling percpu_rwsem_release() after freezing and percpu_rwsem_acquire() before thawing. However, the new rwsem debug code runs afoul with this scheme by warning that the task that releases the rwsem isn't the one that acquires it, as reported by Amir Goldstein: DEBUG_LOCKS_WARN_ON(sem->owner != get_current()) WARNING: CPU: 1 PID: 1401 at /home/amir/build/src/linux/kernel/locking/rwsem.c:133 up_write+0x59/0x79 Call Trace: percpu_up_write+0x1f/0x28 thaw_super_locked+0xdf/0x120 do_vfs_ioctl+0x270/0x5f1 ksys_ioctl+0x52/0x71 __x64_sys_ioctl+0x16/0x19 do_syscall_64+0x5d/0x167 entry_SYSCALL_64_after_hwframe+0x49/0xbe To work properly with the rwsem debug code, we need to annotate that the rwsem ownership is unknown during the tranfer period until a brave soul comes forward to acquire the ownership. During that period, optimistic spinning will be disabled. Reported-by: Amir Goldstein Tested-by: Amir Goldstein Signed-off-by: Waiman Long Acked-by: Peter Zijlstra Cc: Andrew Morton Cc: Davidlohr Bueso Cc: Jan Kara Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Oleg Nesterov Cc: Paul E. McKenney Cc: Theodore Y. Ts'o Cc: Thomas Gleixner Cc: Will Deacon Cc: linux-fsdevel@vger.kernel.org Link: http://lkml.kernel.org/r/1526420991-21213-3-git-send-email-longman@redhat.com Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- include/linux/percpu-rwsem.h | 6 +++++- include/linux/rwsem.h | 6 ++++++ kernel/locking/rwsem-xadd.c | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h index b1f37a89e368..79b99d653e03 100644 --- a/include/linux/percpu-rwsem.h +++ b/include/linux/percpu-rwsem.h @@ -133,7 +133,7 @@ static inline void percpu_rwsem_release(struct percpu_rw_semaphore *sem, lock_release(&sem->rw_sem.dep_map, 1, ip); #ifdef CONFIG_RWSEM_SPIN_ON_OWNER if (!read) - sem->rw_sem.owner = NULL; + sem->rw_sem.owner = RWSEM_OWNER_UNKNOWN; #endif } @@ -141,6 +141,10 @@ static inline void percpu_rwsem_acquire(struct percpu_rw_semaphore *sem, bool read, unsigned long ip) { lock_acquire(&sem->rw_sem.dep_map, 0, 1, read, 1, NULL, ip); +#ifdef CONFIG_RWSEM_SPIN_ON_OWNER + if (!read) + sem->rw_sem.owner = current; +#endif } #endif diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index dfa34d803439..c427ffaa4904 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h @@ -44,6 +44,12 @@ struct rw_semaphore { #endif }; +/* + * Setting bit 0 of the owner field with other non-zero bits will indicate + * that the rwsem is writer-owned with an unknown owner. + */ +#define RWSEM_OWNER_UNKNOWN ((struct task_struct *)-1L) + extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_down_read_failed_killable(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 604d247ea8c3..a90336779375 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -352,6 +352,8 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem) struct task_struct *owner; bool ret = true; + BUILD_BUG_ON(!rwsem_has_anonymous_owner(RWSEM_OWNER_UNKNOWN)); + if (need_resched()) return false; -- GitLab From 96ef5c44149479f13b8943a556f4193d126e1222 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 16 May 2018 17:00:26 +0300 Subject: [PATCH 0654/1299] drm/dumb-buffers: Integer overflow in drm_mode_create_ioctl() [ Upstream commit 2b6207291b7b277a5df9d1aab44b56815a292dba ] There is a comment here which says that DIV_ROUND_UP() and that's where the problem comes from. Say you pick: args->bpp = UINT_MAX - 7; args->width = 4; args->height = 1; The integer overflow in DIV_ROUND_UP() means "cpp" is UINT_MAX / 8 and because of how we picked args->width that means cpp < UINT_MAX / 4. I've fixed it by preventing the integer overflow in DIV_ROUND_UP(). I removed the check for !cpp because it's not possible after this change. I also changed all the 0xffffffffU references to U32_MAX. Signed-off-by: Dan Carpenter Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20180516140026.GA19340@mwanda Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_dumb_buffers.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_dumb_buffers.c b/drivers/gpu/drm/drm_dumb_buffers.c index 39ac15ce4702..9e2ae02f31e0 100644 --- a/drivers/gpu/drm/drm_dumb_buffers.c +++ b/drivers/gpu/drm/drm_dumb_buffers.c @@ -65,12 +65,13 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev, return -EINVAL; /* overflow checks for 32bit size calculations */ - /* NOTE: DIV_ROUND_UP() can overflow */ + if (args->bpp > U32_MAX - 8) + return -EINVAL; cpp = DIV_ROUND_UP(args->bpp, 8); - if (!cpp || cpp > 0xffffffffU / args->width) + if (cpp > U32_MAX / args->width) return -EINVAL; stride = cpp * args->width; - if (args->height > 0xffffffffU / stride) + if (args->height > U32_MAX / stride) return -EINVAL; /* test for wrap-around */ -- GitLab From fb49d19ed9da82f26d3e43122ddaf8bf31a122bd Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Wed, 16 May 2018 21:53:47 +0200 Subject: [PATCH 0655/1299] sched/debug: Move the print_rt_rq() and print_dl_rq() declarations to kernel/sched/sched.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit f6a3463063f42d9fb2c78f386437a822e0ad1792 ] In the following commit: 6b55c9654fcc ("sched/debug: Move print_cfs_rq() declaration to kernel/sched/sched.h") the print_cfs_rq() prototype was added to , right next to the prototypes for print_cfs_stats(), print_rt_stats() and print_dl_stats(). Finish this previous commit and also move related prototypes for print_rt_rq() and print_dl_rq(). Remove existing extern declarations now that they not needed anymore. Silences the following GCC warning, triggered by W=1: kernel/sched/debug.c:573:6: warning: no previous prototype for ‘print_rt_rq’ [-Wmissing-prototypes] kernel/sched/debug.c:603:6: warning: no previous prototype for ‘print_dl_rq’ [-Wmissing-prototypes] Signed-off-by: Mathieu Malaterre Acked-by: Peter Zijlstra Cc: Linus Torvalds Cc: Srikar Dronamraju Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20180516195348.30426-1-malat@debian.org Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- kernel/sched/deadline.c | 2 -- kernel/sched/rt.c | 2 -- kernel/sched/sched.h | 5 +++-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 4ae5c1ea90e2..1f4047c7362e 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -2655,8 +2655,6 @@ bool dl_cpu_busy(unsigned int cpu) #endif #ifdef CONFIG_SCHED_DEBUG -extern void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq); - void print_dl_stats(struct seq_file *m, int cpu) { print_dl_rq(m, cpu, &cpu_rq(cpu)->dl); diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 113eaeb6c0f8..bba2217652ff 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -2689,8 +2689,6 @@ int sched_rr_handler(struct ctl_table *table, int write, } #ifdef CONFIG_SCHED_DEBUG -extern void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq); - void print_rt_stats(struct seq_file *m, int cpu) { rt_rq_iter_t iter; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 307c35d33660..b29376169f3f 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1969,8 +1969,9 @@ extern bool sched_debug_enabled; extern void print_cfs_stats(struct seq_file *m, int cpu); extern void print_rt_stats(struct seq_file *m, int cpu); extern void print_dl_stats(struct seq_file *m, int cpu); -extern void -print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq); +extern void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq); +extern void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq); +extern void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq); #ifdef CONFIG_NUMA_BALANCING extern void show_numa_stats(struct task_struct *p, struct seq_file *m); -- GitLab From 588977742078d730aca04fb9eacdbfcae8873316 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Wed, 16 May 2018 22:09:02 +0200 Subject: [PATCH 0656/1299] sched/deadline: Make the grub_reclaim() function static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 3febfc8a219a036633b57a34c6678e21b6a0580d ] Since the grub_reclaim() function can be made static, make it so. Silences the following GCC warning (W=1): kernel/sched/deadline.c:1120:5: warning: no previous prototype for ‘grub_reclaim’ [-Wmissing-prototypes] Signed-off-by: Mathieu Malaterre Acked-by: Peter Zijlstra Cc: Linus Torvalds Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20180516200902.959-1-malat@debian.org Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- kernel/sched/deadline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 1f4047c7362e..501f17c642ab 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -1084,7 +1084,7 @@ extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq); * should be larger than 2^(64 - 20 - 8), which is more than 64 seconds. * So, overflow is not an issue here. */ -u64 grub_reclaim(u64 delta, struct rq *rq, struct sched_dl_entity *dl_se) +static u64 grub_reclaim(u64 delta, struct rq *rq, struct sched_dl_entity *dl_se) { u64 u_inact = rq->dl.this_bw - rq->dl.running_bw; /* Utot - Uact */ u64 u_act; -- GitLab From 3f5c7add0d0f568e30c7b645175ef2edd5c9bebb Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 18 May 2018 16:12:12 +0200 Subject: [PATCH 0657/1299] parisc: Move setup_profiling_timer() out of init section [ Upstream commit 01f56832cfb6fcc204e7203f46841b6185ebd574 ] No other architecture has setup_profiling_timer() in the init section, thus on parisc we face this section mismatch warning: Reference from the function devm_device_add_group() to the function .init.text:setup_profiling_timer() Signed-off-by: Helge Deller Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/smp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 30c28ab14540..ab4d5580bb02 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -418,8 +418,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) } #ifdef CONFIG_PROC_FS -int __init -setup_profiling_timer(unsigned int multiplier) +int setup_profiling_timer(unsigned int multiplier) { return -EINVAL; } -- GitLab From 823e02ea7be553c9a2dddffe72ac3bc88c6a3933 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Fri, 18 May 2018 16:08:41 +0200 Subject: [PATCH 0658/1299] efi/libstub/arm64: Handle randomized TEXT_OFFSET [ Upstream commit 4f74d72aa7067e75af92fbab077e6d7d0210be66 ] When CONFIG_RANDOMIZE_TEXT_OFFSET=y, TEXT_OFFSET is an arbitrary multiple of PAGE_SIZE in the interval [0, 2MB). The EFI stub does not account for the potential misalignment of TEXT_OFFSET relative to EFI_KIMG_ALIGN, and produces a randomized physical offset which is always a round multiple of EFI_KIMG_ALIGN. This may result in statically allocated objects whose alignment exceeds PAGE_SIZE to appear misaligned in memory. This has been observed to result in spurious stack overflow reports and failure to make use of the IRQ stacks, and theoretically could result in a number of other issues. We can OR in the low bits of TEXT_OFFSET to ensure that we have the necessary offset (and hence preserve the misalignment of TEXT_OFFSET relative to EFI_KIMG_ALIGN), so let's do that. Reported-by: Kim Phillips Tested-by: Kim Phillips [ardb: clarify comment and commit log, drop unneeded parens] Signed-off-by: Mark Rutland Signed-off-by: Ard Biesheuvel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Fixes: 6f26b3671184c36d ("arm64: kaslr: increase randomization granularity") Link: http://lkml.kernel.org/r/20180518140841.9731-2-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/efi/libstub/arm64-stub.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c index b9bd827caa22..1b4d465cc5d9 100644 --- a/drivers/firmware/efi/libstub/arm64-stub.c +++ b/drivers/firmware/efi/libstub/arm64-stub.c @@ -97,6 +97,16 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg, u32 offset = !IS_ENABLED(CONFIG_DEBUG_ALIGN_RODATA) ? (phys_seed >> 32) & mask : TEXT_OFFSET; + /* + * With CONFIG_RANDOMIZE_TEXT_OFFSET=y, TEXT_OFFSET may not + * be a multiple of EFI_KIMG_ALIGN, and we must ensure that + * we preserve the misalignment of 'offset' relative to + * EFI_KIMG_ALIGN so that statically allocated objects whose + * alignment exceeds PAGE_SIZE appear correctly aligned in + * memory. + */ + offset |= TEXT_OFFSET % EFI_KIMG_ALIGN; + /* * If KASLR is enabled, and we have some randomness available, * locate the kernel at a randomized offset in physical memory. -- GitLab From c7d7e3f62dbe0908213a922a714961ec56628c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Stelmach?= Date: Tue, 3 Apr 2018 09:04:57 +0100 Subject: [PATCH 0659/1299] ARM: 8753/1: decompressor: add a missing parameter to the addruart macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit e07e3c33b9c0b5751ade624f44325c9bf2487ea6 ] In commit 639da5ee374b ("ARM: add an extra temp register to the low level debugging addruart macro") an additional temporary register was added to the addruart macro, but the decompressor code wasn't updated. Fixes: 639da5ee374b ("ARM: add an extra temp register to the low level debugging addruart macro") Signed-off-by: Łukasz Stelmach Signed-off-by: Russell King Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/compressed/head.S | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 8a756870c238..f51c009c00dc 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -29,19 +29,19 @@ #if defined(CONFIG_DEBUG_ICEDCC) #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7) - .macro loadsp, rb, tmp + .macro loadsp, rb, tmp1, tmp2 .endm .macro writeb, ch, rb mcr p14, 0, \ch, c0, c5, 0 .endm #elif defined(CONFIG_CPU_XSCALE) - .macro loadsp, rb, tmp + .macro loadsp, rb, tmp1, tmp2 .endm .macro writeb, ch, rb mcr p14, 0, \ch, c8, c0, 0 .endm #else - .macro loadsp, rb, tmp + .macro loadsp, rb, tmp1, tmp2 .endm .macro writeb, ch, rb mcr p14, 0, \ch, c1, c0, 0 @@ -57,7 +57,7 @@ .endm #if defined(CONFIG_ARCH_SA1100) - .macro loadsp, rb, tmp + .macro loadsp, rb, tmp1, tmp2 mov \rb, #0x80000000 @ physical base address #ifdef CONFIG_DEBUG_LL_SER3 add \rb, \rb, #0x00050000 @ Ser3 @@ -66,8 +66,8 @@ #endif .endm #else - .macro loadsp, rb, tmp - addruart \rb, \tmp + .macro loadsp, rb, tmp1, tmp2 + addruart \rb, \tmp1, \tmp2 .endm #endif #endif @@ -1295,7 +1295,7 @@ phex: adr r3, phexbuf b 1b @ puts corrupts {r0, r1, r2, r3} -puts: loadsp r3, r1 +puts: loadsp r3, r2, r1 1: ldrb r2, [r0], #1 teq r2, #0 moveq pc, lr @@ -1312,8 +1312,8 @@ puts: loadsp r3, r1 @ putc corrupts {r0, r1, r2, r3} putc: mov r2, r0 + loadsp r3, r1, r0 mov r0, #0 - loadsp r3, r1 b 2b @ memdump corrupts {r0, r1, r2, r3, r10, r11, r12, lr} -- GitLab From bb7a554ae7454ba921d3d59d9480e90c117f97d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Stelmach?= Date: Wed, 4 Apr 2018 08:46:58 +0100 Subject: [PATCH 0660/1299] ARM: 8758/1: decompressor: restore r1 and r2 just before jumping to the kernel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit f2ae9de019e4e2807d812ec4fe1df7c34788a0a0 ] The hypervisor setup before __enter_kernel destroys the value sotred in r1. The value needs to be restored just before the jump. Fixes: 6b52f7bdb888 ("ARM: hyp-stub: Use r1 for the soft-restart address") Signed-off-by: Łukasz Stelmach Signed-off-by: Russell King Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/compressed/head.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index f51c009c00dc..5f687ba1eaa7 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -559,8 +559,6 @@ not_relocated: mov r0, #0 bl decompress_kernel bl cache_clean_flush bl cache_off - mov r1, r7 @ restore architecture number - mov r2, r8 @ restore atags pointer #ifdef CONFIG_ARM_VIRT_EXT mrs r0, spsr @ Get saved CPU boot mode @@ -1363,6 +1361,8 @@ __hyp_reentry_vectors: __enter_kernel: mov r0, #0 @ must be 0 + mov r1, r7 @ restore architecture number + mov r2, r8 @ restore atags pointer ARM( mov pc, r4 ) @ call kernel M_CLASS( add r4, r4, #1 ) @ enter in Thumb mode for M class THUMB( bx r4 ) @ entry point is always ARM for A/R classes -- GitLab From 5e4b5b7194d3d561e8791c167eb1e671b96ca575 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 11 Apr 2018 18:24:01 +0100 Subject: [PATCH 0661/1299] ARM: kexec: fix kdump register saving on panic() [ Upstream commit 2d7b3c64431245c95b05a441669c074da10db943 ] When a panic() occurs, the kexec code uses smp_send_stop() to stop the other CPUs, but this results in the CPU register state not being saved, and gdb is unable to inspect the state of other CPUs. Commit 0ee59413c967 ("x86/panic: replace smp_send_stop() with kdump friendly version in panic path") addressed the issue on x86, but ignored other architectures. Address the issue on ARM by splitting out the crash stop implementation to crash_smp_send_stop() and adding the necessary protection. Signed-off-by: Russell King Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/machine_kexec.c | 34 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 6b38d7a634c1..c15318431986 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -95,6 +95,27 @@ void machine_crash_nonpanic_core(void *unused) cpu_relax(); } +void crash_smp_send_stop(void) +{ + static int cpus_stopped; + unsigned long msecs; + + if (cpus_stopped) + return; + + atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); + smp_call_function(machine_crash_nonpanic_core, NULL, false); + msecs = 1000; /* Wait at most a second for the other cpus to stop */ + while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { + mdelay(1); + msecs--; + } + if (atomic_read(&waiting_for_crash_ipi) > 0) + pr_warn("Non-crashing CPUs did not react to IPI\n"); + + cpus_stopped = 1; +} + static void machine_kexec_mask_interrupts(void) { unsigned int i; @@ -120,19 +141,8 @@ static void machine_kexec_mask_interrupts(void) void machine_crash_shutdown(struct pt_regs *regs) { - unsigned long msecs; - local_irq_disable(); - - atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); - smp_call_function(machine_crash_nonpanic_core, NULL, false); - msecs = 1000; /* Wait at most a second for the other cpus to stop */ - while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { - mdelay(1); - msecs--; - } - if (atomic_read(&waiting_for_crash_ipi) > 0) - pr_warn("Non-crashing CPUs did not react to IPI\n"); + crash_smp_send_stop(); crash_save_cpu(regs, smp_processor_id()); machine_kexec_mask_interrupts(); -- GitLab From db5f02cc70a8251e103241cc230e01392729739c Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Fri, 15 Jun 2018 02:39:01 +0000 Subject: [PATCH 0662/1299] Revert "Btrfs: fix scrub to repair raid6 corruption" This reverts commit d91bb7c6988bd6450284c762b33f2e1ea3fe7c97. This commit used an incorrect log message. Signed-off-by: Sasha Levin Reported-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/raid56.c | 18 ++++-------------- fs/btrfs/volumes.c | 9 +-------- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index 2e995e565633..d1bda68a3386 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c @@ -2172,21 +2172,11 @@ int raid56_parity_recover(struct btrfs_fs_info *fs_info, struct bio *bio, } /* - * Loop retry: - * for 'mirror == 2', reconstruct from all other stripes. - * for 'mirror_num > 2', select a stripe to fail on every retry. + * reconstruct from the q stripe if they are + * asking for mirror 3 */ - if (mirror_num > 2) { - /* - * 'mirror == 3' is to fail the p stripe and - * reconstruct from the q stripe. 'mirror > 3' is to - * fail a data stripe and reconstruct from p+q stripe. - */ - rbio->failb = rbio->real_stripes - (mirror_num - 1); - ASSERT(rbio->failb > 0); - if (rbio->failb <= rbio->faila) - rbio->failb--; - } + if (mirror_num == 3) + rbio->failb = rbio->real_stripes - 2; ret = lock_stripe_add(rbio); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 08afafb6ecf7..69bc37a87c5a 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -5110,14 +5110,7 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len) else if (map->type & BTRFS_BLOCK_GROUP_RAID5) ret = 2; else if (map->type & BTRFS_BLOCK_GROUP_RAID6) - /* - * There could be two corrupted data stripes, we need - * to loop retry in order to rebuild the correct data. - * - * Fail a stripe at a time on every retry except the - * stripe under reconstruction. - */ - ret = map->num_stripes; + ret = 3; else ret = 1; free_extent_map(em); -- GitLab From 6bf89b7c6b319259f7991a424187ab2647db6424 Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Fri, 15 Jun 2018 02:39:02 +0000 Subject: [PATCH 0663/1299] Btrfs: fix scrub to repair raid6 corruption [ Upstream commit 762221f095e3932669093466aaf4b85ed9ad2ac1 ] The raid6 corruption is that, suppose that all disks can be read without problems and if the content that was read out doesn't match its checksum, currently for raid6 btrfs at most retries twice, - the 1st retry is to rebuild with all other stripes, it'll eventually be a raid5 xor rebuild, - if the 1st fails, the 2nd retry will deliberately fail parity p so that it will do raid6 style rebuild, however, the chances are that another non-parity stripe content also has something corrupted, so that the above retries are not able to return correct content. We've fixed normal reads to rebuild raid6 correctly with more retries in Patch "Btrfs: make raid6 rebuild retry more"[1], this is to fix scrub to do the exactly same rebuild process. [1]: https://patchwork.kernel.org/patch/10091755/ Signed-off-by: Liu Bo Signed-off-by: David Sterba Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/scrub.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index e3f6c49e5c4d..24613b4e224c 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -301,6 +301,11 @@ static void __scrub_blocked_if_needed(struct btrfs_fs_info *fs_info); static void scrub_blocked_if_needed(struct btrfs_fs_info *fs_info); static void scrub_put_ctx(struct scrub_ctx *sctx); +static inline int scrub_is_page_on_raid56(struct scrub_page *page) +{ + return page->recover && + (page->recover->bbio->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK); +} static void scrub_pending_bio_inc(struct scrub_ctx *sctx) { @@ -1323,15 +1328,34 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check) * could happen otherwise that a correct page would be * overwritten by a bad one). */ - for (mirror_index = 0; - mirror_index < BTRFS_MAX_MIRRORS && - sblocks_for_recheck[mirror_index].page_count > 0; - mirror_index++) { + for (mirror_index = 0; ;mirror_index++) { struct scrub_block *sblock_other; if (mirror_index == failed_mirror_index) continue; - sblock_other = sblocks_for_recheck + mirror_index; + + /* raid56's mirror can be more than BTRFS_MAX_MIRRORS */ + if (!scrub_is_page_on_raid56(sblock_bad->pagev[0])) { + if (mirror_index >= BTRFS_MAX_MIRRORS) + break; + if (!sblocks_for_recheck[mirror_index].page_count) + break; + + sblock_other = sblocks_for_recheck + mirror_index; + } else { + struct scrub_recover *r = sblock_bad->pagev[0]->recover; + int max_allowed = r->bbio->num_stripes - + r->bbio->num_tgtdevs; + + if (mirror_index >= max_allowed) + break; + if (!sblocks_for_recheck[1].page_count) + break; + + ASSERT(failed_mirror_index == 0); + sblock_other = sblocks_for_recheck + 1; + sblock_other->pagev[0]->mirror_num = 1 + mirror_index; + } /* build and submit the bios, check checksums */ scrub_recheck_block(fs_info, sblock_other, 0); @@ -1679,18 +1703,13 @@ static void scrub_bio_wait_endio(struct bio *bio) complete(&ret->event); } -static inline int scrub_is_page_on_raid56(struct scrub_page *page) -{ - return page->recover && - (page->recover->bbio->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK); -} - static int scrub_submit_raid56_bio_wait(struct btrfs_fs_info *fs_info, struct bio *bio, struct scrub_page *page) { struct scrub_bio_ret done; int ret; + int mirror_num; init_completion(&done.event); done.status = 0; @@ -1698,9 +1717,10 @@ static int scrub_submit_raid56_bio_wait(struct btrfs_fs_info *fs_info, bio->bi_private = &done; bio->bi_end_io = scrub_bio_wait_endio; + mirror_num = page->sblock->pagev[0]->mirror_num; ret = raid56_parity_recover(fs_info, bio, page->recover->bbio, page->recover->map_length, - page->mirror_num, 0); + mirror_num, 0); if (ret) return ret; -- GitLab From 7ab8fc065fff258d0b2c5e48e529fd780905db45 Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Fri, 15 Jun 2018 02:39:04 +0000 Subject: [PATCH 0664/1299] Btrfs: make raid6 rebuild retry more [ Upstream commit 8810f7517a3bc4ca2d41d022446d3f5fd6b77c09 ] There is a scenario that can end up with rebuild process failing to return good content, i.e. suppose that all disks can be read without problems and if the content that was read out doesn't match its checksum, currently for raid6 btrfs at most retries twice, - the 1st retry is to rebuild with all other stripes, it'll eventually be a raid5 xor rebuild, - if the 1st fails, the 2nd retry will deliberately fail parity p so that it will do raid6 style rebuild, however, the chances are that another non-parity stripe content also has something corrupted, so that the above retries are not able to return correct content, and users will think of this as data loss. More seriouly, if the loss happens on some important internal btree roots, it could refuse to mount. This extends btrfs to do more retries and each retry fails only one stripe. Since raid6 can tolerate 2 disk failures, if there is one more failure besides the failure on which we're recovering, this can always work. The worst case is to retry as many times as the number of raid6 disks, but given the fact that such a scenario is really rare in practice, it's still acceptable. Signed-off-by: Liu Bo Signed-off-by: David Sterba Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/raid56.c | 18 ++++++++++++++---- fs/btrfs/volumes.c | 9 ++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index d1bda68a3386..2e995e565633 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c @@ -2172,11 +2172,21 @@ int raid56_parity_recover(struct btrfs_fs_info *fs_info, struct bio *bio, } /* - * reconstruct from the q stripe if they are - * asking for mirror 3 + * Loop retry: + * for 'mirror == 2', reconstruct from all other stripes. + * for 'mirror_num > 2', select a stripe to fail on every retry. */ - if (mirror_num == 3) - rbio->failb = rbio->real_stripes - 2; + if (mirror_num > 2) { + /* + * 'mirror == 3' is to fail the p stripe and + * reconstruct from the q stripe. 'mirror > 3' is to + * fail a data stripe and reconstruct from p+q stripe. + */ + rbio->failb = rbio->real_stripes - (mirror_num - 1); + ASSERT(rbio->failb > 0); + if (rbio->failb <= rbio->faila) + rbio->failb--; + } ret = lock_stripe_add(rbio); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 69bc37a87c5a..08afafb6ecf7 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -5110,7 +5110,14 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len) else if (map->type & BTRFS_BLOCK_GROUP_RAID5) ret = 2; else if (map->type & BTRFS_BLOCK_GROUP_RAID6) - ret = 3; + /* + * There could be two corrupted data stripes, we need + * to loop retry in order to rebuild the correct data. + * + * Fail a stripe at a time on every retry except the + * stripe under reconstruction. + */ + ret = map->num_stripes; else ret = 1; free_extent_map(em); -- GitLab From 40c809774c692877b1167003d9807f7aaa46ad2b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 10 Dec 2017 17:55:02 -0800 Subject: [PATCH 0665/1299] tcp: do not overshoot window_clamp in tcp_rcv_space_adjust() commit 02db55718d53f9d426cee504c27fb768e9ed4ffe upstream. While rcvbuf is properly clamped by tcp_rmem[2], rcvwin is left to a potentially too big value. It has no serious effect, since : 1) tcp_grow_window() has very strict checks. 2) window_clamp can be mangled by user space to any value anyway. tcp_init_buffer_space() and companions use tcp_full_space(), we use tcp_win_from_space() to avoid reloading sk->sk_rcvbuf Signed-off-by: Eric Dumazet Acked-by: Soheil Hassas Yeganeh Acked-by: Wei Wang Acked-by: Neal Cardwell Signed-off-by: David S. Miller Cc: Benjamin Gilbert Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 125b49c166a4..f0caff3139ed 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -647,7 +647,7 @@ void tcp_rcv_space_adjust(struct sock *sk) sk->sk_rcvbuf = rcvbuf; /* Make the window clamp follow along. */ - tp->window_clamp = rcvwin; + tp->window_clamp = tcp_win_from_space(rcvbuf); } } tp->rcvq_space.space = copied; -- GitLab From 33445c07cd45541410fb4cabd08b10827764c07f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 21 Jun 2018 04:03:02 +0900 Subject: [PATCH 0666/1299] Linux 4.14.51 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 84374c5ba60e..a33376204c17 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 50 +SUBLEVEL = 51 EXTRAVERSION = NAME = Petit Gorille -- GitLab From df4ae340cc5500e48f2c4c8b6776f7643d9032c9 Mon Sep 17 00:00:00 2001 From: Karthikeyan Ramasubramanian Date: Wed, 20 Jun 2018 14:24:50 -0600 Subject: [PATCH 0667/1299] drivers: of: of_slimbus: Register the slimbus slaves that are enabled Currently all the child nodes of slimbus controller are registered even if they are disabled. This leads to slimbus slave drivers getting probed even if the slimbus slave devices are enabled. Use for_each_available_child_of_node helper function to register only the nodes that are enabled. Change-Id: I930f5bf2ee4ddef7f74521bf3e8cc444b75f86e6 Signed-off-by: Karthikeyan Ramasubramanian --- drivers/of/of_slimbus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/of/of_slimbus.c b/drivers/of/of_slimbus.c index 2b3d2401f61e..41f64faf4599 100644 --- a/drivers/of/of_slimbus.c +++ b/drivers/of/of_slimbus.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, 2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2012, 2017-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -29,7 +29,7 @@ int of_register_slim_devices(struct slim_controller *ctrl) if (!ctrl->dev.of_node) return -EINVAL; - for_each_child_of_node(ctrl->dev.of_node, node) { + for_each_available_child_of_node(ctrl->dev.of_node, node) { struct property *prop; struct slim_device *slim; char *name; -- GitLab From e2f22cc49d16e7cc8e54cdf63ff9507b4ced3e1a Mon Sep 17 00:00:00 2001 From: David Dai Date: Tue, 19 Jun 2018 14:34:09 -0700 Subject: [PATCH 0668/1299] msm: msm_bus: Ignore -EBUSY from disp rsc when sending AMC cmds Excess logging may occur when benign errors are returned when AMC requests are sent to the display RSC when it's in solver mode. Change-Id: I7089699a351e3e6c34dafd752120d8e4d198cdd9 Signed-off-by: David Dai --- drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c index f16c2bb938b0..f00a8c09b324 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "msm_bus_core.h" #include "msm_bus_rpmh.h" #include "msm_bus_noc.h" @@ -621,12 +622,12 @@ int msm_bus_commit_data(struct list_head *clist) MSM_BUS_ERR("%s: Error invalidating mbox: %d\n", __func__, ret); - if (cur_rsc->rscdev->req_state == RPMH_AWAKE_STATE) { - ret = rpmh_write(cur_mbox, cur_rsc->rscdev->req_state, - cmdlist_active, cnt_active); + if (cur_rsc->node_info->id == MSM_BUS_RSC_DISP) { + ret = rpmh_write_batch(cur_mbox, cur_rsc->rscdev->req_state, + cmdlist_active, n_active); /* - * Ignore -EBUSY from rpmh_write if it's an AWAKE_STATE - * request since AWAKE requests are invalid when + * Ignore -EBUSY from rpmh_write if it's an AMC + * request to Display RSC which are invalid when * the display RSC is in solver mode and the bus driver * does not know the current state of the display RSC. */ -- GitLab From 3c517cd888c35dba5d694e1afea970787fde44c3 Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Wed, 20 Jun 2018 16:42:31 -0700 Subject: [PATCH 0669/1299] ARM: dts: msm: Use correct msm-id for SM8150P Currently, the wrong msm-id is used for target sm8150p. Change msm-id to correct msm-id. Change-Id: Icd030dcb02b9b749aae90183f2356766a9c5d4ef Signed-off-by: Isaac J. Manjarres --- arch/arm64/boot/dts/qcom/sm8150p-v2.dtsi | 2 +- arch/arm64/boot/dts/qcom/sm8150p.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150p-v2.dtsi b/arch/arm64/boot/dts/qcom/sm8150p-v2.dtsi index 4351f650b1ea..d4d2cf37d745 100644 --- a/arch/arm64/boot/dts/qcom/sm8150p-v2.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150p-v2.dtsi @@ -15,5 +15,5 @@ / { model = "Qualcomm Technologies, Inc. SM8150P v2"; qcom,msm-name = "SM8150P v2"; - qcom,msm-id = <356 0x20000>; + qcom,msm-id = <361 0x20000>; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150p.dtsi b/arch/arm64/boot/dts/qcom/sm8150p.dtsi index 87632a0933e0..2ed1d50cd296 100644 --- a/arch/arm64/boot/dts/qcom/sm8150p.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150p.dtsi @@ -15,5 +15,5 @@ / { model = "Qualcomm Technologies, Inc. SM8150P v1"; qcom,msm-name = "SM8150P v1"; - qcom,msm-id = <356 0x10000>; + qcom,msm-id = <361 0x10000>; }; -- GitLab From f5114467e207ebc938926f6ce1bf276433e0c418 Mon Sep 17 00:00:00 2001 From: Patrik Torstensson Date: Fri, 13 Apr 2018 15:34:48 -0700 Subject: [PATCH 0670/1299] ANDROID: Add kconfig to make dm-verity check_at_most_once default enabled This change adds a kernel config for default enable the check_at_most_once dm-verity option. This is to give us the ability to enforce the usage of at_most_once for entry-level phones. Change-Id: Id40416672c4c2209a9866997d8c164b5de5dc7dc Signed-off-by: Patrik Torstensson Bug: 72664474 --- drivers/md/Kconfig | 20 ++++++++++++++++++++ drivers/md/dm-verity-target.c | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 6ac0297db28c..9f8b4e0dc3cc 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -572,4 +572,24 @@ config DM_ANDROID_VERITY of the metadata contents are verified against the key included in the system keyring. Upon success, the underlying verity target is setup. + +config DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED + bool "Verity will validate blocks at most once" + depends on DM_VERITY + ---help--- + Default enables at_most_once option for dm-verity + + Verify data blocks only the first time they are read from the + data device, rather than every time. This reduces the overhead + of dm-verity so that it can be used on systems that are memory + and/or CPU constrained. However, it provides a reduced level + of security because only offline tampering of the data device's + content will be detected, not online tampering. + + Hash blocks are still verified each time they are read from the + hash device, since verification of hash blocks is less performance + critical than data blocks, and a hash block will not be verified + any more after all the data blocks it covers have been verified anyway. + + If unsure, say N. endif # MD diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index 751855c24d5a..ecb506b6923d 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -1123,6 +1123,14 @@ int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) goto bad; } +#ifdef CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED + if (!v->validated_blocks) { + r = verity_alloc_most_once(v); + if (r) + goto bad; + } +#endif + v->hash_per_block_bits = __fls((1 << v->hash_dev_block_bits) / v->digest_size); -- GitLab From 59edf872db1ad893e88339106f5d17f50d78b6eb Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Wed, 20 Jun 2018 15:44:03 -0700 Subject: [PATCH 0671/1299] power: smb5: Fix ITERM thresholds configuration The registers CHGR_ADC_ITERM_UP_THD_MSB and CHGR_ADC_ITERM_LO_THD_MSB (and their corresponding lower halves, *_LSB) are in big-endian format. Write to, and read from, these registers in the big-endian format. CRs-Fixed: 2264651 Change-Id: I16f31f411e865b6bbfe1e299fe8e9e2aff50b536 Signed-off-by: Guru Das Srinagesh --- drivers/power/supply/qcom/qpnp-smb5.c | 10 ++++++++-- drivers/power/supply/qcom/smb5-lib.c | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 3e2cc6c231f0..55634d0896b6 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -1516,8 +1516,9 @@ static int smb5_configure_micro_usb(struct smb_charger *chg) static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip) { + u8 *buf; int rc = 0; - int raw_hi_thresh, raw_lo_thresh; + s16 raw_hi_thresh, raw_lo_thresh; struct smb_charger *chg = &chip->chg; if (chip->dt.term_current_thresh_hi_ma < -10000 || @@ -1530,13 +1531,16 @@ static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip) /* * Conversion: - * raw (A) = (scaled_mA * ADC_CHG_TERM_MASK) / (10 * 1000) + * raw (A) = (scaled_mA * ADC_CHG_TERM_MASK) / (10 * 1000) + * Note: raw needs to be converted to big-endian format. */ if (chip->dt.term_current_thresh_hi_ma) { raw_hi_thresh = ((chip->dt.term_current_thresh_hi_ma * ADC_CHG_TERM_MASK) / 10000); raw_hi_thresh = sign_extend32(raw_hi_thresh, 15); + buf = (u8 *)&raw_hi_thresh; + raw_hi_thresh = buf[1] | (buf[0] << 8); rc = smblib_batch_write(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, (u8 *)&raw_hi_thresh, 2); @@ -1551,6 +1555,8 @@ static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip) raw_lo_thresh = ((chip->dt.term_current_thresh_lo_ma * ADC_CHG_TERM_MASK) / 10000); raw_lo_thresh = sign_extend32(raw_lo_thresh, 15); + buf = (u8 *)&raw_lo_thresh; + raw_lo_thresh = buf[1] | (buf[0] << 8); rc = smblib_batch_write(chg, CHGR_ADC_ITERM_LO_THD_MSB_REG, (u8 *)&raw_lo_thresh, 2); diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index ef298f777010..f0a957217ecf 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -1561,7 +1561,7 @@ int smblib_get_prop_batt_iterm(struct smb_charger *chg, union power_supply_propval *val) { int rc, temp; - u8 stat; + u8 stat, buf[2]; /* * Currently, only ADC comparator-based termination is supported, @@ -1580,8 +1580,7 @@ int smblib_get_prop_batt_iterm(struct smb_charger *chg, return 0; } - rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, - (u8 *)&temp, 2); + rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, buf, 2); if (rc < 0) { smblib_err(chg, "Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n", @@ -1589,6 +1588,7 @@ int smblib_get_prop_batt_iterm(struct smb_charger *chg, return rc; } + temp = buf[1] | (buf[0] << 8); temp = sign_extend32(temp, 15); temp = DIV_ROUND_CLOSEST(temp * 10000, ADC_CHG_TERM_MASK); val->intval = temp; -- GitLab From 06183625a0aefbf769ded99f97ae38df92546de9 Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Wed, 13 Jun 2018 14:00:14 +0800 Subject: [PATCH 0672/1299] usb: gadget: f_rndis: Add 'wceis' flag to indicate 'Wireless' RNDIS The 'wceis' flag used to indicate the device as wireless controller. Set the default value is true as this is what we want in most of the cases. Change-Id: Idc03717526350421d94b9445333b36823a372aad Signed-off-by: Liangliang Lu --- drivers/usb/gadget/function/f_rndis.c | 28 +++++++++++ .../usb/gadget/function/u_ether_configfs.h | 46 +++++++++++++++++++ drivers/usb/gadget/function/u_rndis.h | 3 ++ 3 files changed, 77 insertions(+) diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c index 6b457fbf610a..c14b02aa1ade 100644 --- a/drivers/usb/gadget/function/f_rndis.c +++ b/drivers/usb/gadget/function/f_rndis.c @@ -752,6 +752,27 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) rndis_data_intf.bInterfaceNumber = status; rndis_union_desc.bSlaveInterface0 = status; + if (rndis_opts->wceis) { + /* "Wireless" RNDIS; auto-detected by Windows */ + rndis_iad_descriptor.bFunctionClass = + USB_CLASS_WIRELESS_CONTROLLER; + rndis_iad_descriptor.bFunctionSubClass = 0x01; + rndis_iad_descriptor.bFunctionProtocol = 0x03; + rndis_control_intf.bInterfaceClass = + USB_CLASS_WIRELESS_CONTROLLER; + rndis_control_intf.bInterfaceSubClass = 0x01; + rndis_control_intf.bInterfaceProtocol = 0x03; + } else { + rndis_iad_descriptor.bFunctionClass = USB_CLASS_COMM; + rndis_iad_descriptor.bFunctionSubClass = + USB_CDC_SUBCLASS_ETHERNET; + rndis_iad_descriptor.bFunctionProtocol = USB_CDC_PROTO_NONE; + rndis_control_intf.bInterfaceClass = USB_CLASS_COMM; + rndis_control_intf.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM; + rndis_control_intf.bInterfaceProtocol = + USB_CDC_ACM_PROTO_VENDOR; + } + status = -ENODEV; /* allocate instance-specific endpoints */ @@ -890,6 +911,9 @@ USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, subclass); /* f_rndis_opts_protocol */ USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, protocol); +/* f_rndis_opts_wceis */ +USB_ETHERNET_CONFIGFS_ITEM_ATTR_WCEIS(rndis); + static struct configfs_attribute *rndis_attrs[] = { &rndis_opts_attr_dev_addr, &rndis_opts_attr_host_addr, @@ -898,6 +922,7 @@ static struct configfs_attribute *rndis_attrs[] = { &rndis_opts_attr_class, &rndis_opts_attr_subclass, &rndis_opts_attr_protocol, + &rndis_opts_attr_wceis, NULL, }; @@ -962,6 +987,9 @@ static struct usb_function_instance *rndis_alloc_inst(void) } opts->rndis_interf_group = rndis_interf_group; + /* Enable "Wireless" RNDIS by default */ + opts->wceis = true; + return &opts->func_inst; } diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h index e4c3f84af4c3..cea4a0abeaae 100644 --- a/drivers/usb/gadget/function/u_ether_configfs.h +++ b/drivers/usb/gadget/function/u_ether_configfs.h @@ -188,4 +188,50 @@ out: \ \ CONFIGFS_ATTR(_f_##_opts_, _n_) +#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_WCEIS(_f_) \ + static ssize_t _f_##_opts_wceis_show(struct config_item *item, \ + char *page) \ + { \ + struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ + bool wceis; \ + \ + if (opts->bound == false) { \ + pr_err("Gadget function do not bind yet.\n"); \ + return -ENODEV; \ + } \ + \ + mutex_lock(&opts->lock); \ + wceis = opts->wceis; \ + mutex_unlock(&opts->lock); \ + return snprintf(page, PAGE_SIZE, "%d", wceis); \ + } \ + \ + static ssize_t _f_##_opts_wceis_store(struct config_item *item, \ + const char *page, size_t len)\ + { \ + struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ + bool wceis; \ + int ret; \ + \ + if (opts->bound == false) { \ + pr_err("Gadget function do not bind yet.\n"); \ + return -ENODEV; \ + } \ + \ + mutex_lock(&opts->lock); \ + \ + ret = kstrtobool(page, &wceis); \ + if (ret) \ + goto out; \ + \ + opts->wceis = wceis; \ + ret = len; \ +out: \ + mutex_unlock(&opts->lock); \ + \ + return ret; \ + } \ + \ + CONFIGFS_ATTR(_f_##_opts_, wceis) + #endif /* __U_ETHER_CONFIGFS_H */ diff --git a/drivers/usb/gadget/function/u_rndis.h b/drivers/usb/gadget/function/u_rndis.h index efdb7ac381d9..9a183914dd00 100644 --- a/drivers/usb/gadget/function/u_rndis.h +++ b/drivers/usb/gadget/function/u_rndis.h @@ -42,6 +42,9 @@ struct f_rndis_opts { */ struct mutex lock; int refcnt; + + /* "Wireless" RNDIS; auto-detected by Windows */ + bool wceis; }; void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net); -- GitLab From e1ba8be6c5f2b8e37871591e90537e851f418a64 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Tue, 14 Jul 2015 13:57:52 -0600 Subject: [PATCH 0673/1299] net: Copy ndisc_nodetype from original skb in skb_clone skb_clone does not copy all fields from original skb. Fields which are uninitialized may cause unexpected behavior when they are passed down to network stack. In case ndisc_nodetype is set to a random value for a router advertisement, kernel looks at this field and drops it assuming that this packet originates from a node and not a router. Fix this by copying the ndisc_nodetype from the original skb rather than relying on an uninitialized cloned skb. CRs-Fixed: 2233026 Change-Id: I9686e31808c94a3bbf309007f521c0e06bac2e96 Signed-off-by: Subash Abhinov Kasiviswanathan --- net/core/skbuff.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b73e7c87f926..db973bf72b76 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -870,6 +870,10 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) atomic_inc(&(skb_shinfo(skb)->dataref)); skb->cloned = 1; +#ifdef CONFIG_IPV6_NDISC_NODETYPE + C(ndisc_nodetype); +#endif + return n; #undef C } -- GitLab From 3279acc1490a51c812b010f81b9a3baeb55881af Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Thu, 31 May 2018 21:16:55 -0600 Subject: [PATCH 0674/1299] net: qualcomm: rmnet: Clone UDP and command packets This allows for more efficient processing of UDP and command packets in the network stack. TCP packets cannot be cloned since they need to be processed with GRO. Also reset the hash to prevent RPS from having an invalid input. CRs-Fixed: 2233026 Change-Id: If34fb8caa23c31a851c7b595adfec9af84707336 Signed-off-by: Subash Abhinov Kasiviswanathan --- .../ethernet/qualcomm/rmnet/rmnet_map_data.c | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c index 623ddba14945..9cee9597e45e 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c @@ -23,6 +23,7 @@ #define RMNET_MAP_DEAGGR_SPACING 64 #define RMNET_MAP_DEAGGR_HEADROOM (RMNET_MAP_DEAGGR_SPACING / 2) +#define RMNET_MAP_PKT_COPY_THRESHOLD 64 static __sum16 *rmnet_map_get_csum_field(unsigned char protocol, const void *txporthdr) @@ -307,11 +308,34 @@ struct rmnet_map_header *rmnet_map_add_map_header(struct sk_buff *skb, } /* Deaggregates a single packet - * A whole new buffer is allocated for each portion of an aggregated frame. + * A whole new buffer is allocated for each portion of an aggregated frame + * except when a UDP or command packet is received. * Caller should keep calling deaggregate() on the source skb until 0 is * returned, indicating that there are no more packets to deaggregate. Caller * is responsible for freeing the original skb. */ +static int rmnet_validate_clone(struct sk_buff *skb) +{ + if (RMNET_MAP_GET_CD_BIT(skb)) + return 0; + + if (skb->len < RMNET_MAP_PKT_COPY_THRESHOLD) + return 1; + + switch (skb->data[4] & 0xF0) { + case 0x40: + if (((struct iphdr *)&skb->data[4])->protocol == IPPROTO_UDP) + return 0; + break; + case 0x60: + if (((struct ipv6hdr *)&skb->data[4])->nexthdr == IPPROTO_UDP) + return 0; + /* Fall through */ + } + + return 1; +} + struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb, struct rmnet_port *port) { @@ -335,13 +359,27 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb, if (ntohs(maph->pkt_len) == 0) return NULL; - skbn = alloc_skb(packet_len + RMNET_MAP_DEAGGR_SPACING, GFP_ATOMIC); - if (!skbn) - return NULL; - skb_reserve(skbn, RMNET_MAP_DEAGGR_HEADROOM); - skb_put(skbn, packet_len); - memcpy(skbn->data, skb->data, packet_len); + if (rmnet_validate_clone(skb)) { + skbn = alloc_skb(packet_len + RMNET_MAP_DEAGGR_SPACING, + GFP_ATOMIC); + if (!skbn) + return NULL; + + skb_reserve(skbn, RMNET_MAP_DEAGGR_HEADROOM); + skb_put(skbn, packet_len); + memcpy(skbn->data, skb->data, packet_len); + + } else { + skbn = skb_clone(skb, GFP_ATOMIC); + if (!skbn) + return NULL; + + skb_trim(skbn, packet_len); + skbn->truesize = SKB_TRUESIZE(packet_len); + __skb_set_hash(skbn, 0, 0, 0); + } + skb_pull(skb, packet_len); return skbn; -- GitLab From f5438882fb2ccb64b55e169df1c5e76f5b2b7e87 Mon Sep 17 00:00:00 2001 From: Runmin Wang Date: Fri, 15 Jun 2018 16:49:08 -0700 Subject: [PATCH 0675/1299] sched: fair: mark parent domain overutilized if !SD_LOAD_BALANCE If sd does not have SD_LOAD_BALANCE flag set, load balancer code will not be run. As a result, the overutilized flag could be set by the tick path but never be cleared from rebalance_domain. Instead of setting local sd as overutilized, propagate it to parent sd. Change-Id: Ib08b0ea0da568e6298fdaa895717c0a4a2134f4c Signed-off-by: Runmin Wang --- kernel/sched/fair.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 929b5fa2adbf..d40ddeddf8e3 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5003,9 +5003,10 @@ static inline void update_overutilized_status(struct rq *rq) rcu_read_lock(); sd = rcu_dereference(rq->sd); - if (sd && !sd_overutilized(sd) && - cpu_overutilized(rq->cpu)) + if (sd && (sd->flags & SD_LOAD_BALANCE)) set_sd_overutilized(sd); + else if (sd && sd->parent) + set_sd_overutilized(sd->parent); rcu_read_unlock(); } #else -- GitLab From 0d138f0fb5c3a887e2b2652b4e29d78dd6ae23c8 Mon Sep 17 00:00:00 2001 From: Chris Redpath Date: Fri, 1 Jun 2018 20:34:10 +0100 Subject: [PATCH 0676/1299] ANDROID: sched/fair: Attempt to improve throughput for asym cap systems In some systems the capacity and group weights line up to defeat all the small imbalance correction conditions in fix_small_imbalance, which can cause bad task placement. Add a new condition if the existing code can't see anything to fix: If we have asymmetric capacity, and there are more tasks than CPUs in the busiest group *and* there are less tasks than CPUs in the local group then we try to pull something. There could be transient small tasks which prevent this from working, but on the whole it is beneficial for those systems with inconvenient capacity/cluster size relationships. Change-Id: Icf81cde215c082a61f816534b7990ccb70aee409 Signed-off-by: Chris Redpath Git-commit: 92f1c4fa958a0f01dd35408c08b489f046e8b68c Git-repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Runmin Wang --- kernel/sched/fair.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index d40ddeddf8e3..7f909049b487 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -9914,7 +9914,22 @@ void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds) capa_move /= SCHED_CAPACITY_SCALE; /* Move if we gain throughput */ - if (capa_move > capa_now) + if (capa_move > capa_now) { + env->imbalance = busiest->load_per_task; + return; + } + + /* We can't see throughput improvement with the load-based + * method, but it is possible depending upon group size and + * capacity range that there might still be an underutilized + * cpu available in an asymmetric capacity system. Do one last + * check just in case. + */ + if (env->sd->flags & SD_ASYM_CPUCAPACITY && + busiest->group_type == group_overloaded && + busiest->sum_nr_running > busiest->group_weight && + local->sum_nr_running < local->group_weight && + local->group_capacity < busiest->group_capacity) env->imbalance = busiest->load_per_task; } -- GitLab From 9707e84cef484c31ae8fe3980c75c255b0c09620 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Wed, 6 Jun 2018 22:00:58 +0530 Subject: [PATCH 0677/1299] msm: kgsl: Fix gmu_dev_ops null pointer deference Add a NULL check for gmu_dev_ops to fix NULL pointer dereference on non gmu devices. Change-Id: I01cad027557014e45727d88aba96a3d3d9367b0c Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno.c | 26 +++++++++++++------------- drivers/gpu/msm/adreno.h | 4 ++-- drivers/gpu/msm/adreno_a6xx.c | 7 +++++-- drivers/gpu/msm/adreno_a6xx_preempt.c | 4 ++-- drivers/gpu/msm/adreno_a6xx_snapshot.c | 2 +- drivers/gpu/msm/adreno_perfcounter.c | 4 ++-- drivers/gpu/msm/adreno_snapshot.c | 2 +- drivers/gpu/msm/kgsl_gmu_core.h | 4 ++++ 8 files changed, 30 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index a9775a341b7a..b3cffde3d492 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1832,13 +1832,13 @@ static int _adreno_start(struct adreno_device *adreno_dev) } /* Send OOB request to turn on the GX */ - if (gmu_dev_ops->oob_set) { + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_set)) { status = gmu_dev_ops->oob_set(adreno_dev, oob_gpu); if (status) goto error_mmu_off; } - if (gmu_dev_ops->hfi_start_msg) { + if (GMU_DEV_OP_VALID(gmu_dev_ops, hfi_start_msg)) { status = gmu_dev_ops->hfi_start_msg(adreno_dev); if (status) goto error_mmu_off; @@ -2028,7 +2028,7 @@ static int _adreno_start(struct adreno_device *adreno_dev) pmqos_active_vote); /* Send OOB request to allow IFPC */ - if (gmu_dev_ops->oob_clear) { + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_clear)) { gmu_dev_ops->oob_clear(adreno_dev, oob_gpu); /* If we made it this far, the BOOT OOB was sent to the GMU */ @@ -2039,7 +2039,7 @@ static int _adreno_start(struct adreno_device *adreno_dev) return 0; error_oob_clear: - if (gmu_dev_ops->oob_clear) + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_clear)) gmu_dev_ops->oob_clear(adreno_dev, oob_gpu); error_mmu_off: @@ -2092,9 +2092,9 @@ static int adreno_stop(struct kgsl_device *device) return 0; /* Turn the power on one last time before stopping */ - if (gmu_dev_ops->oob_set) { + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_set)) { error = gmu_dev_ops->oob_set(adreno_dev, oob_gpu); - if (error) { + if (error && GMU_DEV_OP_VALID(gmu_dev_ops, oob_clear)) { gmu_dev_ops->oob_clear(adreno_dev, oob_gpu); if (gmu_core_regulator_isenabled(device)) { /* GPU is on. Try recovery */ @@ -2128,7 +2128,7 @@ static int adreno_stop(struct kgsl_device *device) /* Save physical performance counter values before GPU power down*/ adreno_perfcounter_save(adreno_dev); - if (gmu_dev_ops->oob_clear) + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_clear)) gmu_dev_ops->oob_clear(adreno_dev, oob_gpu); /* @@ -2137,7 +2137,7 @@ static int adreno_stop(struct kgsl_device *device) * GMU to return to the lowest idle level. This is * because some idle level transitions require VBIF and MMU. */ - if (!error && gmu_dev_ops->wait_for_lowest_idle && + if (!error && GMU_DEV_OP_VALID(gmu_dev_ops, wait_for_lowest_idle) && gmu_dev_ops->wait_for_lowest_idle(adreno_dev)) { gmu_core_setbit(device, GMU_FAULT); @@ -2789,7 +2789,7 @@ int adreno_soft_reset(struct kgsl_device *device) struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device); int ret; - if (gmu_dev_ops->oob_set) { + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_set)) { ret = gmu_dev_ops->oob_set(adreno_dev, oob_gpu); if (ret) return ret; @@ -2813,7 +2813,7 @@ int adreno_soft_reset(struct kgsl_device *device) else ret = _soft_reset(adreno_dev); if (ret) { - if (gmu_dev_ops->oob_clear) + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_clear)) gmu_dev_ops->oob_clear(adreno_dev, oob_gpu); return ret; } @@ -2867,7 +2867,7 @@ int adreno_soft_reset(struct kgsl_device *device) /* Restore physical performance counter values after soft reset */ adreno_perfcounter_restore(adreno_dev); - if (gmu_dev_ops->oob_clear) + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_clear)) gmu_dev_ops->oob_clear(adreno_dev, oob_gpu); return ret; @@ -3215,7 +3215,7 @@ unsigned int adreno_gmu_ifpc_show(struct adreno_device *adreno_dev) struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS( KGSL_DEVICE(adreno_dev)); - if (gmu_dev_ops->ifpc_show) + if (GMU_DEV_OP_VALID(gmu_dev_ops, ifpc_show)) return gmu_dev_ops->ifpc_show(adreno_dev); return 0; @@ -3226,7 +3226,7 @@ int adreno_gmu_ifpc_store(struct adreno_device *adreno_dev, unsigned int val) struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS( KGSL_DEVICE(adreno_dev)); - if (gmu_dev_ops->ifpc_store) + if (GMU_DEV_OP_VALID(gmu_dev_ops, ifpc_store)) return gmu_dev_ops->ifpc_store(adreno_dev, val); return -EINVAL; diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index ddda2bc1453f..73d3a68a1a73 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -1869,7 +1869,7 @@ static inline int adreno_perfcntr_active_oob_get( if (ret) return ret; - if (gmu_dev_ops->oob_set) { + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_set)) { ret = gmu_dev_ops->oob_set(adreno_dev, oob_perfcntr); if (ret) kgsl_active_count_put(KGSL_DEVICE(adreno_dev)); @@ -1884,7 +1884,7 @@ static inline void adreno_perfcntr_active_oob_put( struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS( KGSL_DEVICE(adreno_dev)); - if (gmu_dev_ops->oob_clear) + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_clear)) gmu_dev_ops->oob_clear(adreno_dev, oob_perfcntr); kgsl_active_count_put(KGSL_DEVICE(adreno_dev)); diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 49174774c54f..170e7d3c4206 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -917,7 +917,7 @@ static void a6xx_start(struct adreno_device *adreno_dev) * 3. HFI * At this point, we are guaranteed all. */ - if (gmu_dev_ops->enable_lm) + if (GMU_DEV_OP_VALID(gmu_dev_ops, enable_lm)) gmu_dev_ops->enable_lm(device); } @@ -1336,7 +1336,10 @@ static int a6xx_microcode_read(struct adreno_device *adreno_dev) return ret; } - return gmu_dev_ops->load_firmware(device); + if (GMU_DEV_OP_VALID(gmu_dev_ops, load_firmware)) + return gmu_dev_ops->load_firmware(device); + + return 0; } static int a6xx_soft_reset(struct adreno_device *adreno_dev) diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c index 0c308edea824..d705ae9000d6 100644 --- a/drivers/gpu/msm/adreno_a6xx_preempt.c +++ b/drivers/gpu/msm/adreno_a6xx_preempt.c @@ -46,7 +46,7 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer) if (in_interrupt() == 0) { int status; - if (gmu_dev_ops->oob_set) { + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_set)) { status = gmu_dev_ops->oob_set(adreno_dev, oob_preempt); if (status) return; @@ -75,7 +75,7 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer) spin_unlock_irqrestore(&rb->preempt_lock, flags); if (in_interrupt() == 0) { - if (gmu_dev_ops->oob_clear) + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_clear)) gmu_dev_ops->oob_clear(adreno_dev, oob_preempt); } } diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c index 4b26b7d50b15..16b478a89fc0 100644 --- a/drivers/gpu/msm/adreno_a6xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c @@ -1498,7 +1498,7 @@ void a6xx_snapshot(struct adreno_device *adreno_dev, unsigned int i; /* GMU TCM data dumped through AHB */ - if (gmu_dev_ops->snapshot) + if (GMU_DEV_OP_VALID(gmu_dev_ops, snapshot)) gmu_dev_ops->snapshot(adreno_dev, snapshot); sptprac_on = gpudev->sptprac_is_on(adreno_dev); diff --git a/drivers/gpu/msm/adreno_perfcounter.c b/drivers/gpu/msm/adreno_perfcounter.c index 066423c1265c..891fcb3a4b04 100644 --- a/drivers/gpu/msm/adreno_perfcounter.c +++ b/drivers/gpu/msm/adreno_perfcounter.c @@ -181,7 +181,7 @@ inline void adreno_perfcounter_save(struct adreno_device *adreno_dev) if (counters == NULL) return; - if (gmu_dev_ops->oob_set) + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_set)) ret = gmu_dev_ops->oob_set(adreno_dev, oob_perfcntr); /* if oob_set timeout, clear the mask and return */ @@ -209,7 +209,7 @@ inline void adreno_perfcounter_save(struct adreno_device *adreno_dev) } done: - if (gmu_dev_ops->oob_clear) + if (GMU_DEV_OP_VALID(gmu_dev_ops, oob_clear)) gmu_dev_ops->oob_clear(adreno_dev, oob_perfcntr); } diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c index 6cd503e8c0bd..9df89e38cb11 100644 --- a/drivers/gpu/msm/adreno_snapshot.c +++ b/drivers/gpu/msm/adreno_snapshot.c @@ -960,7 +960,7 @@ void adreno_snapshot_gmu(struct kgsl_device *device, struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Add GMU specific sections */ - if (gmu_dev_ops && gmu_dev_ops->snapshot) + if (GMU_DEV_OP_VALID(gmu_dev_ops, snapshot)) gmu_dev_ops->snapshot(adreno_dev, snapshot); if (gpudev->snapshot_debugbus) diff --git a/drivers/gpu/msm/kgsl_gmu_core.h b/drivers/gpu/msm/kgsl_gmu_core.h index b3ff2130d807..d9bfacb8ef9b 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.h +++ b/drivers/gpu/msm/kgsl_gmu_core.h @@ -17,6 +17,10 @@ #define GMU_DEVICE_OPS(_a) ((_a)->gmu_core.dev_ops) #define GMU_CORE_OPS(_a) ((_a)->gmu_core.core_ops) +#define GMU_DEV_OP_VALID(_devops, _field) \ + (((_devops) != NULL) && \ + ((_devops)->_field != NULL)) + #define NUM_BW_LEVELS 100 #define MAX_GX_LEVELS 16 #define MAX_CX_LEVELS 4 -- GitLab From 5b65da228525d381ac6ffd699bcc6ed4aab84579 Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Thu, 21 Jun 2018 10:37:35 +0530 Subject: [PATCH 0678/1299] clk: smd-rpm: Add support for additional clocks for QCS405 Add support for required rf_clk3 clocks in RPM clock driver. Also, add the clock references for the same. Change-Id: I1f789d059aca8614b9cd7eb71c5a376d53991143 Signed-off-by: Shefali Jain --- drivers/clk/qcom/clk-smd-rpm.c | 11 +++-- include/dt-bindings/clock/qcom,rpmcc.h | 58 ++++++++++++++------------ 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index cfac51124578..729af0ebfa20 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -610,9 +610,10 @@ DEFINE_CLK_SMD_RPM(qcs405, bimc_gpu_clk, bimc_gpu_a_clk, /* SMD_XO_BUFFER */ DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs405, ln_bb_clk, ln_bb_clk_a, 8); DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs405, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs405, div_clk1, div_clk1_a, 0xb); +DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs405, rf_clk3, rf_clk3_a, 6); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs405, ln_bb_clk_pin, ln_bb_clk_a_pin, 8); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs405, rf_clk1_pin, rf_clk1_a_pin, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs405, rf_clk3_pin, rf_clk3_a_pin, 6); /* Voter clocks */ static DEFINE_CLK_VOTER(pnoc_msmbus_clk, pnoc_clk, LONG_MAX); @@ -663,12 +664,14 @@ static struct clk_hw *qcs405_clks[] = { [RPM_SMD_RF_CLK1_A] = &qcs405_rf_clk1_a.hw, [RPM_SMD_RF_CLK1_PIN] = &qcs405_rf_clk1_pin.hw, [RPM_SMD_RF_CLK1_A_PIN] = &qcs405_rf_clk1_a_pin.hw, + [RPM_SMD_RF_CLK3] = &qcs405_rf_clk3.hw, + [RPM_SMD_RF_CLK3_A] = &qcs405_rf_clk3_a.hw, + [RPM_SMD_RF_CLK3_PIN] = &qcs405_rf_clk3_pin.hw, + [RPM_SMD_RF_CLK3_A_PIN] = &qcs405_rf_clk3_a_pin.hw, [RPM_SMD_LN_BB_CLK] = &qcs405_ln_bb_clk.hw, [RPM_SMD_LN_BB_CLK_A] = &qcs405_ln_bb_clk_a.hw, [RPM_SMD_LN_BB_CLK_PIN] = &qcs405_ln_bb_clk_pin.hw, [RPM_SMD_LN_BB_CLK_A_PIN] = &qcs405_ln_bb_clk_a_pin.hw, - [RPM_SMD_DIV_CLK1] = &qcs405_div_clk1.hw, - [RPM_SMD_DIV_A_CLK1] = &qcs405_div_clk1_a.hw, [RPM_SMD_PNOC_CLK] = &qcs405_pnoc_clk.hw, [RPM_SMD_PNOC_A_CLK] = &qcs405_pnoc_a_clk.hw, [RPM_SMD_CE1_CLK] = &qcs405_ce1_clk.hw, @@ -708,7 +711,7 @@ static struct clk_hw *qcs405_clks[] = { static const struct rpm_smd_clk_desc rpm_clk_qcs405 = { .clks = qcs405_clks, - .num_rpm_clks = RPM_SMD_BIMC_GPU_A_CLK, + .num_rpm_clks = RPM_SMD_RF_CLK3_A_PIN, .num_clks = ARRAY_SIZE(qcs405_clks), }; diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h index 33891f2b7153..a0876ac455d8 100644 --- a/include/dt-bindings/clock/qcom,rpmcc.h +++ b/include/dt-bindings/clock/qcom,rpmcc.h @@ -111,32 +111,36 @@ #define RPM_SMD_LN_BB_CLK_A 71 #define RPM_SMD_LN_BB_CLK_PIN 72 #define RPM_SMD_LN_BB_CLK_A_PIN 73 -#define PNOC_MSMBUS_CLK 74 -#define PNOC_MSMBUS_A_CLK 75 -#define PNOC_KEEPALIVE_A_CLK 76 -#define SNOC_MSMBUS_CLK 77 -#define SNOC_MSMBUS_A_CLK 78 -#define BIMC_MSMBUS_CLK 79 -#define BIMC_MSMBUS_A_CLK 80 -#define PNOC_USB_CLK 81 -#define PNOC_USB_A_CLK 82 -#define SNOC_USB_CLK 83 -#define SNOC_USB_A_CLK 84 -#define BIMC_USB_CLK 85 -#define BIMC_USB_A_CLK 86 -#define SNOC_WCNSS_A_CLK 87 -#define BIMC_WCNSS_A_CLK 88 -#define MCD_CE1_CLK 89 -#define QCEDEV_CE1_CLK 90 -#define QCRYPTO_CE1_CLK 91 -#define QSEECOM_CE1_CLK 92 -#define SCM_CE1_CLK 93 -#define CXO_SMD_OTG_CLK 94 -#define CXO_SMD_LPM_CLK 95 -#define CXO_SMD_PIL_PRONTO_CLK 96 -#define CXO_SMD_PIL_MSS_CLK 97 -#define CXO_SMD_WLAN_CLK 98 -#define CXO_SMD_PIL_LPASS_CLK 99 -#define CXO_SMD_PIL_CDSP_CLK 100 +#define RPM_SMD_RF_CLK3 74 +#define RPM_SMD_RF_CLK3_A 75 +#define RPM_SMD_RF_CLK3_PIN 76 +#define RPM_SMD_RF_CLK3_A_PIN 77 +#define PNOC_MSMBUS_CLK 78 +#define PNOC_MSMBUS_A_CLK 79 +#define PNOC_KEEPALIVE_A_CLK 80 +#define SNOC_MSMBUS_CLK 81 +#define SNOC_MSMBUS_A_CLK 82 +#define BIMC_MSMBUS_CLK 83 +#define BIMC_MSMBUS_A_CLK 84 +#define PNOC_USB_CLK 85 +#define PNOC_USB_A_CLK 86 +#define SNOC_USB_CLK 87 +#define SNOC_USB_A_CLK 88 +#define BIMC_USB_CLK 89 +#define BIMC_USB_A_CLK 90 +#define SNOC_WCNSS_A_CLK 91 +#define BIMC_WCNSS_A_CLK 92 +#define MCD_CE1_CLK 93 +#define QCEDEV_CE1_CLK 94 +#define QCRYPTO_CE1_CLK 95 +#define QSEECOM_CE1_CLK 96 +#define SCM_CE1_CLK 97 +#define CXO_SMD_OTG_CLK 98 +#define CXO_SMD_LPM_CLK 99 +#define CXO_SMD_PIL_PRONTO_CLK 100 +#define CXO_SMD_PIL_MSS_CLK 101 +#define CXO_SMD_WLAN_CLK 102 +#define CXO_SMD_PIL_LPASS_CLK 103 +#define CXO_SMD_PIL_CDSP_CLK 104 #endif -- GitLab From 1c462be3af8e3bbc8f69488144e0ac174eeb1d1b Mon Sep 17 00:00:00 2001 From: Yogesh Lal Date: Thu, 7 Jun 2018 11:44:53 +0530 Subject: [PATCH 0679/1299] lib: stackdepot: Add support to configure STACK_HASH_SIZE Use STACK_HASH_ORDER_SHIFT to configure STACK_HASH_SIZE. Aim is to have configurable value for STACK_HASH_SIZE, so depend on use case one can configure it. One example is of Page Owner, default value of STACK_HASH_SIZE lead stack depot to consume 8MB of static memory. Making it configurable and use lower value helps to enable features like CONFIG_PAGE_OWNER without any significant overhead. Change-Id: If6b64d4d4d42c763b00e2719fde5a25e94c10597 Signed-off-by: Yogesh Lal --- lib/Kconfig | 9 +++++++++ lib/stackdepot.c | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/Kconfig b/lib/Kconfig index b1445b22a6de..f4788fbae4d0 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -574,6 +574,15 @@ config STACKDEPOT bool select STACKTRACE +config STACK_HASH_ORDER_SHIFT + int "stack depot hash size (12 => 4KB, 20 => 1024KB)" + range 12 20 + default 20 + depends on STACKDEPOT + help + Select the hash size as a power of 2 for the stackdepot hash table. + Choose a lower value to reduce the memory impact. + config SBITMAP bool diff --git a/lib/stackdepot.c b/lib/stackdepot.c index f87d138e9672..da258c507675 100644 --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -146,8 +146,7 @@ static struct stack_record *depot_alloc_stack(unsigned long *entries, int size, return stack; } -#define STACK_HASH_ORDER 20 -#define STACK_HASH_SIZE (1L << STACK_HASH_ORDER) +#define STACK_HASH_SIZE (1L << CONFIG_STACK_HASH_ORDER_SHIFT) #define STACK_HASH_MASK (STACK_HASH_SIZE - 1) #define STACK_HASH_SEED 0x9747b28c -- GitLab From 2343f1d2fa7bcd762355682bb5077ec7a1935c83 Mon Sep 17 00:00:00 2001 From: Yogesh Lal Date: Wed, 20 Jun 2018 14:52:36 +0530 Subject: [PATCH 0680/1299] defconfig: Enable page_owner for sm8150 on perf config This patch enables CONFIG_PAGE_OWNER on perf config. The feature is not enabled by default and needs to be enabled via boot param "page_owner=on". Set STACK_HASH_ORDER_SHIFT to 12 to reduce stack depot hash size. Default value of STACK_HASH_ORDER_SHIFT=20 makes stack depot to consume 8MB of static memory. With STACK_HASH_ORDER_SHIFT=12 stack depot consume only 104KB. The time taken to read from /sys/kernel/debug/page_owner increased by around 60 secs with this patch on a 6 GB target, but we can live with it as it's a only debug feature. Change-Id: I772aa69865ee30c4834cfb2fa0d7feafd3853c0c Signed-off-by: Yogesh Lal --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 418e04724ed9..8d10b24d876e 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -598,6 +598,7 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO=y +CONFIG_PAGE_OWNER=y CONFIG_MAGIC_SYSRQ=y CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y @@ -639,3 +640,4 @@ CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_STACK_HASH_ORDER_SHIFT=12 -- GitLab From be98f0e39e00a010ea059810b6681b592b666eef Mon Sep 17 00:00:00 2001 From: Maria Yu Date: Wed, 13 Jun 2018 11:14:01 +0800 Subject: [PATCH 0681/1299] defconfig: sm8150: align with android config requirement Align with android-base.cfg which is android kernel config requirement for sm8150 defconfig and perf defconfig. Change-Id: Ic9f529456d661218d9fd9d0aed7caff7a47139cf Signed-off-by: Maria Yu --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 2 ++ arch/arm64/configs/vendor/sm8150_defconfig | 3 +++ 2 files changed, 5 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 418e04724ed9..5ec5cea54f78 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -1,5 +1,6 @@ CONFIG_LOCALVERSION="-perf" # CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_FHANDLE is not set CONFIG_AUDIT=y # CONFIG_AUDITSYSCALL is not set CONFIG_NO_HZ=y @@ -624,6 +625,7 @@ CONFIG_HARDENED_USERCOPY=y CONFIG_FORTIFY_SOURCE=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y +CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 729d35991e5b..95be2728bed8 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -1,4 +1,5 @@ # CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_FHANDLE is not set CONFIG_AUDIT=y # CONFIG_AUDITSYSCALL is not set CONFIG_NO_HZ=y @@ -318,6 +319,7 @@ CONFIG_INPUT_UINPUT=y # CONFIG_SERIO_SERPORT is not set # CONFIG_VT is not set # CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set CONFIG_SERIAL_MSM_GENI=y CONFIG_SERIAL_MSM_GENI_CONSOLE=y CONFIG_SERIAL_DEV_BUS=y @@ -705,6 +707,7 @@ CONFIG_HARDENED_USERCOPY_PAGESPAN=y CONFIG_FORTIFY_SOURCE=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y +CONFIG_CRYPTO_GCM=y CONFIG_CRYPTO_XCBC=y CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y -- GitLab From 52aa0c5edf991df0398b638884ab47129d1daf63 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Thu, 21 Jun 2018 11:29:17 +0300 Subject: [PATCH 0682/1299] wil6210: report amsdu support in BA resp only if it is supported Currently the driver sets the amsdu bit in BA response command if it was set in the BA request, regardless of the FW support of this feature. This can cause a case where we report amsdu enable when it is not supported if we negotiate with a device that supports it. Fix the above issue by adding a check if FW and driver supports amsdu. Change-Id: Ife9f1766494c92f55833c75270b5ea1b6775a2fe Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/rx_reorder.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index ce017e4bdd6e..ec158a412641 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -314,7 +314,10 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) * bits 6..15: buffer size */ u16 req_agg_wsize = WIL_GET_BITS(param_set, 6, 15); - bool agg_amsdu = !!(param_set & BIT(0)); + bool agg_amsdu = wil->use_enhanced_dma_hw && + use_rx_hw_reordering && + test_bit(WMI_FW_CAPABILITY_AMSDU, wil->fw_capabilities) && + wil->amsdu_en && (param_set & BIT(0)); int ba_policy = param_set & BIT(1); u16 status = WLAN_STATUS_SUCCESS; u16 ssn = seq_ctrl >> 4; -- GitLab From 6fd99b3e6347fba624ada5a2d3aa6d7e30a2d1f1 Mon Sep 17 00:00:00 2001 From: Ping Li Date: Tue, 1 May 2018 18:16:28 -0400 Subject: [PATCH 0683/1299] drm/msm/sde: Add check before applying color-prop properties After device goes into suspend state for a while, we notice that atomic commit calls are made, and they will cause all the dirty color-processing properties to be applied during suspend state. When device actually resumes, all the dirty color-processing won't be applied again and cause color-processing features not persist over suspend/resume. This change adds a check to make sure sde_crtc is enabled before applying color-processing properties to avoid the issue. Signed-off-by: Ping Li Signed-off-by: Xu Yang Change-Id: Ia001b5d4074da05d0ad266cb0876e5283b9bdda1 CRs-Fixed: 2234358 --- drivers/gpu/drm/msm/sde/sde_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index a5e293b5d7dd..29e5916d4049 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -3134,7 +3134,7 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, * apply color processing properties only if * smmu state is attached, */ - if (sde_kms_is_cp_operation_allowed(sde_kms)) + if (sde_kms_is_cp_operation_allowed(sde_kms) && sde_crtc->enabled) sde_cp_crtc_apply_properties(crtc); /* -- GitLab From c4fd66d298fcce1f63431c4fcb3f464211d7aaf2 Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Thu, 21 Jun 2018 10:31:28 +0530 Subject: [PATCH 0684/1299] clk: qcom: Update BCR address to spare register The USB phy BCR addresses have been updated as per HW design, update the address and the bit associated. Also add support for dcc clocks for DCC client to put across clock vote. Change-Id: Ia1cc615cfe8f1de12a537714463b728b3eaa08d2 Signed-off-by: Shefali Jain --- drivers/clk/qcom/debugcc-qcs405.c | 3 +++ drivers/clk/qcom/gcc-qcs405.c | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/debugcc-qcs405.c b/drivers/clk/qcom/debugcc-qcs405.c index b7b07f5e934e..1695bb3ace2f 100644 --- a/drivers/clk/qcom/debugcc-qcs405.c +++ b/drivers/clk/qcom/debugcc-qcs405.c @@ -110,6 +110,7 @@ static const char *const debug_mux_parent_names[] = { "gcc_usb_hs_inactivity_timers_clk", "gcc_usb_hs_phy_cfg_ahb_clk", "gcc_usb_hs_system_clk", + "gcc_dcc_clk", "apcs_mux_clk", }; @@ -278,6 +279,8 @@ static struct clk_debug_mux gcc_debug_mux = { 0x64, 0x1FF, 0, 0xF000, 12, 4, 0x74000, 0x74000, 0x74000 }, { "gcc_usb_hs_system_clk", 0x60, 4, GCC, 0x60, 0x1FF, 0, 0xF000, 12, 4, 0x74000, 0x74000, 0x74000 }, + { "gcc_dcc_clk", 0x1B9, 4, GCC, + 0x1B9, 0x1FF, 0, 0xF000, 12, 4, 0x74000, 0x74000, 0x74000 }, { "apcs_mux_clk", 0x16A, CPU_CC, 0x000, 0x3, 8, 0x0FF }, ), .hw.init = &(struct clk_init_data){ diff --git a/drivers/clk/qcom/gcc-qcs405.c b/drivers/clk/qcom/gcc-qcs405.c index 9ffc684ac62b..7d723d015171 100644 --- a/drivers/clk/qcom/gcc-qcs405.c +++ b/drivers/clk/qcom/gcc-qcs405.c @@ -1471,6 +1471,19 @@ static struct clk_branch gcc_blsp1_ahb_clk = { }, }; +static struct clk_branch gcc_dcc_clk = { + .halt_reg = 0x77004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x77004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_dcc_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_blsp1_qup0_i2c_apps_clk = { .halt_reg = 0x6028, .halt_check = BRANCH_HALT, @@ -2819,15 +2832,16 @@ static struct clk_regmap *gcc_qcs405_clocks[] = { [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr, [GCC_MDP_TBU_CLK] = &gcc_mdp_tbu_clk.clkr, [GCC_QDSS_DAP_CLK] = &gcc_qdss_dap_clk.clkr, + [GCC_DCC_CLK] = &gcc_dcc_clk.clkr, }; static const struct qcom_reset_map gcc_qcs405_resets[] = { [GCC_GENI_IR_BCR] = {0x0F000}, [GCC_USB_HS_BCR] = {0x41000}, - [GCC_USB2_HS_PHY_ONLY_BCR] = {0x41034}, + [GCC_USB2_HS_PHY_ONLY_BCR] = {0x0000C, 0}, [GCC_QUSB2_PHY_BCR] = {0x4103C}, [GCC_USB_HS_PHY_CFG_AHB_BCR] = {0x41038}, - [GCC_USB2A_PHY_BCR] = {0x41028}, + [GCC_USB2A_PHY_BCR] = {0x0000C, 1}, [GCC_USB3_PHY_BCR] = {0x39004}, [GCC_USB_30_BCR] = {0x39000}, [GCC_USB3PHY_PHY_BCR] = {0x39008}, -- GitLab From 596bbdf72636d0d53562ff78d837f8ce20302d90 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Thu, 21 Jun 2018 14:58:22 +0530 Subject: [PATCH 0685/1299] msm: kgsl: Fix gmu & hfi irq remove failures devm_free_irq() API fails for gmu and hfi irq due to the incorrect dev_id parameter. Fix this by passing the correct dev_id. Change-Id: Iac0ffc40932c8998c1f4a1ff9dfa4a1fadc9034a Signed-off-by: Akhil P Oommen --- drivers/gpu/msm/kgsl_gmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index adcb51a163c4..189a83be07e6 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -1725,13 +1725,13 @@ static void gmu_remove(struct kgsl_device *device) if (gmu->gmu_interrupt_num) { devm_free_irq(&gmu->pdev->dev, - gmu->gmu_interrupt_num, gmu); + gmu->gmu_interrupt_num, device); gmu->gmu_interrupt_num = 0; } if (hfi->hfi_interrupt_num) { devm_free_irq(&gmu->pdev->dev, - hfi->hfi_interrupt_num, hfi); + hfi->hfi_interrupt_num, device); hfi->hfi_interrupt_num = 0; } -- GitLab From d85b981bccea818a632e39fffdc4a7c16343f70f Mon Sep 17 00:00:00 2001 From: Sayali Lokhande Date: Thu, 21 Jun 2018 16:03:25 +0530 Subject: [PATCH 0686/1299] ARM: dts: msm: Add sdhc1 and sdhc2 regulator details for qcs405 Add regulator and pin control related configuration details for sdhc1 and sdhc2 in common dtsi file for qcs405 platform. Change-Id: Ia2bdff3aff77c446c7409e833bca0f3a6098de69 Signed-off-by: Sayali Lokhande --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 29 ++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 94a61ad6738a..6b7b7e8d9f5a 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -892,7 +892,19 @@ clock-names = "iface_clk", "core_clk"; qcom,nonremovable; - status = "disabled"; + + /* VDD external regulator is enabled/disabled by pms405_l6 */ + vdd-io-supply = <&pms405_l6>; + qcom,vdd-io-always-on; + qcom,vdd-io-lpm-sup; + qcom,vdd-io-voltage-level = <1704000 1800000>; + qcom,vdd-io-current-level = <0 325000>; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; + pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; + + status = "ok"; }; sdhc_2: sdhci@7844000 { @@ -907,17 +919,26 @@ qcom,large-address-bus; qcom,clk-rates = <400000 20000000 25000000 - 50000000 100000000 201500000>; + 50000000 100000000 200000000>; qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104"; - qcom,devfreq,freq-table = <50000000 201500000>; + qcom,devfreq,freq-table = <50000000 200000000>; clocks = <&clock_gcc GCC_SDCC2_AHB_CLK>, <&clock_gcc GCC_SDCC2_APPS_CLK>; clock-names = "iface_clk", "core_clk"; - status = "disabled"; + /* VDD is an external regulator eLDO5 */ + vdd-io-supply = <&pms405_l11>; + qcom,vdd-io-voltage-level = <2696000 3304000>; + qcom,vdd-io-current-level = <0 22000>; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>; + + status = "ok"; }; qnand_1: nand@4c0000 { -- GitLab From bdb2d261685462dd7603070c5185e0af41ddf89d Mon Sep 17 00:00:00 2001 From: Kaushal Kumar Date: Thu, 21 Jun 2018 17:04:54 +0530 Subject: [PATCH 0687/1299] defconfig: move qcs405 defconfigs to vendor/ subdirectory Move qcs405 defconfigs down one level to vendor/. Create symlinks as necessary for userspace components that are still hard-coded to the older location. Change-Id: Iffe729b76a2c401fc4bc899cfcaff91decde2211 Signed-off-by: Kaushal Kumar --- arch/arm/configs/qcs405_defconfig | 501 +------------------- arch/arm/configs/vendor/qcs405_defconfig | 500 ++++++++++++++++++++ arch/arm64/configs/qcs405_defconfig | 502 +-------------------- arch/arm64/configs/vendor/qcs405_defconfig | 501 ++++++++++++++++++++ 4 files changed, 1003 insertions(+), 1001 deletions(-) mode change 100644 => 120000 arch/arm/configs/qcs405_defconfig create mode 100644 arch/arm/configs/vendor/qcs405_defconfig mode change 100644 => 120000 arch/arm64/configs/qcs405_defconfig create mode 100644 arch/arm64/configs/vendor/qcs405_defconfig diff --git a/arch/arm/configs/qcs405_defconfig b/arch/arm/configs/qcs405_defconfig deleted file mode 100644 index fac263b18316..000000000000 --- a/arch/arm/configs/qcs405_defconfig +++ /dev/null @@ -1,500 +0,0 @@ -CONFIG_AUDIT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_SCHED_WALT=y -CONFIG_TASKSTATS=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_CGROUPS=y -CONFIG_CGROUP_SCHED=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_CGROUP_DEBUG=y -CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set -# CONFIG_PID_NS is not set -CONFIG_DEFAULT_USE_ENERGY_AWARE=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_KALLSYMS_ALL=y -CONFIG_EMBEDDED=y -CONFIG_PROFILING=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SIG=y -CONFIG_MODULE_SIG_FORCE=y -CONFIG_MODULE_SIG_SHA512=y -CONFIG_PARTITION_ADVANCED=y -CONFIG_ARCH_QCOM=y -CONFIG_ARCH_QCS405=y -# CONFIG_VDSO is not set -CONFIG_SMP=y -CONFIG_ARM_PSCI=y -CONFIG_PREEMPT=y -CONFIG_CLEANCACHE=y -CONFIG_CMA=y -CONFIG_CMA_DEBUGFS=y -CONFIG_ZSMALLOC=y -CONFIG_SECCOMP=y -CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -CONFIG_CPU_IDLE=y -CONFIG_VFP=y -CONFIG_NEON=y -CONFIG_KERNEL_MODE_NEON=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_PM_AUTOSLEEP=y -CONFIG_PM_WAKELOCKS=y -CONFIG_PM_WAKELOCKS_LIMIT=0 -# CONFIG_PM_WAKELOCKS_GC is not set -CONFIG_PM_DEBUG=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_XFRM_STATISTICS=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_XFRM_MODE_BEET is not set -CONFIG_INET_DIAG_DESTROY=y -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_ROUTE_INFO=y -CONFIG_IPV6_OPTIMISTIC_DAD=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_IPV6_MIP6=y -CONFIG_IPV6_MULTIPLE_TABLES=y -CONFIG_IPV6_SUBTREES=y -CONFIG_NETFILTER=y -CONFIG_NF_CONNTRACK=y -CONFIG_NF_CONNTRACK_SECMARK=y -CONFIG_NF_CONNTRACK_EVENTS=y -CONFIG_NF_CONNTRACK_AMANDA=y -CONFIG_NF_CONNTRACK_FTP=y -CONFIG_NF_CONNTRACK_H323=y -CONFIG_NF_CONNTRACK_IRC=y -CONFIG_NF_CONNTRACK_NETBIOS_NS=y -CONFIG_NF_CONNTRACK_PPTP=y -CONFIG_NF_CONNTRACK_SANE=y -CONFIG_NF_CONNTRACK_TFTP=y -CONFIG_NF_CT_NETLINK=y -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y -CONFIG_NETFILTER_XT_TARGET_CONNMARK=y -CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y -CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y -CONFIG_NETFILTER_XT_TARGET_LOG=y -CONFIG_NETFILTER_XT_TARGET_MARK=y -CONFIG_NETFILTER_XT_TARGET_NFLOG=y -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y -CONFIG_NETFILTER_XT_TARGET_NOTRACK=y -CONFIG_NETFILTER_XT_TARGET_TEE=y -CONFIG_NETFILTER_XT_TARGET_TPROXY=y -CONFIG_NETFILTER_XT_TARGET_TRACE=y -CONFIG_NETFILTER_XT_TARGET_SECMARK=y -CONFIG_NETFILTER_XT_TARGET_TCPMSS=y -CONFIG_NETFILTER_XT_MATCH_COMMENT=y -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y -CONFIG_NETFILTER_XT_MATCH_CONNMARK=y -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -CONFIG_NETFILTER_XT_MATCH_DSCP=y -CONFIG_NETFILTER_XT_MATCH_ESP=y -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y -CONFIG_NETFILTER_XT_MATCH_HELPER=y -CONFIG_NETFILTER_XT_MATCH_IPRANGE=y -CONFIG_NETFILTER_XT_MATCH_LENGTH=y -CONFIG_NETFILTER_XT_MATCH_LIMIT=y -CONFIG_NETFILTER_XT_MATCH_MAC=y -CONFIG_NETFILTER_XT_MATCH_MARK=y -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y -CONFIG_NETFILTER_XT_MATCH_POLICY=y -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y -CONFIG_NETFILTER_XT_MATCH_QUOTA=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -CONFIG_NETFILTER_XT_MATCH_STATE=y -CONFIG_NETFILTER_XT_MATCH_STATISTIC=y -CONFIG_NETFILTER_XT_MATCH_STRING=y -CONFIG_NETFILTER_XT_MATCH_TIME=y -CONFIG_NETFILTER_XT_MATCH_U32=y -CONFIG_NF_CONNTRACK_IPV4=y -CONFIG_IP_NF_IPTABLES=y -CONFIG_IP_NF_MATCH_AH=y -CONFIG_IP_NF_MATCH_ECN=y -CONFIG_IP_NF_MATCH_RPFILTER=y -CONFIG_IP_NF_MATCH_TTL=y -CONFIG_IP_NF_FILTER=y -CONFIG_IP_NF_TARGET_REJECT=y -CONFIG_IP_NF_NAT=y -CONFIG_IP_NF_TARGET_MASQUERADE=y -CONFIG_IP_NF_TARGET_NETMAP=y -CONFIG_IP_NF_TARGET_REDIRECT=y -CONFIG_IP_NF_MANGLE=y -CONFIG_IP_NF_RAW=y -CONFIG_IP_NF_SECURITY=y -CONFIG_IP_NF_ARPTABLES=y -CONFIG_IP_NF_ARPFILTER=y -CONFIG_IP_NF_ARP_MANGLE=y -CONFIG_NF_CONNTRACK_IPV6=y -CONFIG_IP6_NF_IPTABLES=y -CONFIG_IP6_NF_MATCH_RPFILTER=y -CONFIG_IP6_NF_FILTER=y -CONFIG_IP6_NF_TARGET_REJECT=y -CONFIG_IP6_NF_MANGLE=y -CONFIG_IP6_NF_RAW=y -CONFIG_BRIDGE_NF_EBTABLES=y -CONFIG_BRIDGE_EBT_BROUTE=y -CONFIG_L2TP=y -CONFIG_L2TP_DEBUGFS=y -CONFIG_L2TP_V3=y -CONFIG_L2TP_IP=y -CONFIG_L2TP_ETH=y -CONFIG_BRIDGE=y -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_HTB=y -CONFIG_NET_SCH_PRIO=y -CONFIG_NET_CLS_FW=y -CONFIG_NET_CLS_U32=y -CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_FLOW=y -CONFIG_NET_EMATCH=y -CONFIG_NET_EMATCH_CMP=y -CONFIG_NET_EMATCH_NBYTE=y -CONFIG_NET_EMATCH_U32=y -CONFIG_NET_EMATCH_META=y -CONFIG_NET_EMATCH_TEXT=y -CONFIG_NET_CLS_ACT=y -CONFIG_QRTR=y -CONFIG_QRTR_SMD=y -CONFIG_RMNET_DATA=y -CONFIG_RMNET_DATA_FC=y -CONFIG_RMNET_DATA_DEBUG_PKT=y -CONFIG_BT=y -CONFIG_BT_RFCOMM=y -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=y -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -CONFIG_BT_HIDP=y -CONFIG_CFG80211=y -CONFIG_CFG80211_INTERNAL_REGDB=y -CONFIG_RFKILL=y -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y -CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y -CONFIG_DMA_CMA=y -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_MSM_QPIC_NAND=y -CONFIG_MTD_NAND=y -CONFIG_MTD_UBI=y -CONFIG_ZRAM=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_UID_SYS_STATS=y -CONFIG_QPNP_MISC=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_SG=y -CONFIG_CHR_DEV_SCH=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_UFSHCD=y -CONFIG_SCSI_UFSHCD_PLATFORM=y -CONFIG_SCSI_UFS_QCOM=y -CONFIG_MD=y -CONFIG_BLK_DEV_DM=y -CONFIG_DM_CRYPT=y -CONFIG_DM_VERITY=y -CONFIG_DM_VERITY_FEC=y -CONFIG_NETDEVICES=y -CONFIG_DUMMY=y -CONFIG_TUN=y -CONFIG_KS8851=y -CONFIG_PPP=y -CONFIG_PPP_BSDCOMP=y -CONFIG_PPP_DEFLATE=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=y -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOE=y -CONFIG_PPPOL2TP=y -CONFIG_PPPOLAC=y -CONFIG_PPPOPNS=y -CONFIG_PPP_ASYNC=y -CONFIG_PPP_SYNC_TTY=y -CONFIG_USB_USBNET=y -CONFIG_USB_NET_SMSC75XX=y -CONFIG_WCNSS_MEM_PRE_ALLOC=y -CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_EVBUG=m -CONFIG_INPUT_KEYRESET=y -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_JOYSTICK=y -CONFIG_JOYSTICK_XPAD=y -CONFIG_INPUT_TABLET=y -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ATMEL_MXT=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_HBTP_INPUT=y -CONFIG_INPUT_QPNP_POWER_ON=y -CONFIG_INPUT_KEYCHORD=y -CONFIG_INPUT_UINPUT=y -CONFIG_INPUT_GPIO=y -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVMEM is not set -CONFIG_SERIAL_MSM=y -CONFIG_SERIAL_MSM_CONSOLE=y -CONFIG_HW_RANDOM=y -CONFIG_MSM_ADSPRPC=y -CONFIG_I2C_CHARDEV=y -CONFIG_SPI=y -CONFIG_SPI_DEBUG=y -CONFIG_SPI_SPIDEV=y -CONFIG_SPMI=y -CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y -CONFIG_PINCTRL_QCS405=y -CONFIG_PINCTRL_QCOM_SPMI_PMIC=y -CONFIG_GPIOLIB=y -CONFIG_POWER_SUPPLY=y -CONFIG_SMB1351_USB_CHARGER=y -CONFIG_THERMAL=y -CONFIG_THERMAL_GOV_USER_SPACE=y -CONFIG_THERMAL_GOV_LOW_LIMITS=y -CONFIG_CPU_THERMAL=y -CONFIG_DEVFREQ_THERMAL=y -CONFIG_QCOM_SPMI_TEMP_ALARM=y -CONFIG_THERMAL_TSENS=y -CONFIG_QTI_VIRTUAL_SENSOR=y -CONFIG_QTI_QMI_COOLING_DEVICE=y -CONFIG_REGULATOR_COOLING_DEVICE=y -CONFIG_MFD_SPMI_PMIC=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_FAN53555=y -CONFIG_REGULATOR_CPR=y -CONFIG_REGULATOR_MEM_ACC=y -CONFIG_REGULATOR_RPM_SMD=y -CONFIG_REGULATOR_SPM=y -CONFIG_REGULATOR_STUB=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_MEDIA_RADIO_SUPPORT=y -CONFIG_MEDIA_CONTROLLER=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_SOC_CAMERA=y -CONFIG_SOC_CAMERA_PLATFORM=y -CONFIG_FB=y -CONFIG_FB_MSM=y -CONFIG_FB_MSM_MDSS=y -CONFIG_FB_MSM_MDSS_WRITEBACK=y -CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y -CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_USB_AUDIO=y -CONFIG_SND_SOC=y -CONFIG_HIDRAW=y -CONFIG_UHID=y -CONFIG_HID_APPLE=y -CONFIG_HID_ELECOM=y -CONFIG_HID_MAGICMOUSE=y -CONFIG_HID_MICROSOFT=y -CONFIG_HID_MULTITOUCH=y -CONFIG_USB_HIDDEV=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_MON=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_ACM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_USBAT=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_STORAGE_ALAUDA=y -CONFIG_USB_STORAGE_KARMA=y -CONFIG_USB_STORAGE_CYPRESS_ATACB=y -CONFIG_USB_DWC3=y -CONFIG_USB_DWC3_MSM=y -CONFIG_USB_SERIAL=y -CONFIG_USB_EHSET_TEST_FIXTURE=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_MSM_SNPS_FEMTO_PHY=y -CONFIG_USB_MSM_SSPHY=y -CONFIG_USB_QCOM_EMU_PHY=y -CONFIG_DUAL_ROLE_USB_INTF=y -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_DEBUG_FILES=y -CONFIG_USB_GADGET_DEBUG_FS=y -CONFIG_USB_GADGET_VBUS_DRAW=900 -CONFIG_USB_CONFIGFS=y -CONFIG_USB_CONFIGFS_F_FS=y -CONFIG_USB_CONFIGFS_F_DIAG=y -CONFIG_MMC=y -CONFIG_MMC_PERF_PROFILING=y -CONFIG_MMC_BLOCK_MINORS=32 -CONFIG_MMC_BLOCK_DEFERRED_RESUME=y -CONFIG_MMC_TEST=m -CONFIG_MMC_RING_BUFFER=y -CONFIG_MMC_PARANOID_SD_INIT=y -CONFIG_MMC_CLKGATE=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_MSM=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_QPNP=y -CONFIG_DMADEVICES=y -CONFIG_UIO=y -CONFIG_STAGING=y -CONFIG_ASHMEM=y -CONFIG_ION=y -CONFIG_QPNP_REVID=y -CONFIG_SPS=y -CONFIG_SPS_SUPPORT_NDP_BAM=y -CONFIG_QCOM_MDSS_PLL=y -CONFIG_COMMON_CLK_QCOM=y -CONFIG_QCOM_CLK_SMD_RPM=y -CONFIG_SPMI_PMIC_CLKDIV=y -CONFIG_MDM_GCC_QCS405=y -CONFIG_MDM_DEBUGCC_QCS405=y -CONFIG_CLOCK_CPU_QCS405=y -CONFIG_HWSPINLOCK=y -CONFIG_HWSPINLOCK_QCOM=y -CONFIG_MAILBOX=y -CONFIG_QCOM_APCS_IPC=y -CONFIG_ARM_SMMU=y -CONFIG_QCOM_LAZY_MAPPING=y -CONFIG_IOMMU_DEBUG=y -CONFIG_IOMMU_DEBUG_TRACKING=y -CONFIG_IOMMU_TESTS=y -CONFIG_QCOM_IOMMU=y -CONFIG_RPMSG_CHAR=y -CONFIG_RPMSG_QCOM_GLINK_RPM=y -CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_RPMSG_QCOM_SMD=y -CONFIG_QCOM_QMI_HELPERS=y -CONFIG_QCOM_SMEM=y -CONFIG_QCOM_SMD_RPM=y -CONFIG_MSM_SPM=y -CONFIG_MSM_L2_SPM=y -CONFIG_QCOM_SCM=y -CONFIG_QCOM_SMP2P=y -CONFIG_MSM_SERVICE_LOCATOR=y -CONFIG_MSM_SERVICE_NOTIFIER=y -CONFIG_MSM_SUBSYSTEM_RESTART=y -CONFIG_MSM_PIL=y -CONFIG_MSM_SYSMON_QMI_COMM=y -CONFIG_MSM_PIL_SSR_GENERIC=y -CONFIG_MSM_BOOT_STATS=y -CONFIG_MSM_CORE_HANG_DETECT=y -CONFIG_QCOM_DCC_V2=y -CONFIG_QCOM_BUS_SCALING=y -CONFIG_QCOM_GLINK=y -CONFIG_QCOM_GLINK_PKT=y -# CONFIG_MSM_JTAGV8 is not set -CONFIG_EXTCON_USB_GPIO=y -CONFIG_IIO=y -CONFIG_QCOM_SPMI_ADC5=y -CONFIG_PWM=y -CONFIG_PWM_QTI_LPG=y -CONFIG_QTI_MPM=y -CONFIG_ANDROID=y -CONFIG_ANDROID_BINDER_IPC=y -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT3_FS=y -CONFIG_EXT4_FS_SECURITY=y -CONFIG_QUOTA=y -CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set -CONFIG_QFMT_V2=y -CONFIG_FUSE_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_UBIFS_FS=y -CONFIG_UBIFS_FS_ADVANCED_COMPR=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y -CONFIG_PRINTK_TIME=y -CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_INFO=y -CONFIG_PAGE_OWNER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_OBJECTS=y -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_WORK=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_DEBUG_KMEMLEAK=y -CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 -CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y -CONFIG_DEBUG_STACK_USAGE=y -CONFIG_DEBUG_MEMORY_INIT=y -CONFIG_PANIC_TIMEOUT=5 -CONFIG_SCHEDSTATS=y -CONFIG_SCHED_STACK_END_CHECK=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_ATOMIC_SLEEP=y -CONFIG_DEBUG_LIST=y -CONFIG_FAULT_INJECTION=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_UFS_FAULT_INJECTION=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_IPC_LOGGING=y -CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_LKDTM=y -CONFIG_CORESIGHT=y -CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y -CONFIG_CORESIGHT_SOURCE_ETM4X=y -CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y -CONFIG_CORESIGHT_STM=y -CONFIG_CORESIGHT_CTI=y -CONFIG_CORESIGHT_TPDA=y -CONFIG_CORESIGHT_TPDM=y -CONFIG_CORESIGHT_HWEVENT=y -CONFIG_CORESIGHT_DUMMY=y -CONFIG_CORESIGHT_REMOTE_ETM=y -CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 -CONFIG_CORESIGHT_EVENT=y -CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y -CONFIG_SECURITY=y -CONFIG_SECURITY_NETWORK=y -CONFIG_LSM_MMAP_MIN_ADDR=4096 -CONFIG_HARDENED_USERCOPY=y -CONFIG_SECURITY_SELINUX=y -CONFIG_CRYPTO_CTR=y -CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_TWOFISH=y diff --git a/arch/arm/configs/qcs405_defconfig b/arch/arm/configs/qcs405_defconfig new file mode 120000 index 000000000000..372fd3e54d88 --- /dev/null +++ b/arch/arm/configs/qcs405_defconfig @@ -0,0 +1 @@ +vendor/qcs405_defconfig \ No newline at end of file diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig new file mode 100644 index 000000000000..fac263b18316 --- /dev/null +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -0,0 +1,500 @@ +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_SCHED_WALT=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_DEBUG=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_DEFAULT_USE_ENERGY_AWARE=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +CONFIG_PROFILING=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_FORCE=y +CONFIG_MODULE_SIG_SHA512=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_QCS405=y +# CONFIG_VDSO is not set +CONFIG_SMP=y +CONFIG_ARM_PSCI=y +CONFIG_PREEMPT=y +CONFIG_CLEANCACHE=y +CONFIG_CMA=y +CONFIG_CMA_DEBUGFS=y +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_IDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_DEBUG=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_L2TP=y +CONFIG_L2TP_DEBUGFS=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +CONFIG_RMNET_DATA=y +CONFIG_RMNET_DATA_FC=y +CONFIG_RMNET_DATA_DEBUG_PKT=y +CONFIG_BT=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y +CONFIG_CFG80211=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_RFKILL=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_CMA=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_MSM_QPIC_NAND=y +CONFIG_MTD_NAND=y +CONFIG_MTD_UBI=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_UID_SYS_STATS=y +CONFIG_QPNP_MISC=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +CONFIG_TUN=y +CONFIG_KS8851=y +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_USBNET=y +CONFIG_USB_NET_SMSC75XX=y +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=m +CONFIG_INPUT_KEYRESET=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y +CONFIG_INPUT_TABLET=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ATMEL_MXT=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y +CONFIG_INPUT_KEYCHORD=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_MSM_ADSPRPC=y +CONFIG_I2C_CHARDEV=y +CONFIG_SPI=y +CONFIG_SPI_DEBUG=y +CONFIG_SPI_SPIDEV=y +CONFIG_SPMI=y +CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y +CONFIG_PINCTRL_QCS405=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_GPIOLIB=y +CONFIG_POWER_SUPPLY=y +CONFIG_SMB1351_USB_CHARGER=y +CONFIG_THERMAL=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_LOW_LIMITS=y +CONFIG_CPU_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_QCOM_SPMI_TEMP_ALARM=y +CONFIG_THERMAL_TSENS=y +CONFIG_QTI_VIRTUAL_SENSOR=y +CONFIG_QTI_QMI_COOLING_DEVICE=y +CONFIG_REGULATOR_COOLING_DEVICE=y +CONFIG_MFD_SPMI_PMIC=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_CPR=y +CONFIG_REGULATOR_MEM_ACC=y +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_SPM=y +CONFIG_REGULATOR_STUB=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_FB=y +CONFIG_FB_MSM=y +CONFIG_FB_MSM_MDSS=y +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y +CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_MSM=y +CONFIG_USB_SERIAL=y +CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_MSM_SNPS_FEMTO_PHY=y +CONFIG_USB_MSM_SSPHY=y +CONFIG_USB_QCOM_EMU_PHY=y +CONFIG_DUAL_ROLE_USB_INTF=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=900 +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_DIAG=y +CONFIG_MMC=y +CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_DEFERRED_RESUME=y +CONFIG_MMC_TEST=m +CONFIG_MMC_RING_BUFFER=y +CONFIG_MMC_PARANOID_SD_INIT=y +CONFIG_MMC_CLKGATE=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_QPNP=y +CONFIG_DMADEVICES=y +CONFIG_UIO=y +CONFIG_STAGING=y +CONFIG_ASHMEM=y +CONFIG_ION=y +CONFIG_QPNP_REVID=y +CONFIG_SPS=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_QCOM_MDSS_PLL=y +CONFIG_COMMON_CLK_QCOM=y +CONFIG_QCOM_CLK_SMD_RPM=y +CONFIG_SPMI_PMIC_CLKDIV=y +CONFIG_MDM_GCC_QCS405=y +CONFIG_MDM_DEBUGCC_QCS405=y +CONFIG_CLOCK_CPU_QCS405=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_MAILBOX=y +CONFIG_QCOM_APCS_IPC=y +CONFIG_ARM_SMMU=y +CONFIG_QCOM_LAZY_MAPPING=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_DEBUG_TRACKING=y +CONFIG_IOMMU_TESTS=y +CONFIG_QCOM_IOMMU=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_QCOM_GLINK_RPM=y +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_SMD=y +CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_SMD_RPM=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_QCOM_SCM=y +CONFIG_QCOM_SMP2P=y +CONFIG_MSM_SERVICE_LOCATOR=y +CONFIG_MSM_SERVICE_NOTIFIER=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_MSM_CORE_HANG_DETECT=y +CONFIG_QCOM_DCC_V2=y +CONFIG_QCOM_BUS_SCALING=y +CONFIG_QCOM_GLINK=y +CONFIG_QCOM_GLINK_PKT=y +# CONFIG_MSM_JTAGV8 is not set +CONFIG_EXTCON_USB_GPIO=y +CONFIG_IIO=y +CONFIG_QCOM_SPMI_ADC5=y +CONFIG_PWM=y +CONFIG_PWM_QTI_LPG=y +CONFIG_QTI_MPM=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT3_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_PAGE_OWNER=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_WORK=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_STACK_END_CHECK=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_FAULT_INJECTION=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_UFS_FAULT_INJECTION=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_IPC_LOGGING=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LKDTM=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_SOURCE_ETM4X=y +CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +CONFIG_CORESIGHT_HWEVENT=y +CONFIG_CORESIGHT_DUMMY=y +CONFIG_CORESIGHT_REMOTE_ETM=y +CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 +CONFIG_CORESIGHT_EVENT=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_LSM_MMAP_MIN_ADDR=4096 +CONFIG_HARDENED_USERCOPY=y +CONFIG_SECURITY_SELINUX=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_TWOFISH=y diff --git a/arch/arm64/configs/qcs405_defconfig b/arch/arm64/configs/qcs405_defconfig deleted file mode 100644 index 02b38899a145..000000000000 --- a/arch/arm64/configs/qcs405_defconfig +++ /dev/null @@ -1,501 +0,0 @@ -CONFIG_AUDIT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_SCHED_WALT=y -CONFIG_TASKSTATS=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_CGROUPS=y -CONFIG_CGROUP_SCHED=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_CGROUP_DEBUG=y -CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set -# CONFIG_PID_NS is not set -CONFIG_DEFAULT_USE_ENERGY_AWARE=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_KALLSYMS_ALL=y -CONFIG_EMBEDDED=y -CONFIG_PROFILING=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SIG=y -CONFIG_MODULE_SIG_FORCE=y -CONFIG_MODULE_SIG_SHA512=y -CONFIG_PARTITION_ADVANCED=y -CONFIG_ARCH_QCOM=y -CONFIG_ARCH_QCS405=y -CONFIG_NR_CPUS=4 -CONFIG_PREEMPT=y -CONFIG_CLEANCACHE=y -CONFIG_CMA=y -CONFIG_CMA_DEBUGFS=y -CONFIG_ZSMALLOC=y -CONFIG_SECCOMP=y -# CONFIG_HARDEN_BRANCH_PREDICTOR is not set -CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_PM_AUTOSLEEP=y -CONFIG_PM_WAKELOCKS=y -CONFIG_PM_WAKELOCKS_LIMIT=0 -# CONFIG_PM_WAKELOCKS_GC is not set -CONFIG_PM_DEBUG=y -CONFIG_CPU_IDLE=y -CONFIG_ARM_CPUIDLE=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_XFRM_STATISTICS=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -# CONFIG_INET_XFRM_MODE_BEET is not set -CONFIG_INET_DIAG_DESTROY=y -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_ROUTE_INFO=y -CONFIG_IPV6_OPTIMISTIC_DAD=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_IPV6_MIP6=y -CONFIG_IPV6_MULTIPLE_TABLES=y -CONFIG_IPV6_SUBTREES=y -CONFIG_NETFILTER=y -CONFIG_NF_CONNTRACK=y -CONFIG_NF_CONNTRACK_SECMARK=y -CONFIG_NF_CONNTRACK_EVENTS=y -CONFIG_NF_CONNTRACK_AMANDA=y -CONFIG_NF_CONNTRACK_FTP=y -CONFIG_NF_CONNTRACK_H323=y -CONFIG_NF_CONNTRACK_IRC=y -CONFIG_NF_CONNTRACK_NETBIOS_NS=y -CONFIG_NF_CONNTRACK_PPTP=y -CONFIG_NF_CONNTRACK_SANE=y -CONFIG_NF_CONNTRACK_TFTP=y -CONFIG_NF_CT_NETLINK=y -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y -CONFIG_NETFILTER_XT_TARGET_CONNMARK=y -CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y -CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y -CONFIG_NETFILTER_XT_TARGET_LOG=y -CONFIG_NETFILTER_XT_TARGET_MARK=y -CONFIG_NETFILTER_XT_TARGET_NFLOG=y -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y -CONFIG_NETFILTER_XT_TARGET_NOTRACK=y -CONFIG_NETFILTER_XT_TARGET_TEE=y -CONFIG_NETFILTER_XT_TARGET_TPROXY=y -CONFIG_NETFILTER_XT_TARGET_TRACE=y -CONFIG_NETFILTER_XT_TARGET_SECMARK=y -CONFIG_NETFILTER_XT_TARGET_TCPMSS=y -CONFIG_NETFILTER_XT_MATCH_COMMENT=y -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y -CONFIG_NETFILTER_XT_MATCH_CONNMARK=y -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -CONFIG_NETFILTER_XT_MATCH_DSCP=y -CONFIG_NETFILTER_XT_MATCH_ESP=y -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y -CONFIG_NETFILTER_XT_MATCH_HELPER=y -CONFIG_NETFILTER_XT_MATCH_IPRANGE=y -CONFIG_NETFILTER_XT_MATCH_LENGTH=y -CONFIG_NETFILTER_XT_MATCH_LIMIT=y -CONFIG_NETFILTER_XT_MATCH_MAC=y -CONFIG_NETFILTER_XT_MATCH_MARK=y -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y -CONFIG_NETFILTER_XT_MATCH_POLICY=y -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y -CONFIG_NETFILTER_XT_MATCH_QUOTA=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -CONFIG_NETFILTER_XT_MATCH_STATE=y -CONFIG_NETFILTER_XT_MATCH_STATISTIC=y -CONFIG_NETFILTER_XT_MATCH_STRING=y -CONFIG_NETFILTER_XT_MATCH_TIME=y -CONFIG_NETFILTER_XT_MATCH_U32=y -CONFIG_NF_CONNTRACK_IPV4=y -CONFIG_IP_NF_IPTABLES=y -CONFIG_IP_NF_MATCH_AH=y -CONFIG_IP_NF_MATCH_ECN=y -CONFIG_IP_NF_MATCH_RPFILTER=y -CONFIG_IP_NF_MATCH_TTL=y -CONFIG_IP_NF_FILTER=y -CONFIG_IP_NF_TARGET_REJECT=y -CONFIG_IP_NF_NAT=y -CONFIG_IP_NF_TARGET_MASQUERADE=y -CONFIG_IP_NF_TARGET_NETMAP=y -CONFIG_IP_NF_TARGET_REDIRECT=y -CONFIG_IP_NF_MANGLE=y -CONFIG_IP_NF_RAW=y -CONFIG_IP_NF_SECURITY=y -CONFIG_IP_NF_ARPTABLES=y -CONFIG_IP_NF_ARPFILTER=y -CONFIG_IP_NF_ARP_MANGLE=y -CONFIG_NF_CONNTRACK_IPV6=y -CONFIG_IP6_NF_IPTABLES=y -CONFIG_IP6_NF_MATCH_RPFILTER=y -CONFIG_IP6_NF_FILTER=y -CONFIG_IP6_NF_TARGET_REJECT=y -CONFIG_IP6_NF_MANGLE=y -CONFIG_IP6_NF_RAW=y -CONFIG_BRIDGE_NF_EBTABLES=y -CONFIG_BRIDGE_EBT_BROUTE=y -CONFIG_L2TP=y -CONFIG_L2TP_DEBUGFS=y -CONFIG_L2TP_V3=y -CONFIG_L2TP_IP=y -CONFIG_L2TP_ETH=y -CONFIG_BRIDGE=y -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_HTB=y -CONFIG_NET_SCH_PRIO=y -CONFIG_NET_CLS_FW=y -CONFIG_NET_CLS_U32=y -CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_FLOW=y -CONFIG_NET_EMATCH=y -CONFIG_NET_EMATCH_CMP=y -CONFIG_NET_EMATCH_NBYTE=y -CONFIG_NET_EMATCH_U32=y -CONFIG_NET_EMATCH_META=y -CONFIG_NET_EMATCH_TEXT=y -CONFIG_NET_CLS_ACT=y -CONFIG_QRTR=y -CONFIG_QRTR_SMD=y -CONFIG_RMNET_DATA=y -CONFIG_RMNET_DATA_FC=y -CONFIG_RMNET_DATA_DEBUG_PKT=y -CONFIG_BT=y -CONFIG_BT_RFCOMM=y -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=y -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -CONFIG_BT_HIDP=y -CONFIG_CFG80211=y -CONFIG_CFG80211_INTERNAL_REGDB=y -CONFIG_RFKILL=y -CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y -CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y -CONFIG_DMA_CMA=y -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_MSM_QPIC_NAND=y -CONFIG_MTD_NAND=y -CONFIG_MTD_UBI=y -CONFIG_ZRAM=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_UID_SYS_STATS=y -CONFIG_QPNP_MISC=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_SG=y -CONFIG_CHR_DEV_SCH=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_UFSHCD=y -CONFIG_SCSI_UFSHCD_PLATFORM=y -CONFIG_SCSI_UFS_QCOM=y -CONFIG_SCSI_UFSHCD_CMD_LOGGING=y -CONFIG_MD=y -CONFIG_BLK_DEV_DM=y -CONFIG_DM_CRYPT=y -CONFIG_DM_VERITY=y -CONFIG_DM_VERITY_FEC=y -CONFIG_NETDEVICES=y -CONFIG_DUMMY=y -CONFIG_TUN=y -CONFIG_KS8851=y -CONFIG_PPP=y -CONFIG_PPP_BSDCOMP=y -CONFIG_PPP_DEFLATE=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=y -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOE=y -CONFIG_PPPOL2TP=y -CONFIG_PPPOLAC=y -CONFIG_PPPOPNS=y -CONFIG_PPP_ASYNC=y -CONFIG_PPP_SYNC_TTY=y -CONFIG_USB_USBNET=y -CONFIG_USB_NET_SMSC75XX=y -CONFIG_WCNSS_MEM_PRE_ALLOC=y -CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_EVBUG=m -CONFIG_INPUT_KEYRESET=y -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_JOYSTICK=y -CONFIG_JOYSTICK_XPAD=y -CONFIG_INPUT_TABLET=y -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ATMEL_MXT=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_HBTP_INPUT=y -CONFIG_INPUT_QPNP_POWER_ON=y -CONFIG_INPUT_KEYCHORD=y -CONFIG_INPUT_UINPUT=y -CONFIG_INPUT_GPIO=y -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVMEM is not set -CONFIG_SERIAL_MSM=y -CONFIG_SERIAL_MSM_CONSOLE=y -CONFIG_SERIAL_MSM_HS=y -CONFIG_HW_RANDOM=y -CONFIG_MSM_ADSPRPC=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MSM_V2=y -CONFIG_SPI=y -CONFIG_SPI_DEBUG=y -CONFIG_SPI_QUP=y -CONFIG_SPI_SPIDEV=y -CONFIG_SPMI=y -CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y -CONFIG_SLIMBUS=y -CONFIG_SLIMBUS_MSM_NGD=y -CONFIG_PINCTRL_QCS405=y -CONFIG_PINCTRL_QCOM_SPMI_PMIC=y -CONFIG_SMB1351_USB_CHARGER=y -CONFIG_THERMAL=y -CONFIG_THERMAL_WRITABLE_TRIPS=y -CONFIG_THERMAL_GOV_USER_SPACE=y -CONFIG_THERMAL_GOV_LOW_LIMITS=y -CONFIG_CPU_THERMAL=y -CONFIG_DEVFREQ_THERMAL=y -CONFIG_QCOM_SPMI_TEMP_ALARM=y -CONFIG_THERMAL_TSENS=y -CONFIG_QTI_VIRTUAL_SENSOR=y -CONFIG_QTI_QMI_COOLING_DEVICE=y -CONFIG_REGULATOR_COOLING_DEVICE=y -CONFIG_MFD_SPMI_PMIC=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_FAN53555=y -CONFIG_REGULATOR_CPR=y -CONFIG_REGULATOR_MEM_ACC=y -CONFIG_REGULATOR_RPM_SMD=y -CONFIG_REGULATOR_SPM=y -CONFIG_REGULATOR_STUB=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_MEDIA_RADIO_SUPPORT=y -CONFIG_MEDIA_CONTROLLER=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_SOC_CAMERA=y -CONFIG_SOC_CAMERA_PLATFORM=y -CONFIG_FB=y -CONFIG_FB_MSM=y -CONFIG_FB_MSM_MDSS=y -CONFIG_FB_MSM_MDSS_WRITEBACK=y -CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y -CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_USB_AUDIO=y -CONFIG_SND_SOC=y -CONFIG_HIDRAW=y -CONFIG_UHID=y -CONFIG_HID_APPLE=y -CONFIG_HID_ELECOM=y -CONFIG_HID_MAGICMOUSE=y -CONFIG_HID_MICROSOFT=y -CONFIG_HID_MULTITOUCH=y -CONFIG_USB_HIDDEV=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_MON=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_ACM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_USBAT=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_STORAGE_ALAUDA=y -CONFIG_USB_STORAGE_KARMA=y -CONFIG_USB_STORAGE_CYPRESS_ATACB=y -CONFIG_USB_DWC3=y -CONFIG_USB_DWC3_MSM=y -CONFIG_USB_SERIAL=y -CONFIG_USB_EHSET_TEST_FIXTURE=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_MSM_SNPS_FEMTO_PHY=y -CONFIG_USB_MSM_SSPHY=y -CONFIG_USB_QCOM_EMU_PHY=y -CONFIG_DUAL_ROLE_USB_INTF=y -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_DEBUG_FILES=y -CONFIG_USB_GADGET_DEBUG_FS=y -CONFIG_USB_GADGET_VBUS_DRAW=900 -CONFIG_USB_CONFIGFS=y -CONFIG_USB_CONFIGFS_F_FS=y -CONFIG_USB_CONFIGFS_F_DIAG=y -CONFIG_MMC=y -CONFIG_MMC_PERF_PROFILING=y -CONFIG_MMC_BLOCK_MINORS=32 -CONFIG_MMC_BLOCK_DEFERRED_RESUME=y -CONFIG_MMC_TEST=m -CONFIG_MMC_RING_BUFFER=y -CONFIG_MMC_PARANOID_SD_INIT=y -CONFIG_MMC_CLKGATE=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_MSM=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_QPNP=y -CONFIG_DMADEVICES=y -CONFIG_QCOM_SPS_DMA=y -CONFIG_UIO=y -CONFIG_STAGING=y -CONFIG_ASHMEM=y -CONFIG_ION=y -CONFIG_QPNP_REVID=y -CONFIG_SPS=y -CONFIG_SPS_SUPPORT_NDP_BAM=y -CONFIG_QCOM_MDSS_PLL=y -CONFIG_QCOM_CLK_SMD_RPM=y -CONFIG_SPMI_PMIC_CLKDIV=y -CONFIG_MDM_GCC_QCS405=y -CONFIG_MDM_DEBUGCC_QCS405=y -CONFIG_CLOCK_CPU_QCS405=y -CONFIG_HWSPINLOCK=y -CONFIG_HWSPINLOCK_QCOM=y -CONFIG_MAILBOX=y -CONFIG_QCOM_APCS_IPC=y -CONFIG_ARM_SMMU=y -CONFIG_QCOM_LAZY_MAPPING=y -CONFIG_IOMMU_DEBUG=y -CONFIG_IOMMU_DEBUG_TRACKING=y -CONFIG_IOMMU_TESTS=y -CONFIG_RPMSG_CHAR=y -CONFIG_RPMSG_QCOM_GLINK_RPM=y -CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_QCOM_QMI_HELPERS=y -CONFIG_QCOM_SMEM=y -CONFIG_QCOM_SMD_RPM=y -CONFIG_MSM_SPM=y -CONFIG_MSM_L2_SPM=y -CONFIG_QCOM_SCM=y -CONFIG_QCOM_SMP2P=y -CONFIG_MSM_SERVICE_LOCATOR=y -CONFIG_MSM_SERVICE_NOTIFIER=y -CONFIG_MSM_SUBSYSTEM_RESTART=y -CONFIG_MSM_PIL=y -CONFIG_MSM_SYSMON_QMI_COMM=y -CONFIG_MSM_PIL_SSR_GENERIC=y -CONFIG_MSM_BOOT_STATS=y -CONFIG_MSM_CORE_HANG_DETECT=y -CONFIG_QCOM_DCC_V2=y -CONFIG_MSM_RPM_SMD=y -CONFIG_QCOM_BUS_SCALING=y -CONFIG_QCOM_GLINK=y -CONFIG_QCOM_GLINK_PKT=y -CONFIG_MSM_PM=y -CONFIG_EXTCON_USB_GPIO=y -CONFIG_IIO=y -CONFIG_QCOM_SPMI_ADC5=y -CONFIG_PWM=y -CONFIG_PWM_QTI_LPG=y -CONFIG_QCOM_KGSL=y -CONFIG_QTI_MPM=y -CONFIG_ANDROID=y -CONFIG_ANDROID_BINDER_IPC=y -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT3_FS=y -CONFIG_EXT4_FS_SECURITY=y -CONFIG_QUOTA=y -CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set -CONFIG_QFMT_V2=y -CONFIG_FUSE_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_UBIFS_FS=y -CONFIG_UBIFS_FS_ADVANCED_COMPR=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y -CONFIG_PRINTK_TIME=y -CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_INFO=y -CONFIG_PAGE_OWNER=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_OBJECTS=y -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_WORK=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_DEBUG_KMEMLEAK=y -CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 -CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y -CONFIG_DEBUG_STACK_USAGE=y -CONFIG_DEBUG_MEMORY_INIT=y -CONFIG_PANIC_TIMEOUT=5 -CONFIG_SCHEDSTATS=y -CONFIG_SCHED_STACK_END_CHECK=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_ATOMIC_SLEEP=y -CONFIG_DEBUG_LIST=y -CONFIG_FAULT_INJECTION=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_UFS_FAULT_INJECTION=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_IPC_LOGGING=y -CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_LKDTM=y -CONFIG_CORESIGHT=y -CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y -CONFIG_CORESIGHT_SOURCE_ETM4X=y -CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y -CONFIG_CORESIGHT_STM=y -CONFIG_CORESIGHT_CTI=y -CONFIG_CORESIGHT_TPDA=y -CONFIG_CORESIGHT_TPDM=y -CONFIG_CORESIGHT_HWEVENT=y -CONFIG_CORESIGHT_DUMMY=y -CONFIG_CORESIGHT_REMOTE_ETM=y -CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 -CONFIG_CORESIGHT_EVENT=y -CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y -CONFIG_SECURITY=y -CONFIG_SECURITY_NETWORK=y -CONFIG_LSM_MMAP_MIN_ADDR=4096 -CONFIG_HARDENED_USERCOPY=y -CONFIG_SECURITY_SELINUX=y -CONFIG_CRYPTO_CTR=y -CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_TWOFISH=y diff --git a/arch/arm64/configs/qcs405_defconfig b/arch/arm64/configs/qcs405_defconfig new file mode 120000 index 000000000000..372fd3e54d88 --- /dev/null +++ b/arch/arm64/configs/qcs405_defconfig @@ -0,0 +1 @@ +vendor/qcs405_defconfig \ No newline at end of file diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig new file mode 100644 index 000000000000..5cf358ccdab1 --- /dev/null +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -0,0 +1,501 @@ +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_SCHED_WALT=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_DEBUG=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_DEFAULT_USE_ENERGY_AWARE=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +CONFIG_PROFILING=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_FORCE=y +CONFIG_MODULE_SIG_SHA512=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_QCS405=y +CONFIG_NR_CPUS=4 +CONFIG_PREEMPT=y +CONFIG_CLEANCACHE=y +CONFIG_CMA=y +CONFIG_CMA_DEBUGFS=y +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +# CONFIG_HARDEN_BRANCH_PREDICTOR is not set +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_DEBUG=y +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_L2TP=y +CONFIG_L2TP_DEBUGFS=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +CONFIG_RMNET_DATA=y +CONFIG_RMNET_DATA_FC=y +CONFIG_RMNET_DATA_DEBUG_PKT=y +CONFIG_BT=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y +CONFIG_CFG80211=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_RFKILL=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_CMA=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_MSM_QPIC_NAND=y +CONFIG_MTD_NAND=y +CONFIG_MTD_UBI=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_UID_SYS_STATS=y +CONFIG_QPNP_MISC=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFSHCD_CMD_LOGGING=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +CONFIG_TUN=y +CONFIG_KS8851=y +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_USBNET=y +CONFIG_USB_NET_SMSC75XX=y +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=m +CONFIG_INPUT_KEYRESET=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y +CONFIG_INPUT_TABLET=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ATMEL_MXT=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y +CONFIG_INPUT_KEYCHORD=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SERIAL_MSM_HS=y +CONFIG_HW_RANDOM=y +CONFIG_MSM_ADSPRPC=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MSM_V2=y +CONFIG_SPI=y +CONFIG_SPI_DEBUG=y +CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=y +CONFIG_SPMI=y +CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y +CONFIG_SLIMBUS=y +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_PINCTRL_QCS405=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_SMB1351_USB_CHARGER=y +CONFIG_THERMAL=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_LOW_LIMITS=y +CONFIG_CPU_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_QCOM_SPMI_TEMP_ALARM=y +CONFIG_THERMAL_TSENS=y +CONFIG_QTI_VIRTUAL_SENSOR=y +CONFIG_QTI_QMI_COOLING_DEVICE=y +CONFIG_REGULATOR_COOLING_DEVICE=y +CONFIG_MFD_SPMI_PMIC=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_CPR=y +CONFIG_REGULATOR_MEM_ACC=y +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_SPM=y +CONFIG_REGULATOR_STUB=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_FB=y +CONFIG_FB_MSM=y +CONFIG_FB_MSM_MDSS=y +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y +CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_MSM=y +CONFIG_USB_SERIAL=y +CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_MSM_SNPS_FEMTO_PHY=y +CONFIG_USB_MSM_SSPHY=y +CONFIG_USB_QCOM_EMU_PHY=y +CONFIG_DUAL_ROLE_USB_INTF=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=900 +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_DIAG=y +CONFIG_MMC=y +CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_DEFERRED_RESUME=y +CONFIG_MMC_TEST=m +CONFIG_MMC_RING_BUFFER=y +CONFIG_MMC_PARANOID_SD_INIT=y +CONFIG_MMC_CLKGATE=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_QPNP=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_SPS_DMA=y +CONFIG_UIO=y +CONFIG_STAGING=y +CONFIG_ASHMEM=y +CONFIG_ION=y +CONFIG_QPNP_REVID=y +CONFIG_SPS=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_QCOM_MDSS_PLL=y +CONFIG_QCOM_CLK_SMD_RPM=y +CONFIG_SPMI_PMIC_CLKDIV=y +CONFIG_MDM_GCC_QCS405=y +CONFIG_MDM_DEBUGCC_QCS405=y +CONFIG_CLOCK_CPU_QCS405=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_MAILBOX=y +CONFIG_QCOM_APCS_IPC=y +CONFIG_ARM_SMMU=y +CONFIG_QCOM_LAZY_MAPPING=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_DEBUG_TRACKING=y +CONFIG_IOMMU_TESTS=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_QCOM_GLINK_RPM=y +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_MSM_RPM_SMD=y +CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_SMD_RPM=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_QCOM_SCM=y +CONFIG_QCOM_SMP2P=y +CONFIG_MSM_SERVICE_LOCATOR=y +CONFIG_MSM_SERVICE_NOTIFIER=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_MSM_CORE_HANG_DETECT=y +CONFIG_QCOM_DCC_V2=y +CONFIG_QCOM_BUS_SCALING=y +CONFIG_QCOM_GLINK=y +CONFIG_QCOM_GLINK_PKT=y +CONFIG_MSM_PM=y +CONFIG_EXTCON_USB_GPIO=y +CONFIG_IIO=y +CONFIG_QCOM_SPMI_ADC5=y +CONFIG_PWM=y +CONFIG_PWM_QTI_LPG=y +CONFIG_QCOM_KGSL=y +CONFIG_QTI_MPM=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT3_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_PAGE_OWNER=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_WORK=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_STACK_END_CHECK=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_FAULT_INJECTION=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_UFS_FAULT_INJECTION=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_IPC_LOGGING=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LKDTM=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_SOURCE_ETM4X=y +CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +CONFIG_CORESIGHT_HWEVENT=y +CONFIG_CORESIGHT_DUMMY=y +CONFIG_CORESIGHT_REMOTE_ETM=y +CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 +CONFIG_CORESIGHT_EVENT=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_LSM_MMAP_MIN_ADDR=4096 +CONFIG_HARDENED_USERCOPY=y +CONFIG_SECURITY_SELINUX=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_TWOFISH=y -- GitLab From 490abb23219ec348b7e8921a8674afce9cacd33b Mon Sep 17 00:00:00 2001 From: Raviteja Tamatam Date: Tue, 5 Jun 2018 21:35:13 +0530 Subject: [PATCH 0688/1299] drm/msm/sde: validate de-interlace and scalar concurrency In de-interlace video plus scalar concurrency case- pipe fetch, unpack output and scalar block input number of lines should match. Otherwise, it will lead to hang. Added check to validate this condition. Change-Id: I00453dda36b5291948b99d0f0a89105b6875c039 Signed-off-by: Raviteja Tamatam --- drivers/gpu/drm/msm/sde/sde_plane.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index f44e74561220..208439aaf760 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -3452,6 +3452,25 @@ static int _sde_plane_validate_scaler_v2(struct sde_plane *psde, src_w, src_h); return -EINVAL; } + + /* + * SSPP fetch , unpack output and QSEED3 input lines need + * to match for Y plane + */ + if (i == 0 && + (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) & + BIT(SDE_DRM_DEINTERLACE)) && + ((pstate->scaler3_cfg.src_height[i] != (src_h/2)) || + (pstate->pixel_ext.roi_h[i] != (src_h/2)))) { + SDE_ERROR_PLANE(psde, + "de-interlace fail roi[%d] %d/%d, src %dx%d, src %dx%d\n", + i, pstate->pixel_ext.roi_w[i], + pstate->pixel_ext.roi_h[i], + pstate->scaler3_cfg.src_width[i], + pstate->scaler3_cfg.src_height[i], + src_w, src_h); + return -EINVAL; + } } pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2; -- GitLab From 3299df99e0613caab5380ebc087abeeb9e68b384 Mon Sep 17 00:00:00 2001 From: Ping Li Date: Tue, 19 Jun 2018 18:14:01 -0700 Subject: [PATCH 0689/1299] drm/msm/sde: correct VIG GAMUT/IGC opmode address for read When programing VIG feature blocks, LUT DMA path and AHB path use different base address of VIG. LUT DMA is used for writing the VIG features, and AHB is used for reading the opmode. This change corrects the VIG Gamut/IGC opmode address for reading. Change-Id: Ia2dbe66f731383ff988e99814911aa05e6143971 Signed-off-by: Ping Li --- drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c index b03fc9ea1360..c95054a33581 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -1725,7 +1725,7 @@ void reg_dmav1_setup_vig_gamutv5(struct sde_hw_pipe *ctx, void *cfg) hw_cfg->len, sizeof(struct drm_msm_3d_gamut)); return; } - op_mode = SDE_REG_READ(&ctx->hw, gamut_base); + op_mode = SDE_REG_READ(&ctx->hw, ctx->cap->sblk->gamut_blk.base); payload = hw_cfg->payload; rc = sde_gamut_get_mode_info(SSPP, payload, &tbl_len, &tbl_off, &op_mode, &scale_off); @@ -1896,7 +1896,7 @@ void reg_dmav1_setup_vig_igcv5(struct sde_hw_pipe *ctx, void *cfg) if (!data) return; - reg = SDE_REG_READ(&ctx->hw, igc_base); + reg = SDE_REG_READ(&ctx->hw, ctx->cap->sblk->igc_blk[0].base); lut_enable = (reg >> 8) & BIT(0); lut_sel = (reg >> 9) & BIT(0); /* select LUT table (0 or 1) when 1D LUT is in active mode */ -- GitLab From 5ec4e77af79853b2699c3d63f9efd3a166e340c0 Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Tue, 3 May 2016 16:44:32 -0400 Subject: [PATCH 0690/1299] ALSA: timer: Fix leak in events via snd_timer_user_tinterrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The stack object “r1” has a total size of 32 bytes. Its field “event” and “val” both contain 4 bytes padding. These 8 bytes padding bytes are sent to user without being initialized. b/28980217 Signed-off-by: Kangjie Lu Signed-off-by: Takashi Iwai Change-Id: I53aa15632e941199010aae670cefb65c8fd56833 Git-commit: e4ec8cc8039a7063e24204299b462bd1383184a5 Git-repo: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git Signed-off-by: Dennis Cagle --- sound/core/timer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/core/timer.c b/sound/core/timer.c index c8b8d7a01917..7f728085568f 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1352,6 +1352,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, } if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && tu->last_resolution != resolution) { + memset(&r1, 0, sizeof(r1)); r1.event = SNDRV_TIMER_EVENT_RESOLUTION; r1.tstamp = tstamp; r1.val = resolution; -- GitLab From cc717b29f9faf868d0cfc918e9d3aff3236bde52 Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Thu, 21 Jun 2018 12:58:15 -0700 Subject: [PATCH 0691/1299] msm: vidc: Fix corruption in bus vote msm_comm_vote_bus() calculates and prepares core->vote_data structure under core->lock for all instances and sets the prepared vote_data to hfi layer after releasing core->lock. There is a possibility that this prepared vote_data can be corrupted while hfi layer accessesing it if msm_comm_vote_bus() is called by another instance in parallel. Fix the issue by allocating a new vote_data structure for every call to msm_comm_vote_bus() function. Change-Id: I502027054d994ee8144a8505c47954a1f1e06be4 Signed-off-by: Maheshwar Ajja --- .../media/platform/msm/vidc/msm_v4l2_vidc.c | 8 ------- .../media/platform/msm/vidc/msm_vidc_clocks.c | 21 ++++++++++++------- .../platform/msm/vidc/msm_vidc_internal.h | 1 - 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c index 2262ae6dc3a1..376f204815cc 100644 --- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c @@ -364,13 +364,6 @@ static int msm_vidc_initialize_core(struct platform_device *pdev, INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler); INIT_WORK(&core->ssr_work, msm_vidc_ssr_handler); - mutex_lock(&core->lock); - core->vote_data = kcalloc(MAX_SUPPORTED_INSTANCES, - sizeof(*core->vote_data), GFP_KERNEL); - if (!core->vote_data) - dprintk(VIDC_ERR, "%s: failed to allocate memory\n", __func__); - mutex_unlock(&core->lock); - msm_vidc_init_core_clk_ops(core); return rc; } @@ -764,7 +757,6 @@ static int msm_vidc_remove(struct platform_device *pdev) v4l2_device_unregister(&core->v4l2_dev); msm_vidc_free_platform_resources(&core->resources); - kfree(core->vote_data); sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group); dev_set_drvdata(&pdev->dev, NULL); mutex_destroy(&core->lock); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c index 1a258c452820..f97a2ba18986 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c @@ -194,19 +194,23 @@ int msm_comm_vote_bus(struct msm_vidc_core *core) dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, core); return -EINVAL; } - hdev = core->device; - mutex_lock(&core->lock); - vote_data = core->vote_data; + vote_data = kzalloc(sizeof(struct vidc_bus_vote_data) * + MAX_SUPPORTED_INSTANCES, GFP_ATOMIC); if (!vote_data) { - dprintk(VIDC_PROF, - "Failed to get vote_data for inst %pK\n", - inst); - mutex_unlock(&core->lock); - return -EINVAL; + dprintk(VIDC_DBG, + "vote_data allocation with GFP_ATOMIC failed\n"); + vote_data = kzalloc(sizeof(struct vidc_bus_vote_data) * + MAX_SUPPORTED_INSTANCES, GFP_KERNEL); + if (!vote_data) { + dprintk(VIDC_DBG, + "vote_data allocation failed\n"); + return -EINVAL; + } } + mutex_lock(&core->lock); list_for_each_entry(inst, &core->instances, list) { int codec = 0; struct msm_vidc_buffer *temp, *next; @@ -328,6 +332,7 @@ int msm_comm_vote_bus(struct msm_vidc_core *core) rc = call_hfi_op(hdev, vote_bus, hdev->hfi_device_data, vote_data, vote_data_count); + kfree(vote_data); return rc; } diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index 3b3882026bd4..5eb829d70413 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -396,7 +396,6 @@ struct msm_vidc_core { bool trigger_ssr; unsigned long min_freq; unsigned long curr_freq; - struct vidc_bus_vote_data *vote_data; struct msm_vidc_core_ops *core_ops; }; -- GitLab From 81a4468ca5f5f6b791dbbee1cf3e92371d9d0f00 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Thu, 21 Jun 2018 13:37:06 -0600 Subject: [PATCH 0692/1299] net: qualcomm: rmnet: Remove locking from dowlink marker All downlink marker operations occur in sequence - module init on bootup and marker list parse during transfer time. Remove this unnecessary locking for now. CRs-Fixed: 2233026 Change-Id: I881a3e7f594218f9068dbe4037fe553a82b637d3 Signed-off-by: Subash Abhinov Kasiviswanathan --- .../ethernet/qualcomm/rmnet/rmnet_config.h | 1 - .../qualcomm/rmnet/rmnet_map_command.c | 19 ------------------- 2 files changed, 20 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h index 06a93b53e4f6..8749905b19cc 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h @@ -68,7 +68,6 @@ struct rmnet_port { void *qmi_info; /* dl marker elements */ - spinlock_t dl_list_lock; struct list_head dl_list; struct rmnet_port_priv_stats stats; }; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c index fba75f2e964d..0a7530548a39 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c @@ -99,12 +99,8 @@ static void rmnet_map_dl_hdr_notify(struct rmnet_port *port, { struct rmnet_map_dl_ind *tmp; - spin_lock(&port->dl_list_lock); - list_for_each_entry(tmp, &port->dl_list, list) tmp->dl_hdr_handler(dlhdr); - - spin_unlock(&port->dl_list_lock); } static void rmnet_map_dl_trl_notify(struct rmnet_port *port, @@ -112,12 +108,8 @@ static void rmnet_map_dl_trl_notify(struct rmnet_port *port, { struct rmnet_map_dl_ind *tmp; - spin_lock(&port->dl_list_lock); - list_for_each_entry(tmp, &port->dl_list, list) tmp->dl_trl_handler(dltrl); - - spin_unlock(&port->dl_list_lock); } static void rmnet_map_process_flow_start(struct sk_buff *skb, @@ -229,18 +221,13 @@ void rmnet_map_cmd_exit(struct rmnet_port *port) { struct rmnet_map_dl_ind *tmp, *idx; - spin_lock(&port->dl_list_lock); - list_for_each_entry_safe(tmp, idx, &port->dl_list, list) list_del_rcu(&tmp->list); - - spin_unlock(&port->dl_list_lock); } void rmnet_map_cmd_init(struct rmnet_port *port) { INIT_LIST_HEAD(&port->dl_list); - spin_lock_init(&port->dl_list_lock); } int rmnet_map_dl_ind_register(struct rmnet_port *port, @@ -250,9 +237,7 @@ int rmnet_map_dl_ind_register(struct rmnet_port *port, !dl_ind->dl_trl_handler) return -EINVAL; - spin_lock(&port->dl_list_lock); list_add_rcu(&dl_ind->list, &port->dl_list); - spin_unlock(&port->dl_list_lock); return 0; } @@ -265,8 +250,6 @@ int rmnet_map_dl_ind_deregister(struct rmnet_port *port, if (!port || !dl_ind) return -EINVAL; - spin_lock(&port->dl_list_lock); - list_for_each_entry(tmp, &port->dl_list, list) { if (tmp == dl_ind) { list_del_rcu(&dl_ind->list); @@ -275,7 +258,5 @@ int rmnet_map_dl_ind_deregister(struct rmnet_port *port, } done: - spin_unlock(&port->dl_list_lock); - return 0; } -- GitLab From 15f76e83b55fd6d42e9137abf81b6f62c1cdbcbd Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Tue, 19 Sep 2017 10:55:17 -0700 Subject: [PATCH 0693/1299] clocksource: arch_timer: make virtual counter access configurable Change-Id: Ibdb1fd768b748002b90bfc165612c12c8311f8a2 Signed-off-by: Greg Hackmann Signed-off-by: Kyle Yan Signed-off-by: Isaac J. Manjarres --- drivers/clocksource/Kconfig | 8 ++++++++ drivers/clocksource/arm_arch_timer.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index cc6062049170..4bb47be12c9e 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -374,6 +374,14 @@ config ARM64_ERRATUM_858921 The workaround will be dynamically enabled when an affected core is detected. +config ARM_ARCH_TIMER_VCT_ACCESS + bool "Support for ARM architected timer virtual counter access in userspace" + default !ARM64 + depends on ARM_ARCH_TIMER + help + This option enables support for reading the ARM architected timer's + virtual counter in userspace. + config ARM_GLOBAL_TIMER bool "Support for the ARM global timer" if COMPILE_TEST select TIMER_OF if OF diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index f8df0d8bb301..dd9614496f53 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -777,7 +777,7 @@ static void arch_counter_set_user_access(void) */ if (arch_timer_this_cpu_has_cntvct_wa()) pr_info("CPU%d: Trapping CNTVCT access\n", smp_processor_id()); - else + else if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)) cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; arch_timer_set_cntkctl(cntkctl); -- GitLab From ec7c732b9030a1983db481c90834b73b1de7e991 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 20 Dec 2016 15:59:19 -0800 Subject: [PATCH 0694/1299] android: fiq_debugger: restrict access to critical commands. Sysrq must be enabled via /proc/sys/kernel/sysrq as a security measure to enable various critical fiq debugger commands that either leak information or can be used as a system attack. Default disabled, this will leave the reboot, reset, irqs, sleep, nosleep, console and ps commands. Reboot and reset commands will be restricted from taking any parameters. We will also switch to showing the limited command set in this mode. Signed-off-by: Mark Salyzyn Bug: 32402555 Change-Id: I3f74b1ff5e4971d619bcb37a911fed68fbb538d5 [dcagle@codeaurora.org: Resolve merge conflict] Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 1031836c0895f1f5a05c25efec83bfa11aa08ca9 Signed-off-by: Dennis Cagle --- .../android/fiq_debugger/fiq_debugger.c | 86 ++++++++++++------- drivers/tty/sysrq.c | 3 +- include/linux/sysrq.h | 1 + 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.c b/drivers/staging/android/fiq_debugger/fiq_debugger.c index f6a806219f84..63dd2d69e568 100644 --- a/drivers/staging/android/fiq_debugger/fiq_debugger.c +++ b/drivers/staging/android/fiq_debugger/fiq_debugger.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -400,7 +401,7 @@ static void fiq_debugger_work(struct work_struct *work) cmd += 6; while (*cmd == ' ') cmd++; - if (*cmd != '\0') + if ((*cmd != '\0') && sysrq_on()) kernel_restart(cmd); else kernel_restart(NULL); @@ -430,29 +431,39 @@ static void fiq_debugger_irq_exec(struct fiq_debugger_state *state, char *cmd) static void fiq_debugger_help(struct fiq_debugger_state *state) { fiq_debugger_printf(&state->output, - "FIQ Debugger commands:\n" - " pc PC status\n" - " regs Register dump\n" - " allregs Extended Register dump\n" - " bt Stack trace\n" - " reboot [] Reboot with command \n" - " reset [] Hard reset with command \n" - " irqs Interupt status\n" - " kmsg Kernel log\n" - " version Kernel version\n"); - fiq_debugger_printf(&state->output, - " sleep Allow sleep while in FIQ\n" - " nosleep Disable sleep while in FIQ\n" - " console Switch terminal to console\n" - " cpu Current CPU\n" - " cpu Switch to CPU\n"); + "FIQ Debugger commands:\n"); + if (sysrq_on()) { + fiq_debugger_printf(&state->output, + " pc PC status\n" + " regs Register dump\n" + " allregs Extended Register dump\n" + " bt Stack trace\n"); + fiq_debugger_printf(&state->output, + " reboot [] Reboot with command \n" + " reset [] Hard reset with command \n" + " irqs Interrupt status\n" + " kmsg Kernel log\n" + " version Kernel version\n"); + fiq_debugger_printf(&state->output, + " cpu Current CPU\n" + " cpu Switch to CPU\n" + " sysrq sysrq options\n" + " sysrq Execute sysrq with \n"); + } else { + fiq_debugger_printf(&state->output, + " reboot Reboot\n" + " reset Hard reset\n" + " irqs Interrupt status\n"); + } fiq_debugger_printf(&state->output, - " ps Process list\n" - " sysrq sysrq options\n" - " sysrq Execute sysrq with \n"); + " sleep Allow sleep while in FIQ\n" + " nosleep Disable sleep while in FIQ\n" + " console Switch terminal to console\n" + " ps Process list\n"); #ifdef CONFIG_KGDB - fiq_debugger_printf(&state->output, - " kgdb Enter kernel debugger\n"); + if (fiq_kgdb_enable) { + fiq_debugger_printf(&state->output, + " kgdb Enter kernel debugger\n"); #endif } @@ -484,18 +495,23 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) { fiq_debugger_help(state); } else if (!strcmp(cmd, "pc")) { - fiq_debugger_dump_pc(&state->output, regs); + if (sysrq_on()) + fiq_debugger_dump_pc(&state->output, regs); } else if (!strcmp(cmd, "regs")) { - fiq_debugger_dump_regs(&state->output, regs); + if (sysrq_on()) + fiq_debugger_dump_regs(&state->output, regs); } else if (!strcmp(cmd, "allregs")) { - fiq_debugger_dump_allregs(&state->output, regs); + if (sysrq_on()) + fiq_debugger_dump_allregs(&state->output, regs); } else if (!strcmp(cmd, "bt")) { - fiq_debugger_dump_stacktrace(&state->output, regs, 100, svc_sp); + if (sysrq_on()) + fiq_debugger_dump_stacktrace(&state->output, regs, + 100, svc_sp); } else if (!strncmp(cmd, "reset", 5)) { cmd += 5; while (*cmd == ' ') cmd++; - if (*cmd) { + if (*cmd && sysrq_on()) { char tmp_cmd[32]; strlcpy(tmp_cmd, cmd, sizeof(tmp_cmd)); machine_restart(tmp_cmd); @@ -505,9 +521,12 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, } else if (!strcmp(cmd, "irqs")) { fiq_debugger_dump_irqs(state); } else if (!strcmp(cmd, "kmsg")) { - fiq_debugger_dump_kernel_log(state); + if (sysrq_on()) + fiq_debugger_dump_kernel_log(state); } else if (!strcmp(cmd, "version")) { - fiq_debugger_printf(&state->output, "%s\n", linux_banner); + if (sysrq_on()) + fiq_debugger_printf(&state->output, "%s\n", + linux_banner); } else if (!strcmp(cmd, "sleep")) { state->no_sleep = false; fiq_debugger_printf(&state->output, "enabling sleep\n"); @@ -519,14 +538,17 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, fiq_debugger_uart_flush(state); state->console_enable = true; } else if (!strcmp(cmd, "cpu")) { - fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu); - } else if (!strncmp(cmd, "cpu ", 4)) { + if (sysrq_on()) + fiq_debugger_printf(&state->output, "cpu %d\n", + state->current_cpu); + } else if (!strncmp(cmd, "cpu ", 4) && sysrq_on()) { unsigned long cpu = 0; if (kstrtoul(cmd + 4, 10, &cpu) == 0) fiq_debugger_switch_cpu(state, cpu); else fiq_debugger_printf(&state->output, "invalid cpu\n"); - fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu); + fiq_debugger_printf(&state->output, "cpu %d\n", + state->current_cpu); } else { if (state->debug_busy) { fiq_debugger_printf(&state->output, diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 377b3592384e..4e6a3713fae0 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -58,10 +58,11 @@ static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE; static bool __read_mostly sysrq_always_enabled; -static bool sysrq_on(void) +bool sysrq_on(void) { return sysrq_enabled || sysrq_always_enabled; } +EXPORT_SYMBOL(sysrq_on); /* * A value of 1 means 'all', other nonzero values are an op mask: diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 8c71874e8485..c21a1f170768 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -43,6 +43,7 @@ struct sysrq_key_op { * are available -- else NULL's). */ +bool sysrq_on(void); void handle_sysrq(int key); void __handle_sysrq(int key, bool check_mask); int register_sysrq_key(int key, struct sysrq_key_op *op); -- GitLab From cd86a45f2c317ef766fbe33986b9e4cf903f252b Mon Sep 17 00:00:00 2001 From: Jim Lin Date: Fri, 13 Jan 2017 16:07:58 +0800 Subject: [PATCH 0695/1299] CHROMIUM: usb: gadget: configfs: Fix KASAN use-after-free When gadget is disconnected, running sequence is like this. . composite_disconnect . Call trace: usb_string_copy+0xd0/0x128 gadget_config_name_configuration_store+0x4 gadget_config_name_attr_store+0x40/0x50 configfs_write_file+0x198/0x1f4 vfs_write+0x100/0x220 SyS_write+0x58/0xa8 . configfs_composite_unbind . configfs_composite_bind In configfs_composite_bind, it has "cn->strings.s = cn->configuration;" When usb_string_copy is invoked. it would allocate memory, copy input string, release previous pointed memory space, and use new allocated memory. When gadget is connected, host sends down request to get information. Call trace: usb_gadget_get_string+0xec/0x168 lookup_string+0x64/0x98 composite_setup+0xa34/0x1ee8 If gadget is disconnected and connected quickly, in the failed case, cn->configuration memory has been released by usb_string_copy kfree but configfs_composite_bind hasn't been run in time to assign new allocated "cn->configuration" pointer to "cn->strings.s". When "strlen(s->s) of usb_gadget_get_string is being executed, the dangling memory is accessed, "BUG: KASAN: use-after-free" error occurs. BUG=chrome-os-partner:58412 TEST=After smaug device was connected to ubuntu PC host, detached and attached type-C cable quickly several times without seeing "BUG: KASAN: use-after-free in usb_gadget_get_string". Change-Id: I58240ee7c55ae8f8fb8597d14f09c5ac07abb032 Signed-off-by: Jim Lin Reviewed-on: https://chromium-review.googlesource.com/428059 Commit-Ready: Jim Lin Tested-by: Jim Lin Reviewed-by: Adrian Salido Reviewed-by: Benson Leung Git-repo: https://chromium.googlesource.com/chromiumos/third_party/kernel Git-commit: a7b597d255d70f6f0c6bfdfb7e4e04f67fcebf9d Signed-off-by: Dennis Cagle --- drivers/usb/gadget/configfs.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index bf2d0ce80c99..0a9346d000ae 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -137,21 +137,28 @@ struct gadget_config_name { struct list_head list; }; +#define MAX_USB_STRING_LEN 126 +#define MAX_USB_STRING_WITH_NULL_LEN (MAX_USB_STRING_LEN+1) + static int usb_string_copy(const char *s, char **s_copy) { int ret; char *str; char *copy = *s_copy; ret = strlen(s); - if (ret > 126) + if (ret > MAX_USB_STRING_LEN) return -EOVERFLOW; - str = kstrdup(s, GFP_KERNEL); - if (!str) - return -ENOMEM; + if (copy) { + str = copy; + } else { + str = kmalloc(MAX_USB_STRING_WITH_NULL_LEN, GFP_KERNEL); + if (!str) + return -ENOMEM; + } + strncpy(str, s, MAX_USB_STRING_WITH_NULL_LEN); if (str[ret - 1] == '\n') str[ret - 1] = '\0'; - kfree(copy); *s_copy = str; return 0; } -- GitLab From e3f474f65820825d9af2372aabffb14c7bc7e375 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Thu, 21 Jun 2018 14:18:03 -0700 Subject: [PATCH 0696/1299] iommu: arm-smmu: Remove sysfs bind/unbind files It is not realistic to expect iommu clients to handle userspace disabling the iommu driver. Change-Id: Ibc519c3ee5b9249492cb19da20eab0bb789dad80 Signed-off-by: Patrick Daly --- drivers/iommu/arm-smmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index d2629d41078a..96971e2d72e7 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -4686,6 +4686,7 @@ static struct platform_driver arm_smmu_driver = { .name = "arm-smmu", .of_match_table = of_match_ptr(arm_smmu_of_match), .pm = &arm_smmu_pm_ops, + .suppress_bind_attrs = true, }, .probe = arm_smmu_device_dt_probe, .remove = arm_smmu_device_remove, -- GitLab From 7dec44d582510aa24f1e7e7a15be64c76ca7d4ec Mon Sep 17 00:00:00 2001 From: Robb Glasser Date: Tue, 14 Feb 2017 13:25:46 -0800 Subject: [PATCH 0697/1299] Prevent heap overflow in uvc driver The size of uvc_control_mapping is user controlled leading to a potential heap overflow in the uvc driver. This adds a check to verify the user provided size fits within the bounds of the defined buffer size. Bug: 33300353 Change-Id: If29c1b396633b6137966a12e38f6fd1841b045bd Signed-off-by: Robb Glasser Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 8bc3ec72a02052187397d0de1a7b8bbe7340451c Signed-off-by: Dennis Cagle --- drivers/media/usb/uvc/uvc_ctrl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 20397aba6849..9f2a64cb691d 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1992,6 +1992,9 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, if (!found) return -ENOENT; + if (ctrl->info.size < mapping->size) + return -EINVAL; + if (mutex_lock_interruptible(&chain->ctrl_mutex)) return -ERESTARTSYS; -- GitLab From 72a0a19f2f4ee2628115b1455ad3a52c3cd2afca Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 3 Mar 2017 15:40:12 -0800 Subject: [PATCH 0698/1299] tracing: do not leak kernel addresses This likely breaks tracing tools like trace-cmd. It logs in the same format but now addresses are all 0x0. Bug: 34277115 Change-Id: Ifb0d4d2a184bf0d95726de05b1acee0287a375d9 Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 9ad8f2cc1bb73a3e2255dff4ee9c45c909869225 Signed-off-by: Srinivasa Rao Kuppala Signed-off-by: Dennis Cagle --- kernel/trace/trace_printk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index ad1d6164e946..e82cff5c842c 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -304,7 +304,7 @@ static int t_show(struct seq_file *m, void *v) if (!*fmt) return 0; - seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt); + seq_printf(m, "0x%lx : \"", 0L); /* * Tabs and new lines need to be converted. -- GitLab From be1e4788800f8429d3019e53141f5aae67a9a63d Mon Sep 17 00:00:00 2001 From: Swathi Sridhar Date: Thu, 21 Jun 2018 15:27:04 -0700 Subject: [PATCH 0699/1299] defconfig: sdxprairie: Enable SMMU driver for sdxprairie Enable SMMU driver, fast mapping and iommu debug for sdxprairie. Change-Id: Ie5063c6473dac94825bded2e24f84c5e5a23f55e Signed-off-by: Swathi Sridhar --- arch/arm/configs/vendor/sdxprairie-perf_defconfig | 5 +++++ arch/arm/configs/vendor/sdxprairie_defconfig | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/configs/vendor/sdxprairie-perf_defconfig b/arch/arm/configs/vendor/sdxprairie-perf_defconfig index 2eec35da3b18..b7a0d8e8f518 100644 --- a/arch/arm/configs/vendor/sdxprairie-perf_defconfig +++ b/arch/arm/configs/vendor/sdxprairie-perf_defconfig @@ -247,6 +247,11 @@ CONFIG_SPS_SUPPORT_NDP_BAM=y CONFIG_USB_BAM=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y +CONFIG_IOMMU_IO_PGTABLE_FAST=y +CONFIG_ARM_SMMU=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_DEBUG_TRACKING=y +CONFIG_IOMMU_TESTS=y CONFIG_QCOM_SMEM=y CONFIG_PWM=y CONFIG_ANDROID=y diff --git a/arch/arm/configs/vendor/sdxprairie_defconfig b/arch/arm/configs/vendor/sdxprairie_defconfig index 06a40fd9ab18..5f9bd5c32f18 100644 --- a/arch/arm/configs/vendor/sdxprairie_defconfig +++ b/arch/arm/configs/vendor/sdxprairie_defconfig @@ -236,6 +236,11 @@ CONFIG_SPS=y CONFIG_SPS_SUPPORT_NDP_BAM=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y +CONFIG_IOMMU_IO_PGTABLE_FAST=y +CONFIG_ARM_SMMU=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_DEBUG_TRACKING=y +CONFIG_IOMMU_TESTS=y CONFIG_QCOM_SMEM=y CONFIG_MSM_BOOT_STATS=y CONFIG_PWM=y -- GitLab From e957eb531d5a11a1ca0d855f900a0e09ea15fbd4 Mon Sep 17 00:00:00 2001 From: Vijaykumar Badiger Date: Thu, 21 Jun 2018 15:45:03 -0700 Subject: [PATCH 0700/1299] ARM: dts: msm: rename automotive device tree files for SA8150 Rename the Automotive device tree file names from sm8150 to sa8150. Change-Id: I453c3457085495471c56c37a808b3b34fd4631c9 Signed-off-by: Vijaykumar Badiger --- Documentation/devicetree/bindings/arm/msm/msm.txt | 4 ++-- arch/arm64/boot/dts/qcom/Makefile | 6 +++--- ...dp-star-overlay.dts => sa8150-adp-star-overlay.dts} | 8 ++++---- .../{sm8150-auto-adp-star.dts => sa8150-adp-star.dts} | 10 +++++----- ...{sm8150-auto-adp-star.dtsi => sa8150-adp-star.dtsi} | 2 +- ...auto-pmic-overlay.dtsi => sa8150-pmic-overlay.dtsi} | 0 ...m8150-auto-regulator.dtsi => sa8150-regulator.dtsi} | 0 .../boot/dts/qcom/{sm8150-auto.dts => sa8150.dts} | 6 +++--- .../boot/dts/qcom/{sm8150-auto.dtsi => sa8150.dtsi} | 10 +++++----- 9 files changed, 23 insertions(+), 23 deletions(-) rename arch/arm64/boot/dts/qcom/{sm8150-auto-adp-star-overlay.dts => sa8150-adp-star-overlay.dts} (76%) rename arch/arm64/boot/dts/qcom/{sm8150-auto-adp-star.dts => sa8150-adp-star.dts} (73%) rename arch/arm64/boot/dts/qcom/{sm8150-auto-adp-star.dtsi => sa8150-adp-star.dtsi} (98%) rename arch/arm64/boot/dts/qcom/{sm8150-auto-pmic-overlay.dtsi => sa8150-pmic-overlay.dtsi} (100%) rename arch/arm64/boot/dts/qcom/{sm8150-auto-regulator.dtsi => sa8150-regulator.dtsi} (100%) rename arch/arm64/boot/dts/qcom/{sm8150-auto.dts => sa8150.dts} (84%) rename arch/arm64/boot/dts/qcom/{sm8150-auto.dtsi => sa8150.dtsi} (96%) diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index cf28eb84fe8a..40d302efe0a9 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -163,8 +163,8 @@ compatible = "qcom,sm6150-idp" compatible = "qcom,qcs405-rumi" compatible = "qcom,qcs405-iot" compatible = "qcom,qcs403-iot" -compatible = "qcom,sm8150-auto-adp-star" -compatible = "qcom,auto-adp-star" +compatible = "qcom,sa8150-adp-star" +compatible = "qcom,adp-star" compatible = "qcom,sdxprairie-rumi" compatible = "qcom,sdxprairie-mtp" compatible = "qcom,sdxprairie-cdp" diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index d6e44ecc2ee1..6d1a678feb0e 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -25,7 +25,7 @@ ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y) sm8150-rumi-overlay.dtbo \ sm8150-qrd-overlay.dtbo \ sm8150-qrd-dvt-overlay.dtbo \ - sm8150-auto-adp-star-overlay.dtbo \ + sa8150-adp-star-overlay.dtbo \ sm8150p-cdp-overlay.dtbo \ sm8150p-mtp-overlay.dtbo \ sm8150p-qrd-overlay.dtbo \ @@ -39,7 +39,7 @@ sm8150-mtp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-rumi-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-qrd-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-qrd-dvt-overlay.dtbo-base := sm8150-v2.dtb -sm8150-auto-adp-star-overlay.dtbo-base := sm8150-auto.dtb +sa8150-adp-star-overlay.dtbo-base := sa8150.dtb sm8150-sdx50m-cdp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-sdx50m-mtp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-sdx50m-mtp-2.5k-panel-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb @@ -51,7 +51,7 @@ dtb-$(CONFIG_ARCH_SM8150) += sm8150-rumi.dtb \ sm8150-mtp.dtb \ sm8150-cdp.dtb \ sm8150-qrd.dtb \ - sm8150-auto-adp-star.dtb \ + sa8150-adp-star.dtb \ sm8150-v2-rumi.dtb \ sm8150-v2-mtp.dtb \ sm8150-v2-cdp.dtb \ diff --git a/arch/arm64/boot/dts/qcom/sm8150-auto-adp-star-overlay.dts b/arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts similarity index 76% rename from arch/arm64/boot/dts/qcom/sm8150-auto-adp-star-overlay.dts rename to arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts index 889797e681af..22af3db58f83 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-auto-adp-star-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts @@ -13,11 +13,11 @@ /dts-v1/; /plugin/; -#include "sm8150-auto-adp-star.dtsi" +#include "sa8150-adp-star.dtsi" / { - model = "Qualcomm Technologies, Inc. SM8150 AUTO-ADP-STAR"; - compatible = "qcom,sm8150-auto-adp-star", "qcom,sm8150", - "qcom,auto-adp-star"; + model = "Qualcomm Technologies, Inc. SA8150 ADP-STAR"; + compatible = "qcom,sa8150-adp-star", "qcom,sa8150", + "qcom,adp-star"; qcom,board-id = <25 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150-auto-adp-star.dts b/arch/arm64/boot/dts/qcom/sa8150-adp-star.dts similarity index 73% rename from arch/arm64/boot/dts/qcom/sm8150-auto-adp-star.dts rename to arch/arm64/boot/dts/qcom/sa8150-adp-star.dts index 250b080ae57c..9b104006e485 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-auto-adp-star.dts +++ b/arch/arm64/boot/dts/qcom/sa8150-adp-star.dts @@ -11,12 +11,12 @@ */ /dts-v1/; -#include "sm8150-auto.dtsi" -#include "sm8150-auto-adp-star.dtsi" +#include "sa8150.dtsi" +#include "sa8150-adp-star.dtsi" / { - model = "Qualcomm Technologies, Inc. SM8150 AUTO-ADP-STAR"; - compatible = "qcom,sm8150-auto-adp-star", "qcom,sm8150", - "qcom,auto-adp-star"; + model = "Qualcomm Technologies, Inc. SA8150 ADP-STAR"; + compatible = "qcom,sa8150-adp-star", "qcom,sa8150", + "qcom,adp-star"; qcom,board-id = <25 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150-auto-adp-star.dtsi b/arch/arm64/boot/dts/qcom/sa8150-adp-star.dtsi similarity index 98% rename from arch/arm64/boot/dts/qcom/sm8150-auto-adp-star.dtsi rename to arch/arm64/boot/dts/qcom/sa8150-adp-star.dtsi index 6a419fd61463..9631fbec0aa7 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-auto-adp-star.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8150-adp-star.dtsi @@ -13,7 +13,7 @@ #include #include -#include "sm8150-auto-pmic-overlay.dtsi" +#include "sa8150-pmic-overlay.dtsi" &qupv3_se0_spi { status = "ok"; diff --git a/arch/arm64/boot/dts/qcom/sm8150-auto-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sa8150-pmic-overlay.dtsi similarity index 100% rename from arch/arm64/boot/dts/qcom/sm8150-auto-pmic-overlay.dtsi rename to arch/arm64/boot/dts/qcom/sa8150-pmic-overlay.dtsi diff --git a/arch/arm64/boot/dts/qcom/sm8150-auto-regulator.dtsi b/arch/arm64/boot/dts/qcom/sa8150-regulator.dtsi similarity index 100% rename from arch/arm64/boot/dts/qcom/sm8150-auto-regulator.dtsi rename to arch/arm64/boot/dts/qcom/sa8150-regulator.dtsi diff --git a/arch/arm64/boot/dts/qcom/sm8150-auto.dts b/arch/arm64/boot/dts/qcom/sa8150.dts similarity index 84% rename from arch/arm64/boot/dts/qcom/sm8150-auto.dts rename to arch/arm64/boot/dts/qcom/sa8150.dts index e948626cf6d1..cc1ce1f51a3e 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-auto.dts +++ b/arch/arm64/boot/dts/qcom/sa8150.dts @@ -12,11 +12,11 @@ /dts-v1/; -#include "sm8150-auto.dtsi" +#include "sa8150.dtsi" / { - model = "Qualcomm Technologies, Inc. SM8150 AUTO SoC"; - compatible = "qcom,sm8150"; + model = "Qualcomm Technologies, Inc. SA8150 SoC"; + compatible = "qcom,sa8150"; qcom,pmic-name = "PM8150"; qcom,board-id = <0 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150-auto.dtsi b/arch/arm64/boot/dts/qcom/sa8150.dtsi similarity index 96% rename from arch/arm64/boot/dts/qcom/sm8150-auto.dtsi rename to arch/arm64/boot/dts/qcom/sa8150.dtsi index 5b1c5faa8cf4..d79e27f6c662 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-auto.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8150.dtsi @@ -13,12 +13,12 @@ #include "sm8150.dtsi" / { - model = "Qualcomm Technologies, Inc. SM8150 AUTO"; - qcom,msm-name = "SM8150 AUTO"; + model = "Qualcomm Technologies, Inc. SA8150"; + qcom,msm-name = "SA8150"; qcom,msm-id = <362 0x10000>; }; -/* Remove regulator nodes specific to SM8150 */ +/* Remove regulator nodes specific to SA8150 */ &soc { /delete-node/ regulator-pm8150-s4; /delete-node/ rpmh-regulator-msslvl; @@ -67,8 +67,8 @@ /delete-node/ rpmh-regulator-ldof6; }; -/* Add regulator nodes specific to SM8150 Auto */ -#include "sm8150-auto-regulator.dtsi" +/* Add regulator nodes specific to SA8150 */ +#include "sa8150-regulator.dtsi" &cam_csiphy0 { mipi-csi-vdd-supply = <&pm8150_2_l8>; -- GitLab From 7d1fc34efc515a5f9a1ecdd8a82ce97590096298 Mon Sep 17 00:00:00 2001 From: SaiVamshi Dobbali Date: Wed, 9 May 2018 18:15:43 +0530 Subject: [PATCH 0701/1299] msm vidc : Fix memory leak in venus_hfi_core_init() In venus_hfi_core_init() vote_data structure memory is allocated and it is being overwritten in consecutive function __init_bus() without freeing the original memory causing memory leak. Fix the memory leak issue by removing the default initialisation in __init_bus(). Change-Id: I007e6363327a32c4fd66bcaf02199fe627a4260f Signed-off-by: SaiVamshi Dobbali Signed-off-by: Maheshwar Ajja --- drivers/media/platform/msm/vidc/venus_hfi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 1776769e34bb..424d80d3d5b7 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -4071,7 +4071,6 @@ static int __init_bus(struct venus_hfi_device *device) devfreq_suspend_device(bus->devfreq); } - device->bus_vote = DEFAULT_BUS_VOTE; return 0; err_add_dev: -- GitLab From a0e89a86e837db49a336e8969f1a7128a0ec7902 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Thu, 21 Jun 2018 13:01:04 -0700 Subject: [PATCH 0702/1299] power: fg-memif: Fix incorrect usage of error return value 'Commit ac85d9878621 ("power: fg-memif: Modify FG SRAM access configuration over DMA")' made changes to fix the order of DMA request and release but it bought in an incorrect usage of error return value. While doing SRAM access over DMA, if there is an error, DMA should be released. "ret" is used to hold the error return value of fg_direct_mem_release() so that the previous error return value if any can be retained in "rc" and returned back. Fix it. Change-Id: Id3e9f1ec4bd3ae00a76399923e9e8d3f225f5bf4 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-memif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/fg-memif.c b/drivers/power/supply/qcom/fg-memif.c index d14a55db72fb..5f44934d57b6 100644 --- a/drivers/power/supply/qcom/fg-memif.c +++ b/drivers/power/supply/qcom/fg-memif.c @@ -1076,7 +1076,7 @@ static int __fg_direct_mem_rw(struct fg_dev *fg, u16 sram_addr, u8 offset, offset = 0; } - rc = fg_direct_mem_release(fg); + ret = fg_direct_mem_release(fg); if (ret < 0) { pr_err("Error in releasing direct_mem access rc=%d\n", rc); return ret; -- GitLab From a5a5ed7cc76b44aa5210452f16121ea0e8bb845d Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Thu, 21 Jun 2018 16:57:12 -0700 Subject: [PATCH 0703/1299] soc: qcom: qsee_ipc_irq: Sanitize IRQ desc There is a chance that the irq_to_desc function will return NULL if the client unregisters their IRQ. Check if desc is NULL before calling the IRQ_HANDLER. Change-Id: I10950e19138eb8e6f7673f61b7de78696e4c2c27 Signed-off-by: Chris Lew --- drivers/soc/qcom/qsee_ipc_irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qsee_ipc_irq.c b/drivers/soc/qcom/qsee_ipc_irq.c index 99a29c61f560..0e397261488b 100644 --- a/drivers/soc/qcom/qsee_ipc_irq.c +++ b/drivers/soc/qcom/qsee_ipc_irq.c @@ -100,7 +100,8 @@ static irqreturn_t qsee_intr(int irq, void *data) irq_pin = irq_find_mapping(qirq->domain, to_hwirq(i, j)); desc = irq_to_desc(irq_pin); - handle_simple_irq(desc); + if (desc) + handle_simple_irq(desc); regmap_write(qirq->regmap, bank->data->clear, BIT(j)); } -- GitLab From 0396304ed60b7d065ab93053fc6c8d5bd1304fd5 Mon Sep 17 00:00:00 2001 From: Robb Glasser Date: Fri, 24 Mar 2017 16:23:37 -0700 Subject: [PATCH 0704/1299] Prevent potential double frees in sg driver sg_ioctl could be spammed by requests, leading to a double free in __free_pages. This protects the entry points of sg_ioctl where the memory could be corrupted by a double call to __free_pages if multiple requests are happening concurrently. Bug:35644812 Change-Id: Ie13f65beb6974430f90292e2742841b26aecb8b1 Signed-off-by: Robb Glasser [dcagle@codeaurora.org: Resolve trivial merge conflicts] Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 22d8e80738b5ce8784d59b48b0b051a520da4bec Signed-off-by: Dennis Cagle --- drivers/scsi/sg.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 2eb1ac6da530..7486e81cf51c 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -498,7 +498,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) old_hdr->result = EIO; break; case DID_ERROR: - old_hdr->result = (srp->sense_b[0] == 0 && + old_hdr->result = (srp->sense_b[0] == 0 && hp->masked_status == GOOD) ? 0 : EIO; break; default: @@ -891,8 +891,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) return -ENXIO; if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR)) return -EFAULT; + mutex_lock(&sfp->parentdp->open_rel_lock); result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR, 1, read_only, 1, &srp); + mutex_unlock(&sfp->parentdp->open_rel_lock); if (result < 0) return result; result = wait_event_interruptible(sfp->read_wait, @@ -993,8 +995,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) result = get_user(val, ip); if (result) return result; - if (val < 0) - return -EINVAL; + if (val < 0) + return -EINVAL; val = min_t(int, val, max_sectors_bytes(sdp->device->request_queue)); mutex_lock(&sfp->f_mutex); @@ -1004,9 +1006,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) mutex_unlock(&sfp->f_mutex); return -EBUSY; } - + mutex_lock(&sfp->parentdp->open_rel_lock); sg_remove_scat(sfp, &sfp->reserve); sg_build_reserve(sfp, val); + mutex_unlock(&sfp->parentdp->open_rel_lock); } mutex_unlock(&sfp->f_mutex); return 0; @@ -1132,14 +1135,14 @@ static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned lon return -ENXIO; sdev = sdp->device; - if (sdev->host->hostt->compat_ioctl) { + if (sdev->host->hostt->compat_ioctl) { int ret; ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); return ret; } - + return -ENOIOCTLCMD; } #endif @@ -1635,7 +1638,7 @@ init_sg(void) else def_reserved_size = sg_big_buff; - rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), + rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), SG_MAX_DEVS, "sg"); if (rc) return rc; @@ -2295,7 +2298,7 @@ static const struct file_operations adio_fops = { }; static int sg_proc_single_open_dressz(struct inode *inode, struct file *file); -static ssize_t sg_proc_write_dressz(struct file *filp, +static ssize_t sg_proc_write_dressz(struct file *filp, const char __user *buffer, size_t count, loff_t *off); static const struct file_operations dressz_fops = { .owner = THIS_MODULE, @@ -2435,7 +2438,7 @@ static int sg_proc_single_open_adio(struct inode *inode, struct file *file) return single_open(file, sg_proc_seq_show_int, &sg_allow_dio); } -static ssize_t +static ssize_t sg_proc_write_adio(struct file *filp, const char __user *buffer, size_t count, loff_t *off) { @@ -2456,7 +2459,7 @@ static int sg_proc_single_open_dressz(struct inode *inode, struct file *file) return single_open(file, sg_proc_seq_show_int, &sg_big_buff); } -static ssize_t +static ssize_t sg_proc_write_dressz(struct file *filp, const char __user *buffer, size_t count, loff_t *off) { -- GitLab From 7e117411900043ec5aa820aaccef16706405655a Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Thu, 25 Jan 2018 18:45:48 -0800 Subject: [PATCH 0705/1299] ion: carveout: Add secure carveout heap type A secure carveout heap manages memory that may never be accessed by HLOS. Several pools of differing types of secure memory may be selected from based on the flags argument to ion_alloc(). Change-Id: Ieb3d043ab7d5a0e88a32042f9ba24b3535a863ec Signed-off-by: Patrick Daly --- .../devicetree/bindings/arm/msm/msm_ion.txt | 31 +++ drivers/staging/android/ion/ion.h | 5 + .../staging/android/ion/ion_carveout_heap.c | 201 +++++++++++++++++- drivers/staging/android/ion/ion_heap.c | 6 + drivers/staging/android/ion/ion_secure_util.c | 41 ++++ drivers/staging/android/ion/ion_secure_util.h | 1 + drivers/staging/android/ion/msm/msm_ion_of.c | 5 + drivers/staging/android/uapi/msm_ion.h | 2 + 8 files changed, 290 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/msm/msm_ion.txt b/Documentation/devicetree/bindings/arm/msm/msm_ion.txt index 3b6cf9c03463..5ef7cc1fc583 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm_ion.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm_ion.txt @@ -19,6 +19,7 @@ Required properties for Ion heaps the following: - "SYSTEM" - "CARVEOUT" + - "SECURE_CARVEOUT" - "DMA" - "HYP_CMA" - "SYSTEM_SECURE" @@ -28,6 +29,7 @@ Optional properties for Ion heaps - memory-region: phandle to memory region associated with heap. + Example: qcom,ion { compatible = "qcom,msm-ion"; @@ -57,3 +59,32 @@ Example: }; }; + +"SECURE_CARVEOUT" + +This heap type is expected to contain multiple child nodes. Each child node +shall contain the following required properties: + +- memory-region: +Refer to Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt + +- token: +A u32 containing the set of secure domains which will be able to access the +memory-region. + +Example: +qcom,ion { + compatible = "qcom,msm-ion"; + #address-cells = <1>; + #size-cells = <0>; + + qcom,ion-heap@14 { + reg = <14>; + qcom,ion-heap-type = "SECURE_CARVEOUT"; + + node1 { + memory-region = <&cp_region>; + token = ; + }; + }; +}; diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index a8b9baae205f..2f8fb2f4db12 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -37,6 +37,7 @@ #define ION_SYSTEM_HEAP_NAME "system" #define ION_MM_HEAP_NAME "mm" #define ION_SPSS_HEAP_NAME "spss" +#define ION_SECURE_CARVEOUT_HEAP_NAME "secure_carveout" #define ION_QSECOM_HEAP_NAME "qsecom" #define ION_QSECOM_TA_HEAP_NAME "qsecom_ta" #define ION_SECURE_HEAP_NAME "secure_heap" @@ -415,6 +416,10 @@ void ion_system_secure_heap_destroy(struct ion_heap *heap); struct ion_heap *ion_cma_secure_heap_create(struct ion_platform_heap *heap); void ion_cma_secure_heap_destroy(struct ion_heap *heap); +struct ion_heap *ion_secure_carveout_heap_create( + struct ion_platform_heap *heap); +void ion_secure_carveout_heap_destroy(struct ion_heap *heap); + /** * functions for creating and destroying a heap pool -- allows you * to keep a pool of pre allocated memory to use from your heap. Keeping diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index d66398d946dd..ffc7e8272178 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -22,7 +22,12 @@ #include #include #include +#include +#include +#include +#include #include "ion.h" +#include "ion_secure_util.h" #define ION_CARVEOUT_ALLOCATE_FAIL -1 @@ -122,7 +127,9 @@ static struct ion_heap_ops carveout_heap_ops = { .unmap_kernel = ion_heap_unmap_kernel, }; -struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) +static struct ion_heap *__ion_carveout_heap_create( + struct ion_platform_heap *heap_data, + bool sync) { struct ion_carveout_heap *carveout_heap; int ret; @@ -134,7 +141,8 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) page = pfn_to_page(PFN_DOWN(heap_data->base)); size = heap_data->size; - ion_pages_sync_for_device(dev, page, size, DMA_BIDIRECTIONAL); + if (sync) + ion_pages_sync_for_device(dev, page, size, DMA_BIDIRECTIONAL); ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL)); if (ret) @@ -159,6 +167,11 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) return &carveout_heap->heap; } +struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) +{ + return __ion_carveout_heap_create(heap_data, true); +} + void ion_carveout_heap_destroy(struct ion_heap *heap) { struct ion_carveout_heap *carveout_heap = @@ -168,3 +181,187 @@ void ion_carveout_heap_destroy(struct ion_heap *heap) kfree(carveout_heap); carveout_heap = NULL; } + +struct ion_sc_entry { + struct list_head list; + struct ion_heap *heap; + u32 token; +}; + +struct ion_sc_heap { + struct ion_heap heap; + struct device *dev; + struct list_head children; +}; + +static struct ion_heap *ion_sc_find_child(struct ion_heap *heap, u32 flags) +{ + struct ion_sc_heap *manager; + struct ion_sc_entry *entry; + + manager = container_of(heap, struct ion_sc_heap, heap); + flags = flags & ION_FLAGS_CP_MASK; + list_for_each_entry(entry, &manager->children, list) { + if (entry->token == flags) + return entry->heap; + } + return NULL; +} + +static int ion_sc_heap_allocate(struct ion_heap *heap, + struct ion_buffer *buffer, unsigned long len, + unsigned long flags) +{ + struct ion_heap *child; + + /* cache maintenance is not possible on secure memory */ + flags &= ~((unsigned long)ION_FLAG_CACHED); + buffer->flags = flags; + + child = ion_sc_find_child(heap, flags); + if (!child) + return -EINVAL; + return ion_carveout_heap_allocate(child, buffer, len, flags); +} + +static void ion_sc_heap_free(struct ion_buffer *buffer) +{ + struct ion_heap *child; + struct sg_table *table = buffer->sg_table; + struct page *page = sg_page(table->sgl); + phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); + + child = ion_sc_find_child(buffer->heap, buffer->flags); + if (!child) { + WARN(1, "ion_secure_carvout: invalid buffer flags on free. Memory will be leaked\n."); + return; + } + + ion_carveout_free(child, paddr, buffer->size); + sg_free_table(table); + kfree(table); +} + +static struct ion_heap_ops ion_sc_heap_ops = { + .allocate = ion_sc_heap_allocate, + .free = ion_sc_heap_free, +}; + +static int ion_sc_get_dt_token(struct ion_sc_entry *entry, + struct device_node *np, u64 base, u64 size) +{ + u32 token; + int ret = -EINVAL; + + if (of_property_read_u32(np, "token", &token)) + return -EINVAL; + + ret = ion_hyp_assign_from_flags(base, size, token); + if (ret) + pr_err("secure_carveout_heap: Assign token 0x%x failed\n", + token); + else + entry->token = token; + + return ret; +} + +static int ion_sc_add_child(struct ion_sc_heap *manager, + struct device_node *np) +{ + struct device *dev = manager->dev; + struct ion_platform_heap heap_data = {0}; + struct ion_sc_entry *entry; + struct device_node *phandle; + const __be32 *basep; + u64 base, size; + int ret; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + INIT_LIST_HEAD(&entry->list); + + phandle = of_parse_phandle(np, "memory-region", 0); + if (!phandle) + goto out_free; + + basep = of_get_address(phandle, 0, &size, NULL); + if (!basep) + goto out_free; + + base = of_translate_address(phandle, basep); + if (base == OF_BAD_ADDR) + goto out_free; + + heap_data.priv = dev; + heap_data.base = base; + heap_data.size = size; + + /* This will zero memory initially */ + entry->heap = __ion_carveout_heap_create(&heap_data, false); + if (IS_ERR(entry->heap)) + goto out_free; + + ret = ion_sc_get_dt_token(entry, np, base, size); + if (ret) + goto out_free_carveout; + + list_add(&entry->list, &manager->children); + dev_info(dev, "ion_secure_carveout: creating heap@0x%llx, size 0x%llx\n", + base, size); + return 0; + +out_free_carveout: + ion_carveout_heap_destroy(entry->heap); +out_free: + kfree(entry); + return -EINVAL; +} + +void ion_secure_carveout_heap_destroy(struct ion_heap *heap) +{ + struct ion_sc_heap *manager = + container_of(heap, struct ion_sc_heap, heap); + struct ion_sc_entry *entry, *tmp; + + list_for_each_entry_safe(entry, tmp, &manager->children, list) { + ion_carveout_heap_destroy(entry->heap); + kfree(entry); + } + kfree(manager); +} + +struct ion_heap *ion_secure_carveout_heap_create( + struct ion_platform_heap *heap_data) +{ + struct device *dev = heap_data->priv; + int ret; + struct ion_sc_heap *manager; + struct device_node *np; + + manager = kzalloc(sizeof(*manager), GFP_KERNEL); + if (!manager) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&manager->children); + manager->dev = dev; + + for_each_child_of_node(dev->of_node, np) { + ret = ion_sc_add_child(manager, np); + if (ret) { + dev_err(dev, "Creating child pool %s failed\n", + np->name); + goto err; + } + } + + manager->heap.ops = &ion_sc_heap_ops; + manager->heap.type = (enum ion_heap_type)ION_HEAP_TYPE_SECURE_CARVEOUT; + return &manager->heap; + +err: + ion_secure_carveout_heap_destroy(&manager->heap); + return ERR_PTR(-EINVAL); +} diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index a30fa2b2cd46..32426fc04220 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -348,6 +348,9 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) case (enum ion_heap_type)ION_HEAP_TYPE_SYSTEM_SECURE: heap = ion_system_secure_heap_create(heap_data); break; + case (enum ion_heap_type)ION_HEAP_TYPE_SECURE_CARVEOUT: + heap = ion_secure_carveout_heap_create(heap_data); + break; default: pr_err("%s: Invalid heap type %d\n", __func__, heap_data->type); @@ -403,6 +406,9 @@ void ion_heap_destroy(struct ion_heap *heap) case (enum ion_heap_type)ION_HEAP_TYPE_SYSTEM_SECURE: ion_system_secure_heap_destroy(heap); break; + case (enum ion_heap_type)ION_HEAP_TYPE_SECURE_CARVEOUT: + ion_secure_carveout_heap_destroy(heap); + break; default: pr_err("%s: Invalid heap type %d\n", __func__, heap->type); diff --git a/drivers/staging/android/ion/ion_secure_util.c b/drivers/staging/android/ion/ion_secure_util.c index 472763a29c18..fe46c5fdaab2 100644 --- a/drivers/staging/android/ion/ion_secure_util.c +++ b/drivers/staging/android/ion/ion_secure_util.c @@ -239,3 +239,44 @@ bool hlos_accessible_buffer(struct ion_buffer *buffer) return true; } + +int ion_hyp_assign_from_flags(u64 base, u64 size, unsigned long flags) +{ + u32 *vmids, *modes; + u32 nr, i; + int ret = -EINVAL; + u32 src_vm = VMID_HLOS; + + nr = count_set_bits(flags); + vmids = kcalloc(nr, sizeof(*vmids), GFP_KERNEL); + if (!vmids) + return -ENOMEM; + + modes = kcalloc(nr, sizeof(*modes), GFP_KERNEL); + if (!modes) { + kfree(vmids); + return -ENOMEM; + } + + if ((flags & ~ION_FLAGS_CP_MASK) || + populate_vm_list(flags, vmids, nr)) { + pr_err("%s: Failed to parse secure flags 0x%x\n", __func__, + flags); + goto out; + } + + for (i = 0; i < nr; i++) + if (vmids[i] == VMID_CP_SEC_DISPLAY) + modes[i] = PERM_READ; + else + modes[i] = PERM_READ | PERM_WRITE; + + ret = hyp_assign_phys(base, size, &src_vm, 1, vmids, modes, nr); + if (ret) + pr_err("%s: Assign call failed, flags 0x%x\n", __func__, flags); + +out: + kfree(modes); + kfree(vmids); + return ret; +} diff --git a/drivers/staging/android/ion/ion_secure_util.h b/drivers/staging/android/ion/ion_secure_util.h index ea9d85e75781..7947452daa48 100644 --- a/drivers/staging/android/ion/ion_secure_util.h +++ b/drivers/staging/android/ion/ion_secure_util.h @@ -25,6 +25,7 @@ int ion_hyp_unassign_sg_from_flags(struct sg_table *sgt, unsigned long flags, bool set_page_private); int ion_hyp_assign_sg_from_flags(struct sg_table *sgt, unsigned long flags, bool set_page_private); +int ion_hyp_assign_from_flags(u64 base, u64 size, unsigned long flags); bool hlos_accessible_buffer(struct ion_buffer *buffer); diff --git a/drivers/staging/android/ion/msm/msm_ion_of.c b/drivers/staging/android/ion/msm/msm_ion_of.c index 57a705f58b0f..1b5064033320 100644 --- a/drivers/staging/android/ion/msm/msm_ion_of.c +++ b/drivers/staging/android/ion/msm/msm_ion_of.c @@ -72,6 +72,10 @@ static struct ion_heap_desc ion_heap_meta[] = { { .id = ION_AUDIO_HEAP_ID, .name = ION_AUDIO_HEAP_NAME, + }, + { + .id = ION_SECURE_CARVEOUT_HEAP_ID, + .name = ION_SECURE_CARVEOUT_HEAP_NAME, } }; #endif @@ -87,6 +91,7 @@ static struct heap_types_info { MAKE_HEAP_TYPE_MAPPING(SYSTEM), MAKE_HEAP_TYPE_MAPPING(SYSTEM_CONTIG), MAKE_HEAP_TYPE_MAPPING(CARVEOUT), + MAKE_HEAP_TYPE_MAPPING(SECURE_CARVEOUT), MAKE_HEAP_TYPE_MAPPING(CHUNK), MAKE_HEAP_TYPE_MAPPING(DMA), MAKE_HEAP_TYPE_MAPPING(SECURE_DMA), diff --git a/drivers/staging/android/uapi/msm_ion.h b/drivers/staging/android/uapi/msm_ion.h index a725b84bcf45..578bd82fe521 100644 --- a/drivers/staging/android/uapi/msm_ion.h +++ b/drivers/staging/android/uapi/msm_ion.h @@ -17,6 +17,7 @@ enum msm_ion_heap_types { ION_HEAP_TYPE_SECURE_DMA = ION_HEAP_TYPE_MSM_START, ION_HEAP_TYPE_SYSTEM_SECURE, ION_HEAP_TYPE_HYP_CMA, + ION_HEAP_TYPE_SECURE_CARVEOUT, }; /** @@ -44,6 +45,7 @@ enum ion_heap_ids { * Newly added heap ids have to be #define(d) since all API changes must * include a new #define. */ +#define ION_SECURE_CARVEOUT_HEAP_ID 14 #define ION_QSECOM_TA_HEAP_ID 19 #define ION_AUDIO_HEAP_ID 28 #define ION_CAMERA_HEAP_ID 20 -- GitLab From 60b9f55a00f4e3684919b3154415a9c5f44d2d27 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Tue, 6 Feb 2018 17:38:54 -0800 Subject: [PATCH 0706/1299] ion: msm: Add support for VMID_CP_CDSP Add necessary flags for userspace to request this type of memory. Change-Id: Ic603cb6cf186f3dec483b5a769ed4c405667d9e4 Signed-off-by: Patrick Daly --- drivers/staging/android/ion/ion_secure_util.c | 5 ++++- drivers/staging/android/uapi/msm_ion.h | 2 ++ include/soc/qcom/secure_buffer.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_secure_util.c b/drivers/staging/android/ion/ion_secure_util.c index fe46c5fdaab2..93fafcac33ac 100644 --- a/drivers/staging/android/ion/ion_secure_util.c +++ b/drivers/staging/android/ion/ion_secure_util.c @@ -30,7 +30,8 @@ bool is_secure_vmid_valid(int vmid) vmid == VMID_CP_CAMERA_PREVIEW || vmid == VMID_CP_SPSS_SP || vmid == VMID_CP_SPSS_SP_SHARED || - vmid == VMID_CP_SPSS_HLOS_SHARED); + vmid == VMID_CP_SPSS_HLOS_SHARED || + vmid == VMID_CP_CDSP); } int get_secure_vmid(unsigned long flags) @@ -57,6 +58,8 @@ int get_secure_vmid(unsigned long flags) return VMID_CP_SPSS_SP_SHARED; if (flags & ION_FLAG_CP_SPSS_HLOS_SHARED) return VMID_CP_SPSS_HLOS_SHARED; + if (flags & ION_FLAG_CP_CDSP) + return VMID_CP_CDSP; return -EINVAL; } diff --git a/drivers/staging/android/uapi/msm_ion.h b/drivers/staging/android/uapi/msm_ion.h index 578bd82fe521..b5fec227f377 100644 --- a/drivers/staging/android/uapi/msm_ion.h +++ b/drivers/staging/android/uapi/msm_ion.h @@ -64,6 +64,8 @@ enum ion_heap_ids { #define ION_FLAG_CP_SEC_DISPLAY ION_BIT(25) #define ION_FLAG_CP_APP ION_BIT(26) #define ION_FLAG_CP_CAMERA_PREVIEW ION_BIT(27) +/* ION_FLAG_ALLOW_NON_CONTIG uses ION_BIT(28) */ +#define ION_FLAG_CP_CDSP ION_BIT(29) #define ION_FLAG_CP_SPSS_HLOS_SHARED ION_BIT(30) #define ION_FLAGS_CP_MASK 0x7FFF0000 diff --git a/include/soc/qcom/secure_buffer.h b/include/soc/qcom/secure_buffer.h index b9b333e266c8..75f017ce0dff 100644 --- a/include/soc/qcom/secure_buffer.h +++ b/include/soc/qcom/secure_buffer.h @@ -41,6 +41,7 @@ enum vmid { VMID_CP_CAMERA_PREVIEW = 0x1D, VMID_CP_SPSS_SP_SHARED = 0x22, VMID_CP_SPSS_HLOS_SHARED = 0x24, + VMID_CP_CDSP = 0x2A, VMID_LAST, VMID_INVAL = -1 }; -- GitLab From bbfa49a9523a1f17687bf199689a0b369624259d Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Tue, 31 Oct 2017 16:55:26 -0700 Subject: [PATCH 0707/1299] ANDROID: sound: rawmidi: Hold lock around realloc The SNDRV_RAWMIDI_STREAM_{OUTPUT,INPUT} ioctls may reallocate runtime->buffer while other kernel threads are accessing it. If the underlying krealloc() call frees the original buffer, then this can turn into a use-after-free. Most of these accesses happen while the thread is holding runtime->lock, and can be fixed by just holding the same lock while replacing runtime->buffer, however we can't hold this spinlock while snd_rawmidi_kernel_{read1,write1} are copying to/from userspace. We need to add and acquire a new mutex to prevent this from happening concurrently with reallocation. We hold this mutex during the entire reallocation process, to also prevent multiple concurrent reallocations leading to a double-free. Signed-off-by: Daniel Rosenberg bug: 64315347 Change-Id: I05764d4f1a38f373eb7c0ac1c98607ee5ff0eded [dcagle@codeaurora.org: Resolve trivial merge conflict] Git-repo: https://android.googlesource.com/kernel/msm Git-commit: d7193540482d11ff0ad3a07fc18717811641c6eb Signed-off-by: Dennis Cagle Signed-off-by: Aaditya Vohra --- include/sound/rawmidi.h | 1 + sound/core/rawmidi.c | 44 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index 6665cb29e1a2..9955e0b85de5 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -78,6 +78,7 @@ struct snd_rawmidi_runtime { size_t xruns; /* over/underruns counter */ /* misc */ spinlock_t lock; + struct mutex realloc_mutex; wait_queue_head_t sleep; /* event handler (new bytes, input only) */ void (*event)(struct snd_rawmidi_substream *substream); diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index f055ca10bbc1..4b44386d5d22 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -115,6 +115,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) return -ENOMEM; runtime->substream = substream; spin_lock_init(&runtime->lock); + mutex_init(&runtime->realloc_mutex); init_waitqueue_head(&runtime->sleep); INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work); runtime->event = NULL; @@ -636,8 +637,10 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, struct snd_rawmidi_params * params) { char *newbuf; + char *oldbuf; struct snd_rawmidi_runtime *runtime = substream->runtime; - + unsigned long flags; + if (substream->append && substream->use_count > 1) return -EBUSY; snd_rawmidi_drain_output(substream); @@ -648,13 +651,22 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, return -EINVAL; } if (params->buffer_size != runtime->buffer_size) { - newbuf = krealloc(runtime->buffer, params->buffer_size, + mutex_lock(&runtime->realloc_mutex); + newbuf = __krealloc(runtime->buffer, params->buffer_size, GFP_KERNEL); - if (!newbuf) + if (!newbuf) { + mutex_unlock(&runtime->realloc_mutex); return -ENOMEM; + } + spin_lock_irqsave(&runtime->lock, flags); + oldbuf = runtime->buffer; runtime->buffer = newbuf; runtime->buffer_size = params->buffer_size; runtime->avail = runtime->buffer_size; + spin_unlock_irqrestore(&runtime->lock, flags); + if (oldbuf != newbuf) + kfree(oldbuf); + mutex_unlock(&runtime->realloc_mutex); } runtime->avail_min = params->avail_min; substream->active_sensing = !params->no_active_sensing; @@ -666,7 +678,9 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, struct snd_rawmidi_params * params) { char *newbuf; + char *oldbuf; struct snd_rawmidi_runtime *runtime = substream->runtime; + unsigned long flags; snd_rawmidi_drain_input(substream); if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) { @@ -676,12 +690,21 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, return -EINVAL; } if (params->buffer_size != runtime->buffer_size) { - newbuf = krealloc(runtime->buffer, params->buffer_size, + mutex_lock(&runtime->realloc_mutex); + newbuf = __krealloc(runtime->buffer, params->buffer_size, GFP_KERNEL); - if (!newbuf) + if (!newbuf) { + mutex_unlock(&runtime->realloc_mutex); return -ENOMEM; + } + spin_lock_irqsave(&runtime->lock, flags); + oldbuf = runtime->buffer; runtime->buffer = newbuf; runtime->buffer_size = params->buffer_size; + spin_unlock_irqrestore(&runtime->lock, flags); + if (oldbuf != newbuf) + kfree(oldbuf); + mutex_unlock(&runtime->realloc_mutex); } runtime->avail_min = params->avail_min; return 0; @@ -954,6 +977,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, unsigned long appl_ptr; spin_lock_irqsave(&runtime->lock, flags); + if (userbuf) + mutex_lock(&runtime->realloc_mutex); while (count > 0 && runtime->avail) { count1 = runtime->buffer_size - runtime->appl_ptr; if (count1 > count) @@ -973,6 +998,7 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, spin_unlock_irqrestore(&runtime->lock, flags); if (copy_to_user(userbuf + result, runtime->buffer + appl_ptr, count1)) { + mutex_unlock(&runtime->realloc_mutex); return result > 0 ? result : -EFAULT; } spin_lock_irqsave(&runtime->lock, flags); @@ -981,6 +1007,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, count -= count1; } spin_unlock_irqrestore(&runtime->lock, flags); + if (userbuf) + mutex_unlock(&runtime->realloc_mutex); return result; } @@ -1245,10 +1273,14 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, return -EINVAL; result = 0; + if (userbuf) + mutex_lock(&runtime->realloc_mutex); spin_lock_irqsave(&runtime->lock, flags); if (substream->append) { if ((long)runtime->avail < count) { spin_unlock_irqrestore(&runtime->lock, flags); + if (userbuf) + mutex_unlock(&runtime->realloc_mutex); return -EAGAIN; } } @@ -1284,6 +1316,8 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, __end: count1 = runtime->avail < runtime->buffer_size; spin_unlock_irqrestore(&runtime->lock, flags); + if (userbuf) + mutex_unlock(&runtime->realloc_mutex); if (count1) snd_rawmidi_output_trigger(substream, 1); return result; -- GitLab From 8368f6cd8c0c69a813d8e0b00ee91b1212f45b9b Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Wed, 13 Jun 2018 16:12:44 -0700 Subject: [PATCH 0708/1299] msm: gsi: allow start_xfer when channel is not running GSI doorbell can be rang even if the channel is not running. The doorbell will be cached and will be applied when channel moves to running state. This change allow ringing the doorbell for channels before starting them to avoid a race condition between initial buffer replenish and channel start. Change-Id: Iea187b98319c16a259d7b8ba5ee9abc338f52c30 Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/gsi/gsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index ac00093c6590..71fb666862cf 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -2777,7 +2777,7 @@ int gsi_start_xfer(unsigned long chan_hdl) return -GSI_STATUS_UNSUPPORTED_OP; } - if (ctx->state != GSI_CHAN_STATE_STARTED) { + if (ctx->state == GSI_CHAN_STATE_NOT_ALLOCATED) { GSIERR("bad state %d\n", ctx->state); return -GSI_STATUS_UNSUPPORTED_OP; } -- GitLab From 7ed25593f2a8a635e9a6763562ca6ae13ef074da Mon Sep 17 00:00:00 2001 From: Sayali Lokhande Date: Fri, 8 Jun 2018 14:00:54 +0530 Subject: [PATCH 0709/1299] scsi: ufs: Get UFS ref_clk min/max voltage from device tree This change allows selecting the UFS ref clk voltage level by setting ref-clk-min-uV and ref-clk-max-uV in device tree. If ref_clk voltage level setting is not found in device tree, use default values provided by driver. Change-Id: Ia3c0c61a508045448057cc3057a30546a458bfc9 Signed-off-by: Sayali Lokhande --- .../devicetree/bindings/ufs/ufs-qcom.txt | 2 ++ drivers/scsi/ufs/ufs-qcom.c | 20 ++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt index 17c3c40a3146..6ba6e0cf7777 100644 --- a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt +++ b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt @@ -36,6 +36,8 @@ Optional properties: - vdda-pll-max-microamp : specifies max. load that can be drawn from pll supply - vddp-ref-clk-supply : phandle to UFS device ref_clk pad power supply - vddp-ref-clk-max-microamp : specifies max. load that can be drawn from this supply +- vddp-ref-clk-min-uV : specifies min voltage that can be set for reference clock supply +- vddp-ref-clk-max-uV : specifies max voltage that can be set for reference clock supply - qcom,disable-lpm : disable various LPM mechanisms in UFS for platform compatibility (limit link to PWM Gear-1, 1-lane slow mode; disable hibernate, and avoid suspend/resume) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 119b3d8de689..fb42b567a1b7 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2086,8 +2086,22 @@ static int ufs_qcom_parse_reg_info(struct ufs_qcom_host *host, char *name, dev_err(dev, "%s: %s get failed, err=%d\n", __func__, vreg->name, ret); } - vreg->min_uV = VDDP_REF_CLK_MIN_UV; - vreg->max_uV = VDDP_REF_CLK_MAX_UV; + + snprintf(prop_name, MAX_PROP_SIZE, "%s-min-uV", name); + ret = of_property_read_u32(np, prop_name, &vreg->min_uV); + if (ret) { + dev_dbg(dev, "%s: unable to find %s err %d, using default\n", + __func__, prop_name, ret); + vreg->min_uV = VDDP_REF_CLK_MIN_UV; + } + + snprintf(prop_name, MAX_PROP_SIZE, "%s-max-uV", name); + ret = of_property_read_u32(np, prop_name, &vreg->max_uV); + if (ret) { + dev_dbg(dev, "%s: unable to find %s err %d, using default\n", + __func__, prop_name, ret); + vreg->max_uV = VDDP_REF_CLK_MAX_UV; + } out: if (!ret) -- GitLab From 54a13ce6862383e85d8b73ca3e96747210ebcd53 Mon Sep 17 00:00:00 2001 From: Vijay Viswanath Date: Fri, 5 Jan 2018 11:22:03 +0530 Subject: [PATCH 0710/1299] mmc: sdhci-msm: Remove printing tlmm physical address Remove the debug log which leaks physical address, eventhough tlmm is no longer used. Change-Id: Ie6968c46ea063e9192e2ccef053107ee7d8f5775 Signed-off-by: Vijay Viswanath --- drivers/mmc/host/sdhci-msm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index bdfa411e13ad..0ee20275a65d 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -4769,8 +4769,6 @@ static int sdhci_msm_probe(struct platform_device *pdev) goto vreg_deinit; } writel_relaxed(readl_relaxed(tlmm_mem) | 0x2, tlmm_mem); - dev_dbg(&pdev->dev, "tlmm reg %pa value 0x%08x\n", - &tlmm_memres->start, readl_relaxed(tlmm_mem)); } /* -- GitLab From d27f681eb3a53ac2fd212ee45ca268350f286f93 Mon Sep 17 00:00:00 2001 From: Vijay Viswanath Date: Mon, 11 Dec 2017 10:50:29 +0530 Subject: [PATCH 0711/1299] mmc: cmdq-hci: Change unnecessary pr_err logs to pr_debug Now that CMDQ device and driver are stable, Change unnecessary pr_err logs to pr_debug. Also use %pK instead of %p while printing addresses to avoid leaking of kernel addresses. Change-Id: I95683ffe0410daef86dd9a376f5769d8f40ae990 Signed-off-by: Vijay Viswanath --- drivers/mmc/host/cmdq_hci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c index 4f210dd891dc..eade0cd87a0b 100644 --- a/drivers/mmc/host/cmdq_hci.c +++ b/drivers/mmc/host/cmdq_hci.c @@ -359,7 +359,7 @@ static int cmdq_host_alloc_tdl(struct cmdq_host *cq_host) if (!cq_host->desc_base || !cq_host->trans_desc_base) return -ENOMEM; - pr_info("desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n", + pr_debug("desc-base: 0x%pK trans-base: 0x%pK\n desc_dma 0x%llx trans_dma: 0x%llx\n", cq_host->desc_base, cq_host->trans_desc_base, (unsigned long long)cq_host->desc_dma_base, (unsigned long long) cq_host->trans_desc_dma_base); -- GitLab From f3e7fd5a694111352e43b1f5a6c252f15143360f Mon Sep 17 00:00:00 2001 From: Vijay Viswanath Date: Mon, 11 Dec 2017 10:52:49 +0530 Subject: [PATCH 0712/1299] mmc: sdhci-msm: Avoid leaking kernel address from mmc platform driver Remove printing the address of sdhci_msm driver variables to avoid leaking the kernel addresses. This is no longer required as the sdhci_msm driver has become stable. Change-Id: I88d9d66d9d00adad8ec79df689ae80f4aae97b7e Signed-off-by: Vijay Viswanath --- drivers/mmc/host/sdhci-msm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index bdfa411e13ad..d6921e767d55 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -4199,11 +4199,10 @@ void sdhci_msm_pm_qos_cpu_init(struct sdhci_host *host, group->latency = PM_QOS_DEFAULT_VALUE; pm_qos_add_request(&group->req, PM_QOS_CPU_DMA_LATENCY, group->latency); - pr_info("%s (): voted for group #%d (mask=0x%lx) latency=%d (0x%p)\n", + pr_info("%s (): voted for group #%d (mask=0x%lx) latency=%d\n", __func__, i, group->req.cpus_affine.bits[0], - group->latency, - &latency[i].latency[SDHCI_PERFORMANCE_MODE]); + group->latency); } msm_host->pm_qos_prev_cpu = -1; msm_host->pm_qos_group_enable = true; -- GitLab From 96b13eb594f57c8ab781a47e55036ef7c5888ef7 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 22 Jun 2018 09:36:37 +0530 Subject: [PATCH 0713/1299] ARM: dts: msm: Add support for AOP clocks for SDMMAGPIE Add the clock_aop device node for clients to request for the clock. Change-Id: I5de1ae3b0c8220891abb2ee7affb707a933eb710 Signed-off-by: Taniya Das --- arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index ab204a1dcd93..74db21462fc1 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -19,6 +19,7 @@ #include #include #include +#include #include / { @@ -594,6 +595,12 @@ #clock-cells = <1>; }; + clock_aop: qcom,aopclk { + compatible = "qcom,dummycc"; + clock-output-names = "aop_clocks"; + #clock-cells = <1>; + }; + clock_gcc: qcom,gcc { compatible = "qcom,dummycc"; clock-output-names = "gcc_clocks"; -- GitLab From f4390b0e92dc7621cf9dde4ca3095a7de52a1948 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Thu, 31 May 2018 19:07:58 +0530 Subject: [PATCH 0714/1299] msm: ipa: mhi: Enable IPC logging for IPA MHI driver IPC logging was missed to enable on mhi driver, enable it. Change-Id: Ibc203e8c9dc8d05107a5eba396c76e29c1646479 Signed-off-by: Mohammed Javid --- .../msm/ipa/ipa_clients/ipa_mhi_client.c | 33 ++++++++++++++++--- drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c | 4 +-- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c index 761c0a80dbe3..6cbfa4bcc12f 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -22,11 +22,36 @@ #include "../ipa_v3/ipa_pm.h" #define IPA_MHI_DRV_NAME "ipa_mhi_client" + #define IPA_MHI_DBG(fmt, args...) \ - pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \ - __func__, __LINE__, ## args) + do { \ + pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + +#define IPA_MHI_DBG_LOW(fmt, args...) \ + do { \ + pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + + #define IPA_MHI_ERR(fmt, args...) \ - pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) + do { \ + pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + #define IPA_MHI_FUNC_ENTRY() \ IPA_MHI_DBG("ENTRY\n") #define IPA_MHI_FUNC_EXIT() \ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c index 4eb44b40862d..0b1abf5eda94 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c @@ -56,9 +56,9 @@ #define IPA_MHI_FUNC_ENTRY() \ - IPA_MHI_DBG_LOW("ENTRY\n") + IPA_MHI_DBG("ENTRY\n") #define IPA_MHI_FUNC_EXIT() \ - IPA_MHI_DBG_LOW("EXIT\n") + IPA_MHI_DBG("EXIT\n") #define IPA_MHI_MAX_UL_CHANNELS 1 #define IPA_MHI_MAX_DL_CHANNELS 1 -- GitLab From d1f8e7a19393999c2ccbe1e6ef0e34ddca68596b Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Fri, 22 Jun 2018 08:50:57 +0300 Subject: [PATCH 0715/1299] wil6210: remove crash dump collection from OTP section In some cases where the device is stuck, reading from OTP can timeout. As OTP section is known there is no need to read it during device crash dump collection. Adding a new field to struct fw_map to indicate if to include this section in crash dump collection. Change-Id: I7d333db1b6ced675883f72a4693c34b71f20c49d Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/wil6210.h | 1 + .../net/wireless/ath/wil6210/wil_crash_dump.c | 5 +- drivers/net/wireless/ath/wil6210/wmi.c | 86 +++++++++---------- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index dffb00c8857a..6ecfeb1fbe30 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -411,6 +411,7 @@ struct fw_map { u32 host; /* PCI/Host address - BAR0 + 0x880000 */ const char *name; /* for debugfs */ bool fw; /* true if FW mapping, false if UCODE mapping */ + bool crash_dump; /* true if should be dumped during crash dump */ }; /* array size should be in sync with actual definition in the wmi.c */ diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c index 1ed330674d9b..dc33a0b4c3fa 100644 --- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c +++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015,2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -36,7 +37,7 @@ static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil, for (i = 1; i < ARRAY_SIZE(fw_mapping); i++) { map = &fw_mapping[i]; - if (!map->fw) + if (!map->crash_dump) continue; if (map->host < host_min) @@ -85,7 +86,7 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { map = &fw_mapping[i]; - if (!map->fw) + if (!map->crash_dump) continue; data = (void * __force)wil->csr + HOSTADDR(map->host); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 49f25ac3382b..9d82c37ece6f 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -90,28 +90,28 @@ MODULE_PARM_DESC(led_id, */ const struct fw_map sparrow_fw_mapping[] = { /* FW code RAM 256k */ - {0x000000, 0x040000, 0x8c0000, "fw_code", true}, + {0x000000, 0x040000, 0x8c0000, "fw_code", true, true}, /* FW data RAM 32k */ - {0x800000, 0x808000, 0x900000, "fw_data", true}, + {0x800000, 0x808000, 0x900000, "fw_data", true, true}, /* periph data 128k */ - {0x840000, 0x860000, 0x908000, "fw_peri", true}, + {0x840000, 0x860000, 0x908000, "fw_peri", true, true}, /* various RGF 40k */ - {0x880000, 0x88a000, 0x880000, "rgf", true}, + {0x880000, 0x88a000, 0x880000, "rgf", true, true}, /* AGC table 4k */ - {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true}, + {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true}, /* Pcie_ext_rgf 4k */ - {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true}, + {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true}, /* mac_ext_rgf 512b */ - {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true}, + {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true, true}, /* upper area 548k */ - {0x8c0000, 0x949000, 0x8c0000, "upper", true}, + {0x8c0000, 0x949000, 0x8c0000, "upper", true, true}, /* UCODE areas - accessible by debugfs blobs but not by * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas! */ /* ucode code RAM 128k */ - {0x000000, 0x020000, 0x920000, "uc_code", false}, + {0x000000, 0x020000, 0x920000, "uc_code", false, false}, /* ucode data RAM 16k */ - {0x800000, 0x804000, 0x940000, "uc_data", false}, + {0x800000, 0x804000, 0x940000, "uc_data", false, false}, }; /** @@ -119,7 +119,7 @@ const struct fw_map sparrow_fw_mapping[] = { * it is a bit larger to support extra features */ const struct fw_map sparrow_d0_mac_rgf_ext = { - 0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true + 0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true, true }; /** @@ -135,34 +135,34 @@ const struct fw_map sparrow_d0_mac_rgf_ext = { */ const struct fw_map talyn_fw_mapping[] = { /* FW code RAM 1M */ - {0x000000, 0x100000, 0x900000, "fw_code", true}, + {0x000000, 0x100000, 0x900000, "fw_code", true, true}, /* FW data RAM 128k */ - {0x800000, 0x820000, 0xa00000, "fw_data", true}, + {0x800000, 0x820000, 0xa00000, "fw_data", true, true}, /* periph. data RAM 96k */ - {0x840000, 0x858000, 0xa20000, "fw_peri", true}, + {0x840000, 0x858000, 0xa20000, "fw_peri", true, true}, /* various RGF 40k */ - {0x880000, 0x88a000, 0x880000, "rgf", true}, + {0x880000, 0x88a000, 0x880000, "rgf", true, true}, /* AGC table 4k */ - {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true}, + {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true}, /* Pcie_ext_rgf 4k */ - {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true}, + {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true}, /* mac_ext_rgf 1344b */ - {0x88c000, 0x88c540, 0x88c000, "mac_rgf_ext", true}, + {0x88c000, 0x88c540, 0x88c000, "mac_rgf_ext", true, true}, /* ext USER RGF 4k */ - {0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true}, + {0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true, true}, /* OTP 4k */ - {0x8a0000, 0x8a1000, 0x8a0000, "otp", true}, + {0x8a0000, 0x8a1000, 0x8a0000, "otp", true, false}, /* DMA EXT RGF 64k */ - {0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true}, + {0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true, true}, /* upper area 1536k */ - {0x900000, 0xa80000, 0x900000, "upper", true}, + {0x900000, 0xa80000, 0x900000, "upper", true, true}, /* UCODE areas - accessible by debugfs blobs but not by * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas! */ /* ucode code RAM 256k */ - {0x000000, 0x040000, 0xa38000, "uc_code", false}, + {0x000000, 0x040000, 0xa38000, "uc_code", false, false}, /* ucode data RAM 32k */ - {0x800000, 0x808000, 0xa78000, "uc_data", false}, + {0x800000, 0x808000, 0xa78000, "uc_data", false, false}, }; /** @@ -178,46 +178,46 @@ const struct fw_map talyn_fw_mapping[] = { */ const struct fw_map talyn_mb_fw_mapping[] = { /* FW code RAM 768k */ - {0x000000, 0x0c0000, 0x900000, "fw_code", true}, + {0x000000, 0x0c0000, 0x900000, "fw_code", true, true}, /* FW data RAM 128k */ - {0x800000, 0x820000, 0xa00000, "fw_data", true}, + {0x800000, 0x820000, 0xa00000, "fw_data", true, true}, /* periph. data RAM 96k */ - {0x840000, 0x858000, 0xa20000, "fw_peri", true}, + {0x840000, 0x858000, 0xa20000, "fw_peri", true, true}, /* various RGF 40k */ - {0x880000, 0x88a000, 0x880000, "rgf", true}, + {0x880000, 0x88a000, 0x880000, "rgf", true, true}, /* AGC table 4k */ - {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true}, + {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true}, /* Pcie_ext_rgf 4k */ - {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true}, + {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true}, /* mac_ext_rgf 2256b */ - {0x88c000, 0x88c8d0, 0x88c000, "mac_rgf_ext", true}, + {0x88c000, 0x88c8d0, 0x88c000, "mac_rgf_ext", true, true}, /* ext USER RGF 4k */ - {0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true}, + {0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true, true}, /* SEC PKA 16k */ - {0x890000, 0x894000, 0x890000, "sec_pka", true}, + {0x890000, 0x894000, 0x890000, "sec_pka", true, true}, /* SEC KDF RGF 3096b */ - {0x898000, 0x898c18, 0x898000, "sec_kdf_rgf", true}, + {0x898000, 0x898c18, 0x898000, "sec_kdf_rgf", true, true}, /* SEC MAIN 2124b */ - {0x89a000, 0x89a84c, 0x89a000, "sec_main", true}, + {0x89a000, 0x89a84c, 0x89a000, "sec_main", true, true}, /* OTP 4k */ - {0x8a0000, 0x8a1000, 0x8a0000, "otp", true}, + {0x8a0000, 0x8a1000, 0x8a0000, "otp", true, false}, /* DMA EXT RGF 64k */ - {0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true}, + {0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true, true}, /* DUM USER RGF 528b */ - {0x8c0000, 0x8c0210, 0x8c0000, "dum_user_rgf", true}, + {0x8c0000, 0x8c0210, 0x8c0000, "dum_user_rgf", true, true}, /* DMA OFU 296b */ - {0x8c2000, 0x8c2128, 0x8c2000, "dma_ofu", true}, + {0x8c2000, 0x8c2128, 0x8c2000, "dma_ofu", true, true}, /* ucode debug 4k */ - {0x8c3000, 0x8c4000, 0x8c3000, "ucode_debug", true}, + {0x8c3000, 0x8c4000, 0x8c3000, "ucode_debug", true, true}, /* upper area 1536k */ - {0x900000, 0xa80000, 0x900000, "upper", true}, + {0x900000, 0xa80000, 0x900000, "upper", true, true}, /* UCODE areas - accessible by debugfs blobs but not by * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas! */ /* ucode code RAM 256k */ - {0x000000, 0x040000, 0xa38000, "uc_code", false}, + {0x000000, 0x040000, 0xa38000, "uc_code", false, false}, /* ucode data RAM 32k */ - {0x800000, 0x808000, 0xa78000, "uc_data", false}, + {0x800000, 0x808000, 0xa78000, "uc_data", false, false}, }; struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE]; -- GitLab From 3c3889337e97e8a7035e00bc7384dde7264a73b6 Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Thu, 21 Jun 2018 18:38:29 -0700 Subject: [PATCH 0716/1299] power: smb5-lib: Fix Type-C CTM status Typec-C connector temperature mitgation status is reported one level higher than what it is supposed to be, which leads to over-reduction of USB input current limit. Fix it. Change-Id: I547efece8e9cd6e2b076713af822b8dada2661f5 Signed-off-by: Harry Yang --- drivers/power/supply/qcom/qpnp-smb5.c | 2 +- drivers/power/supply/qcom/smb5-lib.c | 32 +++++++++------------------ drivers/power/supply/qcom/smb5-lib.h | 3 +-- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 3e2cc6c231f0..f263813e5856 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -611,7 +611,7 @@ static int smb5_usb_get_prop(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CONNECTOR_HEALTH: if (chg->connector_health == -EINVAL) - rc = smblib_get_prop_connector_health(chg, val); + val->intval = smblib_get_prop_connector_health(chg); else val->intval = chg->connector_health; break; diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index ef298f777010..2ff4cd1d2168 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -2324,8 +2324,7 @@ int smblib_get_prop_die_health(struct smb_charger *chg, return 0; } -int smblib_get_prop_connector_health(struct smb_charger *chg, - union power_supply_propval *val) +int smblib_get_prop_connector_health(struct smb_charger *chg) { int rc; u8 stat; @@ -2334,28 +2333,19 @@ int smblib_get_prop_connector_health(struct smb_charger *chg, if (rc < 0) { smblib_err(chg, "Couldn't read CONNECTOR_TEMP_STATUS_REG, rc=%d\n", rc); - return rc; + return POWER_SUPPLY_HEALTH_UNKNOWN; } - /* Thermal status bits are mutually exclusive */ - switch (stat) { - case CONNECTOR_TEMP_LB_BIT: - val->intval = POWER_SUPPLY_HEALTH_COOL; - break; - case CONNECTOR_TEMP_UB_BIT: - val->intval = POWER_SUPPLY_HEALTH_WARM; - break; - case CONNECTOR_TEMP_RST_BIT: - val->intval = POWER_SUPPLY_HEALTH_HOT; - break; - case CONNECTOR_TEMP_SHDN_BIT: - val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; - break; - default: - val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; - } + if (stat & CONNECTOR_TEMP_RST_BIT) + return POWER_SUPPLY_HEALTH_OVERHEAT; - return 0; + if (stat & CONNECTOR_TEMP_UB_BIT) + return POWER_SUPPLY_HEALTH_HOT; + + if (stat & CONNECTOR_TEMP_LB_BIT) + return POWER_SUPPLY_HEALTH_WARM; + + return POWER_SUPPLY_HEALTH_COOL; } #define SDP_CURRENT_UA 500000 diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 5a720836dc03..b977a5fe168b 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -517,8 +517,7 @@ int smblib_get_prop_charger_temp(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_die_health(struct smb_charger *chg, union power_supply_propval *val); -int smblib_get_prop_connector_health(struct smb_charger *chg, - union power_supply_propval *val); +int smblib_get_prop_connector_health(struct smb_charger *chg); int smblib_set_prop_pd_current_max(struct smb_charger *chg, const union power_supply_propval *val); int smblib_set_prop_sdp_current_max(struct smb_charger *chg, -- GitLab From 2baef1347f6f1622e65076b6c91d0e74fde2c0f4 Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Thu, 21 Jun 2018 19:16:21 -0700 Subject: [PATCH 0717/1299] power: smb5: Disable SMB thermal regulation Disable SMB temp sensing/regulation for both SMB1355 and SMB1390. SMB1390 has its own over-temp shutdown and has thermal balancing SW to adjust PM/SMB charger current ratio using VBUS/VWLS. SMB1355 has both CTM and thermal balance to regulate SMB ICHG. Change-Id: I9fdedbb4055dc757187531d6aa0b5394c3916c1c Signed-off-by: Harry Yang --- drivers/power/supply/qcom/qpnp-smb5.c | 9 +++++++++ drivers/power/supply/qcom/smb5-reg.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index f263813e5856..49515c6a8725 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -1607,6 +1607,15 @@ static int smb5_init_hw(struct smb5 *chip) return rc; } + /* Disable SMB Temperature ADC INT */ + rc = smblib_masked_write(chg, MISC_THERMREG_SRC_CFG_REG, + THERMREG_SMB_ADC_SRC_EN_BIT, 0); + if (rc < 0) { + dev_err(chg->dev, "Couldn't configure SMB thermal regulation rc=%d\n", + rc); + return rc; + } + /* Use SW based VBUS control, disable HW autonomous mode */ rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h index a8255b5416bc..d25d484681ed 100644 --- a/drivers/power/supply/qcom/smb5-reg.h +++ b/drivers/power/supply/qcom/smb5-reg.h @@ -387,6 +387,9 @@ enum { #define AICL_RERUN_TIME_CFG_REG (MISC_BASE + 0x61) #define AICL_RERUN_TIME_12S_VAL 0x01 +#define MISC_THERMREG_SRC_CFG_REG (MISC_BASE + 0x70) +#define THERMREG_SMB_ADC_SRC_EN_BIT BIT(5) + #define MISC_SMB_CFG_REG (MISC_BASE + 0x90) #define SMB_EN_SEL_BIT BIT(4) #define CP_EN_POLARITY_CFG_BIT BIT(3) -- GitLab From 3d4d2a30e6d2bed29267c3b592ca9054b4d1dfe2 Mon Sep 17 00:00:00 2001 From: Vijay Viswanath Date: Fri, 5 Jan 2018 10:40:28 +0530 Subject: [PATCH 0718/1299] mmc: sdhci: Avoid leaking kernel addresses Use %pK instead of %p in debug logs so that kernel addresses don't get leaked when debug logs are dynamically enabled. Change-Id: I3c0df8a8db6643ab547d8599dd03b54030f76ece Signed-off-by: Vijay Viswanath --- drivers/mmc/host/sdhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 77d0c7de6b2e..473f977637c5 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3158,13 +3158,13 @@ static void sdhci_adma_show_error(struct sdhci_host *host) struct sdhci_adma2_64_desc *dma_desc = desc; if (host->flags & SDHCI_USE_64_BIT_DMA) - DBG("%p: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", + DBG("%pK: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", desc, le32_to_cpu(dma_desc->addr_hi), le32_to_cpu(dma_desc->addr_lo), le16_to_cpu(dma_desc->len), le16_to_cpu(dma_desc->cmd)); else - DBG("%p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", + DBG("%pK: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", desc, le32_to_cpu(dma_desc->addr_lo), le16_to_cpu(dma_desc->len), le16_to_cpu(dma_desc->cmd)); -- GitLab From 9d0e4cf60ca2e1caa3030fd90bbb0cdb4bc1eb2e Mon Sep 17 00:00:00 2001 From: Shrey Vijay Date: Fri, 25 May 2018 19:57:17 +0530 Subject: [PATCH 0719/1299] ARM: dts: msm: Add QUPV3 and Slimbus DT nodes for SDMMAGPIE Add initial device tree nodes for QUPV3 serial engine and Slimbus instances to support buses protocols for SDMMAGPIE. Change-Id: I08113ec5c104ee973f9f640d516dd6287333397f Signed-off-by: Shrey Vijay Signed-off-by: Mukesh Kumar Savaliya --- .../boot/dts/qcom/sdmmagpie-pinctrl.dtsi | 801 ++++++++++++++++++ arch/arm64/boot/dts/qcom/sdmmagpie-qupv3.dtsi | 565 ++++++++++++ arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 51 ++ 3 files changed, 1417 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sdmmagpie-qupv3.dtsi diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi index d466f4d3ab7e..dcbb1cf0e0fc 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi @@ -19,5 +19,806 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + + /* QUPv3 South SE mappings */ + /* SE 0 pin mappings */ + qupv3_se0_i2c_pins: qupv3_se0_i2c_pins { + qupv3_se0_i2c_active: qupv3_se0_i2c_active { + mux { + pins = "gpio49", "gpio50"; + function = "qup00"; + }; + + config { + pins = "gpio49", "gpio50"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se0_i2c_sleep: qupv3_se0_i2c_sleep { + mux { + pins = "gpio49", "gpio50"; + function = "gpio"; + }; + + config { + pins = "gpio49", "gpio50"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se0_spi_pins: qupv3_se0_spi_pins { + qupv3_se0_spi_active: qupv3_se0_spi_active { + mux { + pins = "gpio49", "gpio50", "gpio51", + "gpio52"; + function = "qup00"; + }; + + config { + pins = "gpio49", "gpio50", "gpio51", + "gpio52"; + drive-strength = <6>; + bias-disable; + }; + }; + + qupv3_se0_spi_sleep: qupv3_se0_spi_sleep { + mux { + pins = "gpio49", "gpio50", "gpio51", + "gpio52"; + function = "gpio"; + }; + + config { + pins = "gpio49", "gpio50", "gpio51", + "gpio52"; + drive-strength = <6>; + bias-disable; + }; + }; + }; + + /* SE 1 pin mappings */ + qupv3_se1_i2c_pins: qupv3_se1_i2c_pins { + qupv3_se1_i2c_active: qupv3_se1_i2c_active { + mux { + pins = "gpio0", "gpio1"; + function = "qup01"; + }; + + config { + pins = "gpio0", "gpio1"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se1_i2c_sleep: qupv3_se1_i2c_sleep { + mux { + pins = "gpio0", "gpio1"; + function = "gpio"; + }; + + config { + pins = "gpio0", "gpio1"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se1_spi_pins: qupv3_se1_spi_pins { + qupv3_se1_spi_active: qupv3_se1_spi_active { + mux { + pins = "gpio0", "gpio1", "gpio2", + "gpio3"; + function = "qup01"; + }; + + config { + pins = "gpio0", "gpio1", "gpio2", + "gpio3"; + drive-strength = <6>; + bias-disable; + }; + }; + + qupv3_se1_spi_sleep: qupv3_se1_spi_sleep { + mux { + pins = "gpio0", "gpio1", "gpio2", + "gpio3"; + function = "gpio"; + }; + + config { + pins = "gpio0", "gpio1", "gpio2", + "gpio3"; + drive-strength = <6>; + bias-disable; + }; + }; + }; + + /* SE 2 pin mappings */ + qupv3_se2_i2c_pins: qupv3_se2_i2c_pins { + qupv3_se2_i2c_active: qupv3_se2_i2c_active { + mux { + pins = "gpio34", "gpio35"; + function = "qup02"; + }; + + config { + pins = "gpio34", "gpio35"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se2_i2c_sleep: qupv3_se2_i2c_sleep { + mux { + pins = "gpio34", "gpio35"; + function = "gpio"; + }; + + config { + pins = "gpio34", "gpio35"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + /* SE 3 pin mappings */ + qupv3_se3_i2c_pins: qupv3_se3_i2c_pins { + qupv3_se3_i2c_active: qupv3_se3_i2c_active { + mux { + pins = "gpio38", "gpio39"; + function = "qup03"; + }; + + config { + pins = "gpio38", "gpio39"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se3_i2c_sleep: qupv3_se3_i2c_sleep { + mux { + pins = "gpio38", "gpio39"; + function = "gpio"; + }; + + config { + pins = "gpio38", "gpio39"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se3_4uart_pins: qupv3_se3_4uart_pins { + qupv3_se3_ctsrx: qupv3_se3_ctsrx { + mux { + pins = "gpio38", "gpio41"; + function = "qup03"; + }; + + config { + pins = "gpio38", "gpio41"; + drive-strength = <2>; + bias-no-pull; + }; + }; + + qupv3_se3_rts: qupv3_se3_rts { + mux { + pins = "gpio39"; + function = "qup03"; + }; + + config { + pins = "gpio39"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + qupv3_se3_tx: qupv3_se3_tx { + mux { + pins = "gpio40"; + function = "qup03"; + }; + + config { + pins = "gpio40"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se3_spi_pins: qupv3_se3_spi_pins { + qupv3_se3_spi_active: qupv3_se3_spi_active { + mux { + pins = "gpio38", "gpio39", "gpio40", + "gpio41"; + function = "qup03"; + }; + + config { + pins = "gpio38", "gpio39", "gpio40", + "gpio41"; + drive-strength = <6>; + bias-disable; + }; + }; + + qupv3_se3_spi_sleep: qupv3_se3_spi_sleep { + mux { + pins = "gpio38", "gpio39", "gpio40", + "gpio41"; + function = "gpio"; + }; + + config { + pins = "gpio38", "gpio39", "gpio40", + "gpio41"; + drive-strength = <6>; + bias-disable; + }; + }; + }; + + /* SE 4 pin mappings */ + qupv3_se4_i2c_pins: qupv3_se4_i2c_pins { + qupv3_se4_i2c_active: qupv3_se4_i2c_active { + mux { + pins = "gpio53", "gpio54"; + function = "qup04"; + }; + + config { + pins = "gpio53", "gpio54"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se4_i2c_sleep: qupv3_se4_i2c_sleep { + mux { + pins = "gpio53", "gpio54"; + function = "gpio"; + }; + + config { + pins = "gpio53", "gpio54"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se4_4uart_pins: qupv3_se4_4uart_pins { + qupv3_se4_ctsrx: qupv3_se4_ctsrx { + mux { + pins = "gpio53", "gpio56"; + function = "qup04"; + }; + + config { + pins = "gpio53", "gpio56"; + drive-strength = <2>; + bias-no-pull; + }; + }; + + qupv3_se4_rts: qupv3_se4_rts { + mux { + pins = "gpio54"; + function = "qup04"; + }; + + config { + pins = "gpio54"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + qupv3_se4_tx: qupv3_se4_tx { + mux { + pins = "gpio55"; + function = "qup04"; + }; + + config { + pins = "gpio55"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se4_spi_pins: qupv3_se4_spi_pins { + qupv3_se4_spi_active: qupv3_se4_spi_active { + mux { + pins = "gpio53", "gpio54", "gpio55", + "gpio56"; + function = "qup04"; + }; + + config { + pins = "gpio53", "gpio54", "gpio55", + "gpio56"; + drive-strength = <6>; + bias-disable; + }; + }; + + qupv3_se4_spi_sleep: qupv3_se4_spi_sleep { + mux { + pins = "gpio53", "gpio54", "gpio55", + "gpio56"; + function = "gpio"; + }; + + config { + pins = "gpio53", "gpio54", "gpio55", + "gpio56"; + drive-strength = <6>; + bias-disable; + }; + }; + }; + + /* QUPv3 North instances */ + /* SE 6 pin mappings */ + qupv3_se6_i2c_pins: qupv3_se6_i2c_pins { + qupv3_se6_i2c_active: qupv3_se6_i2c_active { + mux { + pins = "gpio59", "gpio60"; + function = "qup10"; + }; + + config { + pins = "gpio59", "gpio60"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se6_i2c_sleep: qupv3_se6_i2c_sleep { + mux { + pins = "gpio59", "gpio60"; + function = "gpio"; + }; + + config { + pins = "gpio59", "gpio60"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se6_spi_pins: qupv3_se6_spi_pins { + qupv3_se6_spi_active: qupv3_se6_spi_active { + mux { + pins = "gpio59", "gpio60", "gpio61", + "gpio62"; + function = "qup10"; + }; + + config { + pins = "gpio59", "gpio60", "gpio61", + "gpio62"; + drive-strength = <6>; + bias-disable; + }; + }; + + qupv3_se6_spi_sleep: qupv3_se6_spi_sleep { + mux { + pins = "gpio59", "gpio60", "gpio61", + "gpio62"; + function = "gpio"; + }; + + config { + pins = "gpio59", "gpio60", "gpio61", + "gpio62"; + drive-strength = <6>; + bias-disable; + }; + }; + }; + + /* SE 7 pin mappings */ + qupv3_se7_i2c_pins: qupv3_se7_i2c_pins { + qupv3_se7_i2c_active: qupv3_se7_i2c_active { + mux { + pins = "gpio6", "gpio7"; + function = "qup11"; + }; + + config { + pins = "gpio6", "gpio7"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se7_i2c_sleep: qupv3_se7_i2c_sleep { + mux { + pins = "gpio6", "gpio7"; + function = "gpio"; + }; + + config { + pins = "gpio6", "gpio7"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se7_spi_pins: qupv3_se7_spi_pins { + qupv3_se7_spi_active: qupv3_se7_spi_active { + mux { + pins = "gpio6", "gpio7", "gpio8", + "gpio9"; + function = "qup11"; + }; + + config { + pins = "gpio6", "gpio7", "gpio8", + "gpio9"; + drive-strength = <6>; + bias-disable; + }; + }; + + qupv3_se7_spi_sleep: qupv3_se7_spi_sleep { + mux { + pins = "gpio6", "gpio7", "gpio8", + "gpio9"; + function = "gpio"; + }; + + config { + pins = "gpio6", "gpio7", "gpio8", + "gpio9"; + drive-strength = <6>; + bias-disable; + }; + }; + }; + + /* SE 8 pin mappings */ + qupv3_se8_i2c_pins: qupv3_se8_i2c_pins { + qupv3_se8_i2c_active: qupv3_se8_i2c_active { + mux { + pins = "gpio42", "gpio43"; + function = "qup12"; + }; + + config { + pins = "gpio42", "gpio43"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se8_i2c_sleep: qupv3_se8_i2c_sleep { + mux { + pins = "gpio42", "gpio43"; + function = "gpio"; + }; + + config { + pins = "gpio42", "gpio43"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se8_2uart_pins: qupv3_se8_2uart_pins { + qupv3_se8_2uart_active: qupv3_se8_2uart_active { + mux { + pins = "gpio44", "gpio45"; + function = "qup12"; + }; + + config { + pins = "gpio44", "gpio45"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se8_2uart_sleep: qupv3_se8_2uart_sleep { + mux { + pins = "gpio44", "gpio45"; + function = "gpio"; + }; + + config { + pins = "gpio44", "gpio45"; + drive-strength = <2>; + bias-disable; + }; + }; + }; + + qupv3_se8_spi_pins: qupv3_se8_spi_pins { + qupv3_se8_spi_active: qupv3_se8_spi_active { + mux { + pins = "gpio42", "gpio43", "gpio44", + "gpio45"; + function = "qup12"; + }; + + config { + pins = "gpio42", "gpio43", "gpio44", + "gpio45"; + drive-strength = <6>; + bias-disable; + }; + }; + + qupv3_se8_spi_sleep: qupv3_se8_spi_sleep { + mux { + pins = "gpio42", "gpio43", "gpio44", + "gpio45"; + function = "gpio"; + }; + + config { + pins = "gpio42", "gpio43", "gpio44", + "gpio45"; + drive-strength = <6>; + bias-disable; + }; + }; + }; + + /* SE 9 pin mappings */ + qupv3_se9_i2c_pins: qupv3_se9_i2c_pins { + qupv3_se9_i2c_active: qupv3_se9_i2c_active { + mux { + pins = "gpio46", "gpio47"; + function = "qup13"; + }; + + config { + pins = "gpio46", "gpio47"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se9_i2c_sleep: qupv3_se9_i2c_sleep { + mux { + pins = "gpio46", "gpio47"; + function = "gpio"; + }; + + config { + pins = "gpio6", "gpio7"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + /* SE 10 pin mappings */ + qupv3_se10_i2c_pins: qupv3_se10_i2c_pins { + qupv3_se10_i2c_active: qupv3_se10_i2c_active { + mux { + pins = "gpio110", "gpio111"; + function = "qup14"; + }; + + config { + pins = "gpio110", "gpio111"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se10_i2c_sleep: qupv3_se10_i2c_sleep { + mux { + pins = "gpio110", "gpio111"; + function = "gpio"; + }; + + config { + pins = "gpio110", "gpio111"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se10_4uart_pins: qupv3_se10_4uart_pins { + qupv3_se10_ctsrx: qupv3_se10_ctsrx { + mux { + pins = "gpio110", "gpio113"; + function = "qup14"; + }; + + config { + pins = "gpio110", "gpio113"; + drive-strength = <2>; + bias-no-pull; + }; + }; + + qupv3_se10_rts: qupv3_se10_rts { + mux { + pins = "gpio111"; + function = "qup14"; + }; + + config { + pins = "gpio111"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + qupv3_se10_tx: qupv3_se10_tx { + mux { + pins = "gpio112"; + function = "qup14"; + }; + + config { + pins = "gpio112"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se10_spi_pins: qupv3_se10_spi_pins { + qupv3_se10_spi_active: qupv3_se10_spi_active { + mux { + pins = "gpio110", "gpio111", "gpio112", + "gpio113"; + function = "qup14"; + }; + + config { + pins = "gpio110", "gpio111", "gpio112", + "gpio113"; + drive-strength = <6>; + bias-disable; + }; + }; + + qupv3_se10_spi_sleep: qupv3_se10_spi_sleep { + mux { + pins = "gpio110", "gpio111", "gpio112", + "gpio113"; + function = "gpio"; + }; + + config { + pins = "gpio110", "gpio111", "gpio112", + "gpio113"; + drive-strength = <6>; + bias-disable; + }; + }; + }; + + /* SE 11 pin mappings */ + qupv3_se11_i2c_pins: qupv3_se11_i2c_pins { + qupv3_se11_i2c_active: qupv3_se11_i2c_active { + mux { + pins = "gpio101", "gpio102"; + function = "qup15"; + }; + + config { + pins = "gpio101", "gpio102"; + drive-strength = <2>; + bias-disable; + }; + }; + + qupv3_se11_i2c_sleep: qupv3_se11_i2c_sleep { + mux { + pins = "gpio101", "gpio102"; + function = "gpio"; + }; + + config { + pins = "gpio101", "gpio102"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se11_4uart_pins: qupv3_se11_4uart_pins { + qupv3_se11_ctsrx: qupv3_se11_ctsrx { + mux { + pins = "gpio101", "gpio92"; + function = "qup15"; + }; + + config { + pins = "gpio101", "gpio92"; + drive-strength = <2>; + bias-no-pull; + }; + }; + + qupv3_se11_rts: qupv3_se11_rts { + mux { + pins = "gpio102"; + function = "qup15"; + }; + + config { + pins = "gpio102"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + qupv3_se11_tx: qupv3_se11_tx { + mux { + pins = "gpio103"; + function = "qup15"; + }; + + config { + pins = "gpio103"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + qupv3_se11_spi_pins: qupv3_se11_spi_pins { + qupv3_se11_spi_active: qupv3_se11_spi_active { + mux { + pins = "gpio101", "gpio102", "gpio103", + "gpio92"; + function = "qup15"; + }; + + config { + pins = "gpio101", "gpio102", "gpio103", + "gpio92"; + drive-strength = <6>; + bias-disable; + }; + }; + + qupv3_se11_spi_sleep: qupv3_se11_spi_sleep { + mux { + pins = "gpio101", "gpio102", "gpio103", + "gpio92"; + function = "gpio"; + }; + + config { + pins = "gpio101", "gpio102", "gpio103", + "gpio92"; + drive-strength = <6>; + bias-disable; + }; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-qupv3.dtsi new file mode 100644 index 000000000000..70e03825fc96 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-qupv3.dtsi @@ -0,0 +1,565 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +&soc { + /* QUPv3 South instances */ + qupv3_0: qcom,qupv3_0_geni_se@0x8c0000 { + compatible = "qcom,qupv3-geni-se"; + reg = <0x8c0000 0x2000>; + qcom,bus-mas-id = ; + qcom,bus-slv-id = ; + qcom,iommu-s1-bypass; + + iommu_qupv3_0_geni_se_cb: qcom,iommu_qupv3_0_geni_se_cb { + compatible = "qcom,qupv3-geni-se-cb"; + iommus = <&apps_smmu 0x203 0x0>; + }; + }; + + /* I2C */ + qupv3_se0_i2c: i2c@0x880000 { + compatible = "qcom,i2c-geni"; + reg = <0x880000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S0_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + dmas = <&gpi_dma0 0 0 3 64 0>, + <&gpi_dma0 1 0 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se0_i2c_active>; + pinctrl-1 = <&qupv3_se0_i2c_sleep>; + qcom,wrapper-core = <&qupv3_0>; + status = "disabled"; + }; + + qupv3_se1_i2c: i2c@0x884000 { + compatible = "qcom,i2c-geni"; + reg = <0x884000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S1_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + dmas = <&gpi_dma0 0 1 3 64 0>, + <&gpi_dma0 1 1 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se1_i2c_active>; + pinctrl-1 = <&qupv3_se1_i2c_sleep>; + qcom,wrapper-core = <&qupv3_0>; + status = "disabled"; + }; + + qupv3_se2_i2c: i2c@0x888000 { + compatible = "qcom,i2c-geni"; + reg = <0x888000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S2_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + dmas = <&gpi_dma0 0 2 3 64 0>, + <&gpi_dma0 1 2 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se2_i2c_active>; + pinctrl-1 = <&qupv3_se2_i2c_sleep>; + qcom,wrapper-core = <&qupv3_0>; + status = "disabled"; + }; + + qupv3_se3_i2c: i2c@0x88c000 { + compatible = "qcom,i2c-geni"; + reg = <0x88c000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S3_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + dmas = <&gpi_dma0 0 3 3 64 0>, + <&gpi_dma0 1 3 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se3_i2c_active>; + pinctrl-1 = <&qupv3_se3_i2c_sleep>; + qcom,wrapper-core = <&qupv3_0>; + status = "disabled"; + }; + + qupv3_se4_i2c: i2c@0x890000 { + compatible = "qcom,i2c-geni"; + reg = <0x890000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S4_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + dmas = <&gpi_dma0 0 4 3 64 0>, + <&gpi_dma0 1 4 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se4_i2c_active>; + pinctrl-1 = <&qupv3_se4_i2c_sleep>; + qcom,wrapper-core = <&qupv3_0>; + status = "disabled"; + }; + + /*HS UART*/ + qupv3_se3_4uart: qcom,qup_uart@0x88c000 { + compatible = "qcom,msm-geni-serial-hs"; + reg = <0x88c000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S3_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se3_ctsrx>, <&qupv3_se3_rts>, + <&qupv3_se3_tx>; + pinctrl-1 = <&qupv3_se3_ctsrx>, <&qupv3_se3_rts>, + <&qupv3_se3_tx>; + interrupts-extended = <&pdc GIC_SPI 604 0>, + <&tlmm 41 0>; + status = "disabled"; + qcom,wakeup-byte = <0xFD>; + qcom,wrapper-core = <&qupv3_0>; + }; + + qupv3_se4_4uart: qcom,qup_uart@0x890000 { + compatible = "qcom,msm-geni-serial-hs"; + reg = <0x890000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S4_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se4_ctsrx>, <&qupv3_se4_rts>, + <&qupv3_se4_tx>; + pinctrl-1 = <&qupv3_se4_ctsrx>, <&qupv3_se4_rts>, + <&qupv3_se4_tx>; + interrupts-extended = <&pdc GIC_SPI 605 0>, + <&tlmm 56 0>; + status = "disabled"; + qcom,wakeup-byte = <0xFD>; + qcom,wrapper-core = <&qupv3_0>; + }; + + /* SPI */ + qupv3_se0_spi: spi@0x880000 { + compatible = "qcom,spi-geni"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x880000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S0_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se0_spi_active>; + pinctrl-1 = <&qupv3_se0_spi_sleep>; + interrupts = ; + spi-max-frequency = <50000000>; + qcom,wrapper-core = <&qupv3_0>; + dmas = <&gpi_dma0 0 0 1 64 0>, + <&gpi_dma0 1 0 1 64 0>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + qupv3_se1_spi: spi@0x884000 { + compatible = "qcom,spi-geni"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x884000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S1_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se1_spi_active>; + pinctrl-1 = <&qupv3_se1_spi_sleep>; + interrupts = ; + spi-max-frequency = <50000000>; + qcom,wrapper-core = <&qupv3_0>; + dmas = <&gpi_dma0 0 1 1 64 0>, + <&gpi_dma0 1 1 1 64 0>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + qupv3_se3_spi: spi@0x88c000 { + compatible = "qcom,spi-geni"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x88c000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S3_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se3_spi_active>; + pinctrl-1 = <&qupv3_se3_spi_sleep>; + interrupts = ; + spi-max-frequency = <50000000>; + qcom,wrapper-core = <&qupv3_0>; + dmas = <&gpi_dma0 0 3 1 64 0>, + <&gpi_dma0 1 3 1 64 0>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + qupv3_se4_spi: spi@0x890000 { + compatible = "qcom,spi-geni"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x890000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S4_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se4_spi_active>; + pinctrl-1 = <&qupv3_se4_spi_sleep>; + interrupts = ; + spi-max-frequency = <50000000>; + qcom,wrapper-core = <&qupv3_0>; + dmas = <&gpi_dma0 0 4 1 64 0>, + <&gpi_dma0 1 4 1 64 0>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + + /* QUPv3 North Instances */ + qupv3_1: qcom,qupv3_1_geni_se@0xac0000 { + compatible = "qcom,qupv3-geni-se"; + reg = <0xac0000 0x2000>; + qcom,bus-mas-id = ; + qcom,bus-slv-id = ; + qcom,iommu-s1-bypass; + + iommu_qupv3_1_geni_se_cb: qcom,iommu_qupv3_1_geni_se_cb { + compatible = "qcom,qupv3-geni-se-cb"; + iommus = <&apps_smmu 0x4c3 0x0>; + }; + }; + + /* Debug UART Instance for CDP/MTP/RUMI platform */ + qupv3_se8_2uart: qcom,qup_uart@0xa88000 { + compatible = "qcom,msm-geni-console"; + reg = <0xa88000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S2_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se8_2uart_active>; + pinctrl-1 = <&qupv3_se8_2uart_sleep>; + interrupts = ; + qcom,wrapper-core = <&qupv3_1>; + status = "disabled"; + }; + + /* I2C */ + qupv3_se6_i2c: i2c@0xa80000 { + compatible = "qcom,i2c-geni"; + reg = <0xa80000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S0_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + dmas = <&gpi_dma1 0 0 3 64 0>, + <&gpi_dma1 1 0 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se6_i2c_active>; + pinctrl-1 = <&qupv3_se6_i2c_sleep>; + qcom,wrapper-core = <&qupv3_1>; + status = "disabled"; + }; + + qupv3_se7_i2c: i2c@0xa84000 { + compatible = "qcom,i2c-geni"; + reg = <0xa84000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S1_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + dmas = <&gpi_dma1 0 1 3 64 0>, + <&gpi_dma1 1 1 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se7_i2c_active>; + pinctrl-1 = <&qupv3_se7_i2c_sleep>; + qcom,wrapper-core = <&qupv3_1>; + status = "disabled"; + }; + + qupv3_se8_i2c: i2c@0xa88000 { + compatible = "qcom,i2c-geni"; + reg = <0xa88000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S2_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + dmas = <&gpi_dma1 0 2 3 64 0>, + <&gpi_dma1 1 2 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se8_i2c_active>; + pinctrl-1 = <&qupv3_se8_i2c_sleep>; + qcom,wrapper-core = <&qupv3_1>; + status = "disabled"; + }; + + qupv3_se9_i2c: i2c@0xa8c000 { + compatible = "qcom,i2c-geni"; + reg = <0xa8c000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S3_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + dmas = <&gpi_dma1 0 3 3 64 0>, + <&gpi_dma1 1 3 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se9_i2c_active>; + pinctrl-1 = <&qupv3_se9_i2c_sleep>; + qcom,wrapper-core = <&qupv3_1>; + status = "disabled"; + }; + + qupv3_se10_i2c: i2c@0xa90000 { + compatible = "qcom,i2c-geni"; + reg = <0xa90000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S4_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + dmas = <&gpi_dma1 0 4 3 64 0>, + <&gpi_dma1 1 4 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se10_i2c_active>; + pinctrl-1 = <&qupv3_se10_i2c_sleep>; + qcom,wrapper-core = <&qupv3_1>; + status = "disabled"; + }; + + qupv3_se11_i2c: i2c@0xa94000 { + compatible = "qcom,i2c-geni"; + reg = <0xa94000 0x4000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S5_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + dmas = <&gpi_dma1 0 5 3 64 0>, + <&gpi_dma1 1 5 3 64 0>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se11_i2c_active>; + pinctrl-1 = <&qupv3_se11_i2c_sleep>; + qcom,wrapper-core = <&qupv3_1>; + status = "disabled"; + }; + + /*HS UART*/ + qupv3_se10_4uart: qcom,qup_uart@0xa90000 { + compatible = "qcom,msm-geni-serial-hs"; + reg = <0xa90000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP0_S4_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se10_ctsrx>, <&qupv3_se10_rts>, + <&qupv3_se10_tx>; + pinctrl-1 = <&qupv3_se10_ctsrx>, <&qupv3_se10_rts>, + <&qupv3_se10_tx>; + interrupts-extended = <&pdc GIC_SPI 357 0>, + <&tlmm 113 0>; + status = "disabled"; + qcom,wakeup-byte = <0xFD>; + qcom,wrapper-core = <&qupv3_1>; + }; + + qupv3_se11_4uart: qcom,qup_uart@0xa94000 { + compatible = "qcom,msm-geni-serial-hs"; + reg = <0xa94000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S5_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se11_ctsrx>, <&qupv3_se11_rts>, + <&qupv3_se11_tx>; + pinctrl-1 = <&qupv3_se11_ctsrx>, <&qupv3_se11_rts>, + <&qupv3_se11_tx>; + interrupts-extended = <&pdc GIC_SPI 358 0>, + <&tlmm 92 0>; + status = "disabled"; + qcom,wakeup-byte = <0xFD>; + qcom,wrapper-core = <&qupv3_1>; + }; + + /* SPI */ + qupv3_se6_spi: spi@0xa80000 { + compatible = "qcom,spi-geni"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xa80000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S0_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se6_spi_active>; + pinctrl-1 = <&qupv3_se6_spi_sleep>; + interrupts = ; + spi-max-frequency = <50000000>; + qcom,wrapper-core = <&qupv3_1>; + dmas = <&gpi_dma1 0 0 1 64 0>, + <&gpi_dma1 1 0 1 64 0>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + qupv3_se7_spi: spi@0xa84000 { + compatible = "qcom,spi-geni"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xa84000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S1_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se7_spi_active>; + pinctrl-1 = <&qupv3_se7_spi_sleep>; + interrupts = ; + spi-max-frequency = <50000000>; + qcom,wrapper-core = <&qupv3_1>; + dmas = <&gpi_dma1 0 1 1 64 0>, + <&gpi_dma1 1 1 1 64 0>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + qupv3_se8_spi: spi@0xa88000 { + compatible = "qcom,spi-geni"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xa88000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S2_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se8_spi_active>; + pinctrl-1 = <&qupv3_se8_spi_sleep>; + interrupts = ; + spi-max-frequency = <50000000>; + qcom,wrapper-core = <&qupv3_1>; + dmas = <&gpi_dma1 0 2 1 64 0>, + <&gpi_dma1 1 2 1 64 0>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + qupv3_se10_spi: spi@0xa90000 { + compatible = "qcom,spi-geni"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xa90000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S4_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se10_spi_active>; + pinctrl-1 = <&qupv3_se10_spi_sleep>; + interrupts = ; + spi-max-frequency = <50000000>; + qcom,wrapper-core = <&qupv3_1>; + dmas = <&gpi_dma1 0 4 1 64 0>, + <&gpi_dma1 1 4 1 64 0>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + qupv3_se11_spi: spi@0xa94000 { + compatible = "qcom,spi-geni"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xa94000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk", "m-ahb", "s-ahb"; + clocks = <&clock_gcc GCC_QUPV3_WRAP1_S5_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&clock_gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qupv3_se11_spi_active>; + pinctrl-1 = <&qupv3_se11_spi_sleep>; + interrupts = ; + spi-max-frequency = <50000000>; + qcom,wrapper-core = <&qupv3_1>; + dmas = <&gpi_dma1 0 5 1 64 0>, + <&gpi_dma1 1 5 1 64 0>; + dma-names = "tx", "rx"; + status = "disabled"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index ab204a1dcd93..724198abec06 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -27,6 +27,16 @@ qcom,msm-id = <365 0x0>; interrupt-parent = <&pdc>; + aliases { + spi0 = &qupv3_se0_spi; + spi1 = &qupv3_se4_spi; + i2c0 = &qupv3_se2_i2c; + i2c1 = &qupv3_se7_i2c; + i2c2 = &qupv3_se9_i2c; + serial0 = &qupv3_se8_2uart; + hsuart0 = &qupv3_se3_4uart; + }; + cpus { #address-cells = <2>; #size-cells = <0>; @@ -719,6 +729,46 @@ status = "ok"; }; + slim_aud: slim@62dc0000 { + cell-index = <1>; + compatible = "qcom,slim-ngd"; + reg = <0x62dc0000 0x2c000>, + <0x62d84000 0x2a000>; + reg-names = "slimbus_physical", "slimbus_bam_physical"; + interrupts = <0 163 0>, <0 164 0>; + interrupt-names = "slimbus_irq", "slimbus_bam_irq"; + qcom,apps-ch-pipes = <0x7c0000>; + qcom,ea-pc = <0x300>; + status = "disabled"; + qcom,iommu-s1-bypass; + + iommu_slim_aud_ctrl_cb: qcom,iommu_slim_ctrl_cb { + compatible = "qcom,iommu-slim-ctrl-cb"; + iommus = <&apps_smmu 0x1be6 0x0>, + <&apps_smmu 0x1bed 0x0>, + <&apps_smmu 0x1bee 0x1>, + <&apps_smmu 0x1bf0 0x1>; + }; + + }; + + slim_qca: slim@62e40000 { + cell-index = <3>; + compatible = "qcom,slim-ngd"; + reg = <0x62e40000 0x2c000>, + <0x62e04000 0x20000>; + reg-names = "slimbus_physical", "slimbus_bam_physical"; + interrupts = <0 291 0>, <0 292 0>; + interrupt-names = "slimbus_irq", "slimbus_bam_irq"; + status = "disabled"; + qcom,iommu-s1-bypass; + + iommu_slim_qca_ctrl_cb: qcom,iommu_slim_ctrl_cb { + compatible = "qcom,iommu-slim-ctrl-cb"; + iommus = <&apps_smmu 0x1bf3 0x0>; + }; + }; + wdog: qcom,wdt@17c10000{ compatible = "qcom,msm-watchdog"; reg = <0x17c10000 0x1000>; @@ -952,6 +1002,7 @@ #include "sdmmagpie-pinctrl.dtsi" #include "sdmmagpie-gdsc.dtsi" +#include "sdmmagpie-qupv3.dtsi" &pcie_0_gdsc { status = "ok"; -- GitLab From e8c91eda198eb62a6b4b7e6abaeb5bf5bdb04a8a Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Mon, 9 Apr 2018 18:19:26 +0530 Subject: [PATCH 0720/1299] memshare: Align memshare driver to call new QMI functions The patch deprecates the unused functions and make use of new qmi functions for proper functionality. CRs-Fixed: 2215280 Change-Id: I8064fbcbc6bcea985e8f7efdbd934dfbe8c062d4 Signed-off-by: Manoj Prabhu B --- drivers/soc/qcom/memshare/heap_mem_ext_v01.c | 145 +------- drivers/soc/qcom/memshare/heap_mem_ext_v01.h | 100 +---- drivers/soc/qcom/memshare/msm_memshare.c | 366 ++++--------------- 3 files changed, 96 insertions(+), 515 deletions(-) diff --git a/drivers/soc/qcom/memshare/heap_mem_ext_v01.c b/drivers/soc/qcom/memshare/heap_mem_ext_v01.c index ceb9eebd164a..c2d0ea7b9091 100644 --- a/drivers/soc/qcom/memshare/heap_mem_ext_v01.c +++ b/drivers/soc/qcom/memshare/heap_mem_ext_v01.c @@ -11,133 +11,10 @@ * */ -#include -#include +#include #include "heap_mem_ext_v01.h" -struct elem_info mem_alloc_req_msg_data_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(uint32_t), - .is_array = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct mem_alloc_req_msg_v01, - num_bytes), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(uint8_t), - .is_array = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct mem_alloc_req_msg_v01, - block_alignment_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(uint32_t), - .is_array = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct mem_alloc_req_msg_v01, - block_alignment), - }, - { - .data_type = QMI_EOTI, - .is_array = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct elem_info mem_alloc_resp_msg_data_v01_ei[] = { - { - .data_type = QMI_SIGNED_2_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(uint16_t), - .is_array = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct mem_alloc_resp_msg_v01, - resp), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(uint8_t), - .is_array = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct mem_alloc_resp_msg_v01, - handle_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(uint64_t), - .is_array = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct mem_alloc_resp_msg_v01, - handle), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(uint8_t), - .is_array = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct mem_alloc_resp_msg_v01, - num_bytes_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(uint32_t), - .is_array = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct mem_alloc_resp_msg_v01, - num_bytes), - }, - { - .data_type = QMI_EOTI, - .is_array = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct elem_info mem_free_req_msg_data_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(uint64_t), - .is_array = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct mem_free_req_msg_v01, - handle), - }, - { - .data_type = QMI_EOTI, - .is_array = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct elem_info mem_free_resp_msg_data_v01_ei[] = { - { - .data_type = QMI_SIGNED_2_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(uint16_t), - .is_array = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct mem_free_resp_msg_v01, - resp), - }, - { - .data_type = QMI_EOTI, - .is_array = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct elem_info dhms_mem_alloc_addr_info_type_v01_ei[] = { +struct qmi_elem_info dhms_mem_alloc_addr_info_type_v01_ei[] = { { .data_type = QMI_UNSIGNED_8_BYTE, .elem_len = 1, @@ -165,7 +42,7 @@ struct elem_info dhms_mem_alloc_addr_info_type_v01_ei[] = { }, }; -struct elem_info mem_alloc_generic_req_msg_data_v01_ei[] = { +struct qmi_elem_info mem_alloc_generic_req_msg_data_v01_ei[] = { { .data_type = QMI_UNSIGNED_4_BYTE, .elem_len = 1, @@ -245,7 +122,7 @@ struct elem_info mem_alloc_generic_req_msg_data_v01_ei[] = { }, }; -struct elem_info mem_alloc_generic_resp_msg_data_v01_ei[] = { +struct qmi_elem_info mem_alloc_generic_resp_msg_data_v01_ei[] = { { .data_type = QMI_STRUCT, .elem_len = 1, @@ -255,7 +132,7 @@ struct elem_info mem_alloc_generic_resp_msg_data_v01_ei[] = { .offset = offsetof(struct mem_alloc_generic_resp_msg_v01, resp), - .ei_array = get_qmi_response_type_v01_ei(), + .ei_array = qmi_response_type_v01_ei, }, { .data_type = QMI_OPT_FLAG, @@ -316,7 +193,7 @@ struct elem_info mem_alloc_generic_resp_msg_data_v01_ei[] = { }, }; -struct elem_info mem_free_generic_req_msg_data_v01_ei[] = { +struct qmi_elem_info mem_free_generic_req_msg_data_v01_ei[] = { { .data_type = QMI_DATA_LEN, .elem_len = 1, @@ -380,7 +257,7 @@ struct elem_info mem_free_generic_req_msg_data_v01_ei[] = { }, }; -struct elem_info mem_free_generic_resp_msg_data_v01_ei[] = { +struct qmi_elem_info mem_free_generic_resp_msg_data_v01_ei[] = { { .data_type = QMI_STRUCT, .elem_len = 1, @@ -390,7 +267,7 @@ struct elem_info mem_free_generic_resp_msg_data_v01_ei[] = { .offset = offsetof(struct mem_free_generic_resp_msg_v01, resp), - .ei_array = get_qmi_response_type_v01_ei(), + .ei_array = qmi_response_type_v01_ei, }, { .data_type = QMI_EOTI, @@ -399,7 +276,7 @@ struct elem_info mem_free_generic_resp_msg_data_v01_ei[] = { }, }; -struct elem_info mem_query_size_req_msg_data_v01_ei[] = { +struct qmi_elem_info mem_query_size_req_msg_data_v01_ei[] = { { .data_type = QMI_UNSIGNED_4_BYTE, .elem_len = 1, @@ -434,7 +311,7 @@ struct elem_info mem_query_size_req_msg_data_v01_ei[] = { }, }; -struct elem_info mem_query_size_resp_msg_data_v01_ei[] = { +struct qmi_elem_info mem_query_size_resp_msg_data_v01_ei[] = { { .data_type = QMI_STRUCT, .elem_len = 1, @@ -444,7 +321,7 @@ struct elem_info mem_query_size_resp_msg_data_v01_ei[] = { .offset = offsetof(struct mem_query_size_rsp_msg_v01, resp), - .ei_array = get_qmi_response_type_v01_ei(), + .ei_array = qmi_response_type_v01_ei, }, { .data_type = QMI_OPT_FLAG, diff --git a/drivers/soc/qcom/memshare/heap_mem_ext_v01.h b/drivers/soc/qcom/memshare/heap_mem_ext_v01.h index 56ba9f87abbb..2c2924f17a30 100644 --- a/drivers/soc/qcom/memshare/heap_mem_ext_v01.h +++ b/drivers/soc/qcom/memshare/heap_mem_ext_v01.h @@ -14,10 +14,11 @@ #ifndef HEAP_MEM_EXT_SERVICE_01_H #define HEAP_MEM_EXT_SERVICE_01_H -#include +#include #define MEM_ALLOC_REQ_MAX_MSG_LEN_V01 255 #define MEM_FREE_REQ_MAX_MSG_LEN_V01 255 +#define MEM_QUERY_MAX_MSG_LEN_V01 255 #define MAX_ARR_CNT_V01 64 struct dhms_mem_alloc_addr_info_type_v01 { @@ -82,83 +83,6 @@ enum dhms_mem_block_align_enum_v01 { */ }; -/* Request Message; This command is used for getting - * the multiple physically contiguous - * memory blocks from the server memory subsystem - */ -struct mem_alloc_req_msg_v01 { - - /* Mandatory */ - /*requested size*/ - uint32_t num_bytes; - - /* Optional */ - /* Must be set to true if block_alignment - * is being passed - */ - uint8_t block_alignment_valid; - /* The block alignment for the memory block to be allocated - */ - enum dhms_mem_block_align_enum_v01 block_alignment; -}; /* Message */ - -/* Response Message; This command is used for getting - * the multiple physically contiguous memory blocks - * from the server memory subsystem - */ -struct mem_alloc_resp_msg_v01 { - - /* Mandatory */ - /* Result Code */ - /* The result of the requested memory operation - */ - enum qmi_result_type_v01 resp; - /* Optional */ - /* Memory Block Handle - */ - /* Must be set to true if handle is being passed - */ - uint8_t handle_valid; - /* The physical address of the memory allocated on the HLOS - */ - uint64_t handle; - /* Optional */ - /* Memory block size */ - /* Must be set to true if num_bytes is being passed - */ - uint8_t num_bytes_valid; - /* The number of bytes actually allocated for the request. - * This value can be smaller than the size requested in - * QMI_DHMS_MEM_ALLOC_REQ_MSG. - */ - uint32_t num_bytes; -}; /* Message */ - -/* Request Message; This command is used for releasing - * the multiple physically contiguous - * memory blocks to the server memory subsystem - */ -struct mem_free_req_msg_v01 { - - /* Mandatory */ - /* Physical address of memory to be freed - */ - uint32_t handle; -}; /* Message */ - -/* Response Message; This command is used for releasing - * the multiple physically contiguous - * memory blocks to the server memory subsystem - */ -struct mem_free_resp_msg_v01 { - - /* Mandatory */ - /* Result of the requested memory operation, todo, - * need to check the async operation for free - */ - enum qmi_result_type_v01 resp; -}; /* Message */ - /* Request Message; This command is used for getting * the multiple physically contiguous * memory blocks from the server memory subsystem @@ -330,22 +254,14 @@ struct mem_query_size_rsp_msg_v01 { }; /* Message */ -extern struct elem_info mem_alloc_req_msg_data_v01_ei[]; -extern struct elem_info mem_alloc_resp_msg_data_v01_ei[]; -extern struct elem_info mem_free_req_msg_data_v01_ei[]; -extern struct elem_info mem_free_resp_msg_data_v01_ei[]; -extern struct elem_info mem_alloc_generic_req_msg_data_v01_ei[]; -extern struct elem_info mem_alloc_generic_resp_msg_data_v01_ei[]; -extern struct elem_info mem_free_generic_req_msg_data_v01_ei[]; -extern struct elem_info mem_free_generic_resp_msg_data_v01_ei[]; -extern struct elem_info mem_query_size_req_msg_data_v01_ei[]; -extern struct elem_info mem_query_size_resp_msg_data_v01_ei[]; +extern struct qmi_elem_info mem_alloc_generic_req_msg_data_v01_ei[]; +extern struct qmi_elem_info mem_alloc_generic_resp_msg_data_v01_ei[]; +extern struct qmi_elem_info mem_free_generic_req_msg_data_v01_ei[]; +extern struct qmi_elem_info mem_free_generic_resp_msg_data_v01_ei[]; +extern struct qmi_elem_info mem_query_size_req_msg_data_v01_ei[]; +extern struct qmi_elem_info mem_query_size_resp_msg_data_v01_ei[]; /*Service Message Definition*/ -#define MEM_ALLOC_REQ_MSG_V01 0x0020 -#define MEM_ALLOC_RESP_MSG_V01 0x0020 -#define MEM_FREE_REQ_MSG_V01 0x0021 -#define MEM_FREE_RESP_MSG_V01 0x0021 #define MEM_ALLOC_GENERIC_REQ_MSG_V01 0x0022 #define MEM_ALLOC_GENERIC_RESP_MSG_V01 0x0022 #define MEM_FREE_GENERIC_REQ_MSG_V01 0x0023 diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c index 696c043d8de4..c300bc4b0b0c 100644 --- a/drivers/soc/qcom/memshare/msm_memshare.c +++ b/drivers/soc/qcom/memshare/msm_memshare.c @@ -18,9 +18,9 @@ #include #include #include +#include #include #include -#include #include #include "msm_memshare.h" #include "heap_mem_ext_v01.h" @@ -34,8 +34,6 @@ static unsigned long(attrs); static struct qmi_handle *mem_share_svc_handle; -static void mem_share_svc_recv_msg(struct work_struct *work); -static DECLARE_DELAYED_WORK(work_recv_msg, mem_share_svc_recv_msg); static struct workqueue_struct *mem_share_svc_workqueue; static uint64_t bootup_request; static bool ramdump_event; @@ -58,65 +56,6 @@ static struct memshare_driver *memsh_drv; static struct memshare_child *memsh_child; static struct mem_blocks memblock[MAX_CLIENTS]; static uint32_t num_clients; -static struct msg_desc mem_share_svc_alloc_req_desc = { - .max_msg_len = MEM_ALLOC_REQ_MAX_MSG_LEN_V01, - .msg_id = MEM_ALLOC_REQ_MSG_V01, - .ei_array = mem_alloc_req_msg_data_v01_ei, -}; - -static struct msg_desc mem_share_svc_alloc_resp_desc = { - .max_msg_len = MEM_ALLOC_REQ_MAX_MSG_LEN_V01, - .msg_id = MEM_ALLOC_RESP_MSG_V01, - .ei_array = mem_alloc_resp_msg_data_v01_ei, -}; - -static struct msg_desc mem_share_svc_free_req_desc = { - .max_msg_len = MEM_FREE_REQ_MAX_MSG_LEN_V01, - .msg_id = MEM_FREE_REQ_MSG_V01, - .ei_array = mem_free_req_msg_data_v01_ei, -}; - -static struct msg_desc mem_share_svc_free_resp_desc = { - .max_msg_len = MEM_FREE_REQ_MAX_MSG_LEN_V01, - .msg_id = MEM_FREE_RESP_MSG_V01, - .ei_array = mem_free_resp_msg_data_v01_ei, -}; - -static struct msg_desc mem_share_svc_alloc_generic_req_desc = { - .max_msg_len = MEM_ALLOC_REQ_MAX_MSG_LEN_V01, - .msg_id = MEM_ALLOC_GENERIC_REQ_MSG_V01, - .ei_array = mem_alloc_generic_req_msg_data_v01_ei, -}; - -static struct msg_desc mem_share_svc_alloc_generic_resp_desc = { - .max_msg_len = MEM_ALLOC_REQ_MAX_MSG_LEN_V01, - .msg_id = MEM_ALLOC_GENERIC_RESP_MSG_V01, - .ei_array = mem_alloc_generic_resp_msg_data_v01_ei, -}; - -static struct msg_desc mem_share_svc_free_generic_req_desc = { - .max_msg_len = MEM_FREE_REQ_MAX_MSG_LEN_V01, - .msg_id = MEM_FREE_GENERIC_REQ_MSG_V01, - .ei_array = mem_free_generic_req_msg_data_v01_ei, -}; - -static struct msg_desc mem_share_svc_free_generic_resp_desc = { - .max_msg_len = MEM_FREE_REQ_MAX_MSG_LEN_V01, - .msg_id = MEM_FREE_GENERIC_RESP_MSG_V01, - .ei_array = mem_free_generic_resp_msg_data_v01_ei, -}; - -static struct msg_desc mem_share_svc_size_query_req_desc = { - .max_msg_len = MEM_FREE_REQ_MAX_MSG_LEN_V01, - .msg_id = MEM_QUERY_SIZE_REQ_MSG_V01, - .ei_array = mem_query_size_req_msg_data_v01_ei, -}; - -static struct msg_desc mem_share_svc_size_query_resp_desc = { - .max_msg_len = MEM_FREE_REQ_MAX_MSG_LEN_V01, - .msg_id = MEM_QUERY_SIZE_RESP_MSG_V01, - .ei_array = mem_query_size_resp_msg_data_v01_ei, -}; /* * This API creates ramdump dev handlers @@ -488,49 +427,8 @@ static void shared_hyp_mapping(int client_id) memblock[client_id].hyp_mapping = 1; } -static int handle_alloc_req(void *req_h, void *req, void *conn_h) -{ - struct mem_alloc_req_msg_v01 *alloc_req; - struct mem_alloc_resp_msg_v01 alloc_resp; - int rc = 0; - - mutex_lock(&memsh_drv->mem_share); - alloc_req = (struct mem_alloc_req_msg_v01 *)req; - pr_debug("memshare: %s: Received Alloc Request: alloc_req->num_bytes = %d\n", - __func__, alloc_req->num_bytes); - if (!memblock[GPS].size) { - memset(&alloc_resp, 0, sizeof(alloc_resp)); - alloc_resp.resp = QMI_RESULT_FAILURE_V01; - rc = memshare_alloc(memsh_drv->dev, alloc_req->num_bytes, - &memblock[GPS]); - } - alloc_resp.num_bytes_valid = 1; - alloc_resp.num_bytes = alloc_req->num_bytes; - alloc_resp.handle_valid = 1; - alloc_resp.handle = memblock[GPS].phy_addr; - if (rc) { - alloc_resp.resp = QMI_RESULT_FAILURE_V01; - memblock[GPS].size = 0; - } else { - alloc_resp.resp = QMI_RESULT_SUCCESS_V01; - } - - mutex_unlock(&memsh_drv->mem_share); - - pr_debug("memshare: %s, alloc_resp.num_bytes :%d, alloc_resp.resp :%lx\n", - __func__, alloc_resp.num_bytes, - (unsigned long int)alloc_resp.resp); - rc = qmi_send_resp_from_cb(mem_share_svc_handle, conn_h, req_h, - &mem_share_svc_alloc_resp_desc, &alloc_resp, - sizeof(alloc_resp)); - if (rc < 0) - pr_err("memshare: %s, Error sending the alloc request: %d\n", - __func__, rc); - - return rc; -} - -static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h) +static void handle_alloc_generic_req(struct qmi_handle *handle, + struct sockaddr_qrtr *sq, struct qmi_txn *txn, const void *decoded_msg) { struct mem_alloc_generic_req_msg_v01 *alloc_req; struct mem_alloc_generic_resp_msg_v01 *alloc_resp; @@ -539,14 +437,14 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h) uint32_t size = 0; mutex_lock(&memsh_drv->mem_share); - alloc_req = (struct mem_alloc_generic_req_msg_v01 *)req; + alloc_req = (struct mem_alloc_generic_req_msg_v01 *)decoded_msg; pr_debug("memshare: alloc request client id: %d proc _id: %d\n", alloc_req->client_id, alloc_req->proc_id); alloc_resp = kzalloc(sizeof(*alloc_resp), GFP_KERNEL); if (!alloc_resp) { mutex_unlock(&memsh_drv->mem_share); - return -ENOMEM; + return; } alloc_resp->resp.result = QMI_RESULT_FAILURE_V01; alloc_resp->resp.error = QMI_ERR_NO_MEMORY_V01; @@ -560,7 +458,7 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h) kfree(alloc_resp); alloc_resp = NULL; mutex_unlock(&memsh_drv->mem_share); - return -EINVAL; + return; } if (!memblock[client_id].allotted) { @@ -601,47 +499,22 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h) pr_debug("memshare: alloc_resp.num_bytes :%d, alloc_resp.resp.result :%lx\n", alloc_resp->dhms_mem_alloc_addr_info[0].num_bytes, (unsigned long int)alloc_resp->resp.result); - rc = qmi_send_resp_from_cb(mem_share_svc_handle, conn_h, req_h, - &mem_share_svc_alloc_generic_resp_desc, alloc_resp, - sizeof(alloc_resp)); + rc = qmi_send_response(mem_share_svc_handle, sq, txn, + MEM_ALLOC_GENERIC_RESP_MSG_V01, + sizeof(struct mem_alloc_generic_resp_msg_v01), + mem_alloc_generic_resp_msg_data_v01_ei, alloc_resp); if (rc < 0) - pr_err("memshare: %s, Error sending the alloc request: %d\n", + pr_err("memshare: %s, Error sending the alloc response: %d\n", __func__, rc); kfree(alloc_resp); alloc_resp = NULL; - return rc; + return; } -static int handle_free_req(void *req_h, void *req, void *conn_h) -{ - struct mem_free_req_msg_v01 *free_req; - struct mem_free_resp_msg_v01 free_resp; - int rc; - - mutex_lock(&memsh_drv->mem_free); - if (!memblock[GPS].guarantee) { - free_req = (struct mem_free_req_msg_v01 *)req; - pr_debug("memshare: %s: Received Free Request\n", __func__); - memset(&free_resp, 0, sizeof(free_resp)); - dma_free_coherent(memsh_drv->dev, memblock[GPS].size, - memblock[GPS].virtual_addr, - free_req->handle); - } - free_resp.resp = QMI_RESULT_SUCCESS_V01; - mutex_unlock(&memsh_drv->mem_free); - rc = qmi_send_resp_from_cb(mem_share_svc_handle, conn_h, req_h, - &mem_share_svc_free_resp_desc, &free_resp, - sizeof(free_resp)); - if (rc < 0) - pr_err("memshare: %s, Error sending the free request: %d\n", - __func__, rc); - - return rc; -} - -static int handle_free_generic_req(void *req_h, void *req, void *conn_h) +static void handle_free_generic_req(struct qmi_handle *handle, + struct sockaddr_qrtr *sq, struct qmi_txn *txn, const void *decoded_msg) { struct mem_free_generic_req_msg_v01 *free_req; struct mem_free_generic_resp_msg_v01 free_resp; @@ -652,7 +525,7 @@ static int handle_free_generic_req(void *req_h, void *req, void *conn_h) int dest_perms[1] = {PERM_READ|PERM_WRITE|PERM_EXEC}; mutex_lock(&memsh_drv->mem_free); - free_req = (struct mem_free_generic_req_msg_v01 *)req; + free_req = (struct mem_free_generic_req_msg_v01 *)decoded_msg; pr_debug("memshare: %s: Received Free Request\n", __func__); memset(&free_resp, 0, sizeof(free_resp)); free_resp.resp.error = QMI_ERR_INTERNAL_V01; @@ -709,30 +582,31 @@ static int handle_free_generic_req(void *req_h, void *req, void *conn_h) } mutex_unlock(&memsh_drv->mem_free); - rc = qmi_send_resp_from_cb(mem_share_svc_handle, conn_h, req_h, - &mem_share_svc_free_generic_resp_desc, &free_resp, - sizeof(free_resp)); - + rc = qmi_send_response(mem_share_svc_handle, sq, txn, + MEM_FREE_GENERIC_RESP_MSG_V01, + sizeof(struct mem_free_generic_resp_msg_v01), + mem_free_generic_resp_msg_data_v01_ei, &free_resp); if (rc < 0) - pr_err("memshare: %s, Error sending the free request: %d\n", + pr_err("memshare: %s, Error sending the free response: %d\n", __func__, rc); - return rc; + return; } -static int handle_query_size_req(void *req_h, void *req, void *conn_h) +static void handle_query_size_req(struct qmi_handle *handle, + struct sockaddr_qrtr *sq, struct qmi_txn *txn, const void *decoded_msg) { int rc, client_id; struct mem_query_size_req_msg_v01 *query_req; struct mem_query_size_rsp_msg_v01 *query_resp; mutex_lock(&memsh_drv->mem_share); - query_req = (struct mem_query_size_req_msg_v01 *)req; + query_req = (struct mem_query_size_req_msg_v01 *)decoded_msg; query_resp = kzalloc(sizeof(*query_resp), GFP_KERNEL); if (!query_resp) { mutex_unlock(&memsh_drv->mem_share); - return -ENOMEM; + return; } pr_debug("memshare: query request client id: %d proc _id: %d\n", query_req->client_id, query_req->proc_id); @@ -746,7 +620,7 @@ static int handle_query_size_req(void *req_h, void *req, void *conn_h) kfree(query_resp); query_resp = NULL; mutex_unlock(&memsh_drv->mem_share); - return -EINVAL; + return; } if (memblock[client_id].size) { @@ -763,148 +637,51 @@ static int handle_query_size_req(void *req_h, void *req, void *conn_h) pr_debug("memshare: query_resp.size :%d, query_resp.resp.result :%lx\n", query_resp->size, (unsigned long int)query_resp->resp.result); - rc = qmi_send_resp_from_cb(mem_share_svc_handle, conn_h, req_h, - &mem_share_svc_size_query_resp_desc, query_resp, - sizeof(query_resp)); - + rc = qmi_send_response(mem_share_svc_handle, sq, txn, + MEM_QUERY_SIZE_RESP_MSG_V01, + MEM_QUERY_MAX_MSG_LEN_V01, + mem_query_size_resp_msg_data_v01_ei, query_resp); if (rc < 0) - pr_err("memshare: %s, Error sending the query request: %d\n", + pr_err("memshare: %s, Error sending the query response: %d\n", __func__, rc); kfree(query_resp); query_resp = NULL; - return rc; -} - -static int mem_share_svc_connect_cb(struct qmi_handle *handle, - void *conn_h) -{ - if (mem_share_svc_handle != handle || !conn_h) - return -EINVAL; - - return 0; -} - -static int mem_share_svc_disconnect_cb(struct qmi_handle *handle, - void *conn_h) -{ - if (mem_share_svc_handle != handle || !conn_h) - return -EINVAL; - - return 0; + return; } -static int mem_share_svc_req_desc_cb(unsigned int msg_id, - struct msg_desc **req_desc) +static void mem_share_svc_disconnect_cb(struct qmi_handle *qmi, + unsigned int node, unsigned int port) { - int rc; - - pr_debug("memshare: %s\n", __func__); - switch (msg_id) { - case MEM_ALLOC_REQ_MSG_V01: - *req_desc = &mem_share_svc_alloc_req_desc; - rc = sizeof(struct mem_alloc_req_msg_v01); - break; - - case MEM_FREE_REQ_MSG_V01: - *req_desc = &mem_share_svc_free_req_desc; - rc = sizeof(struct mem_free_req_msg_v01); - break; - - case MEM_ALLOC_GENERIC_REQ_MSG_V01: - *req_desc = &mem_share_svc_alloc_generic_req_desc; - rc = sizeof(struct mem_alloc_generic_req_msg_v01); - break; - - case MEM_FREE_GENERIC_REQ_MSG_V01: - *req_desc = &mem_share_svc_free_generic_req_desc; - rc = sizeof(struct mem_free_generic_req_msg_v01); - break; - - case MEM_QUERY_SIZE_REQ_MSG_V01: - *req_desc = &mem_share_svc_size_query_req_desc; - rc = sizeof(struct mem_query_size_req_msg_v01); - break; - - default: - rc = -ENOTSUPP; - break; - } - return rc; + pr_debug("memshare: Received QMI client disconnect event\n"); } -static int mem_share_svc_req_cb(struct qmi_handle *handle, void *conn_h, - void *req_h, unsigned int msg_id, void *req) -{ - int rc; - - pr_debug("memshare: %s\n", __func__); - if (mem_share_svc_handle != handle || !conn_h) - return -EINVAL; - - switch (msg_id) { - case MEM_ALLOC_REQ_MSG_V01: - rc = handle_alloc_req(req_h, req, conn_h); - break; - - case MEM_FREE_REQ_MSG_V01: - rc = handle_free_req(req_h, req, conn_h); - break; - - case MEM_ALLOC_GENERIC_REQ_MSG_V01: - rc = handle_alloc_generic_req(req_h, req, conn_h); - break; - - case MEM_FREE_GENERIC_REQ_MSG_V01: - rc = handle_free_generic_req(req_h, req, conn_h); - break; - - case MEM_QUERY_SIZE_REQ_MSG_V01: - rc = handle_query_size_req(req_h, req, conn_h); - break; - - default: - rc = -ENOTSUPP; - break; - } - return rc; -} - -static void mem_share_svc_recv_msg(struct work_struct *work) -{ - int rc; - - pr_debug("memshare: %s\n", __func__); - do { - rc = qmi_recv_msg(mem_share_svc_handle); - pr_debug("memshare: %s: Notified about a Receive Event", - __func__); - } while (!rc); - - if (rc != -ENOMSG) - pr_err("memshare: %s: Error = %d while receiving message\n", - __func__, rc); -} - -static void qmi_mem_share_svc_ntfy(struct qmi_handle *handle, - enum qmi_event_type event, void *priv) -{ - pr_debug("memshare: %s\n", __func__); - - if (event == QMI_RECV_MSG) - queue_delayed_work(mem_share_svc_workqueue, - &work_recv_msg, 0); -} +static struct qmi_ops server_ops = { + .del_client = mem_share_svc_disconnect_cb, +}; -static struct qmi_svc_ops_options mem_share_svc_ops_options = { - .version = 1, - .service_id = MEM_SHARE_SERVICE_SVC_ID, - .service_vers = MEM_SHARE_SERVICE_VERS, - .service_ins = MEM_SHARE_SERVICE_INS_ID, - .connect_cb = mem_share_svc_connect_cb, - .disconnect_cb = mem_share_svc_disconnect_cb, - .req_desc_cb = mem_share_svc_req_desc_cb, - .req_cb = mem_share_svc_req_cb, +static struct qmi_msg_handler qmi_memshare_handlers[] = { + { + .type = QMI_REQUEST, + .msg_id = MEM_ALLOC_GENERIC_REQ_MSG_V01, + .ei = mem_alloc_generic_req_msg_data_v01_ei, + .decoded_size = MEM_ALLOC_REQ_MAX_MSG_LEN_V01, + .fn = handle_alloc_generic_req, + }, + { + .type = QMI_REQUEST, + .msg_id = MEM_FREE_GENERIC_REQ_MSG_V01, + .ei = mem_free_generic_req_msg_data_v01_ei, + .decoded_size = MEM_FREE_REQ_MAX_MSG_LEN_V01, + .fn = handle_free_generic_req, + }, + { + .type = QMI_REQUEST, + .msg_id = MEM_QUERY_SIZE_REQ_MSG_V01, + .ei = mem_query_size_req_msg_data_v01_ei, + .decoded_size = MEM_QUERY_MAX_MSG_LEN_V01, + .fn = handle_query_size_req, + }, }; int memshare_alloc(struct device *dev, @@ -937,18 +714,30 @@ static void memshare_init_worker(struct work_struct *work) if (!mem_share_svc_workqueue) return; - mem_share_svc_handle = qmi_handle_create(qmi_mem_share_svc_ntfy, NULL); + mem_share_svc_handle = kzalloc(sizeof(struct qmi_handle), + GFP_KERNEL); if (!mem_share_svc_handle) { + destroy_workqueue(mem_share_svc_workqueue); + return; + } + + rc = qmi_handle_init(mem_share_svc_handle, + sizeof(struct qmi_elem_info), + &server_ops, qmi_memshare_handlers); + if (rc < 0) { pr_err("memshare: %s: Creating mem_share_svc qmi handle failed\n", __func__); + kfree(mem_share_svc_handle); destroy_workqueue(mem_share_svc_workqueue); return; } - rc = qmi_svc_register(mem_share_svc_handle, &mem_share_svc_ops_options); + rc = qmi_add_server(mem_share_svc_handle, MEM_SHARE_SERVICE_SVC_ID, + MEM_SHARE_SERVICE_VERS, MEM_SHARE_SERVICE_INS_ID); if (rc < 0) { pr_err("memshare: %s: Registering mem share svc failed %d\n", __func__, rc); - qmi_handle_destroy(mem_share_svc_handle); + qmi_handle_release(mem_share_svc_handle); + kfree(mem_share_svc_handle); destroy_workqueue(mem_share_svc_workqueue); return; } @@ -1094,11 +883,10 @@ static int memshare_remove(struct platform_device *pdev) if (!memsh_drv) return 0; - qmi_svc_unregister(mem_share_svc_handle); flush_workqueue(mem_share_svc_workqueue); - qmi_handle_destroy(mem_share_svc_handle); + qmi_handle_release(mem_share_svc_handle); + kfree(mem_share_svc_handle); destroy_workqueue(mem_share_svc_workqueue); - return 0; } -- GitLab From 38cdaef4ece3c84c317bf06af3ed8e7fbf8fd9bd Mon Sep 17 00:00:00 2001 From: Ramprasad Katkam Date: Mon, 18 Jun 2018 12:16:14 +0530 Subject: [PATCH 0721/1299] Documentation: sound: Add documentation for new soundwire driver Add documentation for new driver developed to support soundwire for qcs405 target. Change-Id: Ia1aab04e20d81e484489f0c46cf6c6c1ca996029 Signed-off-by: Ramprasad Katkam --- .../bindings/soundwire/swr-mstr-ctrl.txt | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/soundwire/swr-mstr-ctrl.txt diff --git a/Documentation/devicetree/bindings/soundwire/swr-mstr-ctrl.txt b/Documentation/devicetree/bindings/soundwire/swr-mstr-ctrl.txt new file mode 100644 index 000000000000..ba92e093b134 --- /dev/null +++ b/Documentation/devicetree/bindings/soundwire/swr-mstr-ctrl.txt @@ -0,0 +1,49 @@ +Qualcomm Technologies, Inc. SoundWire Master controller + +* swr_master + +Required properties: + +- compatible : should be "qcom,swr-mstr" +- #address-cells: must be 2 +- #size-cells: must be 0 +- qcom,swr-num-ports: number of ports in the master. +- qcom,swr-port-mapping: contains codec port_type and + corresponding ch-mask entries for possible port types + of the master port. + +* wsa881x + +Required properties: + +- compatible : should be "qcom,wsa881x" +- reg : Unique device ID(48 bits) of Soundwire slave device node. + In the below example, wsa881x is soundwire slave device for + which the swr-devid is <0x0 0x032000> where 0x03 represents + device Unique_ID, 0x20 represents Part_Id1 and 0x00 + represents part_Id2. + + Example: + +swr0: swr_master { + compatible = "qcom,swr-mstr"; + #address-cells = <2>; + #size-cells = <0>; + + qcom,swr-num-ports = <8>; + qcom,swr-port-mapping = <1 SPKR_L 0x1>, + <2 SPKR_L_COMP 0xF>, <3 SPKR_L_BOOST 0x3>, + <4 SPKR_R 0x1>, <5 SPKR_R_COMP 0xF>, + <6 SPKR_R_BOOST 0x3>, <7 SPKR_L_VI 0x3>, + <8 SPKR_R_VI 0x3>; + + wsa881x@32000 { + compatible = "qcom,wsa881x"; + reg = <0x00 0x032000>; + }; + + wsa881x@42000 { + compatible = "qcom,wsa881x"; + reg = <0x00 0x042000>; + }; + }; -- GitLab From a95a8d22f88106f170266d04c92fe760decfeba2 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Thu, 7 Jun 2018 19:27:05 +0530 Subject: [PATCH 0722/1299] ARM: dts: msm: Add audio support for qcs405 platform Add device tree files related to all variants of qcs405 platform to support audio. Change-Id: I5f925f628bd0ee8b6517cd769c8eac38791c4c62 Signed-off-by: Aditya Bavanari --- .../bindings/sound/qcom-audio-dev.txt | 2 +- arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi | 38 ++ arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts | 1 + arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts | 1 + .../dts/qcom/qcs405-amic-audio-overlay.dtsi | 26 + .../boot/dts/qcom/qcs405-audio-overlay.dtsi | 86 +++ arch/arm64/boot/dts/qcom/qcs405-audio.dtsi | 141 +++++ .../dts/qcom/qcs405-csra1-audio-overlay.dtsi | 86 +++ .../dts/qcom/qcs405-csra6-audio-overlay.dtsi | 86 +++ arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts | 1 + arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts | 1 + arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts | 1 + arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts | 1 + arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts | 1 + arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts | 1 + arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts | 1 + arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts | 1 + arch/arm64/boot/dts/qcom/qcs405-lpi.dtsi | 304 +++++++++++ .../dts/qcom/qcs405-nowcd-audio-overlay.dtsi | 80 +++ arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi | 511 ++++++++++++++++++ arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi | 96 ++++ .../arm64/boot/dts/qcom/qcs405-va-bolero.dtsi | 34 ++ .../dts/qcom/qcs405-wsa-audio-overlay.dtsi | 113 ++++ .../boot/dts/qcom/qcs405-wsa-bolero.dtsi | 40 ++ arch/arm64/boot/dts/qcom/qcs405-wsa881x.dtsi | 57 ++ arch/arm64/boot/dts/qcom/qcs405.dtsi | 1 + 26 files changed, 1710 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/qcom/qcs405-amic-audio-overlay.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-audio-overlay.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-audio.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-csra1-audio-overlay.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-csra6-audio-overlay.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-lpi.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-nowcd-audio-overlay.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-va-bolero.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-wsa-audio-overlay.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-wsa-bolero.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs405-wsa881x.dtsi diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index ecbc7c2095d8..6ca0b64acfe4 100644 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -676,7 +676,7 @@ Example: q6core { compatible = "qcom,q6core-audio"; bolero: bolero-cdc { - compatible = "qcom,bolero-cdc"; + compatible = "qcom,bolero-codec"; }; }; }; diff --git a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi index 8bf9c1872289..7e4adf41cd97 100644 --- a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi @@ -129,6 +129,44 @@ }; }; + msm_dai_cdc_dma: qcom,msm-dai-cdc-dma { + compatible = "qcom,msm-dai-cdc-dma"; + wsa_cdc_dma_0_rx: qcom,msm-dai-wsa-cdc-dma-0-rx { + compatible = "qcom,msm-dai-cdc-dma-dev"; + qcom,msm-dai-cdc-dma-dev-id = <45056>; + }; + + wsa_cdc_dma_0_tx: qcom,msm-dai-wsa-cdc-dma-0-tx { + compatible = "qcom,msm-dai-cdc-dma-dev"; + qcom,msm-dai-cdc-dma-dev-id = <45057>; + }; + + wsa_cdc_dma_1_rx: qcom,msm-dai-wsa-cdc-dma-1-rx { + compatible = "qcom,msm-dai-cdc-dma-dev"; + qcom,msm-dai-cdc-dma-dev-id = <45058>; + }; + + wsa_cdc_dma_1_tx: qcom,msm-dai-wsa-cdc-dma-1-tx { + compatible = "qcom,msm-dai-cdc-dma-dev"; + qcom,msm-dai-cdc-dma-dev-id = <45059>; + }; + + wsa_cdc_dma_2_tx: qcom,msm-dai-wsa-cdc-dma-2-tx { + compatible = "qcom,msm-dai-cdc-dma-dev"; + qcom,msm-dai-cdc-dma-dev-id = <45061>; + }; + + va_cdc_dma_0_tx: qcom,msm-dai-va-cdc-dma-0-tx { + compatible = "qcom,msm-dai-cdc-dma-dev"; + qcom,msm-dai-cdc-dma-dev-id = <45089>; + }; + + va_cdc_dma_1_tx: qcom,msm-dai-va-cdc-dma-1-tx { + compatible = "qcom,msm-dai-cdc-dma-dev"; + qcom,msm-dai-cdc-dma-dev-id = <45091>; + }; + }; + lsm: qcom,msm-lsm-client { compatible = "qcom,msm-lsm-client"; }; diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts index 2bad4d66d940..a4d7b5526f59 100644 --- a/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts +++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts @@ -14,6 +14,7 @@ /dts-v1/; #include "qcs403.dtsi" +#include "qcs405-wsa-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS403 EVB2 1000 IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts index c97646be3e34..cfcbdcbac88b 100644 --- a/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts +++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts @@ -14,6 +14,7 @@ /dts-v1/; #include "qcs403.dtsi" +#include "qcs405-nowcd-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS403 RCM IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-amic-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/qcs405-amic-audio-overlay.dtsi new file mode 100644 index 000000000000..419580f78059 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-amic-audio-overlay.dtsi @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qcs405-tasha.dtsi" + +&qcs405_snd { + qcom,model = "qcs405-amic-snd-card"; + qcom,tasha-codec = <1>; + asoc-codec = <&stub_codec>, <&bolero>; + asoc-codec-names = "msm-stub-codec.1", "bolero_codec"; + qcom,audio-routing = + "AMIC3", "MIC BIAS3", + "AMIC4", "MIC BIAS4", + "MIC BIAS3", "Analog Mic3", + "MIC BIAS4", "Analog Mic4"; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/qcs405-audio-overlay.dtsi new file mode 100644 index 000000000000..584f4f0212d4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-audio-overlay.dtsi @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qcs405-tasha.dtsi" +#include "qcs405-va-bolero.dtsi" + +&qcs405_snd { + qcom,model = "qcs405-snd-card"; + qcom,va-bolero-codec = <1>; + qcom,tasha-codec = <1>; + asoc-codec = <&stub_codec>, <&bolero>; + asoc-codec-names = "msm-stub-codec.1", "bolero_codec"; + qcom,cdc-dmic01-gpios = <&cdc_dmic01_gpios>; + qcom,cdc-dmic23-gpios = <&cdc_dmic23_gpios>; + qcom,cdc-dmic45-gpios = <&cdc_dmic45_gpios>; + qcom,cdc-dmic67-gpios = <&cdc_dmic67_gpios>; + qcom,audio-routing = + "AMIC3", "MIC BIAS3", + "AMIC4", "MIC BIAS4", + "MIC BIAS3", "Analog Mic3", + "MIC BIAS4", "Analog Mic4", + "VA DMIC0", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic0", + "VA DMIC1", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic1", + "VA DMIC2", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic2", + "VA DMIC3", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic3", + "VA DMIC4", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic4", + "VA DMIC5", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic5", + "VA DMIC6", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic6", + "VA DMIC7", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic7"; +}; + +&bolero { + qcom,num-macros = <1>; +}; + +&soc { + cdc_dmic01_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic01_clk_active &cdc_dmic01_data_active>; + pinctrl-1 = <&cdc_dmic01_clk_sleep &cdc_dmic01_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic23_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic23_clk_active &cdc_dmic23_data_active>; + pinctrl-1 = <&cdc_dmic23_clk_sleep &cdc_dmic23_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic45_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic45_clk_active &cdc_dmic45_data_active>; + pinctrl-1 = <&cdc_dmic45_clk_sleep &cdc_dmic45_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic67_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic67_clk_active &cdc_dmic67_data_active>; + pinctrl-1 = <&cdc_dmic67_clk_sleep &cdc_dmic67_data_sleep>; + qcom,lpi-gpios; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi b/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi new file mode 100644 index 000000000000..26d43b6b20ea --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi @@ -0,0 +1,141 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include "qcs405-lpi.dtsi" +#include "msm-audio-lpass.dtsi" + +&msm_audio_ion { + iommus = <&apps_smmu 0x0801 0x0>; + qcom,smmu-sid-mask = /bits/ 64 <0xf>; +}; + +&soc { + qcom,avtimer@C10000C { + compatible = "qcom,avtimer"; + reg = <0x0C10000C 0x4>, + <0x0C100010 0x4>; + reg-names = "avtimer_lsb_addr", "avtimer_msb_addr"; + qcom,clk-div = <192>; + qcom,clk-mult = <10>; + }; + + audio_apr: qcom,msm-audio-apr { + compatible = "qcom,msm-audio-apr"; + q6core: q6core { + compatible = "qcom,q6core-audio"; + bolero: bolero-cdc { + compatible = "qcom,bolero-codec"; + }; + }; + }; +}; + +&q6core { + qcs405_snd: sound { + compatible = "qcom,qcs405-asoc-snd"; + qcom,model = "qcs405-snd-card"; + qcom,mi2s-audio-intf = <1>; + qcom,auxpcm-audio-intf = <1>; + + asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>, + <&loopback>, <&compress>, <&hostless>, + <&afe>, <&lsm>, <&routing>, <&compr>, + <&pcm_noirq>; + asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1", + "msm-pcm-dsp.2", "msm-voip-dsp", + "msm-pcm-voice", "msm-pcm-loopback", + "msm-compress-dsp", "msm-pcm-hostless", + "msm-pcm-afe", "msm-lsm-client", + "msm-pcm-routing", "msm-compr-dsp", + "msm-pcm-dsp-noirq"; + asoc-cpu = <&dai_dp>, <&dai_mi2s0>, <&dai_mi2s1>, + <&dai_mi2s2>, <&dai_mi2s3>, <&dai_mi2s4>, <&dai_mi2s5>, + <&dai_pri_auxpcm>, <&dai_sec_auxpcm>, + <&dai_tert_auxpcm>, <&dai_quat_auxpcm>, + <&dai_quin_auxpcm>, + <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, + <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>, + <&sb_4_rx>, <&sb_4_tx>, <&sb_5_rx>, <&sb_5_tx>, + <&sb_6_rx>, <&sb_7_rx>, <&sb_7_tx>, + <&sb_8_rx>, <&sb_8_tx>, + <&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>, + <&afe_proxy_tx>, <&incall_record_rx>, + <&incall_record_tx>, <&incall_music_rx>, + <&incall_music_2_rx>, + <&usb_audio_rx>, <&usb_audio_tx>, + <&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>, + <&dai_sec_tdm_rx_0>, <&dai_sec_tdm_tx_0>, + <&dai_tert_tdm_rx_0>, <&dai_tert_tdm_tx_0>, + <&dai_quat_tdm_rx_0>, <&dai_quat_tdm_tx_0>, + <&dai_quin_tdm_rx_0>, <&dai_quin_tdm_tx_0>, + <&wsa_cdc_dma_0_rx>, <&wsa_cdc_dma_0_tx>, + <&wsa_cdc_dma_1_rx>, <&wsa_cdc_dma_1_tx>, + <&wsa_cdc_dma_2_tx>, + <&va_cdc_dma_0_tx>, <&va_cdc_dma_1_tx>; + asoc-cpu-names = "msm-dai-q6-dp.24608", + "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1", + "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", + "msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.5", + "msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2", + "msm-dai-q6-auxpcm.3", "msm-dai-q6-auxpcm.4", + "msm-dai-q6-auxpcm.5", + "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", + "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", + "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389", + "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", + "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393", + "msm-dai-q6-dev.16394", "msm-dai-q6-dev.16395", + "msm-dai-q6-dev.16396", + "msm-dai-q6-dev.16398", "msm-dai-q6-dev.16399", + "msm-dai-q6-dev.16400", "msm-dai-q6-dev.16401", + "msm-dai-q6-dev.224", "msm-dai-q6-dev.225", + "msm-dai-q6-dev.241", "msm-dai-q6-dev.240", + "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772", + "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770", + "msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673", + "msm-dai-q6-tdm.36864", "msm-dai-q6-tdm.36865", + "msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881", + "msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897", + "msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913", + "msm-dai-q6-tdm.36928", "msm-dai-q6-tdm.36929", + "msm-dai-cdc-dma-dev.45056", + "msm-dai-cdc-dma-dev.45057", + "msm-dai-cdc-dma-dev.45058", + "msm-dai-cdc-dma-dev.45059", + "msm-dai-cdc-dma-dev.45061", + "msm-dai-cdc-dma-dev.45089", + "msm-dai-cdc-dma-dev.45091"; + }; +}; + +&slim_aud { + status = "disabled"; + msm_dai_slim { + status = "disabled"; + compatible = "qcom,msm-dai-slim"; + elemental-addr = [ff ff ff fe 17 02]; + }; +}; + +&pms405_gpios { + tasha_mclk { + tasha_mclk_default: tasha_mclk_default{ + pins = "gpio8"; + function = "func1"; + qcom,drive-strength = <2>; + power-source = <0>; + bias-disable; + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-csra1-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/qcs405-csra1-audio-overlay.dtsi new file mode 100644 index 000000000000..2523e6abd8b9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-csra1-audio-overlay.dtsi @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qcs405-tasha.dtsi" +#include "qcs405-va-bolero.dtsi" + +&qcs405_snd { + qcom,model = "qcs405-csra1-snd-card"; + qcom,va-bolero-codec = <1>; + qcom,tasha-codec = <1>; + asoc-codec = <&stub_codec>, <&bolero>; + asoc-codec-names = "msm-stub-codec.1", "bolero_codec"; + qcom,cdc-dmic01-gpios = <&cdc_dmic01_gpios>; + qcom,cdc-dmic23-gpios = <&cdc_dmic23_gpios>; + qcom,cdc-dmic45-gpios = <&cdc_dmic45_gpios>; + qcom,cdc-dmic67-gpios = <&cdc_dmic67_gpios>; + qcom,audio-routing = + "AMIC3", "MIC BIAS3", + "AMIC4", "MIC BIAS4", + "MIC BIAS3", "Analog Mic3", + "MIC BIAS4", "Analog Mic4", + "VA DMIC0", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic0", + "VA DMIC1", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic1", + "VA DMIC2", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic2", + "VA DMIC3", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic3", + "VA DMIC4", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic4", + "VA DMIC5", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic5", + "VA DMIC6", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic6", + "VA DMIC7", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic7"; +}; + +&bolero { + qcom,num-macros = <1>; +}; + +&soc { + cdc_dmic01_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic01_clk_active &cdc_dmic01_data_active>; + pinctrl-1 = <&cdc_dmic01_clk_sleep &cdc_dmic01_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic23_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic23_clk_active &cdc_dmic23_data_active>; + pinctrl-1 = <&cdc_dmic23_clk_sleep &cdc_dmic23_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic45_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic45_clk_active &cdc_dmic45_data_active>; + pinctrl-1 = <&cdc_dmic45_clk_sleep &cdc_dmic45_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic67_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic67_clk_active &cdc_dmic67_data_active>; + pinctrl-1 = <&cdc_dmic67_clk_sleep &cdc_dmic67_data_sleep>; + qcom,lpi-gpios; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-csra6-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/qcs405-csra6-audio-overlay.dtsi new file mode 100644 index 000000000000..7dc047d196b1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-csra6-audio-overlay.dtsi @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qcs405-tasha.dtsi" +#include "qcs405-va-bolero.dtsi" + +&qcs405_snd { + qcom,model = "qcs405-csra6-snd-card"; + qcom,va-bolero-codec = <1>; + qcom,tasha-codec = <1>; + asoc-codec = <&stub_codec>, <&bolero>; + asoc-codec-names = "msm-stub-codec.1", "bolero_codec"; + qcom,cdc-dmic01-gpios = <&cdc_dmic01_gpios>; + qcom,cdc-dmic23-gpios = <&cdc_dmic23_gpios>; + qcom,cdc-dmic45-gpios = <&cdc_dmic45_gpios>; + qcom,cdc-dmic67-gpios = <&cdc_dmic67_gpios>; + qcom,audio-routing = + "AMIC3", "MIC BIAS3", + "AMIC4", "MIC BIAS4", + "MIC BIAS3", "Analog Mic3", + "MIC BIAS4", "Analog Mic4", + "VA DMIC0", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic0", + "VA DMIC1", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic1", + "VA DMIC2", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic2", + "VA DMIC3", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic3", + "VA DMIC4", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic4", + "VA DMIC5", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic5", + "VA DMIC6", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic6", + "VA DMIC7", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic7"; +}; + +&bolero { + qcom,num-macros = <1>; +}; + +&soc { + cdc_dmic01_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic01_clk_active &cdc_dmic01_data_active>; + pinctrl-1 = <&cdc_dmic01_clk_sleep &cdc_dmic01_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic23_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic23_clk_active &cdc_dmic23_data_active>; + pinctrl-1 = <&cdc_dmic23_clk_sleep &cdc_dmic23_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic45_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic45_clk_active &cdc_dmic45_data_active>; + pinctrl-1 = <&cdc_dmic45_clk_sleep &cdc_dmic45_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic67_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic67_clk_active &cdc_dmic67_data_active>; + pinctrl-1 = <&cdc_dmic67_clk_sleep &cdc_dmic67_data_sleep>; + qcom,lpi-gpios; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts index ced1ff96533c..b90cde09f737 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts @@ -14,6 +14,7 @@ /dts-v1/; #include "qcs405.dtsi" +#include "qcs405-wsa-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 1000 IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts index 43737c832578..1ff864c6fea7 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts @@ -14,6 +14,7 @@ /dts-v1/; #include "qcs405.dtsi" +#include "qcs405-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 SPI IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts index ba6c9c151a09..2a54972cb02f 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku3.dts @@ -14,6 +14,7 @@ /dts-v1/; #include "qcs405.dtsi" +#include "qcs405-nowcd-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 sEVB/SLT IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts index 66393d820b73..5cfafbb325e6 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku4.dts @@ -14,6 +14,7 @@ /dts-v1/; #include "qcs405.dtsi" +#include "qcs405-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 DSI IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts index 52144522045f..2cb3dbb03341 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts @@ -14,6 +14,7 @@ /dts-v1/; #include "qcs405.dtsi" +#include "qcs405-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 RGB IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts index 9b5779b74132..a7e4149f4373 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts @@ -14,6 +14,7 @@ /dts-v1/; #include "qcs405.dtsi" +#include "qcs405-csra1-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 CSRA1 IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts index 3be37a281726..b3b723b422b8 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts @@ -14,6 +14,7 @@ /dts-v1/; #include "qcs405.dtsi" +#include "qcs405-csra6-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 CSRA6 IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts index 261cd8bc7051..ea43b030be69 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts @@ -14,6 +14,7 @@ /dts-v1/; #include "qcs405.dtsi" +#include "qcs405-amic-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS405 EVB1 4000 AMIC IOT"; diff --git a/arch/arm64/boot/dts/qcom/qcs405-lpi.dtsi b/arch/arm64/boot/dts/qcom/qcs405-lpi.dtsi new file mode 100644 index 000000000000..210375cfd042 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-lpi.dtsi @@ -0,0 +1,304 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + lpi_tlmm: lpi_pinctrl@C070000 { + compatible = "qcom,lpi-pinctrl"; + reg = <0x0C070000 0x0>; + qcom,num-gpios = <21>; + gpio-controller; + #gpio-cells = <2>; + qcom,lpi-offset-tbl = <0x00000010>, <0x00000020>, + <0x00000030>, <0x00000040>, + <0x00000050>, <0x00000060>, + <0x00000070>, <0x00000080>, + <0x00000090>, <0x00000100>, + <0x00000110>, <0x00000120>, + <0x00000130>, <0x00000140>, + <0x00000150>, <0x00000160>, + <0x00000170>, <0x00000180>, + <0x00000190>, <0x00000200>, + <0x00000210>; + + cdc_dmic01_clk_active: dmic01_clk_active { + mux { + pins = "gpio8"; + function = "func1"; + }; + + config { + pins = "gpio8"; + drive-strength = <8>; + output-high; + }; + }; + + cdc_dmic01_clk_sleep: dmic01_clk_sleep { + mux { + pins = "gpio8"; + function = "func1"; + }; + + config { + pins = "gpio8"; + drive-strength = <2>; + bias-disable; + output-low; + }; + }; + + cdc_dmic01_data_active: dmic01_data_active { + mux { + pins = "gpio9"; + function = "func1"; + }; + + config { + pins = "gpio9"; + drive-strength = <8>; + input-enable; + }; + }; + + cdc_dmic01_data_sleep: dmic01_data_sleep { + mux { + pins = "gpio9"; + function = "func1"; + }; + + config { + pins = "gpio9"; + drive-strength = <2>; + pull-down; + input-enable; + }; + }; + + cdc_dmic23_clk_active: dmic23_clk_active { + mux { + pins = "gpio10"; + function = "func1"; + }; + + config { + pins = "gpio10"; + drive-strength = <8>; + output-high; + }; + }; + + cdc_dmic23_clk_sleep: dmic23_clk_sleep { + mux { + pins = "gpio10"; + function = "func1"; + }; + + config { + pins = "gpio10"; + drive-strength = <2>; + bias-disable; + output-low; + }; + }; + + cdc_dmic23_data_active: dmic23_data_active { + mux { + pins = "gpio11"; + function = "func1"; + }; + + config { + pins = "gpio11"; + drive-strength = <8>; + input-enable; + }; + }; + + cdc_dmic23_data_sleep: dmic23_data_sleep { + mux { + pins = "gpio11"; + function = "func1"; + }; + + config { + pins = "gpio11"; + drive-strength = <2>; + pull-down; + input-enable; + }; + }; + + cdc_dmic45_clk_active: dmic45_clk_active { + mux { + pins = "gpio12"; + function = "func1"; + }; + + config { + pins = "gpio12"; + drive-strength = <8>; + output-high; + }; + }; + + cdc_dmic45_clk_sleep: dmic45_clk_sleep { + mux { + pins = "gpio12"; + function = "func1"; + }; + + config { + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-low; + }; + }; + + cdc_dmic45_data_active: dmic45_data_active { + mux { + pins = "gpio13"; + function = "func1"; + }; + + config { + pins = "gpio13"; + drive-strength = <8>; + input-enable; + }; + }; + + cdc_dmic45_data_sleep: dmic45_data_sleep { + mux { + pins = "gpio13"; + function = "func1"; + }; + + config { + pins = "gpio13"; + drive-strength = <2>; + pull-down; + input-enable; + }; + }; + + cdc_dmic67_clk_active: dmic67_clk_active { + mux { + pins = "gpio14"; + function = "func1"; + }; + + config { + pins = "gpio14"; + drive-strength = <8>; + output-high; + }; + }; + + cdc_dmic67_clk_sleep: dmic67_clk_sleep { + mux { + pins = "gpio14"; + function = "func1"; + }; + + config { + pins = "gpio14"; + drive-strength = <2>; + bias-disable; + output-low; + }; + }; + + cdc_dmic67_data_active: dmic67_data_active { + mux { + pins = "gpio15"; + function = "func1"; + }; + + config { + pins = "gpio15"; + drive-strength = <8>; + input-enable; + }; + }; + + cdc_dmic67_data_sleep: dmic67_data_sleep { + mux { + pins = "gpio15"; + function = "func1"; + }; + + config { + pins = "gpio15"; + drive-strength = <2>; + pull-down; + input-enable; + }; + }; + + wsa_swr_clk_pin { + wsa_swr_clk_sleep: wsa_swr_clk_sleep { + mux { + pins = "gpio5"; + function = "wsa_clk"; + }; + + config { + pins = "gpio5"; + drive-strength = <2>; + bias-bus-hold; + }; + }; + + wsa_swr_clk_active: wsa_swr_clk_active { + mux { + pins = "gpio5"; + function = "wsa_clk"; + }; + + config { + pins = "gpio5"; + drive-strength = <2>; + bias-bus-hold; + }; + }; + }; + + wsa_swr_data_pin { + wsa_swr_data_sleep: wsa_swr_data_sleep { + mux { + pins = "gpio20"; + function = "wsa_data"; + }; + + config { + pins = "gpio20"; + drive-strength = <4>; + bias-bus-hold; + }; + }; + + wsa_swr_data_active: wsa_swr_data_active { + mux { + pins = "gpio20"; + function = "wsa_data"; + }; + + config { + pins = "gpio20"; + drive-strength = <4>; + bias-bus-hold; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-nowcd-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/qcs405-nowcd-audio-overlay.dtsi new file mode 100644 index 000000000000..bb1e52859635 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-nowcd-audio-overlay.dtsi @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qcs405-va-bolero.dtsi" + +&qcs405_snd { + qcom,model = "qcs405-nowcd-snd-card"; + qcom,va-bolero-codec = <1>; + asoc-codec = <&stub_codec>, <&bolero>; + asoc-codec-names = "msm-stub-codec.1", "bolero_codec"; + qcom,cdc-dmic01-gpios = <&cdc_dmic01_gpios>; + qcom,cdc-dmic23-gpios = <&cdc_dmic23_gpios>; + qcom,cdc-dmic45-gpios = <&cdc_dmic45_gpios>; + qcom,cdc-dmic67-gpios = <&cdc_dmic67_gpios>; + qcom,audio-routing = + "VA DMIC0", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic0", + "VA DMIC1", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic1", + "VA DMIC2", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic2", + "VA DMIC3", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic3", + "VA DMIC4", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic4", + "VA DMIC5", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic5", + "VA DMIC6", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic6", + "VA DMIC7", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic7"; +}; + +&bolero { + qcom,num-macros = <1>; +}; + +&soc { + cdc_dmic01_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic01_clk_active &cdc_dmic01_data_active>; + pinctrl-1 = <&cdc_dmic01_clk_sleep &cdc_dmic01_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic23_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic23_clk_active &cdc_dmic23_data_active>; + pinctrl-1 = <&cdc_dmic23_clk_sleep &cdc_dmic23_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic45_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic45_clk_active &cdc_dmic45_data_active>; + pinctrl-1 = <&cdc_dmic45_clk_sleep &cdc_dmic45_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic67_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic67_clk_active &cdc_dmic67_data_active>; + pinctrl-1 = <&cdc_dmic67_clk_sleep &cdc_dmic67_data_sleep>; + qcom,lpi-gpios; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi index 9b51a14b26b2..a4a9f5bb5f87 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi @@ -806,5 +806,516 @@ input-enable; }; }; + + pri_mi2s_mclk { + pri_mi2s_mclk_sleep: pri_mi2s_mclk_sleep { + mux { + pins = "gpio64"; + function = "gpio"; + }; + + config { + pins = "gpio64"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + pri_mi2s_mclk_active: pri_mi2s_mclk_active { + mux { + pins = "gpio64"; + function = "pri_mi2s"; + }; + + config { + pins = "gpio64"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + output-high; + }; + }; + }; + + pri_mi2s_sck { + pri_mi2s_sck_sleep: pri_mi2s_sck_sleep { + mux { + pins = "gpio87"; + function = "i2s_1"; + }; + + config { + pins = "gpio87"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + pri_mi2s_sck_active: pri_mi2s_sck_active { + mux { + pins = "gpio87"; + function = "i2s_1"; + }; + + config { + pins = "gpio87"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + output-high; + }; + }; + }; + + pri_mi2s_ws { + pri_mi2s_ws_sleep: pri_mi2s_ws_sleep { + mux { + pins = "gpio88"; + function = "i2s_1"; + }; + + config { + pins = "gpio88"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + pri_mi2s_ws_active: pri_mi2s_ws_active { + mux { + pins = "gpio88"; + function = "i2s_1"; + }; + + config { + pins = "gpio88"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + output-high; + }; + }; + }; + + pri_mi2s_sd0 { + pri_mi2s_sd0_sleep: pri_mi2s_sd0_sleep { + mux { + pins = "gpio89"; + function = "i2s_1"; + }; + + config { + pins = "gpio89"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + pri_mi2s_sd0_active: pri_mi2s_sd0_active { + mux { + pins = "gpio89"; + function = "i2s_1"; + }; + + config { + pins = "gpio89"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + + pri_mi2s_sd1 { + pri_mi2s_sd1_sleep: pri_mi2s_sd1_sleep { + mux { + pins = "gpio90"; + function = "i2s_1"; + }; + + config { + pins = "gpio90"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + pri_mi2s_sd1_active: pri_mi2s_sd1_active { + mux { + pins = "gpio90"; + function = "i2s_1"; + }; + + config { + pins = "gpio90"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + pri_mi2s_sd2 { + pri_mi2s_sd2_sleep: pri_mi2s_sd2_sleep { + mux { + pins = "gpio91"; + function = "i2s_1"; + }; + + config { + pins = "gpio91"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + pri_mi2s_sd2_active: pri_mi2s_sd2_active { + mux { + pins = "gpio91"; + function = "i2s_1"; + }; + + config { + pins = "gpio91"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + + pri_mi2s_sd3 { + pri_mi2s_sd3_sleep: pri_mi2s_sd3_sleep { + mux { + pins = "gpio92"; + function = "i2s_1"; + }; + + config { + pins = "gpio92"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + pri_mi2s_sd3_active: pri_mi2s_sd3_active { + mux { + pins = "gpio92"; + function = "i2s_1"; + }; + + config { + pins = "gpio92"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + pri_mi2s_sd4 { + pri_mi2s_sd4_sleep: pri_mi2s_sd4_sleep { + mux { + pins = "gpio93"; + function = "i2s_1"; + }; + + config { + pins = "gpio93"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + pri_mi2s_sd4_active: pri_mi2s_sd4_active { + mux { + pins = "gpio93"; + function = "i2s_1"; + }; + + config { + pins = "gpio93"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + + pri_mi2s_sd5 { + pri_mi2s_sd5_sleep: pri_mi2s_sd5_sleep { + mux { + pins = "gpio94"; + function = "i2s_1"; + }; + + config { + pins = "gpio94"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + pri_mi2s_sd5_active: pri_mi2s_sd5_active { + mux { + pins = "gpio94"; + function = "i2s_1"; + }; + + config { + pins = "gpio94"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + sec_mi2s_sck { + sec_mi2s_sck_sleep: sec_mi2s_sck_sleep { + mux { + pins = "gpio97"; + function = "i2s_2"; + }; + + config { + pins = "gpio97"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + sec_mi2s_sck_active: sec_mi2s_sck_active { + mux { + pins = "gpio97"; + function = "i2s_2"; + }; + + config { + pins = "gpio97"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + output-high; + }; + }; + }; + + sec_mi2s_ws { + sec_mi2s_ws_sleep: sec_mi2s_ws_sleep { + mux { + pins = "gpio98"; + function = "i2s_2"; + }; + + config { + pins = "gpio98"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + sec_mi2s_ws_active: sec_mi2s_ws_active { + mux { + pins = "gpio98"; + function = "i2s_2"; + }; + + config { + pins = "gpio98"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + output-high; + }; + }; + }; + + sec_mi2s_sd0 { + sec_mi2s_sd0_sleep: sec_mi2s_sd0_sleep { + mux { + pins = "gpio99"; + function = "i2s_2"; + }; + + config { + pins = "gpio99"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + sec_mi2s_sd0_active: sec_mi2s_sd0_active { + mux { + pins = "gpio99"; + function = "i2s_2"; + }; + + config { + pins = "gpio99"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + + sec_mi2s_sd1 { + sec_mi2s_sd1_sleep: sec_mi2s_sd1_sleep { + mux { + pins = "gpio100"; + function = "i2s_2"; + }; + + config { + pins = "gpio100"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + sec_mi2s_sd1_active: sec_mi2s_sd1_active { + mux { + pins = "gpio100"; + function = "i2s_2"; + }; + + config { + pins = "gpio100"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + sec_mi2s_sd2 { + sec_mi2s_sd2_sleep: sec_mi2s_sd2_sleep { + mux { + pins = "gpio101"; + function = "i2s_2"; + }; + + config { + pins = "gpio101"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + sec_mi2s_sd2_active: sec_mi2s_sd2_active { + mux { + pins = "gpio101"; + function = "i2s_2"; + }; + + config { + pins = "gpio101"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + + sec_mi2s_sd3 { + sec_mi2s_sd3_sleep: sec_mi2s_sd3_sleep { + mux { + pins = "gpio102"; + function = "i2s_2"; + }; + + config { + pins = "gpio102"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + input-enable; + }; + }; + + sec_mi2s_sd3_active: sec_mi2s_sd3_active { + mux { + pins = "gpio102"; + function = "i2s_2"; + }; + + config { + pins = "gpio102"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + + /* WSA speaker reset pins */ + wsa_en_1_2 { + wsa_en_1_2_sleep: wsa_en_1_2_sleep { + mux { + pins = "gpio77"; + function = "gpio"; + }; + + config { + pins = "gpio77"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; + input-enable; + }; + }; + + wsa_en_1_2_active: wsa_en_1_2_active { + mux { + pins = "gpio77"; + function = "gpio"; + }; + + config { + pins = "gpio77"; + drive-strength = <16>; /* 16 mA */ + bias-disable; + output-high; + }; + }; + }; + + wcd9xxx_intr { + wcd_intr_default: wcd_intr_default{ + mux { + pins = "gpio105"; + function = "gpio"; + }; + + config { + pins = "gpio105"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* pull down */ + input-enable; + }; + }; + }; + + cdc_reset_ctrl { + cdc_reset_sleep: cdc_reset_sleep { + mux { + pins = "gpio46"; + function = "gpio"; + }; + config { + pins = "gpio46"; + drive-strength = <16>; + bias-disable; + output-low; + }; + }; + + cdc_reset_active:cdc_reset_active { + mux { + pins = "gpio46"; + function = "gpio"; + }; + config { + pins = "gpio46"; + drive-strength = <16>; + bias-pull-down; + output-high; + }; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi b/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi new file mode 100644 index 000000000000..3f49f98f216d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + wcd9xxx_intc: wcd9xxx-irq { + compatible = "qcom,wcd9xxx-irq"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tlmm>; + qcom,gpio-connect = <&tlmm 105 0>; + pinctrl-names = "default"; + pinctrl-0 = <&wcd_intr_default>; + }; + + clock_audio: audio_ext_clk { + compatible = "qcom,audio-ref-clk"; + qcom,codec-ext-clk-src = <0>; + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&tasha_mclk_default>; + pinctrl-1 = <&tasha_mclk_default>; + #clock-names = "osr_clk"; + #clocks = <&pms405_div_clk>; + #clock-cells = <1>; + }; + + wcd_rst_gpio: msm_cdc_pinctrl@46 { + compatible = "qcom,msm-cdc-pinctrl"; + qcom,cdc-rst-n-gpio = <&tlmm 46 0>; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_reset_active>; + pinctrl-1 = <&cdc_reset_sleep>; + }; +}; + +&slim_aud { + wcd9335: tasha_codec { + compatible = "qcom,tasha-slim-pgd"; + elemental-addr = [00 01 a0 01 17 02]; + + interrupt-parent = <&wcd9xxx_intc>; + interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 + 30>; + + qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>; + + clock-names = "wcd_clk"; + clocks = <&clock_audio AUDIO_PMI_CLK>; + + qcom,cdc-micbias1-mv = <1800>; + qcom,cdc-micbias2-mv = <1800>; + qcom,cdc-micbias3-mv = <1800>; + qcom,cdc-micbias4-mv = <1800>; + + qcom,cdc-mclk-clk-rate = <9600000>; + qcom,cdc-slim-ifd = "tasha-slim-ifd"; + qcom,cdc-slim-ifd-elemental-addr = [00 00 a0 01 17 02]; + qcom,cdc-dmic-sample-rate = <4800000>; + qcom,cdc-mad-dmic-rate = <600000>; + + cdc-vdd-buck-supply = <&pms405_s4>; + qcom,cdc-vdd-buck-voltage = <1800000 1800000>; + qcom,cdc-vdd-buck-current = <594000>; + + cdc-buck-sido-supply = <&pms405_s4>; + qcom,cdc-buck-sido-voltage = <1800000 1800000>; + qcom,cdc-buck-sido-current = <200000>; + + cdc-vdd-tx-h-supply = <&pms405_l6>; + qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>; + qcom,cdc-vdd-tx-h-current = <25000>; + + cdc-vdd-rx-h-supply = <&pms405_l6>; + qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>; + qcom,cdc-vdd-rx-h-current = <25000>; + + cdc-vdd-px-supply = <&pms405_l6>; + qcom,cdc-vdd-px-voltage = <1800000 1800000>; + qcom,cdc-vdd-px-current = <10000>; + + qcom,cdc-static-supplies = "cdc-vdd-buck", + "cdc-buck-sido", + "cdc-vdd-tx-h", + "cdc-vdd-rx-h"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-va-bolero.dtsi b/arch/arm64/boot/dts/qcom/qcs405-va-bolero.dtsi new file mode 100644 index 000000000000..417784cea057 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-va-bolero.dtsi @@ -0,0 +1,34 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&bolero { + va_macro: va_macro { + compatible = "qcom,va-macro"; + reg = <0x0C490000 0x0>; + clock-names = "va_core_clk"; + clocks = <&clock_audio_va 0>; + va-vdd-micb-supply = <&pms405_l7>; + qcom,va-vdd-micb-voltage = <1800000 1800000>; + qcom,va-vdd-micb-current = <11200>; + qcom,va-dmic-sample-rate = <4800000>; + }; +}; + +&soc { + clock_audio_va: va_core_clk { + compatible = "qcom,audio-ref-clk"; + qcom,codec-ext-clk-src = <2>; + qcom,codec-lpass-ext-clk-freq = <9600000>; + qcom,codec-lpass-clk-id = <0x30B>; + #clock-cells = <1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-wsa-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/qcs405-wsa-audio-overlay.dtsi new file mode 100644 index 000000000000..c97b116f79d6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-wsa-audio-overlay.dtsi @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qcs405-tasha.dtsi" +#include "qcs405-va-bolero.dtsi" +#include "qcs405-wsa-bolero.dtsi" +#include "qcs405-wsa881x.dtsi" + +&qcs405_snd { + qcom,model = "qcs405-wsa-snd-card"; + qcom,va-bolero-codec = <1>; + qcom,wsa-bolero-codec = <1>; + qcom,tasha-codec = <1>; + asoc-codec = <&stub_codec>, <&bolero>; + asoc-codec-names = "msm-stub-codec.1", "bolero_codec"; + qcom,wsa-max-devs = <2>; + qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0212>, + <&wsa881x_0213>, <&wsa881x_0214>; + qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight", + "SpkrLeft", "SpkrRight"; + qcom,cdc-dmic01-gpios = <&cdc_dmic01_gpios>; + qcom,cdc-dmic23-gpios = <&cdc_dmic23_gpios>; + qcom,cdc-dmic45-gpios = <&cdc_dmic45_gpios>; + qcom,cdc-dmic67-gpios = <&cdc_dmic67_gpios>; + qcom,audio-routing = + "AMIC3", "MIC BIAS3", + "AMIC4", "MIC BIAS4", + "MIC BIAS3", "Analog Mic3", + "MIC BIAS4", "Analog Mic4", + "VA DMIC0", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic0", + "VA DMIC1", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic1", + "VA DMIC2", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic2", + "VA DMIC3", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic3", + "VA DMIC4", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic4", + "VA DMIC5", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic5", + "VA DMIC6", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic6", + "VA DMIC7", "VA MIC BIAS1", + "VA MIC BIAS1", "Digital Mic7", + "SpkrLeft IN", "WSA_SPK1 OUT", + "SpkrRight IN", "WSA_SPK2 OUT", + "WSA_SPK1 OUT", "VA_MCLK", + "WSA_SPK2 OUT", "VA_MCLK"; +}; + +&bolero { + qcom,num-macros = <2>; +}; + +&soc { + cdc_dmic01_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic01_clk_active &cdc_dmic01_data_active>; + pinctrl-1 = <&cdc_dmic01_clk_sleep &cdc_dmic01_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic23_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic23_clk_active &cdc_dmic23_data_active>; + pinctrl-1 = <&cdc_dmic23_clk_sleep &cdc_dmic23_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic45_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic45_clk_active &cdc_dmic45_data_active>; + pinctrl-1 = <&cdc_dmic45_clk_sleep &cdc_dmic45_data_sleep>; + qcom,lpi-gpios; + }; + + cdc_dmic67_gpios: cdc_dmic_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_dmic67_clk_active &cdc_dmic67_data_active>; + pinctrl-1 = <&cdc_dmic67_clk_sleep &cdc_dmic67_data_sleep>; + qcom,lpi-gpios; + }; + + wsa_swr_gpios: wsa_swr_clk_data_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&wsa_swr_clk_active &wsa_swr_data_active>; + pinctrl-1 = <&wsa_swr_clk_sleep &wsa_swr_data_sleep>; + qcom,lpi-gpios; + }; + + wsa_spkr_en_1_2: wsa_spkr_en_1_2_pinctrl { + compatible = "qcom,msm-cdc-pinctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&wsa_en_1_2_active>; + pinctrl-1 = <&wsa_en_1_2_sleep>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-wsa-bolero.dtsi b/arch/arm64/boot/dts/qcom/qcs405-wsa-bolero.dtsi new file mode 100644 index 000000000000..22c59831a81c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-wsa-bolero.dtsi @@ -0,0 +1,40 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&bolero { + wsa_macro: wsa-macro { + compatible = "qcom,wsa-macro"; + reg = <0x0C2C0000 0x0>; + clock-names = "wsa_core_clk", "wsa_npl_clk"; + clocks = <&clock_audio_wsa_1 0>, + <&clock_audio_wsa_2 0>; + qcom,wsa-swr-gpios = &wsa_swr_gpios; + }; +}; + +&soc { + clock_audio_wsa_1: wsa_core_clk { + compatible = "qcom,audio-ref-clk"; + qcom,codec-ext-clk-src = <2>; + qcom,codec-lpass-ext-clk-freq = <19200000>; + qcom,codec-lpass-clk-id = <0x309>; + #clock-cells = <1>; + }; + + clock_audio_wsa_2: wsa_npl_clk { + compatible = "qcom,audio-ref-clk"; + qcom,codec-ext-clk-src = <2>; + qcom,codec-lpass-ext-clk-freq = <19200000>; + qcom,codec-lpass-clk-id = <0x30A>; + #clock-cells = <1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-wsa881x.dtsi b/arch/arm64/boot/dts/qcom/qcs405-wsa881x.dtsi new file mode 100644 index 000000000000..bdaf3fc9ab84 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-wsa881x.dtsi @@ -0,0 +1,57 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/{ + aliases { + swr0 = &swr_0; + }; +}; + +#include + +&wsa_macro { + swr_0: wsa_swr_master { + compatible = "qcom,swr-mstr"; + #address-cells = <2>; + #size-cells = <0>; + qcom,swr-num-ports = <8>; + qcom,swr-port-mapping = <1 SPKR_L 0x1>, + <2 SPKR_L_COMP 0xF>, <3 SPKR_L_BOOST 0x3>, + <4 SPKR_R 0x1>, <5 SPKR_R_COMP 0xF>, + <6 SPKR_R_BOOST 0x3>, <7 SPKR_L_VI 0x3>, + <8 SPKR_R_VI 0x3>; + + wsa881x_0211: wsa881x@20170211 { + compatible = "qcom,wsa881x"; + reg = <0x0 0x20170211>; + qcom,spkr-sd-n-node = <&wsa_spkr_en_1_2>; + }; + + wsa881x_0212: wsa881x@20170212 { + compatible = "qcom,wsa881x"; + reg = <0x0 0x20170212>; + qcom,spkr-sd-n-node = <&wsa_spkr_en_1_2>; + }; + + wsa881x_0213: wsa881x@21170213 { + compatible = "qcom,wsa881x"; + reg = <0x0 0x21170213>; + qcom,spkr-sd-n-node = <&wsa_spkr_en_1_2>; + }; + + wsa881x_0214: wsa881x@21170214 { + compatible = "qcom,wsa881x"; + reg = <0x0 0x21170214>; + qcom,spkr-sd-n-node = <&wsa_spkr_en_1_2>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 94a61ad6738a..d2fef0fade4e 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -942,6 +942,7 @@ #include "qcs405-regulator.dtsi" #include "qcs405-thermal.dtsi" #include "qcs405-bus.dtsi" +#include "qcs405-audio.dtsi" &gdsc_mdss { status = "ok"; -- GitLab From 0ae60d488f6a6e1e374fe31fabeb8672ba2cf3fb Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Samavedam Date: Thu, 14 Dec 2017 11:13:51 -0800 Subject: [PATCH 0723/1299] usb: dwc3: update HP timer as per new usb 3.1 ECN This is the workaround for STAR 9001198391 which affects dwc3 core version 3.20a only. DWC3 core version:3.20a supports usb 3.1 hp timer ECN but incorrectly sets hp timer timeout to 3us. Update hp timer to 11us to pass usb link layer compliance test: TD 7.1, TD 7.9, TD 7.11, TD 7.13, TD 7.14, TD 7.18, TD 7.23, TD 7.26, TD 7.27, TD 7.28, and TD 7.29. Change-Id: Icdbc1550e96a7dfcbe85604b8c237f0a8730bb23 Signed-off-by: Vamsi Krishna Samavedam --- drivers/usb/dwc3/core.c | 13 +++++++++++++ drivers/usb/dwc3/core.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index da50956e577a..5eb37ad37d9e 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -881,6 +881,19 @@ int dwc3_core_init(struct dwc3 *dwc) dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT); + /* + * Workaround for STAR 9001198391 which affects dwc3 core + * version 3.20a only. Default HP timer value is incorrectly + * set to 3us. Reprogram HP timer value to support USB 3.1 + * HP timer ECN. + */ + if (!dwc3_is_usb31(dwc) && dwc->revision == DWC3_REVISION_320A) { + reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); + reg &= ~DWC3_GUCTL2_HP_TIMER_MASK; + reg |= DWC3_GUCTL2_HP_TIMER(11); + dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); + } + return 0; err3: diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 0b9127188979..1fb07f6bea1c 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -326,6 +326,8 @@ /* Global User Control Register 2 */ #define DWC3_GUCTL2_RST_ACTBITLATER BIT(14) +#define DWC3_GUCTL2_HP_TIMER(n) ((n) << 21) +#define DWC3_GUCTL2_HP_TIMER_MASK DWC3_GUCTL2_HP_TIMER(0x1f) /* Global User Control Register 3 */ #define DWC3_GUCTL3_USB20_RETRY_DISABLE BIT(16) @@ -1062,6 +1064,7 @@ struct dwc3 { #define DWC3_REVISION_290A 0x5533290a #define DWC3_REVISION_300A 0x5533300a #define DWC3_REVISION_310A 0x5533310a +#define DWC3_REVISION_320A 0x5533320a /* * NOTICE: we're using bit 31 as a "is usb 3.1" flag. This is really -- GitLab From d344a7bdb76ef3919519183bf316d9e22aa915a3 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Tue, 12 Jun 2018 20:01:28 +0530 Subject: [PATCH 0724/1299] usb: dwc3: update LC timer as per new usb V3.20 This is the workaround for STAR 9001285599 which affects dwc3 core version 3.20a only. The timer value for PM_LC_TIMER in V3.20a for the Link ECN changes is not correct. If the PM TIMER ECN is enabled thru GUCTL2[19], then link compliance test (TD7.21) may fail. If the ECN is not enabled (GUCTL2[19] = 0), the controller will use the old timer value (5us), which is still fine for Link Compliance test. Hence Clear GUCTL2[19] to pass usb link compliance test: TD 7.21. Change-Id: I5fc535ef2bdd54764086a50cf9a3cb538f92a465 Signed-off-by: Chandana Kishori Chiluveru --- drivers/usb/dwc3/core.c | 15 +++++++++++++++ drivers/usb/dwc3/core.h | 1 + 2 files changed, 16 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 5eb37ad37d9e..5e3c665e5e7b 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -894,6 +894,21 @@ int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); } + /* + * Workaround for STAR 9001285599 which affects dwc3 core version 3.20a + * only. If the PM TIMER ECN is enabled thru GUCTL2[19], then link + * compliance test (TD7.21) may fail. If the ECN is not enabled + * GUCTL2[19] = 0), the controller will use the old timer value (5us), + * which is still fine for Link Compliance test. Hence Do not enable + * PM TIMER ECN in V3.20a by setting GUCTL2[19] by default, + * instead use GUCTL2[19] = 0. + */ + if (dwc->revision == DWC3_REVISION_320A) { + reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); + reg &= ~DWC3_GUCTL2_LC_TIMER; + dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); + } + return 0; err3: diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 1fb07f6bea1c..aaf2311bb4fb 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -328,6 +328,7 @@ #define DWC3_GUCTL2_RST_ACTBITLATER BIT(14) #define DWC3_GUCTL2_HP_TIMER(n) ((n) << 21) #define DWC3_GUCTL2_HP_TIMER_MASK DWC3_GUCTL2_HP_TIMER(0x1f) +#define DWC3_GUCTL2_LC_TIMER (1 << 19) /* Global User Control Register 3 */ #define DWC3_GUCTL3_USB20_RETRY_DISABLE BIT(16) -- GitLab From 956af71ee34ac951a2f105a0a12d5184eccc9eb2 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Tue, 20 Mar 2018 20:08:21 +0530 Subject: [PATCH 0725/1299] ARM: dts: msm: Add IPA device configuration for SM6150 The required configuration to support new IPA HW version 4.2 on SM6150 target. Change-Id: I0625e87d93445e8ece89343d76a8aafbc35d2f90 Acked-by: Ashok Vuyyuru Signed-off-by: Mohammed Javid --- arch/arm64/boot/dts/qcom/sm6150.dtsi | 72 ++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index c744416563c3..5d2ebe110a6b 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -23,6 +23,7 @@ #include #include #include +#include / { model = "Qualcomm Technologies, Inc. SM6150"; @@ -1614,6 +1615,77 @@ mboxes = <&qmp_aop 0>; mbox-names = "cdsp-pil"; }; + + qcom,msm_gsi { + compatible = "qcom,msm_gsi"; + }; + + qcom,rmnet-ipa { + compatible = "qcom,rmnet-ipa3"; + qcom,rmnet-ipa-ssr; + qcom,ipa-loaduC; + qcom,ipa-advertise-sg-support; + qcom,ipa-napi-enable; + }; + + ipa_hw: qcom,ipa@1e00000 { + compatible = "qcom,ipa"; + reg = <0x1e00000 0x34000>, + <0x1e04000 0x2c000>; + reg-names = "ipa-base", "gsi-base"; + interrupts = <0 311 0>, <0 432 0>; + interrupt-names = "ipa-irq", "gsi-irq"; + qcom,ipa-hw-ver = <16>; /* IPA core version = IPAv4.2 */ + qcom,ipa-hw-mode = <1>; + qcom,ee = <0>; + qcom,use-ipa-tethering-bridge; + qcom,modem-cfg-emb-pipe-flt; + qcom,ipa-wdi2; + qcom,ipa-fltrt-not-hashable; + qcom,use-64-bit-dma-mask; + qcom,arm-smmu; + qcom,bandwidth-vote-for-ipa; + qcom,msm-bus,name = "ipa"; + qcom,msm-bus,num-cases = <5>; + qcom,msm-bus,num-paths = <4>; + qcom,msm-bus,vectors-KBps = + /* No vote */ + , + , + , + , + /* SVS2 */ + , + , + , + , + /* SVS */ + , + , + , + , + /* NOMINAL */ + , + , + , + , + /* TURBO */ + , + , + , + ; + qcom,bus-vector-names = + "MIN", "SVS2", "SVS", "NOMINAL", "TURBO"; + + }; + + qcom,ipa_fws { + compatible = "qcom,pil-tz-generic"; + qcom,pas-id = <0xf>; + qcom,firmware-name = "ipa_fws"; + qcom,pil-force-shutdown; + memory-region = <&pil_ipa_fw_mem>; + }; }; #include "pm6150.dtsi" -- GitLab From 6ee38a5468beccbd8aef60765b2c1266d547311f Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Tue, 12 Jun 2018 20:51:03 +0530 Subject: [PATCH 0726/1299] diag: Set new context for peripheral error response The patch sets new error context with TYPE_CMD for buf_num context to add peripheral error responses on apps response path to respective logging session and prevent buffer corruption. Change-Id: I02c246d9a68a4f8e912d8693b3e4844c0e0b6885 Signed-off-by: Manoj Prabhu B --- drivers/char/diag/diagfwd.c | 51 ++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c index f7784fdbb7ef..4a1de0902818 100644 --- a/drivers/char/diag/diagfwd.c +++ b/drivers/char/diag/diagfwd.c @@ -48,6 +48,7 @@ #define STM_RSP_SUPPORTED_INDEX 7 #define STM_RSP_STATUS_INDEX 8 #define STM_RSP_NUM_BYTES 9 +#define RETRY_MAX_COUNT 1000 struct diag_md_hdlc_reset_work { int pid; @@ -248,28 +249,22 @@ static void pack_rsp_and_send(unsigned char *buf, int len, * if its supporting qshrink4 feature. */ if (info && info->peripheral_mask) { - if (info->peripheral_mask == DIAG_CON_ALL || - (info->peripheral_mask & (1 << APPS_DATA)) || - (info->peripheral_mask & (1 << PERIPHERAL_MODEM))) { - rsp_ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_CMD, 1); - } else { - for (i = 0; i < NUM_MD_SESSIONS; i++) { - if (info->peripheral_mask & (1 << i)) - break; - } - rsp_ctxt = SET_BUF_CTXT(i, TYPE_CMD, 1); + for (i = 0; i < NUM_MD_SESSIONS; i++) { + if (info->peripheral_mask & (1 << i)) + break; } + rsp_ctxt = SET_BUF_CTXT(i, TYPE_CMD, TYPE_CMD); } else rsp_ctxt = driver->rsp_buf_ctxt; mutex_unlock(&driver->md_session_lock); /* * Keep trying till we get the buffer back. It should probably - * take one or two iterations. When this loops till UINT_MAX, it + * take one or two iterations. When this loops till RETRY_MAX_COUNT, it * means we did not get a write complete for the previous * response. */ - while (retry_count < UINT_MAX) { + while (retry_count < RETRY_MAX_COUNT) { if (!driver->rsp_buf_busy) break; /* @@ -347,27 +342,21 @@ static void encode_rsp_and_send(unsigned char *buf, int len, * if its supporting qshrink4 feature. */ if (info && info->peripheral_mask) { - if (info->peripheral_mask == DIAG_CON_ALL || - (info->peripheral_mask & (1 << APPS_DATA)) || - (info->peripheral_mask & (1 << PERIPHERAL_MODEM))) { - rsp_ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_CMD, 1); - } else { - for (i = 0; i < NUM_MD_SESSIONS; i++) { - if (info->peripheral_mask & (1 << i)) - break; - } - rsp_ctxt = SET_BUF_CTXT(i, TYPE_CMD, 1); + for (i = 0; i < NUM_MD_SESSIONS; i++) { + if (info->peripheral_mask & (1 << i)) + break; } + rsp_ctxt = SET_BUF_CTXT(i, TYPE_CMD, TYPE_CMD); } else rsp_ctxt = driver->rsp_buf_ctxt; mutex_unlock(&driver->md_session_lock); /* * Keep trying till we get the buffer back. It should probably - * take one or two iterations. When this loops till UINT_MAX, it + * take one or two iterations. When this loops till RETRY_MAX_COUNT, it * means we did not get a write complete for the previous * response. */ - while (retry_count < UINT_MAX) { + while (retry_count < RETRY_MAX_COUNT) { if (!driver->rsp_buf_busy) break; /* @@ -1803,14 +1792,18 @@ static int diagfwd_mux_write_done(unsigned char *buf, int len, int buf_ctxt, } break; case TYPE_CMD: - if (peripheral >= 0 && peripheral < NUM_PERIPHERALS) { + if (peripheral >= 0 && peripheral < NUM_PERIPHERALS && + num != TYPE_CMD) { DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "Marking buffer as free after write done p: %d, t: %d, buf_num: %d\n", - peripheral, type, num); + peripheral, type, num); diagfwd_write_done(peripheral, type, num); - } - if (peripheral == APPS_DATA || - ctxt == DIAG_MEMORY_DEVICE_MODE) { + } else if (peripheral == APPS_DATA || + (peripheral >= 0 && peripheral < NUM_PERIPHERALS && + num == TYPE_CMD)) { + DIAG_LOG(DIAG_DEBUG_PERIPHERALS, + "Marking APPS response buffer free after write done for p: %d, t: %d, buf_num: %d\n", + peripheral, type, num); spin_lock_irqsave(&driver->rsp_buf_busy_lock, flags); driver->rsp_buf_busy = 0; driver->encoded_rsp_len = 0; -- GitLab From ee451c5da85486f201daa3da4be15a69c8eb8f52 Mon Sep 17 00:00:00 2001 From: Amit Nischal Date: Tue, 19 Jun 2018 11:32:25 +0530 Subject: [PATCH 0727/1299] clk: qcom: Add BRANCH_HALT_SKIP flag for gfx3d clock For SM6150, GX GDSC is GMU firmware controlled and polling for the gfx3d clock status would result into error. Add BRANCH_HALT_SKIP flag for gfx3d clock in order to avoid returning error. Change-Id: I955a0e1db7ff8f4161a74aef63337ea47f634649 Signed-off-by: Amit Nischal --- drivers/clk/qcom/gpucc-sm6150.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/gpucc-sm6150.c b/drivers/clk/qcom/gpucc-sm6150.c index eaf4e0a38dbc..d2f7f604908b 100644 --- a/drivers/clk/qcom/gpucc-sm6150.c +++ b/drivers/clk/qcom/gpucc-sm6150.c @@ -345,7 +345,7 @@ static struct clk_branch gpu_cc_cxo_clk = { static struct clk_branch gpu_cc_gx_gfx3d_clk = { .halt_reg = 0x1054, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x1054, .enable_mask = BIT(0), -- GitLab From 12d2aa76f35d6ad5dbd820ce0ebabd3a14b2515b Mon Sep 17 00:00:00 2001 From: Carter Cooper Date: Fri, 25 May 2018 11:54:28 -0600 Subject: [PATCH 0728/1299] msm: kgsl: Disable interrupts before stopping HFI Disable interrupts to ensure no new interrupts come in while trying to stop HFI. Change-Id: I2291730c0afc9817e09781da9be020a4dbb7b9f3 Signed-off-by: Carter Cooper --- drivers/gpu/msm/kgsl_gmu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index adcb51a163c4..4a4912b26a2d 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -1508,9 +1508,8 @@ static int gmu_suspend(struct kgsl_device *device) return 0; /* Pending message in all queues are abandoned */ - hfi_stop(gmu); - clear_bit(GMU_HFI_ON, &gmu->flags); gmu_dev_ops->irq_disable(device); + hfi_stop(gmu); if (gmu_dev_ops->rpmh_gpu_pwrctrl(adreno_dev, GMU_SUSPEND, 0, 0)) return -EINVAL; @@ -1681,9 +1680,8 @@ static void gmu_stop(struct kgsl_device *device) goto error; /* Pending message in all queues are abandoned */ - hfi_stop(gmu); - clear_bit(GMU_HFI_ON, &gmu->flags); gmu_dev_ops->irq_disable(device); + hfi_stop(gmu); gmu_dev_ops->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_STOP, 0, 0); gmu_disable_clks(gmu); -- GitLab From 85c1f013dcf98d3800421481fe4c2cb8553ddbdb Mon Sep 17 00:00:00 2001 From: Carter Cooper Date: Wed, 2 May 2018 11:40:52 -0600 Subject: [PATCH 0729/1299] msm: kgsl: Only look at enabled HFI queues No need to try and read/write from disabled HFI queues. Update the HFI queue status at init to correctly reflect if the queue is open for business. Change-Id: Id23e5d61e73a2e5885bea92b98b52f5cfe964506 Signed-off-by: Carter Cooper --- drivers/gpu/msm/kgsl_hfi.c | 18 ++++++++++++------ drivers/gpu/msm/kgsl_hfi.h | 7 +++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c index c3bea2eabd0b..7f3f16190232 100644 --- a/drivers/gpu/msm/kgsl_hfi.c +++ b/drivers/gpu/msm/kgsl_hfi.c @@ -58,6 +58,9 @@ static int hfi_queue_read(struct gmu_device *gmu, uint32_t queue_idx, uint32_t size; int result = 0; + if (hdr->status == HFI_QUEUE_STATUS_DISABLED) + return -EINVAL; + if (hdr->read_index == hdr->write_index) { hdr->rx_req = 1; return -ENODATA; @@ -113,7 +116,7 @@ static int hfi_queue_write(struct gmu_device *gmu, uint32_t queue_idx, uint32_t size = MSG_HDR_GET_SIZE(*msg); uint32_t id = MSG_HDR_GET_ID(*msg); - if (hdr->enabled == 0) + if (hdr->status == HFI_QUEUE_STATUS_DISABLED) return -EINVAL; if (size > HFI_MAX_MSG_SIZE) { @@ -188,11 +191,12 @@ void hfi_init(struct kgsl_hfi *hfi, struct gmu_memdesc *mem_addr, struct { unsigned int idx; unsigned int pri; + unsigned int status; } queue[HFI_QUEUE_MAX] = { - { HFI_CMD_ID, HFI_CMD_PRI }, - { HFI_MSG_ID, HFI_MSG_PRI }, - { HFI_DBG_ID, HFI_DBG_PRI }, - { HFI_DSP_ID_0, HFI_DSP_PRI_0 }, + { HFI_CMD_IDX, HFI_CMD_PRI, HFI_QUEUE_STATUS_ENABLED }, + { HFI_MSG_IDX, HFI_MSG_PRI, HFI_QUEUE_STATUS_ENABLED }, + { HFI_DBG_IDX, HFI_DBG_PRI, HFI_QUEUE_STATUS_ENABLED }, + { HFI_DSP_IDX_0, HFI_DSP_PRI_0, HFI_QUEUE_STATUS_DISABLED }, }; /* Fill Table Header */ @@ -209,7 +213,7 @@ void hfi_init(struct kgsl_hfi *hfi, struct gmu_memdesc *mem_addr, hdr = &tbl->qhdr[i]; hdr->start_addr = GMU_QUEUE_START_ADDR(mem_addr, i); hdr->type = QUEUE_HDR_TYPE(queue[i].idx, queue[i].pri, 0, 0); - hdr->enabled = 0x1; + hdr->status = queue[i].status; hdr->queue_size = queue_sz_bytes >> 2; /* convert to dwords */ hdr->msg_size = 0; hdr->drop_cnt = 0; @@ -703,6 +707,8 @@ void hfi_stop(struct gmu_device *gmu) /* Flush HFI queues */ for (i = 0; i < HFI_QUEUE_MAX; i++) { hdr = &tbl->qhdr[i]; + if (hdr->status == HFI_QUEUE_STATUS_DISABLED) + continue; if (hdr->read_index != hdr->write_index) dev_err(&gmu->pdev->dev, diff --git a/drivers/gpu/msm/kgsl_hfi.h b/drivers/gpu/msm/kgsl_hfi.h index 0ba4edd6c741..d5e7c764c6b7 100644 --- a/drivers/gpu/msm/kgsl_hfi.h +++ b/drivers/gpu/msm/kgsl_hfi.h @@ -38,6 +38,9 @@ #define HFI_DSP_IDX_BASE 3 #define HFI_DSP_IDX_0 3 +#define HFI_QUEUE_STATUS_DISABLED 0 +#define HFI_QUEUE_STATUS_ENABLED 1 + /* HTOF queue priority, 1 is highest priority */ #define HFI_CMD_PRI 10 #define HFI_MSG_PRI 10 @@ -128,7 +131,7 @@ struct hfi_queue_table_header { /** * struct hfi_queue_header - HFI queue header structure - * @enabled: active: 1; inactive: 0 + * @status: active: 1; inactive: 0 * @start_addr: starting address of the queue in GMU VA space * @type: queue type encoded the priority, ID and send/recevie types * @queue_size: size of the queue @@ -143,7 +146,7 @@ struct hfi_queue_table_header { * @write_index: write index of the queue */ struct hfi_queue_header { - uint32_t enabled; + uint32_t status; uint32_t start_addr; uint32_t type; uint32_t queue_size; -- GitLab From a7af8b883d1f0e583aeceb15e2c9e34614af241e Mon Sep 17 00:00:00 2001 From: Carter Cooper Date: Fri, 25 May 2018 12:09:02 -0600 Subject: [PATCH 0730/1299] msm: kgsl: Don't reset HFI indexes on reset There is no need to reset HFI queue read_index and write_index on device start/stop. They should be equal. If they are not then log the mismatch and force them to be equal. Change-Id: Id6dbf3f028f5a27608cc49f5ede2c76291f71669 Signed-off-by: Carter Cooper --- drivers/gpu/msm/kgsl_hfi.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c index 7f3f16190232..0b855c047a0a 100644 --- a/drivers/gpu/msm/kgsl_hfi.c +++ b/drivers/gpu/msm/kgsl_hfi.c @@ -643,11 +643,28 @@ int hfi_start(struct kgsl_device *device, struct gmu_device *gmu, uint32_t boot_state) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - int result; + struct gmu_memdesc *mem_addr = gmu->hfi_mem; + struct hfi_queue_table *tbl = mem_addr->hostptr; + struct hfi_queue_header *hdr; + int result, i; if (test_bit(GMU_HFI_ON, &gmu->flags)) return 0; + /* Force read_index to the write_index no matter what */ + for (i = 0; i < HFI_QUEUE_MAX; i++) { + hdr = &tbl->qhdr[i]; + if (hdr->status == HFI_QUEUE_STATUS_DISABLED) + continue; + + if (hdr->read_index != hdr->write_index) { + dev_err(&gmu->pdev->dev, + "HFI Q[%d] Index Error: read:0x%X write:0x%X\n", + i, hdr->read_index, hdr->write_index); + hdr->read_index = hdr->write_index; + } + } + if (!adreno_is_a640(adreno_dev) && !adreno_is_a680(adreno_dev)) { result = hfi_send_gmu_init(gmu, boot_state); if (result) @@ -714,9 +731,6 @@ void hfi_stop(struct gmu_device *gmu) dev_err(&gmu->pdev->dev, "HFI queue[%d] is not empty before close: rd=%d,wt=%d", i, hdr->read_index, hdr->write_index); - - hdr->read_index = 0x0; - hdr->write_index = 0x0; } clear_bit(GMU_HFI_ON, &gmu->flags); -- GitLab From 317adbaa6f9de987ec930a2ecc78a81dadba658a Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Fri, 25 May 2018 12:38:25 -0700 Subject: [PATCH 0731/1299] of: Make CONFIG_OF_KOBJ configurable Add help text in order to allow this option to be selectable from menuconfig. Change-Id: I5755037ba3488fc1eff83d68148c5b417d6fccb9 Signed-off-by: Patrick Daly --- drivers/of/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index e4304e70a6d3..0a963b179105 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -47,7 +47,13 @@ config OF_PROMTREE bool config OF_KOBJ + bool "Display devicetree in sysfs" def_bool SYSFS + help + Some embedded platforms have no need to display the devicetree + nodes and properties in sysfs. Disabling this option will save + a small amount of memory, as well as decrease boot time. By + default this option will be enabled if SYSFS is enabled. # Hardly any platforms need this. It is safe to select, but only do so if you # need it. -- GitLab From 5b700bea18c379c124479386c997d2a1bb1c9f3e Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Fri, 18 May 2018 15:29:54 -0700 Subject: [PATCH 0732/1299] driver_core: Avoid NULL dereference when CONFIG_OF_KOBJ=n Avoid creating a symlink to a nonexistent kobject. Change-Id: I6468d8f5d6e585d84826762ba6c34ded71b030cd Signed-off-by: Patrick Daly --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 4fbf07a77fab..32b7113b4962 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1578,7 +1578,7 @@ static int device_add_class_symlinks(struct device *dev) struct device_node *of_node = dev_of_node(dev); int error; - if (of_node) { + if (of_node && of_node_kobj(of_node)) { error = sysfs_create_link(&dev->kobj, of_node_kobj(of_node), "of_node"); if (error) dev_warn(dev, "Error %d creating of_node link\n",error); -- GitLab From 7c98272aa4b8aa94ed6c6e1c1f9009056c755242 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Wed, 13 Jun 2018 18:27:39 -0700 Subject: [PATCH 0733/1299] iommu: arm-smmu: Restore missing call to arm_smmu_write_context_bank arm_smmu_write_context_bank must be called during the hibernation restore sequence to restore all registers. Additionally, enable clocks/regulators as required during hibernation restore. Change-Id: Ib9f5854e780e7867c0bd4f220dfcdbfb387b3144 Signed-off-by: Patrick Daly --- drivers/iommu/arm-smmu.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index d2629d41078a..31a7f563c3a1 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -3720,7 +3720,7 @@ static void arm_smmu_context_bank_reset(struct arm_smmu_device *smmu) for (i = 0; i < smmu->num_context_banks; ++i) { cb_base = ARM_SMMU_CB(smmu, i); - writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR); + arm_smmu_write_context_bank(smmu, i, 0); writel_relaxed(FSR_FAULT, cb_base + ARM_SMMU_CB_FSR); /* * Disable MMU-500's not-particularly-beneficial next-page @@ -4674,8 +4674,15 @@ static int arm_smmu_device_remove(struct platform_device *pdev) static int __maybe_unused arm_smmu_pm_resume(struct device *dev) { struct arm_smmu_device *smmu = dev_get_drvdata(dev); + int ret; + + ret = arm_smmu_power_on(smmu->pwr); + if (ret) + return ret; arm_smmu_device_reset(smmu); + arm_smmu_power_off(smmu->pwr); + return 0; } -- GitLab From 07cff1d205d42cd09fd042ba12d9c6b862eca5d4 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Fri, 6 Apr 2018 18:07:13 -0700 Subject: [PATCH 0734/1299] iommu: arm-smmu: Add PM support for actlr register Save the value of the actlr register so it can be restored upon resume from hibernation/suspend. Change-Id: I02dda54ee5905870adae05357e043c4d95003412 Signed-off-by: Patrick Daly --- drivers/iommu/arm-smmu.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 31a7f563c3a1..558562217f15 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -178,6 +178,7 @@ struct arm_smmu_cb { u32 tcr[2]; u32 mair[2]; struct arm_smmu_cfg *cfg; + u32 actlr; }; struct arm_smmu_master_cfg { @@ -1586,6 +1587,9 @@ static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx, writel_relaxed(cb->mair[1], cb_base + ARM_SMMU_CB_S1_MAIR1); } + /* ACTLR (implementation defined) */ + writel_relaxed(cb->actlr, cb_base + ARM_SMMU_CB_ACTLR); + /* SCTLR */ reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE; @@ -1864,11 +1868,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, /* Initialise the context bank with our page table cfg */ arm_smmu_init_context_bank(smmu_domain, &smmu_domain->pgtbl_cfg); + arm_smmu_arch_init_context_bank(smmu_domain, dev); arm_smmu_write_context_bank(smmu, cfg->cbndx, smmu_domain->attributes ); - - arm_smmu_arch_init_context_bank(smmu_domain, dev); - /* for slave side secure, we may have to force the pagetable * format to V8L. */ @@ -1877,7 +1879,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, if (ret) goto out_clear_smmu; - /* * Request context fault interrupt. Do this last to avoid the * handler seeing a half-initialised domain state. @@ -3620,18 +3621,17 @@ static void qsmmuv2_device_reset(struct arm_smmu_device *smmu) int i; u32 val; struct arm_smmu_impl_def_reg *regs = smmu->impl_def_attach_registers; - void __iomem *cb_base; - /* * SCTLR.M must be disabled here per ARM SMMUv2 spec * to prevent table walks with an inconsistent state. */ for (i = 0; i < smmu->num_context_banks; ++i) { - cb_base = ARM_SMMU_CB(smmu, i); + struct arm_smmu_cb *cb = &smmu->cbs[i]; + val = ACTLR_QCOM_ISH << ACTLR_QCOM_ISH_SHIFT | ACTLR_QCOM_OSH << ACTLR_QCOM_OSH_SHIFT | ACTLR_QCOM_NSH << ACTLR_QCOM_NSH_SHIFT; - writel_relaxed(val, cb_base + ARM_SMMU_CB_ACTLR); + cb->actlr = val; } /* Program implementation defined registers */ @@ -4258,6 +4258,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) sizeof(*smmu->cbs), GFP_KERNEL); if (!smmu->cbs) return -ENOMEM; + for (i = 0; i < smmu->num_context_banks; i++) { + void __iomem *cb_base; + + cb_base = ARM_SMMU_CB(smmu, i); + smmu->cbs[i].actlr = readl_relaxed(cb_base + ARM_SMMU_CB_ACTLR); + } /* ID2 */ id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID2); @@ -5187,19 +5193,14 @@ static void qsmmuv500_init_cb(struct arm_smmu_domain *smmu_domain, struct device *dev) { struct arm_smmu_device *smmu = smmu_domain->smmu; + struct arm_smmu_cb *cb = &smmu->cbs[smmu_domain->cfg.cbndx]; struct qsmmuv500_group_iommudata *iommudata = to_qsmmuv500_group_iommudata(dev->iommu_group); - void __iomem *cb_base; - const struct iommu_gather_ops *tlb; if (!iommudata->has_actlr) return; - tlb = smmu_domain->pgtbl_cfg.tlb; - cb_base = ARM_SMMU_CB(smmu, smmu_domain->cfg.cbndx); - - writel_relaxed(iommudata->actlr, cb_base + ARM_SMMU_CB_ACTLR); - + cb->actlr = iommudata->actlr; /* * Prefetch only works properly if the start and end of all * buffers in the page table are aligned to ARM_SMMU_MIN_IOVA_ALIGN. @@ -5207,12 +5208,6 @@ static void qsmmuv500_init_cb(struct arm_smmu_domain *smmu_domain, if ((iommudata->actlr >> QSMMUV500_ACTLR_DEEP_PREFETCH_SHIFT) & QSMMUV500_ACTLR_DEEP_PREFETCH_MASK) smmu_domain->qsmmuv500_errata1_min_iova_align = true; - - /* - * Flush the context bank after modifying ACTLR to ensure there - * are no cache entries with stale state - */ - tlb->tlb_flush_all(smmu_domain); } static int qsmmuv500_tbu_register(struct device *dev, void *cookie) -- GitLab From c2beab3fa5240688deffeb9e87b7b7ff70ee5334 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Wed, 13 Jun 2018 20:44:08 -0700 Subject: [PATCH 0735/1299] iommu: arm-smmu: Add error message for hibernation usecase The iommu driver may use hyp_assign to ensure its page tables are mapped in stage 2 page table appropriate for a secure usecase. As hypervisor configuration is not restored across hibernation, this usecase is not currently supported. Print an error instead of failing with an access violation. Change-Id: Iaaaae2c2199555f61cff915b994510a07984d42c Signed-off-by: Patrick Daly --- drivers/iommu/arm-smmu.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 558562217f15..6d1fefca46c8 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -515,6 +515,11 @@ static void arm_smmu_secure_domain_unlock(struct arm_smmu_domain *smmu_domain) mutex_unlock(&smmu_domain->assign_lock); } +static bool arm_smmu_opt_hibernation(struct arm_smmu_device *smmu) +{ + return IS_ENABLED(CONFIG_HIBERNATION); +} + /* * init() * Hook for additional device tree parsing at probe time. @@ -1688,6 +1693,14 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, goto out_unlock; } + if (arm_smmu_has_secure_vmid(smmu_domain) && + arm_smmu_opt_hibernation(smmu)) { + dev_err(smmu->dev, + "Secure usecases not supported with hibernation\n"); + ret = -EPERM; + goto out_unlock; + } + /* * Mapping the requested stage onto what we support is surprisingly * complicated, mainly because the spec allows S1+S2 SMMUs without -- GitLab From ca9b6f1b40e5ff5fe7fc9a653e2adb40f8f8e8f7 Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Wed, 9 May 2018 20:03:47 -0700 Subject: [PATCH 0736/1299] drm/msm/dsi-staging: add force_clk_lane_hs support Some panel / bridge require clock lane always in high speed mode, this change added options in DT file to force DSI controller and PHY output clock lane in high speed mode. CRs-Fixed: 2242680 Change-Id: I5e69b942ef9bc77dd7a6542f37f4f41a45ffefea Signed-off-by: Xiaowen Wu --- .../devicetree/bindings/display/msm/dsi.txt | 2 ++ drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c | 5 +++++ drivers/gpu/drm/msm/dsi-staging/dsi_defs.h | 1 + drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 3 +++ drivers/gpu/drm/msm/dsi-staging/dsi_phy.c | 3 +++ drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h | 2 ++ drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c | 14 ++++++++++++++ 7 files changed, 30 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt index 17f9d7516ffb..8951557d42d3 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi.txt +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt @@ -127,6 +127,7 @@ Optional properties: turns off PHY pmic power supply, phy ldo and DSI Lane ldo during idle screen (footswitch control off) when this property is enabled. - qcom,dsi-phy-regulator-min-datarate-bps: Minimum per lane data rate (bps) to turn on PHY regulator. +- qcom,panel-force-clock-lane-hs: A boolean property indicates that panel needs clock lanes in HS mode only [1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Documentation/devicetree/bindings/graph.txt @@ -237,4 +238,5 @@ Example: qcom,dsi-phy-regulator-ldo-mode; qcom,panel-allow-phy-poweroff; qcom,dsi-phy-regulator-min-datarate-bps = <1200000000>; + qcom,panel-force-clock-lane-hs; }; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c index 53717a50ccc8..a82e8558669a 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c @@ -455,6 +455,11 @@ void dsi_ctrl_hw_cmn_video_engine_setup(struct dsi_ctrl_hw *ctrl, /* Disable Timing double buffering */ DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x0); + if (cfg->force_clk_lane_hs) { + reg = DSI_R32(ctrl, DSI_LANE_CTRL); + reg |= BIT(28); + DSI_W32(ctrl, DSI_LANE_CTRL, reg); + } pr_debug("[DSI_%d] Video engine setup done\n", ctrl->index); } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h index 42d7cc0f27c5..879b772bbbaa 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h @@ -451,6 +451,7 @@ struct dsi_video_engine_cfg { bool hsa_lp11_en; bool eof_bllp_lp11_en; bool bllp_lp11_en; + bool force_clk_lane_hs; enum dsi_video_traffic_mode traffic_mode; u32 vc_id; }; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index b4c26514ec22..14c741710aaa 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -1193,6 +1193,9 @@ static int dsi_panel_parse_video_host_config(struct dsi_video_engine_cfg *cfg, cfg->bllp_lp11_en = utils->read_bool(utils->data, "qcom,mdss-dsi-bllp-power-mode"); + cfg->force_clk_lane_hs = of_property_read_bool(utils->data, + "qcom,mdss-dsi-force-clock-lane-hs"); + traffic_mode = utils->get_property(utils->data, "qcom,mdss-dsi-traffic-mode", NULL); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c index df69e7003845..caf554a55d07 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c @@ -311,6 +311,9 @@ static int dsi_phy_settings_init(struct platform_device *pdev, "qcom,dsi-phy-regulator-min-datarate-bps", &phy->regulator_min_datarate_bps); + phy->cfg.force_clk_lane_hs = of_property_read_bool(pdev->dev.of_node, + "qcom,panel-force-clock-lane-hs"); + return 0; err: lane->count_per_lane = 0; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h index 5d0a8e4fb6b3..e25784a7a837 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h @@ -92,6 +92,7 @@ struct dsi_phy_per_lane_cfgs { * @regulators: Regulator settings for lanes. * @pll_source: PLL source. * @lane_map: DSI logical to PHY lane mapping. + * @force_clk_lane_hs:Boolean whether to force clock lane in HS mode. */ struct dsi_phy_cfg { struct dsi_phy_per_lane_cfgs lanecfg; @@ -101,6 +102,7 @@ struct dsi_phy_cfg { struct dsi_phy_per_lane_cfgs regulators; enum dsi_phy_pll_source pll_source; struct dsi_lane_map lane_map; + bool force_clk_lane_hs; }; struct dsi_phy_hw; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c index 4ed484a49e5c..9123cf852c33 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v4_0.c @@ -143,6 +143,12 @@ static void dsi_phy_hw_v4_0_lane_settings(struct dsi_phy_hw *phy, DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(i), tx_dctrl[i]); } + if (cfg->force_clk_lane_hs) { + u32 reg = DSI_R32(phy, DSIPHY_CMN_LANE_CTRL1); + + reg |= BIT(5) | BIT(6); + DSI_W32(phy, DSIPHY_CMN_LANE_CTRL1, reg); + } } /** @@ -335,6 +341,9 @@ void dsi_phy_hw_v4_0_ulps_request(struct dsi_phy_hw *phy, if (lanes & DSI_DATA_LANE_3) reg |= BIT(3); + if (cfg->force_clk_lane_hs) + reg |= BIT(5) | BIT(6); + /* * ULPS entry request. Wait for short time to make sure * that the lanes enter ULPS. Recommended as per HPG. @@ -409,6 +418,11 @@ void dsi_phy_hw_v4_0_ulps_exit(struct dsi_phy_hw *phy, DSI_W32(phy, DSIPHY_CMN_LANE_CTRL3, reg); DSI_W32(phy, DSIPHY_CMN_LANE_CTRL3, 0); usleep_range(100, 110); + + if (cfg->force_clk_lane_hs) { + reg = BIT(5) | BIT(6); + DSI_W32(phy, DSIPHY_CMN_LANE_CTRL1, reg); + } } u32 dsi_phy_hw_v4_0_get_lanes_in_ulps(struct dsi_phy_hw *phy) -- GitLab From 31741b5cfb4cd660db3c128a05af8b4231dd4d4f Mon Sep 17 00:00:00 2001 From: Karthikeyan Ramasubramanian Date: Mon, 30 Oct 2017 14:03:01 -0600 Subject: [PATCH 0737/1299] slimbus: Sequentialize the device state notifications During subsystem restart, queue all the device state notification work in the same workqueue. This ensures that those notifications reach the slave drivers in the expected order. CRs-Fixed: 2139743 Change-Id: I3cdfbdd7ca500c5470c6c29b3a16780dcd2208dc Signed-off-by: Karthikeyan Ramasubramanian --- drivers/slimbus/slimbus.c | 26 +++++++++++++++++--------- include/linux/slimbus/slimbus.h | 2 ++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c index b7ef0ae75814..c44c851f3fd6 100644 --- a/drivers/slimbus/slimbus.c +++ b/drivers/slimbus/slimbus.c @@ -333,6 +333,20 @@ static void slim_report(struct work_struct *work) } } +static void slim_device_reset(struct work_struct *work) +{ + struct slim_driver *sbdrv; + struct slim_device *sbdev = + container_of(work, struct slim_device, device_reset); + + if (!sbdev->dev.driver) + return; + + sbdrv = to_slim_driver(sbdev->dev.driver); + if (sbdrv && sbdrv->reset_device) + sbdrv->reset_device(sbdev); +} + /* * slim_add_device: Add a new device without register board info. * @ctrl: Controller to which this device is to be added to. @@ -353,6 +367,7 @@ int slim_add_device(struct slim_controller *ctrl, struct slim_device *sbdev) INIT_LIST_HEAD(&sbdev->mark_suspend); INIT_LIST_HEAD(&sbdev->mark_removal); INIT_WORK(&sbdev->wd, slim_report); + INIT_WORK(&sbdev->device_reset, slim_device_reset); mutex_lock(&ctrl->m_ctrl); list_add_tail(&sbdev->dev_list, &ctrl->devs); mutex_unlock(&ctrl->m_ctrl); @@ -684,16 +699,9 @@ void slim_framer_booted(struct slim_controller *ctrl) mutex_unlock(&ctrl->sched.m_reconf); mutex_lock(&ctrl->m_ctrl); list_for_each_safe(pos, next, &ctrl->devs) { - struct slim_driver *sbdrv; - sbdev = list_entry(pos, struct slim_device, dev_list); - mutex_unlock(&ctrl->m_ctrl); - if (sbdev && sbdev->dev.driver) { - sbdrv = to_slim_driver(sbdev->dev.driver); - if (sbdrv->reset_device) - sbdrv->reset_device(sbdev); - } - mutex_lock(&ctrl->m_ctrl); + if (sbdev) + queue_work(ctrl->wq, &sbdev->device_reset); } mutex_unlock(&ctrl->m_ctrl); } diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h index 60f0c33fb225..2983e7948781 100644 --- a/include/linux/slimbus/slimbus.h +++ b/include/linux/slimbus/slimbus.h @@ -684,6 +684,7 @@ struct slim_pending_ch { * first time it has reported present. * @dev_list: List of devices on a controller * @wd: Work structure associated with workqueue for presence notification + * @device_reset: Work structure for device reset notification * @sldev_reconf: Mutex to protect the pending data-channel lists. * @pending_msgsl: Message bandwidth reservation request by this client in * slots that's pending reconfiguration. @@ -706,6 +707,7 @@ struct slim_device { bool notified; struct list_head dev_list; struct work_struct wd; + struct work_struct device_reset; struct mutex sldev_reconf; u32 pending_msgsl; u32 cur_msgsl; -- GitLab From 490a3d4b31e6b776df793cdad2232e370592eb74 Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Thu, 14 Jun 2018 09:58:10 -0700 Subject: [PATCH 0738/1299] sched: track mid capacity cpu Tracking the mid capacity cpu will help optimize the placement algorithm in upcoming patches. Change-Id: I49f6719a216ddb578375fde4770be0bbc6cc552a Signed-off-by: Abhijeet Dharmapurikar --- kernel/sched/sched.h | 2 ++ kernel/sched/topology.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 9a537b5fea80..68b803427068 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -731,6 +731,8 @@ struct root_domain { /* First cpu with maximum and minimum original capacity */ int max_cap_orig_cpu, min_cap_orig_cpu; + /* First cpu with mid capacity */ + int mid_cap_orig_cpu; }; extern struct root_domain def_root_domain; diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 2eb04946e4b8..9894e0d87445 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -303,6 +303,7 @@ static int init_rootdomain(struct root_domain *rd) goto free_cpudl; rd->max_cap_orig_cpu = rd->min_cap_orig_cpu = -1; + rd->mid_cap_orig_cpu = -1; return 0; @@ -1851,6 +1852,20 @@ build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *att cpu_attach_domain(sd, d.rd, i); } + + /* set the mid capacity cpu (assumes only 3 capacities) */ + for_each_cpu(i, cpu_map) { + int max_cpu = READ_ONCE(d.rd->max_cap_orig_cpu); + int min_cpu = READ_ONCE(d.rd->min_cap_orig_cpu); + + if ((cpu_rq(i)->cpu_capacity_orig + != cpu_rq(min_cpu)->cpu_capacity_orig) && + (cpu_rq(i)->cpu_capacity_orig + != cpu_rq(max_cpu)->cpu_capacity_orig)) { + WRITE_ONCE(d.rd->mid_cap_orig_cpu, i); + break; + } + } rcu_read_unlock(); if (rq && sched_debug_enabled) { -- GitLab From 1d19c97f509db64150f100fbbe22847f1dd0d81b Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Tue, 5 Jun 2018 13:23:19 -0700 Subject: [PATCH 0739/1299] sched/fair: improve placement logic When all the cpus in the biggest cluster are isolated, a task that should have run there i.e. it has very high demand, ends up finding no clusters able to accept it. find_best_target() returns -1 and since the prev cpu is isolated, the code relies on fallback scheme to find a cpu for it. The fallback scheme doesn't select the best capacity cpu and this leads to bad performance. There is also another related problem where we could have unoptimal placement when the cluster on which the task should be placed is busy. For e.g. when a high demand task wakes up and if the all the cores in its fitting cluster are busy, it gets placed on its prev cpu. There might be a better cpu, one with more spare capacity than the prev_cpu. Both the above issues stem from the way the groups are traversed. We always start with the smallest capacity group and go towards highest capacity group while we skip groups that don't meet the demand or preferred criteria. We loose the opportunity to note the best cpus in the skipped groups which could have been used if the eligible groups are busy. So to address this issue, we need to curb skipping the groups and also introduce tracking the cpu with most spare capacity. Not skipping a smaller capacity group (a group that doesn't meet demand or preferred criteria) may end up setting the placement target to those ones. Hence we need to start with a group that best accommodates the task demand and its preferred group and visit the smaller capacity groups only after starting group and higher capacity groups couldn't fit the task. If a cpu is found,indicated by target_capacity != ULONG_MAX, we need to skip visiting any more groups. Now if a task couldn't be placed on any of the cpus, indicated by target_cpu == -1, in any of the groups we place it on a cpu with the most spare capacity. So in the above problems, where the best fitting group or higher couldn't accommodate itwe would end up using the cpu with most spare capacity. Note that, if no cpu with any spare capacity is found, we still could end up using prev_cpu and if prev_cpu is isolated we could end up employing fallback mechanism. There are few more quirks that need to be addressed with the above scheme: * We reset target_capacity to ULONG_MAX while under placement boost. This was done in order to search higher capacity clusters even when a target was found and was done with the assumption that we always traverse towards higher capacity clusters. This not being the case, since we could traverse low capacity clusters now, reset target_capacity as long as we haven't reached highest capacity cpus. * while we are in active migration i.e p->state == TASK_RUNNING, we limit target to idle cpus. The cpu with most spare capacity may not necessarily be idle, so ensure that we don't put a actively migrated task there unless its idle. Change-Id: I8f67411e2a8015ef1a996875dac95a5a43c8e1a7 Signed-off-by: Abhijeet Dharmapurikar Signed-off-by: Satya Durga Srinivasu Prabhala --- kernel/sched/fair.c | 69 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 7f909049b487..5391307f514c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7047,7 +7047,8 @@ static bool is_packing_eligible(struct task_struct *p, int target_cpu, } static inline bool skip_sg(struct task_struct *p, struct sched_group *sg, - struct cpumask *rtg_target) + struct cpumask *rtg_target, + unsigned long target_capacity) { int fcpu = group_first_cpu(sg); @@ -7062,7 +7063,11 @@ static inline bool skip_sg(struct task_struct *p, struct sched_group *sg, if (cpumask_subset(&p->cpus_allowed, sched_group_span(sg))) return false; - if (!task_fits_max(p, fcpu)) + /* + * if we have found a target cpu within a group, don't bother checking + * other groups + */ + if (target_capacity != ULONG_MAX) return true; if (rtg_target && !cpumask_test_cpu(fcpu, rtg_target)) @@ -7071,11 +7076,40 @@ static inline bool skip_sg(struct task_struct *p, struct sched_group *sg, return false; } -static int start_cpu(bool boosted) +static int start_cpu(struct task_struct *p, bool boosted, + struct cpumask *rtg_target) { struct root_domain *rd = cpu_rq(smp_processor_id())->rd; + int start_cpu = -1; + + if (boosted) + return rd->max_cap_orig_cpu; + + /* Where the task should land based on its demand */ + if (rd->min_cap_orig_cpu != -1 + && task_fits_max(p, rd->min_cap_orig_cpu)) + start_cpu = rd->min_cap_orig_cpu; + else if (rd->mid_cap_orig_cpu != -1 + && task_fits_max(p, rd->mid_cap_orig_cpu)) + start_cpu = rd->mid_cap_orig_cpu; + else + start_cpu = rd->max_cap_orig_cpu; + + /* + * start it up to its preferred cluster if the preferred clusteris + * higher capacity + */ + if (start_cpu != -1 && rtg_target && + !cpumask_test_cpu(start_cpu, rtg_target)) { + int rtg_target_cpu = cpumask_first(rtg_target); - return boosted ? rd->max_cap_orig_cpu : rd->min_cap_orig_cpu; + if (capacity_orig_of(start_cpu) < + capacity_orig_of(rtg_target_cpu)) { + start_cpu = rtg_target_cpu; + } + } + + return start_cpu; } static inline int find_best_target(struct task_struct *p, int *backup_cpu, @@ -7096,13 +7130,14 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, int best_idle_cpu = -1; int target_cpu = -1; int cpu, i; - unsigned long spare_cap; + long spare_cap, most_spare_cap = 0; + int most_spare_cap_cpu = -1; unsigned int active_cpus_count = 0; *backup_cpu = -1; /* Find start CPU based on boost value */ - cpu = start_cpu(boosted); + cpu = start_cpu(p, boosted, fbt_env->rtg_target); if (cpu < 0) return -1; @@ -7114,7 +7149,7 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, /* Scan CPUs in all SDs */ sg = sd->groups; do { - if (skip_sg(p, sg, fbt_env->rtg_target)) + if (skip_sg(p, sg, fbt_env->rtg_target, target_capacity)) continue; for_each_cpu_and(i, &p->cpus_allowed, sched_group_span(sg)) { @@ -7147,6 +7182,11 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, new_util = wake_util + task_util(p); spare_cap = capacity_orig_of(i) - wake_util; + if (spare_cap > most_spare_cap) { + most_spare_cap = spare_cap; + most_spare_cap_cpu = i; + } + /* * Cumulative demand may already be accounting for the * task. If so, add just the boost-utilization to @@ -7340,11 +7380,13 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, } /* - * When placement boost is active, we traverse CPUs - * other than min capacity CPUs. Reset the target_capacity - * to keep traversing the other clusters. + * We start with group where the task should be placed. When + * placement boost is active reset the target_capacity to keep + * traversing the other higher clusters. Don't reset it if we + * are already at the highest cluster. */ - if (fbt_env->placement_boost) + if (fbt_env->placement_boost && + !is_max_capacity_cpu(group_first_cpu(sg))) target_capacity = ULONG_MAX; } while (sg = sg->next, sg != sd->groups); @@ -7384,6 +7426,11 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, ? best_active_cpu : best_idle_cpu; + if (target_cpu == -1 && most_spare_cap_cpu != -1 && + /* ensure we use active cpu for active migration */ + !(p->state == TASK_RUNNING && !idle_cpu(most_spare_cap_cpu))) + target_cpu = most_spare_cap_cpu; + trace_sched_find_best_target(p, prefer_idle, min_util, cpu, best_idle_cpu, best_active_cpu, target_cpu); -- GitLab From e821b9e7a996da2e64b22374541e34a82d448986 Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Wed, 20 Jun 2018 13:31:58 -0700 Subject: [PATCH 0740/1299] sched/fair: relax preferred cluster requirement Although we steer the start_cpu towards preferred cluster, we reject looking at other groups. This leads to unoptimal placements if the task cannot be accommodated on the preferred cluster. For example, for a task whose preferred cluster is the smallest cluster but all the cpus in the smallest cluster cannot accommodate this task, we skip looking at the higher clusters and end up returning -1 from find_best_target() and end up choosing the prev_cpu or a fallback scheme. All this when there could be a better cpu available in another cluster. Fix this by considering groups that do not belong to preferred cluster. With this change preferred cluster will only be used to influence the start cpu during placement. Change-Id: I4ceea8eff04f6f015bedc4d689bfb3207fa0a5bc Signed-off-by: Abhijeet Dharmapurikar --- kernel/sched/fair.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 5391307f514c..d30128ccddcf 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7050,8 +7050,6 @@ static inline bool skip_sg(struct task_struct *p, struct sched_group *sg, struct cpumask *rtg_target, unsigned long target_capacity) { - int fcpu = group_first_cpu(sg); - /* Are all CPUs isolated in this group? */ if (!sg->group_weight) return true; @@ -7070,9 +7068,6 @@ static inline bool skip_sg(struct task_struct *p, struct sched_group *sg, if (target_capacity != ULONG_MAX) return true; - if (rtg_target && !cpumask_test_cpu(fcpu, rtg_target)) - return true; - return false; } -- GitLab From 1dc0d85d7bdf85604fbf892e6c9448d21a35769c Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Mon, 4 Jun 2018 20:46:07 -0700 Subject: [PATCH 0741/1299] drm/msm/sde: fix feature enable check for CWB support Fix the Concurrent Writeback feature enabled validation to check if CWB feature bit set in the Writeback feature flag. Change-Id: Iffd3167b500edaa3c3338094eadcdc08606ff5c1 Signed-off-by: Prabhanjan Kandula --- drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c index 758160d35f69..a18271fbb1ac 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c @@ -580,7 +580,7 @@ static void _sde_enc_phys_wb_detect_cwb(struct sde_encoder_phys *phys_enc, phys_enc->in_clone_mode = false; /* Check if WB has CWB support */ - if (!(wb_cfg->features & SDE_WB_HAS_CWB)) + if (!(wb_cfg->features & BIT(SDE_WB_HAS_CWB))) return; /* Count the number of connectors on the given crtc */ -- GitLab From ef5f24f548511717434e0e376746bb919d608502 Mon Sep 17 00:00:00 2001 From: Narendra Muppalla Date: Thu, 18 Jan 2018 18:00:02 +0530 Subject: [PATCH 0742/1299] drm/msm/sde: Use panel front porch for ROT and MDP fetch start Keep the ROT and MDP fetch start to a fixed value such that they are not affected when dynamic refresh rate changes the front porch. Change-Id: Ic29a2d29e736801b1840538aeedadbf51ba5bb9f Signed-off-by: Kalyan Thota Signed-off-by: Jayant Shekhar Signed-off-by: Narendra Muppalla --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 47 +++++++++++++++++++ drivers/gpu/drm/msm/dsi-staging/dsi_display.h | 10 ++++ drivers/gpu/drm/msm/sde/sde_connector.c | 22 +++++++++ drivers/gpu/drm/msm/sde/sde_connector.h | 18 +++++++ drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 3 ++ .../gpu/drm/msm/sde/sde_encoder_phys_vid.c | 42 ++++++++++++----- drivers/gpu/drm/msm/sde/sde_hw_intf.h | 1 + drivers/gpu/drm/msm/sde/sde_kms.c | 3 ++ 8 files changed, 134 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index d0ca32c99468..1e9036df0360 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -5031,6 +5031,53 @@ int dsi_display_get_modes(struct dsi_display *display, return rc; } +int dsi_display_get_panel_vfp(void *dsi_display, + int h_active, int v_active) +{ + int i, rc = 0; + u32 count, refresh_rate = 0; + struct dsi_dfps_capabilities dfps_caps; + struct dsi_display *display = (struct dsi_display *)dsi_display; + + if (!display) + return -EINVAL; + + rc = dsi_display_get_mode_count(display, &count); + if (rc) + return rc; + + mutex_lock(&display->display_lock); + + if (display->panel && display->panel->cur_mode) + refresh_rate = display->panel->cur_mode->timing.refresh_rate; + + dsi_panel_get_dfps_caps(display->panel, &dfps_caps); + if (dfps_caps.dfps_support) + refresh_rate = dfps_caps.max_refresh_rate; + + if (!refresh_rate) { + mutex_unlock(&display->display_lock); + pr_err("Null Refresh Rate\n"); + return -EINVAL; + } + + h_active *= display->ctrl_count; + + for (i = 0; i < count; i++) { + struct dsi_display_mode *m = &display->modes[i]; + + if (m && v_active == m->timing.v_active && + h_active == m->timing.h_active && + refresh_rate == m->timing.refresh_rate) { + rc = m->timing.v_front_porch; + break; + } + } + mutex_unlock(&display->display_lock); + + return rc; +} + int dsi_display_find_mode(struct dsi_display *display, const struct dsi_display_mode *cmp, struct dsi_display_mode **out_mode) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h index c58b41770f10..eccdae98b8fe 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h @@ -635,4 +635,14 @@ enum dsi_pixel_format dsi_display_get_dst_format( * Return: Zero on Success */ int dsi_display_cont_splash_config(void *display); +/* + * dsi_display_get_panel_vfp - get panel vsync + * @display: Pointer to private display structure + * @h_active: width + * @v_active: height + * Returns: v_front_porch on success error code on failure + */ +int dsi_display_get_panel_vfp(void *display, + int h_active, int v_active); + #endif /* _DSI_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 692e24e3eb85..802b8d4fec3b 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -1391,6 +1391,28 @@ int sde_connector_helper_reset_custom_properties( return 0; } +int sde_connector_get_panel_vfp(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct sde_connector *c_conn; + int vfp = -EINVAL; + + if (!connector || !mode) { + SDE_ERROR("invalid connector\n"); + return vfp; + } + c_conn = to_sde_connector(connector); + if (!c_conn->ops.get_panel_vfp) + return vfp; + + vfp = c_conn->ops.get_panel_vfp(c_conn->display, + mode->hdisplay, mode->vdisplay); + if (vfp <= 0) + SDE_ERROR("Failed get_panel_vfp %d\n", vfp); + + return vfp; +} + static int _sde_debugfs_conn_cmd_tx_open(struct inode *inode, struct file *file) { /* non-seekable */ diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h index 70d8f6458c24..a4d66620f860 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.h +++ b/drivers/gpu/drm/msm/sde/sde_connector.h @@ -299,6 +299,15 @@ struct sde_connector_ops { * Returns: zero for success, negetive for failure */ int (*cont_splash_config)(void *display); + + /** + * get_panel_vfp - returns original panel vfp + * @display: Pointer to private display handle + * @h_active: width + * @v_active: height + * Returns: v_front_porch on success error-code on failure + */ + int (*get_panel_vfp)(void *display, int h_active, int v_active); }; /** @@ -829,4 +838,13 @@ void sde_connector_destroy(struct drm_connector *connector); int sde_connector_event_notify(struct drm_connector *connector, uint32_t type, uint32_t len, uint32_t val); +/** + * sde_connector_get_panel_vfp - helper to get panel vfp + * @connector: pointer to drm connector + * @h_active: panel width + * @v_active: panel heigth + * Returns: v_front_porch on success error-code on failure + */ +int sde_connector_get_panel_vfp(struct drm_connector *connector, + struct drm_display_mode *mode); #endif /* _SDE_CONNECTOR_H_ */ diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 37735df1cd54..62a4a1dad3dd 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -281,6 +281,8 @@ struct sde_encoder_irq { * @cont_splash_single_flush Variable to check if single flush is enabled. * @cont_splash_settings Variable to store continuous splash settings. * @in_clone_mode Indicates if encoder is in clone mode ref@CWB + * @vfp_cached: cached vertical front porch to be used for + * programming ROT and MDP fetch start */ struct sde_encoder_phys { struct drm_encoder *parent; @@ -315,6 +317,7 @@ struct sde_encoder_phys { u32 cont_splash_single_flush; bool cont_splash_settings; bool in_clone_mode; + int vfp_cached; }; static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index 63e143e2fce6..1405ed010448 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -103,6 +103,7 @@ static void drm_mode_to_intf_timing_params( timing->border_clr = 0; timing->underflow_clr = 0xff; timing->hsync_skew = mode->hskew; + timing->v_front_porch_fixed = vid_enc->base.vfp_cached; /* DSI controller cannot handle active-low sync signals. */ if (phys_enc->hw_intf->cap->type == INTF_DSI) { @@ -132,12 +133,16 @@ static inline u32 get_horizontal_total(const struct intf_timing_params *timing) return active + inactive; } -static inline u32 get_vertical_total(const struct intf_timing_params *timing) +static inline u32 get_vertical_total(const struct intf_timing_params *timing, + bool use_fixed_vfp) { + u32 inactive; u32 active = timing->yres; - u32 inactive = - timing->v_back_porch + timing->v_front_porch + - timing->vsync_pulse_width; + u32 v_front_porch = use_fixed_vfp ? + timing->v_front_porch_fixed : timing->v_front_porch; + + inactive = timing->v_back_porch + v_front_porch + + timing->vsync_pulse_width; return active + inactive; } @@ -157,7 +162,8 @@ static inline u32 get_vertical_total(const struct intf_timing_params *timing) */ static u32 programmable_fetch_get_num_lines( struct sde_encoder_phys_vid *vid_enc, - const struct intf_timing_params *timing) + const struct intf_timing_params *timing, + bool use_fixed_vfp) { struct sde_encoder_phys *phys_enc = &vid_enc->base; u32 worst_case_needed_lines = @@ -166,19 +172,21 @@ static u32 programmable_fetch_get_num_lines( timing->v_back_porch + timing->vsync_pulse_width; u32 needed_vfp_lines = worst_case_needed_lines - start_of_frame_lines; u32 actual_vfp_lines = 0; + u32 v_front_porch = use_fixed_vfp ? + timing->v_front_porch_fixed : timing->v_front_porch; /* Fetch must be outside active lines, otherwise undefined. */ if (start_of_frame_lines >= worst_case_needed_lines) { SDE_DEBUG_VIDENC(vid_enc, "prog fetch is not needed, large vbp+vsw\n"); actual_vfp_lines = 0; - } else if (timing->v_front_porch < needed_vfp_lines) { + } else if (v_front_porch < needed_vfp_lines) { /* Warn fetch needed, but not enough porch in panel config */ pr_warn_once ("low vbp+vfp may lead to perf issues in some cases\n"); SDE_DEBUG_VIDENC(vid_enc, "less vfp than fetch req, using entire vfp\n"); - actual_vfp_lines = timing->v_front_porch; + actual_vfp_lines = v_front_porch; } else { SDE_DEBUG_VIDENC(vid_enc, "room in vfp for needed prefetch\n"); actual_vfp_lines = needed_vfp_lines; @@ -186,7 +194,7 @@ static u32 programmable_fetch_get_num_lines( SDE_DEBUG_VIDENC(vid_enc, "v_front_porch %u v_back_porch %u vsync_pulse_width %u\n", - timing->v_front_porch, timing->v_back_porch, + v_front_porch, timing->v_back_porch, timing->vsync_pulse_width); SDE_DEBUG_VIDENC(vid_enc, "wc_lines %u needed_vfp_lines %u actual_vfp_lines %u\n", @@ -223,9 +231,10 @@ static void programmable_fetch_config(struct sde_encoder_phys *phys_enc, m = phys_enc->sde_kms->catalog; - vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, timing); + vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, + timing, true); if (vfp_fetch_lines) { - vert_total = get_vertical_total(timing); + vert_total = get_vertical_total(timing, true); horiz_total = get_horizontal_total(timing); vfp_fetch_start_vsync_counter = (vert_total - vfp_fetch_lines) * horiz_total + 1; @@ -282,9 +291,10 @@ static void programmable_rot_fetch_config(struct sde_encoder_phys *phys_enc, return; timing = &vid_enc->timing_params; - vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, timing); + vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, + timing, true); if (rot_fetch_lines) { - vert_total = get_vertical_total(timing); + vert_total = get_vertical_total(timing, true); horiz_total = get_horizontal_total(timing); if (vert_total >= (vfp_fetch_lines + rot_fetch_lines)) { rot_fetch_start_vsync_counter = @@ -428,6 +438,13 @@ static void sde_encoder_phys_vid_setup_timing_engine( mode.hsync_start, mode.hsync_end); } + if (!phys_enc->vfp_cached) { + phys_enc->vfp_cached = + sde_connector_get_panel_vfp(phys_enc->connector, &mode); + if (phys_enc->vfp_cached <= 0) + phys_enc->vfp_cached = mode.vsync_start - mode.vdisplay; + } + drm_mode_to_intf_timing_params(vid_enc, &mode, &timing_params); vid_enc->timing_params = timing_params; @@ -1078,6 +1095,7 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc) phys_enc->hw_pp->merge_3d->idx); exit: + phys_enc->vfp_cached = 0; phys_enc->enable_state = SDE_ENC_DISABLED; } diff --git a/drivers/gpu/drm/msm/sde/sde_hw_intf.h b/drivers/gpu/drm/msm/sde/sde_hw_intf.h index 387de73a84b3..3cd0dfce12f1 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_intf.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_intf.h @@ -38,6 +38,7 @@ struct intf_timing_params { u32 border_clr; u32 underflow_clr; u32 hsync_skew; + u32 v_front_porch_fixed; }; struct intf_prog_fetch { diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index c43977cec65b..ef9fbd672f20 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -1263,6 +1263,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .enable_event = dsi_conn_enable_event, .cmd_transfer = dsi_display_cmd_transfer, .cont_splash_config = dsi_display_cont_splash_config, + .get_panel_vfp = dsi_display_get_panel_vfp, }; static const struct sde_connector_ops wb_ops = { .post_init = sde_wb_connector_post_init, @@ -1277,6 +1278,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .check_status = NULL, .cmd_transfer = NULL, .cont_splash_config = NULL, + .get_panel_vfp = NULL, }; static const struct sde_connector_ops dp_ops = { .post_init = dp_connector_post_init, @@ -1290,6 +1292,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .config_hdr = dp_connector_config_hdr, .cmd_transfer = NULL, .cont_splash_config = NULL, + .get_panel_vfp = NULL, }; struct msm_display_info info; struct drm_encoder *encoder; -- GitLab From 8cedeac3cc6be3d42943ff5c125335ed08b80bce Mon Sep 17 00:00:00 2001 From: Camus Wong Date: Mon, 12 Mar 2018 18:05:57 -0400 Subject: [PATCH 0743/1299] drm/msm/dsi-staging: Add external DSI bridge support Add external DSI to DP/HDMI bridge support to allow upstream driver in drm/bridge work with dsi-staging driver without any change. CRs-Fixed: 2242018 Change-Id: I92302314da7a1c964a46b52c3315a9d436814dc8 Signed-off-by: Xiaowen Wu --- .../bindings/drm/msm/mdss-dsi-panel.txt | 1 + .../devicetree/bindings/drm/msm/sde-dsi.txt | 5 + drivers/gpu/drm/msm/dsi-staging/dsi_defs.h | 2 + drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 290 ++++++++++++++++++ drivers/gpu/drm/msm/dsi-staging/dsi_display.h | 19 ++ drivers/gpu/drm/msm/dsi-staging/dsi_drm.c | 33 ++ drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 22 +- drivers/gpu/drm/msm/sde/sde_kms.c | 13 + 8 files changed, 382 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt index 1d20423775be..43c9d0bbe06d 100644 --- a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt @@ -528,6 +528,7 @@ Optional properties: to identify the default topology for the display. The first set is indexed by the value 0. +- qcom,mdss-dsi-ext-bridge-mode: External bridge chip is connected instead of panel. Required properties for sub-nodes: None Optional properties: diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt index 0b660ce672d1..b706967565a7 100644 --- a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt +++ b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt @@ -105,3 +105,8 @@ Optional properties: only with simulator panel. It should not be enabled for normal DSI panels. - - qcom,null-insertion-enabled: A boolean to enable NULL packet insertion feature for DSI controller. +- ports: This video port is used when external bridge is present. + The connection is modeled using the OF graph bindings + specified in Documentation/devicetree/bindings/graph.txt. + Video port 0 reg 0 is for the bridge output. The remote + endpoint phandle should be mipi_dsi_device device node. diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h index 42d7cc0f27c5..38b8f8e67c08 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h @@ -408,6 +408,7 @@ struct dsi_mode_info { * @ignore_rx_eot: Ignore Rx EOT packets if set to true. * @append_tx_eot: Append EOT packets for forward transmissions if set to * true. + * @ext_bridge_mode: External bridge is connected. */ struct dsi_host_common_cfg { enum dsi_pixel_format dst_format; @@ -426,6 +427,7 @@ struct dsi_host_common_cfg { u32 t_clk_pre; bool ignore_rx_eot; bool append_tx_eot; + bool ext_bridge_mode; }; /** diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index d0ca32c99468..b3d936415e16 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -3321,6 +3321,9 @@ static int dsi_display_parse_dt(struct dsi_display *display) /* Parse TE gpio */ dsi_display_parse_te_gpio(display); + /* Parse external bridge from port 0, reg 0 */ + display->ext_bridge_of = of_graph_get_remote_node(of_node, 0, 0); + pr_debug("success\n"); error: return rc; @@ -4798,6 +4801,285 @@ int dsi_display_drm_bridge_deinit(struct dsi_display *display) return rc; } +/* Hook functions to call external connector, pointer validation is + * done in dsi_display_drm_ext_bridge_init. + */ +static enum drm_connector_status dsi_display_drm_ext_detect( + struct drm_connector *connector, + bool force, + void *disp) +{ + struct dsi_display *display = disp; + + return display->ext_conn->funcs->detect(display->ext_conn, force); +} + +static int dsi_display_drm_ext_get_modes( + struct drm_connector *connector, void *disp) +{ + struct dsi_display *display = disp; + struct drm_display_mode *pmode, *pt; + int count; + + count = display->ext_conn->helper_private->get_modes( + display->ext_conn); + + list_for_each_entry_safe(pmode, pt, + &display->ext_conn->probed_modes, head) { + list_move_tail(&pmode->head, &connector->probed_modes); + } + + connector->display_info = display->ext_conn->display_info; + + return count; +} + +static enum drm_mode_status dsi_display_drm_ext_mode_valid( + struct drm_connector *connector, + struct drm_display_mode *mode, + void *disp) +{ + struct dsi_display *display = disp; + + return display->ext_conn->helper_private->mode_valid( + display->ext_conn, mode); +} + +static int dsi_display_drm_ext_atomic_check(struct drm_connector *connector, + void *disp, + struct drm_connector_state *c_state) +{ + struct dsi_display *display = disp; + + return display->ext_conn->helper_private->atomic_check( + display->ext_conn, c_state); +} + +static int dsi_display_ext_get_info(struct drm_connector *connector, + struct msm_display_info *info, void *disp) +{ + struct dsi_display *display; + int i; + + if (!info || !disp) { + pr_err("invalid params\n"); + return -EINVAL; + } + + display = disp; + if (!display->panel) { + pr_err("invalid display panel\n"); + return -EINVAL; + } + + mutex_lock(&display->display_lock); + + memset(info, 0, sizeof(struct msm_display_info)); + + info->intf_type = DRM_MODE_CONNECTOR_DSI; + info->num_of_h_tiles = display->ctrl_count; + for (i = 0; i < info->num_of_h_tiles; i++) + info->h_tile_instance[i] = display->ctrl[i].ctrl->cell_index; + + info->is_connected = connector->status != connector_status_disconnected; + info->is_primary = true; + info->capabilities |= (MSM_DISPLAY_CAP_VID_MODE | + MSM_DISPLAY_CAP_EDID | MSM_DISPLAY_CAP_HOT_PLUG); + + mutex_unlock(&display->display_lock); + return 0; +} + +static int dsi_display_ext_get_mode_info(struct drm_connector *connector, + const struct drm_display_mode *drm_mode, + struct msm_mode_info *mode_info, + u32 max_mixer_width, void *display) +{ + struct msm_display_topology *topology; + + if (!drm_mode || !mode_info) + return -EINVAL; + + memset(mode_info, 0, sizeof(*mode_info)); + mode_info->frame_rate = drm_mode->vrefresh; + mode_info->vtotal = drm_mode->vtotal; + + topology = &mode_info->topology; + topology->num_lm = (max_mixer_width <= drm_mode->hdisplay) ? 2 : 1; + topology->num_enc = 0; + topology->num_intf = topology->num_lm; + + mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE; + + return 0; +} + +static int dsi_host_ext_attach(struct mipi_dsi_host *host, + struct mipi_dsi_device *dsi) +{ + struct dsi_display *display = to_dsi_display(host); + struct dsi_panel *panel; + + if (!host || !dsi || !display->panel) { + pr_err("Invalid param\n"); + return -EINVAL; + } + + pr_debug("DSI[%s]: channel=%d, lanes=%d, format=%d, mode_flags=%lx\n", + dsi->name, dsi->channel, dsi->lanes, + dsi->format, dsi->mode_flags); + + panel = display->panel; + panel->host_config.data_lanes = 0; + if (dsi->lanes > 0) + panel->host_config.data_lanes |= DSI_DATA_LANE_0; + if (dsi->lanes > 1) + panel->host_config.data_lanes |= DSI_DATA_LANE_1; + if (dsi->lanes > 2) + panel->host_config.data_lanes |= DSI_DATA_LANE_2; + if (dsi->lanes > 3) + panel->host_config.data_lanes |= DSI_DATA_LANE_3; + + switch (dsi->format) { + case MIPI_DSI_FMT_RGB888: + panel->host_config.dst_format = DSI_PIXEL_FORMAT_RGB888; + break; + case MIPI_DSI_FMT_RGB666: + panel->host_config.dst_format = DSI_PIXEL_FORMAT_RGB666_LOOSE; + break; + case MIPI_DSI_FMT_RGB666_PACKED: + panel->host_config.dst_format = DSI_PIXEL_FORMAT_RGB666; + break; + case MIPI_DSI_FMT_RGB565: + default: + panel->host_config.dst_format = DSI_PIXEL_FORMAT_RGB565; + break; + } + + if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { + panel->panel_mode = DSI_OP_VIDEO_MODE; + + if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) + panel->video_config.traffic_mode = + DSI_VIDEO_TRAFFIC_BURST_MODE; + else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) + panel->video_config.traffic_mode = + DSI_VIDEO_TRAFFIC_SYNC_PULSES; + else + panel->video_config.traffic_mode = + DSI_VIDEO_TRAFFIC_SYNC_START_EVENTS; + + panel->video_config.hsa_lp11_en = + dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSA; + panel->video_config.hbp_lp11_en = + dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HBP; + panel->video_config.hfp_lp11_en = + dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HFP; + panel->video_config.pulse_mode_hsa_he = + dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSE; + panel->video_config.bllp_lp11_en = + dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BLLP; + panel->video_config.eof_bllp_lp11_en = + dsi->mode_flags & MIPI_DSI_MODE_VIDEO_EOF_BLLP; + } else { + panel->panel_mode = DSI_OP_CMD_MODE; + pr_err("command mode not supported by ext bridge\n"); + return -ENOTSUPP; + } + + panel->bl_config.type = DSI_BACKLIGHT_UNKNOWN; + + return 0; +} + +static struct mipi_dsi_host_ops dsi_host_ext_ops = { + .attach = dsi_host_ext_attach, + .detach = dsi_host_detach, + .transfer = dsi_host_transfer, +}; + +int dsi_display_drm_ext_bridge_init(struct dsi_display *display, + struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *drm = encoder->dev; + struct drm_bridge *bridge = encoder->bridge; + struct drm_bridge *ext_bridge; + struct drm_connector *ext_conn; + struct sde_connector *sde_conn = to_sde_connector(connector); + int rc; + + /* check if ext_bridge is already attached */ + if (display->ext_bridge) + return 0; + + /* check if there is no external bridge defined */ + if (!display->ext_bridge_of) + return 0; + + ext_bridge = of_drm_find_bridge(display->ext_bridge_of); + if (IS_ERR_OR_NULL(ext_bridge)) { + rc = PTR_ERR(ext_bridge); + pr_err("failed to find ext bridge\n"); + goto error; + } + + rc = drm_bridge_attach(bridge->encoder, ext_bridge, bridge); + if (rc) { + pr_err("[%s] ext brige attach failed, %d\n", + display->name, rc); + goto error; + } + + display->ext_bridge = ext_bridge; + + /* ext bridge will init its own connector during attach, + * we need to extract it out of the connector list + */ + spin_lock_irq(&drm->mode_config.connector_list_lock); + ext_conn = list_last_entry(&drm->mode_config.connector_list, + struct drm_connector, head); + if (ext_conn && ext_conn != connector && + ext_conn->encoder_ids[0] == bridge->encoder->base.id) { + list_del_init(&ext_conn->head); + display->ext_conn = ext_conn; + } + spin_unlock_irq(&drm->mode_config.connector_list_lock); + + /* if there is no valid external connector created, we'll use default + * setting from panel defined in DT file. + */ + if (!display->ext_conn || + !display->ext_conn->funcs || + !display->ext_conn->helper_private) { + display->ext_conn = NULL; + return 0; + } + + /* otherwise, hook up the functions to use external connector */ + sde_conn->ops.detect = + display->ext_conn->funcs->detect ? + dsi_display_drm_ext_detect : NULL; + sde_conn->ops.get_modes = + display->ext_conn->helper_private->get_modes ? + dsi_display_drm_ext_get_modes : NULL; + sde_conn->ops.mode_valid = + display->ext_conn->helper_private->mode_valid ? + dsi_display_drm_ext_mode_valid : NULL; + sde_conn->ops.atomic_check = + display->ext_conn->helper_private->atomic_check ? + dsi_display_drm_ext_atomic_check : NULL; + sde_conn->ops.get_info = + dsi_display_ext_get_info; + sde_conn->ops.get_mode_info = + dsi_display_ext_get_mode_info; + + /* add support to attach/detach */ + display->host.ops = &dsi_host_ext_ops; + return 0; +error: + return rc; +} + int dsi_display_get_info(struct drm_connector *connector, struct msm_display_info *info, void *disp) { @@ -5047,6 +5329,14 @@ int dsi_display_find_mode(struct dsi_display *display, if (rc) return rc; + if (!display->modes) { + struct dsi_display_mode *m; + + rc = dsi_display_get_modes(display, &m); + if (rc) + return rc; + } + mutex_lock(&display->display_lock); for (i = 0; i < count; i++) { struct dsi_display_mode *m = &display->modes[i]; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h index c58b41770f10..018f05844ae1 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h @@ -128,6 +128,7 @@ struct dsi_display_clk_info { * @pdev: Pointer to platform device. * @drm_dev: DRM device associated with the display. * @drm_conn: Pointer to DRM connector associated with the display + * @ext_conn: Pointer to external connector attached to DSI connector * @name: Name of the display. * @display_type: Display type as defined in device tree. * @list: List pointer. @@ -142,6 +143,7 @@ struct dsi_display_clk_info { * @ctrl: Controller information for DSI display. * @panel: Handle to DSI panel. * @panel_of: pHandle to DSI panel. + * @ext_bridge_of: pHandle to external DSI bridge. * @modes: Array of probed DSI modes * @type: DSI display type. * @clk_master_idx: The master controller for controlling clocks. This is an @@ -161,6 +163,7 @@ struct dsi_display_clk_info { * @phy_idle_power_off: PHY power state. * @host: DRM MIPI DSI Host. * @bridge: Pointer to DRM bridge object. + * @ext_bridge: Pointer to external bridge object attached to DSI bridge. * @cmd_engine_refcount: Reference count enforcing single instance of cmd eng * @clk_mngr: DSI clock manager. * @dsi_clk_handle: DSI clock handle. @@ -174,6 +177,7 @@ struct dsi_display { struct platform_device *pdev; struct drm_device *drm_dev; struct drm_connector *drm_conn; + struct drm_connector *ext_conn; const char *name; const char *display_type; @@ -193,6 +197,7 @@ struct dsi_display { struct device_node *disp_node; struct device_node *panel_of; struct device_node *parser_node; + struct device_node *ext_bridge_of; struct dsi_display_mode *modes; @@ -222,6 +227,7 @@ struct dsi_display { struct mipi_dsi_host host; struct dsi_bridge *bridge; + struct drm_bridge *ext_bridge; u32 cmd_engine_refcount; struct sde_power_handle *phandle; @@ -302,6 +308,19 @@ int dsi_display_drm_bridge_init(struct dsi_display *display, */ int dsi_display_drm_bridge_deinit(struct dsi_display *display); +/** + * dsi_display_drm_ext_bridge_init() - initializes DRM bridge for ext bridge + * @display: Handle to the display. + * @enc: Pointer to the encoder object which is connected to the + * display. + * @connector: Pointer to the connector object which is connected to + * the display. + * + * Return: error code. + */ +int dsi_display_drm_ext_bridge_init(struct dsi_display *display, + struct drm_encoder *enc, struct drm_connector *connector); + /** * dsi_display_get_info() - returns the display properties * @connector: Pointer to drm connector structure diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c index 18933ce402e7..3f4134867ff2 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c @@ -25,6 +25,18 @@ #define to_dsi_bridge(x) container_of((x), struct dsi_bridge, base) #define to_dsi_state(x) container_of((x), struct dsi_connector_state, base) +#define DEFAULT_PANEL_JITTER_NUMERATOR 2 +#define DEFAULT_PANEL_JITTER_DENOMINATOR 1 +#define DEFAULT_PANEL_JITTER_ARRAY_SIZE 2 +#define DEFAULT_PANEL_PREFILL_LINES 25 + +static struct dsi_display_mode_priv_info default_priv_info = { + .panel_jitter_numer = DEFAULT_PANEL_JITTER_NUMERATOR, + .panel_jitter_denom = DEFAULT_PANEL_JITTER_DENOMINATOR, + .panel_prefill_lines = DEFAULT_PANEL_PREFILL_LINES, + .dsc_enabled = false, +}; + static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode, struct dsi_display_mode *dsi_mode) { @@ -63,6 +75,11 @@ static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode, dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS; if (msm_is_mode_seamless_vrr(drm_mode)) dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR; + + dsi_mode->timing.h_sync_polarity = + !!(drm_mode->flags & DRM_MODE_FLAG_PHSYNC); + dsi_mode->timing.v_sync_polarity = + !!(drm_mode->flags & DRM_MODE_FLAG_PVSYNC); } void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode, @@ -101,6 +118,11 @@ void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode, if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VRR) drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_VRR; + if (dsi_mode->timing.h_sync_polarity) + drm_mode->flags |= DRM_MODE_FLAG_PHSYNC; + if (dsi_mode->timing.v_sync_polarity) + drm_mode->flags |= DRM_MODE_FLAG_PVSYNC; + drm_mode_set_name(drm_mode); } @@ -286,6 +308,17 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge, return false; } + /* + * if no timing defined in panel, it must be external mode + * and we'll use empty priv info to populate the mode + */ + if (display->panel && !display->panel->num_timing_nodes) { + *adjusted_mode = *mode; + adjusted_mode->private = (int *)&default_priv_info; + adjusted_mode->private_flags = 0; + return true; + } + convert_to_dsi_mode(mode, &dsi_mode); /* diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index b4c26514ec22..aa0fd00a2c07 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -412,6 +412,9 @@ static int dsi_panel_set_pinctrl_state(struct dsi_panel *panel, bool enable) int rc = 0; struct pinctrl_state *state; + if (panel->host_config.ext_bridge_mode) + return 0; + if (enable) state = panel->pinctrl.active; else @@ -552,6 +555,9 @@ static int dsi_panel_pinctrl_init(struct dsi_panel *panel) { int rc = 0; + if (panel->host_config.ext_bridge_mode) + return 0; + /* TODO: pinctrl is defined in dsi dt node */ panel->pinctrl.pinctrl = devm_pinctrl_get(panel->parent); if (IS_ERR_OR_NULL(panel->pinctrl.pinctrl)) { @@ -643,6 +649,9 @@ static int dsi_panel_bl_register(struct dsi_panel *panel) int rc = 0; struct dsi_backlight_config *bl = &panel->bl_config; + if (panel->host_config.ext_bridge_mode) + return 0; + switch (bl->type) { case DSI_BACKLIGHT_WLED: rc = dsi_panel_wled_register(panel, bl); @@ -664,6 +673,9 @@ static int dsi_panel_bl_unregister(struct dsi_panel *panel) int rc = 0; struct dsi_backlight_config *bl = &panel->bl_config; + if (panel->host_config.ext_bridge_mode) + return 0; + switch (bl->type) { case DSI_BACKLIGHT_WLED: break; @@ -999,6 +1011,9 @@ static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host, host->append_tx_eot = utils->read_bool(utils->data, "qcom,mdss-dsi-tx-eot-append"); + host->ext_bridge_mode = utils->read_bool(utils->data, + "qcom,mdss-dsi-ext-bridge-mode"); + return 0; } @@ -1788,7 +1803,8 @@ static int dsi_panel_parse_gpios(struct dsi_panel *panel) panel->reset_config.reset_gpio = utils->get_named_gpio(utils->data, "qcom,platform-reset-gpio", 0); - if (!gpio_is_valid(panel->reset_config.reset_gpio)) { + if (!gpio_is_valid(panel->reset_config.reset_gpio) && + !panel->host_config.ext_bridge_mode) { pr_err("[%s] failed get reset gpio, rc=%d\n", panel->name, rc); rc = -EINVAL; goto error; @@ -2175,7 +2191,7 @@ static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode, priv_info->phy_timing_len = len; }; - mode->pixel_clk_khz = (mode->timing.h_active * + mode->pixel_clk_khz = (DSI_H_TOTAL(&mode->timing) * DSI_V_TOTAL(&mode->timing) * mode->timing.refresh_rate) / 1000; return rc; @@ -3022,7 +3038,7 @@ int dsi_panel_get_mode_count(struct dsi_panel *panel) timings_np = utils->get_child_by_name(utils->data, "qcom,mdss-dsi-display-timings"); - if (!timings_np) { + if (!timings_np && !panel->host_config.ext_bridge_mode) { pr_err("no display timing nodes defined\n"); rc = -EINVAL; goto error; diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index c43977cec65b..ef0f1e08c6ee 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -2228,6 +2228,7 @@ static void _sde_kms_post_open(struct msm_kms *kms, struct drm_file *file) struct drm_connector *connector = NULL; struct drm_connector_list_iter conn_iter; struct sde_connector *sde_conn = NULL; + int i; if (!kms) { SDE_ERROR("invalid kms\n"); @@ -2245,6 +2246,18 @@ static void _sde_kms_post_open(struct msm_kms *kms, struct drm_file *file) if (!dev->mode_config.poll_enabled) return; + /* init external dsi bridge here to make sure ext bridge is probed*/ + for (i = 0; i < sde_kms->dsi_display_count; ++i) { + struct dsi_display *dsi_display; + + dsi_display = sde_kms->dsi_displays[i]; + if (dsi_display->bridge) { + dsi_display_drm_ext_bridge_init(dsi_display, + dsi_display->bridge->base.encoder, + dsi_display->drm_conn); + } + } + mutex_lock(&dev->mode_config.mutex); drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { -- GitLab From 94ab648b00e46743c50e2f50e556bcfef7456e90 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Sat, 31 Mar 2018 20:56:23 -0700 Subject: [PATCH 0744/1299] ANDROID: xt_qtaguid: Remove unnecessary null checks to device's name 'name' will never be NULL since it isn't a plain pointer but an array of char values. ../net/netfilter/xt_qtaguid.c:1195:27: warning: address of array '(*el_dev)->name' will always evaluate to 'true' [-Wpointer-bool-conversion] if (unlikely(!(*el_dev)->name)) { ~~~~~~~~~~~~^~~~ Change-Id: If3b25f17829b43e8a639193fb9cd04ae45947200 Signed-off-by: Nathan Chancellor (cherry picked from android-4.4 commit 207b579e3db6fd0cb6fe40ba3e929635ad748d89) Signed-off-by: Chenbo Feng --- net/netfilter/xt_qtaguid.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index cd7c34b45221..d261932ee595 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -1194,11 +1194,6 @@ static void get_dev_and_dir(const struct sk_buff *skb, parst->hook, __func__); BUG(); } - if (unlikely(!(*el_dev)->name)) { - pr_err("qtaguid[%d]: %s(): no dev->name?!!\n", - parst->hook, __func__); - BUG(); - } if (skb->dev && *el_dev != skb->dev) { MT_DEBUG("qtaguid[%d]: skb->dev=%p %s vs par->%s=%p %s\n", parst->hook, skb->dev, skb->dev->name, -- GitLab From 5b9b484681b4e0b66c06aa9ccfbeb72a57eea530 Mon Sep 17 00:00:00 2001 From: Narendra Muppalla Date: Wed, 24 Jan 2018 17:09:05 -0800 Subject: [PATCH 0745/1299] drm/msm/sde: add support to scale data bus Current driver has support to vote for only one rate in the data bus. Add support to scale the vote for the data bus. Change-Id: I7fbef0437c7e6f0581275c4bb2c302b41f7918ef Signed-off-by: Ingrid Gallardo Signed-off-by: Narendra Muppalla --- drivers/gpu/drm/msm/sde_power_handle.c | 82 ++++++++++++++++++++++++-- drivers/gpu/drm/msm/sde_power_handle.h | 17 ++++++ 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c index 80049ce0c9eb..b4cdaf65e586 100644 --- a/drivers/gpu/drm/msm/sde_power_handle.c +++ b/drivers/gpu/drm/msm/sde_power_handle.c @@ -847,6 +847,68 @@ void sde_power_resource_deinit(struct platform_device *pdev, sde_rsc_client_destroy(phandle->rsc_client); } + +int sde_power_scale_reg_bus(struct sde_power_handle *phandle, + struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock) +{ + struct sde_power_client *client; + int rc = 0; + u32 max_usecase_ndx = VOTE_INDEX_DISABLE; + + if (!skip_lock) { + mutex_lock(&phandle->phandle_lock); + + if (WARN_ON(pclient->refcount == 0)) { + /* + * This is not expected, clients calling without skip + * lock are outside the power resource enable, which + * means that they should have enabled the power + * resource before trying to scale. + */ + rc = -EINVAL; + goto exit; + } + } + + pr_debug("%pS: current idx:%d requested:%d client:%d\n", + __builtin_return_address(0), pclient->usecase_ndx, + usecase_ndx, pclient->id); + + pclient->usecase_ndx = usecase_ndx; + + list_for_each_entry(client, &phandle->power_client_clist, list) { + if (client->usecase_ndx < VOTE_INDEX_MAX && + client->usecase_ndx > max_usecase_ndx) + max_usecase_ndx = client->usecase_ndx; + } + + rc = sde_power_reg_bus_update(phandle->reg_bus_hdl, + max_usecase_ndx); + if (rc) + pr_err("failed to set reg bus vote rc=%d\n", rc); + +exit: + if (!skip_lock) + mutex_unlock(&phandle->phandle_lock); + + return rc; +} + +static inline bool _resource_changed(u32 current_usecase_ndx, + u32 max_usecase_ndx) +{ + WARN_ON((current_usecase_ndx >= VOTE_INDEX_MAX) + || (max_usecase_ndx >= VOTE_INDEX_MAX)); + + if (((current_usecase_ndx >= VOTE_INDEX_LOW) && /* enabled */ + (max_usecase_ndx == VOTE_INDEX_DISABLE)) || /* max disabled */ + ((current_usecase_ndx == VOTE_INDEX_DISABLE) && /* disabled */ + (max_usecase_ndx >= VOTE_INDEX_LOW))) /* max enabled */ + return true; + + return false; +} + int sde_power_resource_enable(struct sde_power_handle *phandle, struct sde_power_client *pclient, bool enable) { @@ -880,7 +942,15 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, max_usecase_ndx = client->usecase_ndx; } - if (phandle->current_usecase_ndx != max_usecase_ndx) { + /* + * Check if we need to enable/disable the power resource, we won't + * only-scale up/down the AHB vote in this API; if a client wants to + * bump up the AHB clock above the LOW (default) level, it needs to + * call 'sde_power_scale_reg_bus' with the desired vote after the power + * resource was enabled. + */ + if (_resource_changed(phandle->current_usecase_ndx, + max_usecase_ndx)) { changed = true; prev_usecase_ndx = phandle->current_usecase_ndx; phandle->current_usecase_ndx = max_usecase_ndx; @@ -916,8 +986,8 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, goto vreg_err; } - rc = sde_power_reg_bus_update(phandle->reg_bus_hdl, - max_usecase_ndx); + rc = sde_power_scale_reg_bus(phandle, pclient, + max_usecase_ndx, true); if (rc) { pr_err("failed to set reg bus vote rc=%d\n", rc); goto reg_bus_hdl_err; @@ -948,8 +1018,8 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); - sde_power_reg_bus_update(phandle->reg_bus_hdl, - max_usecase_ndx); + sde_power_scale_reg_bus(phandle, pclient, + max_usecase_ndx, true); msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable); @@ -970,7 +1040,7 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, clk_err: sde_power_rsc_update(phandle, false); rsc_err: - sde_power_reg_bus_update(phandle->reg_bus_hdl, prev_usecase_ndx); + sde_power_scale_reg_bus(phandle, pclient, max_usecase_ndx, true); reg_bus_hdl_err: msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0); vreg_err: diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h index b07779f0be9a..2c8665f9bb2b 100644 --- a/drivers/gpu/drm/msm/sde_power_handle.h +++ b/drivers/gpu/drm/msm/sde_power_handle.h @@ -43,11 +43,15 @@ * mdss_bus_vote_type: register bus vote type * VOTE_INDEX_DISABLE: removes the client vote * VOTE_INDEX_LOW: keeps the lowest vote for register bus + * VOTE_INDEX_MEDIUM: keeps medium vote for register bus + * VOTE_INDEX_HIGH: keeps the highest vote for register bus * VOTE_INDEX_MAX: invalid */ enum mdss_bus_vote_type { VOTE_INDEX_DISABLE, VOTE_INDEX_LOW, + VOTE_INDEX_MEDIUM, + VOTE_INDEX_HIGH, VOTE_INDEX_MAX, }; @@ -227,6 +231,19 @@ void sde_power_client_destroy(struct sde_power_handle *phandle, int sde_power_resource_enable(struct sde_power_handle *pdata, struct sde_power_client *pclient, bool enable); +/** + * sde_power_scale_reg_bus() - Scale the registers bus for the specified client + * @phandle: power handle containing the resources + * @pclient: client information to scale its vote + * @usecase_ndx: new use case to scale the reg bus + * @skip_lock: will skip holding the power rsrc mutex during the call, this is + * for internal callers that already hold this required lock. + * + * Return: error code. + */ +int sde_power_scale_reg_bus(struct sde_power_handle *phandle, + struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock); + /** * sde_power_resource_is_enabled() - return true if power resource is enabled * @pdata: power handle containing the resources -- GitLab From 1eeff7668a6081dba3f4504ddf5e0f341496a889 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Fri, 22 Jun 2018 15:41:02 -0700 Subject: [PATCH 0746/1299] mailbox: msm_qmp: Remove IRQ clear IRQ clear was wrongly added because an interrupt was incorrectly configured as a level interrupt. The qmp driver should not clear this interrupt since there is a chance the interrupt will not be read by the remote. Change-Id: Id68af1db0d9ac213958a5b088f1d1c80eb5395a9 Signed-off-by: Chris Lew --- drivers/mailbox/msm_qmp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mailbox/msm_qmp.c b/drivers/mailbox/msm_qmp.c index 9108d7d7041a..e64ad5515e7c 100644 --- a/drivers/mailbox/msm_qmp.c +++ b/drivers/mailbox/msm_qmp.c @@ -222,7 +222,6 @@ static void send_irq(struct qmp_device *mdev) */ wmb(); writel_relaxed(mdev->irq_mask, mdev->tx_irq_reg); - writel_relaxed(0x0, mdev->tx_irq_reg); mdev->tx_irq_count++; } -- GitLab From e0f3d49f0d8c0b4c9c2f82baeed6d79530953a0e Mon Sep 17 00:00:00 2001 From: Steve Cohen Date: Fri, 22 Jun 2018 18:40:10 -0400 Subject: [PATCH 0747/1299] drm/msm: avoid segmentation of dma_buf mappings Ensure dma_buf mappings aren't broken in to multiple segments by setting the devices segment size and boundary. This will improve performance and the sg_dma_len() API will now give the correct buffer size. Change-Id: Ic3a3c520ea488d367c8df0f1ce7aca5000e9f3e7 Signed-off-by: Steve Cohen --- drivers/gpu/drm/msm/msm_smmu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c index 69ab06af5a09..20b3022749ff 100644 --- a/drivers/gpu/drm/msm/msm_smmu.c +++ b/drivers/gpu/drm/msm/msm_smmu.c @@ -488,6 +488,13 @@ static int _msm_smmu_create_mapping(struct msm_smmu_client *client, } } + if (!client->dev->dma_parms) + client->dev->dma_parms = devm_kzalloc(client->dev, + sizeof(*client->dev->dma_parms), GFP_KERNEL); + + dma_set_max_seg_size(client->dev, DMA_BIT_MASK(32)); + dma_set_seg_boundary(client->dev, DMA_BIT_MASK(64)); + iommu_set_fault_handler(client->mmu_mapping->domain, msm_smmu_fault_handler, (void *)client); -- GitLab From 56cfb49cf19ac2ab931d00674c2058d3ec5665d6 Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Wed, 20 Jun 2018 17:01:21 -0700 Subject: [PATCH 0748/1299] ARM: dts: msm: Add smmu support for sm8150 v2 hardware Support smmu for sm8150-v2 hardware by swapping the TBU entries for COMPUTE_DSP_1 and SF_0. The stream id range and base addresses of these TBUs are swapped. Change-Id: I4dfb524552767f7e498da046b0b92b3360ecaa33 Signed-off-by: Sudarshan Rajagopalan --- .../boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi | 390 ++++++++++++++++++ arch/arm64/boot/dts/qcom/sm8150-v2.dtsi | 5 + 2 files changed, 395 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi new file mode 100644 index 000000000000..5c51469f7d52 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi @@ -0,0 +1,390 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +&soc { + kgsl_smmu: kgsl-smmu@0x02ca0000 { + compatible = "qcom,qsmmu-v500"; + reg = <0x02ca0000 0x10000>, + <0x2cc2000 0x20>; + reg-names = "base", "tcu-base"; + #iommu-cells = <2>; + qcom,dynamic; + qcom,skip-init; + qcom,use-3-lvl-tables; + qcom,no-asid-retention; + qcom,disable-atos; + #global-interrupts = <1>; + qcom,regulator-names = "vdd"; + vdd-supply = <&gpu_cx_gdsc>; + clocks = <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&clock_gcc GCC_GPU_SNOC_DVM_GFX_CLK>, + <&clock_gpucc GPU_CC_AHB_CLK>; + clock-names = "gcc_gpu_memnoc_gfx_clk", + "gcc_gpu_snoc_dvm_gfx_clk", + "gpu_cc_ahb_clk"; + #size-cells = <1>; + #address-cells = <1>; + ranges; + interrupts = , + , + , + , + , + , + , + , + ; + + gfx_0_tbu: gfx_0_tbu@0x2cc5000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x2cc5000 0x1000>, + <0x2cc2200 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x0 0x400>; + }; + + gfx_1_tbu: gfx_1_tbu@0x2cc9000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x2cc9000 0x1000>, + <0x2cc2208 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x400 0x400>; + }; + }; + + apps_smmu: apps-smmu@0x15000000 { + compatible = "qcom,qsmmu-v500"; + reg = <0x15000000 0x100000>, + <0x15182000 0x20>; + reg-names = "base", "tcu-base"; + #iommu-cells = <2>; + qcom,skip-init; + qcom,use-3-lvl-tables; + qcom,no-asid-retention; + qcom,disable-atos; + #global-interrupts = <1>; + #size-cells = <1>; + #address-cells = <1>; + ranges; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + + anoc_1_tbu: anoc_1_tbu@0x15185000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15185000 0x1000>, + <0x15182200 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x0 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_aggre_noc_mmu_tbu1_gdsc>; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + + anoc_2_tbu: anoc_2_tbu@0x15189000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15189000 0x1000>, + <0x15182208 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x400 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_aggre_noc_mmu_tbu2_gdsc>; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + + mnoc_hf_0_tbu: mnoc_hf_0_tbu@0x1518d000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x1518d000 0x1000>, + <0x15182210 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x800 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc>; + qcom,msm-bus,name = "mnoc_hf_0_tbu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + + mnoc_hf_1_tbu: mnoc_hf_1_tbu@0x15191000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15191000 0x1000>, + <0x15182218 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0xc00 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc>; + qcom,msm-bus,name = "mnoc_hf_1_tbu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + + compute_dsp_1_tbu: compute_dsp_1_tbu@0x15195000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15195000 0x1000>, + <0x15182220 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x1000 0x400>; + /* No GDSC */ + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + + compute_dsp_0_tbu: compute_dsp_0_tbu@0x15199000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x15199000 0x1000>, + <0x15182228 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x1400 0x400>; + /* No GDSC */ + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + + adsp_tbu: adsp_tbu@0x1519d000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x1519d000 0x1000>, + <0x15182230 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x1800 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_aggre_noc_mmu_audio_tbu_gdsc>; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + + anoc_1_pcie_tbu: anoc_1_pcie_tbu@0x151a1000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x151a1000 0x1000>, + <0x15182238 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x1c00 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc>; + clock-names = "gcc_aggre_noc_pcie_tbu_clk"; + clocks = <&clock_gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>; + qcom,msm-bus,name = "apps_smmu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + + mnoc_sf_0_tbu: mnoc_sf_0_tbu@0x151a5000 { + compatible = "qcom,qsmmuv500-tbu"; + reg = <0x151a5000 0x1000>, + <0x15182240 0x8>; + reg-names = "base", "status-reg"; + qcom,stream-id-range = <0x1c00 0x400>; + qcom,regulator-names = "vdd"; + vdd-supply = <&hlos1_vote_mmnoc_mmu_tbu_sf_gdsc>; + qcom,msm-bus,name = "mnoc_sf_0_tbu"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,active-only; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + <0 0>, + , + , + <0 1000>; + }; + }; + + kgsl_iommu_test_device { + compatible = "iommu-debug-test"; + iommus = <&kgsl_smmu 0x7 0>; + }; + + kgsl_iommu_coherent_test_device { + compatible = "iommu-debug-test"; + iommus = <&kgsl_smmu 0x9 0>; + dma-coherent; + }; + + apps_iommu_test_device { + compatible = "iommu-debug-test"; + iommus = <&apps_smmu 0x21 0>; + }; + + apps_iommu_coherent_test_device { + compatible = "iommu-debug-test"; + iommus = <&apps_smmu 0x23 0>; + dma-coherent; + }; +}; + +&kgsl_smmu { + qcom,actlr = <0x0 0x407 0x303>; +}; + diff --git a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi index 5380383db666..cbe3b4b67955 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi @@ -18,6 +18,10 @@ qcom,msm-id = <339 0x20000>; }; +/* Remove smmu nodes specific to SM8150 */ +/delete-node/ &apps_smmu; +/delete-node/ &kgsl_smmu; + &clock_gcc { compatible = "qcom,gcc-sm8150-v2", "syscon"; }; @@ -37,3 +41,4 @@ &clock_npucc { compatible = "qcom,npucc-sm8150-v2", "syscon"; }; +#include "msm-arm-smmu-sm8150-v2.dtsi" -- GitLab From 8adf8153458986e6f96b4a5b2d7d932e82fbabab Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Wed, 20 Jun 2018 17:27:21 -0700 Subject: [PATCH 0749/1299] ARM: dts: msm: Enable deep pre-fetch for NPU CBs for sm8150 Enable context caching with deep pre-fetch of length 16x pages for all context banks of NPU. Change-Id: Id9510fba21c5366513cdda7299b67cbf31082cda Signed-off-by: Sudarshan Rajagopalan --- arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi index 5c51469f7d52..bd1c8254883a 100644 --- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi @@ -384,7 +384,12 @@ }; }; -&kgsl_smmu { - qcom,actlr = <0x0 0x407 0x303>; +&kgsl_smmu { /* */ + qcom,actlr = <0x0 0x407 0x303>, + <0x1460 0x0 0x303>, + <0x61 0x3400 0x303>, + <0x62 0x3401 0x303>, + <0x64 0x3400 0x303>, + <0x65 0x3400 0x303>; }; -- GitLab From 84b79f1ede66426733433e25b21c1963b2c68dbc Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Wed, 20 Jun 2018 17:54:11 -0700 Subject: [PATCH 0750/1299] ARM: dts: msm: Enable ATOS for kgsl and apps smmu for sm8150 Enable ATOS feature since HW errata is fixed in sm8150-v2. Change-Id: I1d909f7dcaa4e44e9adf49cb5ba1dade8c38af50 Signed-off-by: Sudarshan Rajagopalan --- arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi index bd1c8254883a..ec9721f00de7 100644 --- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi @@ -24,7 +24,6 @@ qcom,skip-init; qcom,use-3-lvl-tables; qcom,no-asid-retention; - qcom,disable-atos; #global-interrupts = <1>; qcom,regulator-names = "vdd"; vdd-supply = <&gpu_cx_gdsc>; @@ -73,7 +72,6 @@ qcom,skip-init; qcom,use-3-lvl-tables; qcom,no-asid-retention; - qcom,disable-atos; #global-interrupts = <1>; #size-cells = <1>; #address-cells = <1>; -- GitLab From e03ad6e08edb3f9f77f634800bd23feebaa0c1ed Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Sat, 23 Jun 2018 19:01:02 +0530 Subject: [PATCH 0751/1299] defconfig: arm64: Enable CDSP request manager and CDSP L3 governor Enable CDSP request manager and CDSP L3 governor to improve CDSP performance for sm8150. Change-Id: Ia67a42ce660820adf4bfb302555033f7ac2d040c Acked-by: Sreekanth Gande Signed-off-by: Tharun Kumar Merugu --- arch/arm64/configs/vendor/sm8150-auto-perf_defconfig | 2 ++ arch/arm64/configs/vendor/sm8150-auto_defconfig | 2 ++ arch/arm64/configs/vendor/sm8150-perf_defconfig | 2 ++ arch/arm64/configs/vendor/sm8150_defconfig | 2 ++ 4 files changed, 8 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-auto-perf_defconfig b/arch/arm64/configs/vendor/sm8150-auto-perf_defconfig index 7badb45b9a6f..874a31783e7c 100644 --- a/arch/arm64/configs/vendor/sm8150-auto-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-auto-perf_defconfig @@ -536,6 +536,7 @@ CONFIG_MSM_PM=y CONFIG_QCOM_FSA4480_I2C=y CONFIG_MSM_PERFORMANCE=y CONFIG_QMP_DEBUGFS_CLIENT=y +CONFIG_QCOM_CDSP_RM=y CONFIG_DEVFREQ_GOV_PASSIVE=y CONFIG_QCOM_BIMC_BWMON=y CONFIG_ARM_MEMLAT_MON=y @@ -546,6 +547,7 @@ CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y CONFIG_DEVFREQ_GOV_MEMLAT=y CONFIG_DEVFREQ_SIMPLE_DEV=y CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_DEVFREQ_GOV_CDSPL3=y CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y diff --git a/arch/arm64/configs/vendor/sm8150-auto_defconfig b/arch/arm64/configs/vendor/sm8150-auto_defconfig index d104e6c4a745..af8898cbc26a 100644 --- a/arch/arm64/configs/vendor/sm8150-auto_defconfig +++ b/arch/arm64/configs/vendor/sm8150-auto_defconfig @@ -561,6 +561,7 @@ CONFIG_MSM_PM=y CONFIG_QCOM_FSA4480_I2C=y CONFIG_MSM_PERFORMANCE=y CONFIG_QMP_DEBUGFS_CLIENT=y +CONFIG_QCOM_CDSP_RM=y CONFIG_DEVFREQ_GOV_PASSIVE=y CONFIG_QCOM_BIMC_BWMON=y CONFIG_ARM_MEMLAT_MON=y @@ -571,6 +572,7 @@ CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y CONFIG_DEVFREQ_GOV_MEMLAT=y CONFIG_DEVFREQ_SIMPLE_DEV=y CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_DEVFREQ_GOV_CDSPL3=y CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index edc85d929078..9fb85b7fe1c1 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -551,6 +551,7 @@ CONFIG_QCOM_FSA4480_I2C=y CONFIG_MSM_PERFORMANCE=y CONFIG_QMP_DEBUGFS_CLIENT=y CONFIG_QCOM_SMP2P_SLEEPSTATE=y +CONFIG_QCOM_CDSP_RM=y CONFIG_DEVFREQ_GOV_PASSIVE=y CONFIG_QCOM_BIMC_BWMON=y CONFIG_ARM_MEMLAT_MON=y @@ -561,6 +562,7 @@ CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y CONFIG_DEVFREQ_GOV_MEMLAT=y CONFIG_DEVFREQ_SIMPLE_DEV=y CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_DEVFREQ_GOV_CDSPL3=y CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 3909b4e5d220..c4873fb06ba4 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -577,6 +577,7 @@ CONFIG_QCOM_FSA4480_I2C=y CONFIG_MSM_PERFORMANCE=y CONFIG_QMP_DEBUGFS_CLIENT=y CONFIG_QCOM_SMP2P_SLEEPSTATE=y +CONFIG_QCOM_CDSP_RM=y CONFIG_DEVFREQ_GOV_PASSIVE=y CONFIG_QCOM_BIMC_BWMON=y CONFIG_ARM_MEMLAT_MON=y @@ -587,6 +588,7 @@ CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y CONFIG_DEVFREQ_GOV_MEMLAT=y CONFIG_DEVFREQ_SIMPLE_DEV=y CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_DEVFREQ_GOV_CDSPL3=y CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y -- GitLab From 2ea2c896b8431773438d41c462fc245a3911f83d Mon Sep 17 00:00:00 2001 From: Yuanyuan Liu Date: Wed, 20 Jun 2018 15:01:39 -0700 Subject: [PATCH 0752/1299] icnss: Check platform state before sending uevent Check icnss platform state before sending uevent to WLAN host driver. Do not call uevent if WLAN FW is not ready or WLAN driver is in unloading state. CRs-Fixed: 2264599 Change-Id: I9630daef6123d9e8b88a7c2019638e8c6f76a820 Signed-off-by: Yuanyuan Liu --- drivers/soc/qcom/icnss.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index c8abef863070..3edc657c3508 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -1238,7 +1238,11 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, event_data->crashed = notif->crashed; fw_down_data.crashed = !!notif->crashed; - icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_DOWN, &fw_down_data); + if (test_bit(ICNSS_FW_READY, &priv->state) && + !test_bit(ICNSS_DRIVER_UNLOADING, &priv->state)) + icnss_call_driver_uevent(priv, + ICNSS_UEVENT_FW_DOWN, + &fw_down_data); icnss_driver_event_post(ICNSS_DRIVER_EVENT_PD_SERVICE_DOWN, ICNSS_EVENT_SYNC, event_data); -- GitLab From 4bf2157be445ed3847d2170669fc31751c4bb150 Mon Sep 17 00:00:00 2001 From: Sayali Lokhande Date: Tue, 12 Jun 2018 16:15:02 +0530 Subject: [PATCH 0753/1299] scsi: ufs: Fix race condition in rls_work and ufshcd_resume In some rare scenario, race condition is observed between rls_work handler and ufshcd_resume operation. Sequence of events: 1.rls_work is scheduled due to UIC error. 2.ufshcd_rls_handler sets host_self_blocked to 1 and then invokes pm_runtime_get_sync 3. pm_runtime_get_sync is not yet completed because runtime_status was RPM_RESUMING. 4.pm_runtime_work schedules at almost same time of rls_work. Here ufshcd_resume schedules out as host_self_blocked was set to 1 by rls_work. Call stacks: -006|wait_for_completion_io(?) -007|blk_execute_rq() -008|scsi_execute() -009|scsi_execute_req_flags() -010|ufshcd_set_dev_pwr_mode() -011|ufshcd_resume() -012|ufshcd_runtime_resume(hba) -013|ufshcd_pltfrm_runtime_resume(?) -014|pm_generic_runtime_resume(?) -015|__rpm_callback(inline) -003|schedule() -004|spin_lock_irq(inline) -004|rpm_resume() -005|__pm_runtime_resume() -006|ufshcd_rls_handler() Fix this by calling pm_runtime_get_sync before setting host_self_blocked to 1 during rls_work. Change-Id: I69f23c169ac8a9eb59062b461302f5521cd57ebc Signed-off-by: Sayali Lokhande --- drivers/scsi/ufs/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9dbc1d97339a..00fc4bf8aead 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7074,8 +7074,8 @@ static void ufshcd_rls_handler(struct work_struct *work) u32 mode; hba = container_of(work, struct ufs_hba, rls_work); - ufshcd_scsi_block_requests(hba); pm_runtime_get_sync(hba->dev); + ufshcd_scsi_block_requests(hba); down_write(&hba->lock); ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX); if (ret) { -- GitLab From 5fa99b30fd6d9e539f763503ab31c97deb184fdb Mon Sep 17 00:00:00 2001 From: Archit Saxena Date: Fri, 22 Jun 2018 12:54:43 +0530 Subject: [PATCH 0754/1299] ARM: dts: msm: Disable chd support for QCS405 Disable chd support for QCS405 as it is not supported by hardware. Also reduce number of registers to four. Change-Id: I9ce24198da12acc98860d719e518d884ba2adc2a Signed-off-by: Archit Saxena --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 3194ab374d0a..337ece4b8338 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -387,10 +387,12 @@ qcom,chd { compatible = "qcom,core-hang-detect"; + label = "gold"; qcom,threshold-arr = <0xb088094 0xb098094 0xb0a8094 - 0xb0b8094 0xb188094 0xb198094 0xb1a8094 0xb1a8094>; + 0xb0b8094>; qcom,config-arr = <0xb08809c 0xb09809c 0xb0a809c - 0xb0b809c 0xb18809c 0xb19809c 0xb1a809c 0xb1b809c>; + 0xb0b809c>; + staus = "disabled"; }; qcom,msm-imem@8600000 { -- GitLab From d844c372b46ea2a20af9d3ccb03cf4c65350c497 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Mon, 25 Jun 2018 13:12:12 +0530 Subject: [PATCH 0755/1299] ARM: dts: msm: fix compilation issue in qcs405 Use correct div_clk node name for tasha to fix compilation issue in qcs405. Use macros in dt- bindings instead of enum to fix syntax error. Change-Id: I5eeafbcfc60500321c942967a84200f89dd81ebc Signed-off-by: Aditya Bavanari --- arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi | 2 +- .../sound/audio-codec-port-types.h | 57 +++++++++---------- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi b/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi index 3f49f98f216d..fa2f21d561bc 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi @@ -29,7 +29,7 @@ pinctrl-0 = <&tasha_mclk_default>; pinctrl-1 = <&tasha_mclk_default>; #clock-names = "osr_clk"; - #clocks = <&pms405_div_clk>; + #clocks = <&pms405_clkdiv>; #clock-cells = <1>; }; diff --git a/include/dt-bindings/sound/audio-codec-port-types.h b/include/dt-bindings/sound/audio-codec-port-types.h index aba5aa0ca7be..b795d0db7db3 100644 --- a/include/dt-bindings/sound/audio-codec-port-types.h +++ b/include/dt-bindings/sound/audio-codec-port-types.h @@ -1,33 +1,32 @@ #ifndef __AUDIO_CODEC_PORT_TYPES_H #define __AUDIO_CODEC_PORT_TYPES_H -enum codec_port_type { - SPKR_L = 1, - SPKR_L_BOOST, - SPKR_L_COMP, - SPKR_L_VI, - SPKR_R, - SPKR_R_BOOST, - SPKR_R_COMP, - SPKR_R_VI, - HPH, - COMPANDER, - CLSH, - LO, - DSD, - MBHC, - ADC1, - ADC2, - ADC3, - DMIC1, - DMIC2, - DMIC3, - DMIC4, - DMIC5, - DMIC6, - DMIC7, - DMIC8, - DMIC9, - DMIC10, -}; +#define SPKR_L 1 +#define SPKR_L_BOOST 2 +#define SPKR_L_COMP 3 +#define SPKR_L_VI 4 +#define SPKR_R 5 +#define SPKR_R_BOOST 6 +#define SPKR_R_COMP 7 +#define SPKR_R_VI 8 +#define HPH 9 +#define COMPANDER 10 +#define CLSH 11 +#define LO 12 +#define DSD 13 +#define MBHC 14 +#define ADC1 15 +#define ADC2 16 +#define ADC3 17 +#define DMIC1 18 +#define DMIC2 19 +#define DMIC3 20 +#define DMIC4 21 +#define DMIC5 22 +#define DMIC6 23 +#define DMIC7 24 +#define DMIC8 25 +#define DMIC9 26 +#define DMIC10 27 + #endif /* __AUDIO_CODEC_PORT_TYPES_H */ -- GitLab From 79d32fba740c1a2f7e49b6beb5991662d553d2ff Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Mon, 25 Jun 2018 12:29:38 +0530 Subject: [PATCH 0756/1299] clk: qcom: Update BCR address to spare register The USB phy BCR addresses have been updated as per HW design, update the address and the bit associated. Change-Id: I5ce725e3e2424bb65bdfe36ef3007ac44d9599ef Signed-off-by: Shefali Jain --- drivers/clk/qcom/gcc-qcs405.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/gcc-qcs405.c b/drivers/clk/qcom/gcc-qcs405.c index 7d723d015171..fdde841f3cbc 100644 --- a/drivers/clk/qcom/gcc-qcs405.c +++ b/drivers/clk/qcom/gcc-qcs405.c @@ -2838,9 +2838,9 @@ static struct clk_regmap *gcc_qcs405_clocks[] = { static const struct qcom_reset_map gcc_qcs405_resets[] = { [GCC_GENI_IR_BCR] = {0x0F000}, [GCC_USB_HS_BCR] = {0x41000}, - [GCC_USB2_HS_PHY_ONLY_BCR] = {0x0000C, 0}, + [GCC_USB2_HS_PHY_ONLY_BCR] = {0x41034}, [GCC_QUSB2_PHY_BCR] = {0x4103C}, - [GCC_USB_HS_PHY_CFG_AHB_BCR] = {0x41038}, + [GCC_USB_HS_PHY_CFG_AHB_BCR] = {0x0000C, 0}, [GCC_USB2A_PHY_BCR] = {0x0000C, 1}, [GCC_USB3_PHY_BCR] = {0x39004}, [GCC_USB_30_BCR] = {0x39000}, -- GitLab From db7fe8c68a2fcc853df34dc4535ec9af13e5a8f9 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Thu, 21 Jun 2018 19:13:40 +0530 Subject: [PATCH 0757/1299] msm: ipa: gsi: mhi: Configure appropriate polling mode bit for MHI ep For MHI --> IPA pipe: When resuming due to transition to M0, set the polling mode bit to 0. In other cases, restore it's value form when you stopped the channel. For IPA-->MHI pipe: Always restore the polling mode bit. Change-Id: Ic856eb1c0dea35eb852bcc831ca29baba7f70860 Signed-off-by: Mohammed Javid --- drivers/platform/msm/gsi/gsi.c | 53 +++++++++++++++++++++++ drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c | 27 +++++++++++- include/linux/msm_gsi.h | 20 +++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 71fb666862cf..bd8bf1551c56 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -1954,6 +1954,26 @@ static void __gsi_write_channel_scratch(unsigned long chan_hdl, gsi_ctx->per.ee)); } +static void __gsi_read_channel_scratch(unsigned long chan_hdl, + union __packed gsi_channel_scratch * val) +{ + val->data.word1 = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(chan_hdl, + gsi_ctx->per.ee)); + + val->data.word2 = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_1_OFFS(chan_hdl, + gsi_ctx->per.ee)); + + val->data.word3 = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_2_OFFS(chan_hdl, + gsi_ctx->per.ee)); + + val->data.word4 = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl, + gsi_ctx->per.ee)); +} + static union __packed gsi_channel_scratch __gsi_update_mhi_channel_scratch( unsigned long chan_hdl, struct __packed gsi_mhi_channel_scratch mscr) { @@ -2046,6 +2066,39 @@ int gsi_write_channel_scratch(unsigned long chan_hdl, } EXPORT_SYMBOL(gsi_write_channel_scratch); +int gsi_read_channel_scratch(unsigned long chan_hdl, + union __packed gsi_channel_scratch *val) +{ + struct gsi_chan_ctx *ctx; + + if (!gsi_ctx) { + pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); + return -GSI_STATUS_NODEV; + } + + if (chan_hdl >= gsi_ctx->max_ch) { + GSIERR("bad params chan_hdl=%lu\n", chan_hdl); + return -GSI_STATUS_INVALID_PARAMS; + } + + if (gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_ALLOCATED && + gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_STARTED && + gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_STOPPED) { + GSIERR("bad state %d\n", + gsi_ctx->chan[chan_hdl].state); + return -GSI_STATUS_UNSUPPORTED_OP; + } + + ctx = &gsi_ctx->chan[chan_hdl]; + + mutex_lock(&ctx->mlock); + __gsi_read_channel_scratch(chan_hdl, val); + mutex_unlock(&ctx->mlock); + + return GSI_STATUS_SUCCESS; +} +EXPORT_SYMBOL(gsi_read_channel_scratch); + int gsi_update_mhi_channel_scratch(unsigned long chan_hdl, struct __packed gsi_mhi_channel_scratch mscr) { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c index 0b1abf5eda94..bc17bdfb7228 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c @@ -554,6 +554,7 @@ int ipa3_mhi_resume_channels_internal(enum ipa_client_type client, int res; int ipa_ep_idx; struct ipa3_ep_context *ep; + union __packed gsi_channel_scratch gsi_ch_scratch; IPA_MHI_FUNC_ENTRY(); @@ -565,11 +566,35 @@ int ipa3_mhi_resume_channels_internal(enum ipa_client_type client, ep = &ipa3_ctx->ep[ipa_ep_idx]; if (brstmode_enabled && !LPTransitionRejected) { + + res = gsi_read_channel_scratch(ep->gsi_chan_hdl, + &gsi_ch_scratch); + if (res) { + IPA_MHI_ERR("read ch scratch fail %d %d\n", res); + return res; + } + /* * set polling mode bit to DB mode before * resuming the channel + * + * For MHI-->IPA pipes: + * when resuming due to transition to M0, + * set the polling mode bit to 0. + * In other cases, restore it's value form + * when you stopped the channel. + * Here, after successful resume client move to M0 state. + * So, by default setting polling mode bit to 0. + * + * For IPA-->MHI pipe: + * always restore the polling mode bit. */ - ch_scratch.mhi.polling_mode = IPA_MHI_POLLING_MODE_DB_MODE; + if (IPA_CLIENT_IS_PROD(client)) + ch_scratch.mhi.polling_mode = + IPA_MHI_POLLING_MODE_DB_MODE; + else + ch_scratch.mhi.polling_mode = + gsi_ch_scratch.mhi.polling_mode; /* Use GSI update API to not affect non-SWI fields * inside the scratch while in suspend-resume operation diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h index 30629b221c8d..fad332bee3f8 100644 --- a/include/linux/msm_gsi.h +++ b/include/linux/msm_gsi.h @@ -880,6 +880,19 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, int gsi_write_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch val); +/** + * gsi_read_channel_scratch - Peripheral should call this function to + * read to the scratch area of the channel context + * + * @chan_hdl: Client handle previously obtained from + * gsi_alloc_channel + * @val: Read value + * + * @Return gsi_status + */ +int gsi_read_channel_scratch(unsigned long chan_hdl, + union __packed gsi_channel_scratch *val); + /** * gsi_update_mhi_channel_scratch - MHI Peripheral should call this * function to update the scratch area of the channel context. Updating @@ -1174,6 +1187,7 @@ int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code); * gsi_alloc_channel (for as many channels as needed; channels can have * no event ring, an exclusive event ring or a shared event ring) * gsi_write_channel_scratch + * gsi_read_channel_scratch * gsi_start_channel * gsi_queue_xfer/gsi_start_xfer * gsi_config_channel_mode/gsi_poll_channel (if clients wants to poll on @@ -1258,6 +1272,12 @@ static inline int gsi_write_channel_scratch(unsigned long chan_hdl, return -GSI_STATUS_UNSUPPORTED_OP; } +static inline int gsi_read_channel_scratch(unsigned long chan_hdl, + union __packed gsi_channel_scratch *val) +{ + return -GSI_STATUS_UNSUPPORTED_OP; +} + static inline int gsi_update_mhi_channel_scratch(unsigned long chan_hdl, struct __packed gsi_mhi_channel_scratch mscr) { -- GitLab From 1e227724e5b8b4d368ed4bdb10e4785ed6066bf3 Mon Sep 17 00:00:00 2001 From: Prasad Sodagudi Date: Sat, 23 Jun 2018 11:48:25 -0700 Subject: [PATCH 0758/1299] cpu-hotplug: Fix the cpus_write_lock usage 'Commit ("5f7b7a9fb8471bfec25 cpu-hotplug: Keep atleast 1 online and un-isolated CPU")' caused regression in CPU hotplug scenario. cpus_write_lock taken and not released in error path. So fix the sequence of checks in _cpu_down function. Change-Id: I96cb3c2f1de93992af0e4f1d85857744b65e7a21 Signed-off-by: Prasad Sodagudi --- kernel/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/cpu.c b/kernel/cpu.c index abc9676a1389..af724a7180e7 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -867,11 +867,11 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen, if (!cpu_present(cpu)) return -EINVAL; - cpus_write_lock(); - if (!tasks_frozen && !cpu_isolated(cpu) && num_online_uniso_cpus() == 1) return -EBUSY; + cpus_write_lock(); + if (trace_cpuhp_latency_enabled()) start_time = sched_clock(); -- GitLab From e538aac7960575d3d393aafeb69b3393663d19ab Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Mon, 25 Jun 2018 16:26:54 +0530 Subject: [PATCH 0759/1299] Documentation: sound: Add documentation for qcs405 VAD dais Add documentation to define a property for the dais which can be supported in the island mode. CRs-Fixed: 2259784 Change-Id: I55c9cbb9674af038c85c3ae5f6c603fc969bcbd3 Signed-off-by: Aditya Bavanari --- .../bindings/sound/qcom-audio-dev.txt | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index 6ca0b64acfe4..06880539a723 100644 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -237,6 +237,13 @@ Required properties: Value is from 45056 to 45061. VA codec dma port ID Value is from 45089 to 45091. +Optional properties: + +- qcom,msm-dai-is-island-supported: Defines whether this dai supported in + island mode or not. + 0 - Unsupported + 1 - Supported + * msm-auxpcm Required properties: @@ -303,6 +310,10 @@ Optional properties: interface to be used for enabling PCM clock. If not defined, selects default AFE clock interface. +- qcom,msm-dai-is-island-supported: Defines whether this dai supported in + island mode or not. + 0 - Unsupported + 1 - Supported * msm-pcm-hostless @@ -791,9 +802,13 @@ Required properties: Optional properties: -- pinctrl-names: Pinctrl state names for each pin group - configuration. -- pinctrl-x: Defines pinctrl state for each pin group +- pinctrl-names: Pinctrl state names for each pin group + configuration. +- pinctrl-x: Defines pinctrl state for each pin group +- qcom,msm-dai-is-island-supported: Defines whether this dai supported in + island mode or not. + 0 - Unsupported + 1 - Supported Example: @@ -977,6 +992,11 @@ Optional properties: - pinctrl-x: Defines pinctrl state for each pin group. + - qcom,msm-dai-is-island-supported: Defines whether this dai supported in + island mode or not. + 0 - Unsupported + 1 - Supported + Example: qcom,msm-dai-tdm-quat-rx { -- GitLab From 8c989f03c4ea2089d66abe4b2087e5b02dbdfd62 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Mon, 25 Jun 2018 15:57:11 +0530 Subject: [PATCH 0760/1299] ARM: dts: msm: Add device tree support for VAD in qcs405 Add island enabled flag for VAD supported DAIs in device tree for qcs405. CRs-Fixed: 2259784 Change-Id: I5d51c7b873c3ef56d717595d1dbd9e1d23ebf4f4 Signed-off-by: Aditya Bavanari --- arch/arm64/boot/dts/qcom/qcs405-audio.dtsi | 12 ++++++++++++ arch/arm64/boot/dts/qcom/qcs405-va-bolero.dtsi | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi b/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi index 26d43b6b20ea..6a8dd8ed7397 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi @@ -139,3 +139,15 @@ }; }; }; + +&dai_mi2s4 { + qcom,msm-dai-is-island-supported = <1>; +}; + +&dai_quin_auxpcm { + qcom,msm-dai-is-island-supported = <1>; +}; + +&dai_quin_tdm_tx_0 { + qcom,msm-dai-is-island-supported = <1>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-va-bolero.dtsi b/arch/arm64/boot/dts/qcom/qcs405-va-bolero.dtsi index 417784cea057..fface1992979 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-va-bolero.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-va-bolero.dtsi @@ -32,3 +32,7 @@ #clock-cells = <1>; }; }; + +&va_cdc_dma_0_tx { + qcom,msm-dai-is-island-supported = <1>; +}; -- GitLab From 1b0ac05a408dd86a146d9026cc652f647d8de104 Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Wed, 20 Jun 2018 17:12:10 -0700 Subject: [PATCH 0761/1299] ARM: dts: msm: add memory_region for qseecom on msmnile add memory_region for qseecom driver on msmnile; this will cause dma_alloc_coherent to return memory from qseecom_mem carveout. Change-Id: Iadbca994f9a081e3c0787e670dc146bec0b107f9 Signed-off-by: Zhen Kong --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index c5529cfd06d3..2d8652c02920 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -2845,6 +2845,7 @@ compatible = "qcom,qseecom"; reg = <0x87900000 0x2200000>; reg-names = "secapp-region"; + memory-region = <&qseecom_mem>; qcom,hlos-num-ce-hw-instances = <1>; qcom,hlos-ce-hw-instance = <0>; qcom,qsee-ce-hw-instance = <0>; -- GitLab From e53e7cab391f5eea288b0797e25f1ef567ffa07b Mon Sep 17 00:00:00 2001 From: Vijaykumar Badiger Date: Sat, 23 Jun 2018 05:20:34 -0700 Subject: [PATCH 0762/1299] ARM: dts: msm: fix machine display name The machine name was not getting shown properly due to duplicate names in the overlay file. Change-Id: I191d9e81814b3daff29c779dca2a1b0528127487 Signed-off-by: Vijaykumar Badiger --- arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts | 2 +- arch/arm64/boot/dts/qcom/sa8150.dtsi | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts b/arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts index 22af3db58f83..627e06a4d415 100644 --- a/arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts @@ -16,7 +16,7 @@ #include "sa8150-adp-star.dtsi" / { - model = "Qualcomm Technologies, Inc. SA8150 ADP-STAR"; + model = "ADP-STAR"; compatible = "qcom,sa8150-adp-star", "qcom,sa8150", "qcom,adp-star"; qcom,board-id = <25 0>; diff --git a/arch/arm64/boot/dts/qcom/sa8150.dtsi b/arch/arm64/boot/dts/qcom/sa8150.dtsi index d79e27f6c662..1208a338712d 100644 --- a/arch/arm64/boot/dts/qcom/sa8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8150.dtsi @@ -14,6 +14,7 @@ / { model = "Qualcomm Technologies, Inc. SA8150"; + compatible = "qcom,sa8150"; qcom,msm-name = "SA8150"; qcom,msm-id = <362 0x10000>; }; -- GitLab From 76b467c5cfad8ef263fdd9eaba86dc6cfe67c825 Mon Sep 17 00:00:00 2001 From: Vijaykumar Badiger Date: Fri, 22 Jun 2018 13:55:54 -0700 Subject: [PATCH 0763/1299] soc: qcom: Add support for sa8150p into socinfo driver Add sa8150p SOC information in socinfo driver. Change-Id: Ia0da2fccd9da9f5667ef20c2b0a1c297f674cd77 Signed-off-by: Vijaykumar Badiger --- drivers/soc/qcom/socinfo.c | 7 +++++++ include/soc/qcom/socinfo.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 0822f7148969..bd11f28cb4ae 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -310,6 +310,9 @@ static struct msm_soc_info cpu_of_id[] = { /* sa8150 ID */ [362] = {MSM_CPU_SA8150, "SA8150"}, + /* sa8150P ID */ + [367] = {MSM_CPU_SA8150P, "SA8150P"}, + /* sdmshrike ID */ [340] = {MSM_CPU_SDMSHRIKE, "SDMSHRIKE"}, @@ -1184,6 +1187,10 @@ static void * __init setup_dummy_socinfo(void) dummy_socinfo.id = 362; strlcpy(dummy_socinfo.build_id, "sa8150 - ", sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_sa8150p()) { + dummy_socinfo.id = 367; + strlcpy(dummy_socinfo.build_id, "sa8150p - ", + sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sdmshrike()) { dummy_socinfo.id = 340; strlcpy(dummy_socinfo.build_id, "sdmshrike - ", diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h index 267cfedb508c..0a67a9e13c22 100644 --- a/include/soc/qcom/socinfo.h +++ b/include/soc/qcom/socinfo.h @@ -61,6 +61,8 @@ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sm8150") #define early_machine_is_sa8150() \ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sa8150") +#define early_machine_is_sa8150p() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sa8150p") #define early_machine_is_sdmshrike() \ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdmshrike") #define early_machine_is_sm6150() \ @@ -91,6 +93,7 @@ #define early_machine_is_msm8996() 0 #define early_machine_is_sm8150() 0 #define early_machine_is_sa8150() 0 +#define early_machine_is_sa8150p() 0 #define early_machine_is_sdmshrike() 0 #define early_machine_is_sm6150() 0 #define early_machine_is_qcs405() 0 @@ -118,6 +121,7 @@ enum msm_cpu { MSM_CPU_8996, MSM_CPU_SM8150, MSM_CPU_SA8150, + MSM_CPU_SA8150P, MSM_CPU_SDMSHRIKE, MSM_CPU_SM6150, MSM_CPU_QCS405, -- GitLab From 269ece2489c9269acf0b1c6189b2faa0da4556e9 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Sat, 7 Apr 2018 16:42:36 -0700 Subject: [PATCH 0764/1299] msm: ipa: support ipacm cleanup Support header/filter, routing rules cleanup when user-space module crashed like ipacm and also cached the wlan client connect messages for ipacm to query. Change-Id: Ib09cbe0e9114aa5a5673898ff796de7e7944af35 Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_api.c | 100 +++++++++-- drivers/platform/msm/ipa/ipa_api.h | 17 +- drivers/platform/msm/ipa/ipa_common_i.h | 2 + drivers/platform/msm/ipa/ipa_v3/ipa.c | 73 +++++++- drivers/platform/msm/ipa/ipa_v3/ipa_flt.c | 83 ++++++--- drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c | 123 +++++++++---- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 37 +++- drivers/platform/msm/ipa/ipa_v3/ipa_intf.c | 164 ++++++++++++++++++ drivers/platform/msm/ipa/ipa_v3/ipa_nat.c | 6 - .../platform/msm/ipa/ipa_v3/ipa_qmi_service.c | 16 ++ drivers/platform/msm/ipa/ipa_v3/ipa_rt.c | 111 ++++++++---- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 3 + include/linux/ipa.h | 42 ++++- include/uapi/linux/msm_ipa.h | 14 +- 14 files changed, 635 insertions(+), 156 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c index e514979115d0..c96446343be9 100644 --- a/drivers/platform/msm/ipa/ipa_api.c +++ b/drivers/platform/msm/ipa/ipa_api.c @@ -703,6 +703,26 @@ int ipa_add_hdr(struct ipa_ioc_add_hdr *hdrs) } EXPORT_SYMBOL(ipa_add_hdr); +/** + * ipa_add_hdr_usr() - add the specified headers to SW and optionally + * commit them to IPA HW + * @hdrs: [inout] set of headers to add + * @user_only: [in] indicate rules installed by userspace + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only) +{ + int ret; + + IPA_API_DISPATCH_RETURN(ipa_add_hdr_usr, hdrs, user_only); + + return ret; +} +EXPORT_SYMBOL(ipa_add_hdr_usr); + /** * ipa_del_hdr() - Remove the specified headers from SW and optionally * commit them to IPA HW @@ -743,15 +763,16 @@ EXPORT_SYMBOL(ipa_commit_hdr); * ipa_reset_hdr() - reset the current header table in SW (does not commit to * HW) * + * @user_only: [in] indicate delete rules installed by userspace * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_reset_hdr(void) +int ipa_reset_hdr(bool user_only) { int ret; - IPA_API_DISPATCH_RETURN(ipa_reset_hdr); + IPA_API_DISPATCH_RETURN(ipa_reset_hdr, user_only); return ret; } @@ -821,16 +842,18 @@ EXPORT_SYMBOL(ipa_copy_hdr); * ipa_add_hdr_proc_ctx() - add the specified headers to SW * and optionally commit them to IPA HW * @proc_ctxs: [inout] set of processing context headers to add + * @user_only: [in] indicate rules installed by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) +int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only) { int ret; - IPA_API_DISPATCH_RETURN(ipa_add_hdr_proc_ctx, proc_ctxs); + IPA_API_DISPATCH_RETURN(ipa_add_hdr_proc_ctx, proc_ctxs, user_only); return ret; } @@ -875,6 +898,26 @@ int ipa_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) } EXPORT_SYMBOL(ipa_add_rt_rule); +/** + * ipa_add_rt_rule_usr() - Add the specified routing rules to SW and optionally + * commit to IPA HW + * @rules: [inout] set of routing rules to add + * @user_only: [in] indicate rules installed by userspace + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only) +{ + int ret; + + IPA_API_DISPATCH_RETURN(ipa_add_rt_rule_usr, rules, user_only); + + return ret; +} +EXPORT_SYMBOL(ipa_add_rt_rule_usr); + /** * ipa_del_rt_rule() - Remove the specified routing rules to SW and optionally * commit to IPA HW @@ -917,16 +960,17 @@ EXPORT_SYMBOL(ipa_commit_rt); * ipa_reset_rt() - reset the current SW routing table of specified type * (does not commit to HW) * @ip: The family of routing tables + * @user_only: [in] indicate delete rules installed by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_reset_rt(enum ipa_ip_type ip) +int ipa_reset_rt(enum ipa_ip_type ip, bool user_only) { int ret; - IPA_API_DISPATCH_RETURN(ipa_reset_rt, ip); + IPA_API_DISPATCH_RETURN(ipa_reset_rt, ip, user_only); return ret; } @@ -1009,6 +1053,7 @@ EXPORT_SYMBOL(ipa_mdfy_rt_rule); /** * ipa_add_flt_rule() - Add the specified filtering rules to SW and optionally * commit to IPA HW + * @rules: [inout] set of filtering rules to add * * Returns: 0 on success, negative on failure * @@ -1024,6 +1069,26 @@ int ipa_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) } EXPORT_SYMBOL(ipa_add_flt_rule); +/** + * ipa_add_flt_rule_usr() - Add the specified filtering rules to + * SW and optionally commit to IPA HW + * @rules: [inout] set of filtering rules to add + * @user_only: [in] indicate rules installed by userspace + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only) +{ + int ret; + + IPA_API_DISPATCH_RETURN(ipa_add_flt_rule_usr, rules, user_only); + + return ret; +} +EXPORT_SYMBOL(ipa_add_flt_rule_usr); + /** * ipa_del_flt_rule() - Remove the specified filtering rules from SW and * optionally commit to IPA HW @@ -1082,17 +1147,18 @@ EXPORT_SYMBOL(ipa_commit_flt); /** * ipa_reset_flt() - Reset the current SW filtering table of specified type * (does not commit to HW) - * @ip: [in] the family of routing tables + * @ip: [in] the family of routing tables + * @user_only: [in] indicate delete rules installed by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_reset_flt(enum ipa_ip_type ip) +int ipa_reset_flt(enum ipa_ip_type ip, bool user_only) { int ret; - IPA_API_DISPATCH_RETURN(ipa_reset_flt, ip); + IPA_API_DISPATCH_RETURN(ipa_reset_flt, ip, user_only); return ret; } @@ -2732,14 +2798,14 @@ int ipa_start_gsi_channel(u32 clnt_hdl) EXPORT_SYMBOL(ipa_start_gsi_channel); /** -* ipa_is_vlan_mode - check if a LAN driver should load in VLAN mode -* @iface - type of vlan capable device -* @res - query result: true for vlan mode, false for non vlan mode -* -* API must be called after ipa_is_ready() returns true, otherwise it will fail -* -* Returns: 0 on success, negative on failure -*/ + * ipa_is_vlan_mode - check if a LAN driver should load in VLAN mode + * @iface - type of vlan capable device + * @res - query result: true for vlan mode, false for non vlan mode + * + * API must be called after ipa_is_ready() returns true, otherwise it will fail + * + * Returns: 0 on success, negative on failure + */ int ipa_is_vlan_mode(enum ipa_vlan_ifaces iface, bool *res) { int ret; diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h index f0541e62d040..8185dfd8ac34 100644 --- a/drivers/platform/msm/ipa/ipa_api.h +++ b/drivers/platform/msm/ipa/ipa_api.h @@ -68,11 +68,13 @@ struct ipa_api_controller { int (*ipa_add_hdr)(struct ipa_ioc_add_hdr *hdrs); + int (*ipa_add_hdr_usr)(struct ipa_ioc_add_hdr *hdrs, bool user_only); + int (*ipa_del_hdr)(struct ipa_ioc_del_hdr *hdls); int (*ipa_commit_hdr)(void); - int (*ipa_reset_hdr)(void); + int (*ipa_reset_hdr)(bool user_only); int (*ipa_get_hdr)(struct ipa_ioc_get_hdr *lookup); @@ -80,17 +82,21 @@ struct ipa_api_controller { int (*ipa_copy_hdr)(struct ipa_ioc_copy_hdr *copy); - int (*ipa_add_hdr_proc_ctx)(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs); + int (*ipa_add_hdr_proc_ctx)(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only); int (*ipa_del_hdr_proc_ctx)(struct ipa_ioc_del_hdr_proc_ctx *hdls); int (*ipa_add_rt_rule)(struct ipa_ioc_add_rt_rule *rules); + int (*ipa_add_rt_rule_usr)(struct ipa_ioc_add_rt_rule *rules, + bool user_only); + int (*ipa_del_rt_rule)(struct ipa_ioc_del_rt_rule *hdls); int (*ipa_commit_rt)(enum ipa_ip_type ip); - int (*ipa_reset_rt)(enum ipa_ip_type ip); + int (*ipa_reset_rt)(enum ipa_ip_type ip, bool user_only); int (*ipa_get_rt_tbl)(struct ipa_ioc_get_rt_tbl *lookup); @@ -102,13 +108,16 @@ struct ipa_api_controller { int (*ipa_add_flt_rule)(struct ipa_ioc_add_flt_rule *rules); + int (*ipa_add_flt_rule_usr)(struct ipa_ioc_add_flt_rule *rules, + bool user_only); + int (*ipa_del_flt_rule)(struct ipa_ioc_del_flt_rule *hdls); int (*ipa_mdfy_flt_rule)(struct ipa_ioc_mdfy_flt_rule *rules); int (*ipa_commit_flt)(enum ipa_ip_type ip); - int (*ipa_reset_flt)(enum ipa_ip_type ip); + int (*ipa_reset_flt)(enum ipa_ip_type ip, bool user_only); int (*ipa_allocate_nat_device)(struct ipa_ioc_nat_alloc_mem *mem); diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h index 92f1ab65b70f..b8a517ee27ce 100644 --- a/drivers/platform/msm/ipa/ipa_common_i.h +++ b/drivers/platform/msm/ipa/ipa_common_i.h @@ -333,11 +333,13 @@ struct ipa_mhi_connect_params_internal { * @link: entry's link in global header offset entries list * @offset: the offset * @bin: bin + * @ipacm_installed: indicate if installed by ipacm */ struct ipa_hdr_offset_entry { struct list_head link; u32 offset; u32 bin; + bool ipacm_installed; }; extern const char *ipa_clients_strings[]; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 771654d6aa5d..bd6de9cc6846 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -369,6 +369,43 @@ int ipa3_active_clients_log_print_table(char *buf, int size) return cnt; } +static int ipa3_clean_modem_rule(void) +{ + struct ipa_install_fltr_rule_req_msg_v01 *req; + struct ipa_install_fltr_rule_req_ex_msg_v01 *req_ex; + int val = 0; + + if (ipa3_ctx->ipa_hw_type < IPA_HW_v3_0) { + req = kzalloc( + sizeof(struct ipa_install_fltr_rule_req_msg_v01), + GFP_KERNEL); + if (!req) { + IPAERR("mem allocated failed!\n"); + return -ENOMEM; + } + req->filter_spec_list_valid = false; + req->filter_spec_list_len = 0; + req->source_pipe_index_valid = 0; + val = ipa3_qmi_filter_request_send(req); + kfree(req); + } else { + req_ex = kzalloc( + sizeof(struct ipa_install_fltr_rule_req_ex_msg_v01), + GFP_KERNEL); + if (!req_ex) { + IPAERR("mem allocated failed!\n"); + return -ENOMEM; + } + req_ex->filter_spec_ex_list_valid = false; + req_ex->filter_spec_ex_list_len = 0; + req_ex->source_pipe_index_valid = 0; + val = ipa3_qmi_filter_request_ex_send(req_ex); + kfree(req_ex); + } + + return val; +} + static int ipa3_active_clients_panic_notifier(struct notifier_block *this, unsigned long event, void *ptr) { @@ -941,7 +978,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa3_add_hdr((struct ipa_ioc_add_hdr *)param)) { + if (ipa3_add_hdr_usr((struct ipa_ioc_add_hdr *)param, + true)) { retval = -EFAULT; break; } @@ -1021,7 +1059,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa3_add_rt_rule((struct ipa_ioc_add_rt_rule *)param)) { + if (ipa3_add_rt_rule_usr((struct ipa_ioc_add_rt_rule *)param, + true)) { retval = -EFAULT; break; } @@ -1225,7 +1264,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa3_add_flt_rule((struct ipa_ioc_add_flt_rule *)param)) { + if (ipa3_add_flt_rule_usr((struct ipa_ioc_add_flt_rule *)param, + true)) { retval = -EFAULT; break; } @@ -1362,19 +1402,19 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = ipa3_commit_hdr(); break; case IPA_IOC_RESET_HDR: - retval = ipa3_reset_hdr(); + retval = ipa3_reset_hdr(false); break; case IPA_IOC_COMMIT_RT: retval = ipa3_commit_rt(arg); break; case IPA_IOC_RESET_RT: - retval = ipa3_reset_rt(arg); + retval = ipa3_reset_rt(arg, false); break; case IPA_IOC_COMMIT_FLT: retval = ipa3_commit_flt(arg); break; case IPA_IOC_RESET_FLT: - retval = ipa3_reset_flt(arg); + retval = ipa3_reset_flt(arg, false); break; case IPA_IOC_GET_RT_TBL: if (copy_from_user(header, (const void __user *)arg, @@ -1762,7 +1802,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } if (ipa3_add_hdr_proc_ctx( - (struct ipa_ioc_add_hdr_proc_ctx *)param)) { + (struct ipa_ioc_add_hdr_proc_ctx *)param, true)) { retval = -EFAULT; break; } @@ -1887,6 +1927,21 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } break; + case IPA_IOC_CLEANUP: + /*Route and filter rules will also be clean*/ + IPADBG("Got IPA_IOC_CLEANUP\n"); + retval = ipa3_reset_hdr(true); + memset(&nat_del, 0, sizeof(nat_del)); + nat_del.table_index = 0; + retval = ipa3_nat_del_cmd(&nat_del); + retval = ipa3_clean_modem_rule(); + break; + + case IPA_IOC_QUERY_WLAN_CLIENT: + IPADBG("Got IPA_IOC_QUERY_WLAN_CLIENT\n"); + retval = ipa3_resend_wlan_msg(); + break; + default: IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); return -ENOTTY; @@ -5381,6 +5436,10 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, init_waitqueue_head(&ipa3_ctx->msg_waitq); mutex_init(&ipa3_ctx->msg_lock); + /* store wlan client-connect-msg-list */ + INIT_LIST_HEAD(&ipa3_ctx->msg_wlan_client_list); + mutex_init(&ipa3_ctx->msg_wlan_client_lock); + mutex_init(&ipa3_ctx->lock); mutex_init(&ipa3_ctx->q6_proxy_clk_vote_mutex); mutex_init(&ipa3_ctx->ipa_cne_evt_lock); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c index 0bc77b55be17..28b8ec466869 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c @@ -833,7 +833,7 @@ static int __ipa_validate_flt_rule(const struct ipa_flt_rule *rule, static int __ipa_create_flt_entry(struct ipa3_flt_entry **entry, const struct ipa_flt_rule *rule, struct ipa3_rt_tbl *rt_tbl, - struct ipa3_flt_tbl *tbl) + struct ipa3_flt_tbl *tbl, bool user) { int id; @@ -856,6 +856,7 @@ static int __ipa_create_flt_entry(struct ipa3_flt_entry **entry, } } (*entry)->rule_id = id; + (*entry)->ipacm_installed = user; return 0; @@ -893,7 +894,7 @@ static int __ipa_finish_flt_rule_add(struct ipa3_flt_tbl *tbl, static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip, const struct ipa_flt_rule *rule, u8 add_rear, - u32 *rule_hdl) + u32 *rule_hdl, bool user) { struct ipa3_flt_entry *entry; struct ipa3_rt_tbl *rt_tbl = NULL; @@ -901,7 +902,7 @@ static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip, if (__ipa_validate_flt_rule(rule, &rt_tbl, ip)) goto error; - if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl)) + if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl, user)) goto error; if (add_rear) { @@ -951,7 +952,7 @@ static int __ipa_add_flt_rule_after(struct ipa3_flt_tbl *tbl, if (__ipa_validate_flt_rule(rule, &rt_tbl, ip)) goto error; - if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl)) + if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl, true)) goto error; list_add(&entry->link, &((*add_after_entry)->link)); @@ -1072,7 +1073,7 @@ static int __ipa_add_flt_get_ep_idx(enum ipa_client_type ep, int *ipa_ep_idx) static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep, const struct ipa_flt_rule *rule, u8 add_rear, - u32 *rule_hdl) + u32 *rule_hdl, bool user) { struct ipa3_flt_tbl *tbl; int ipa_ep_idx; @@ -1090,18 +1091,34 @@ static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep, tbl = &ipa3_ctx->flt_tbl[ipa_ep_idx][ip]; IPADBG_LOW("add ep flt rule ip=%d ep=%d\n", ip, ep); - return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl); + return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl, user); } /** * ipa3_add_flt_rule() - Add the specified filtering rules to SW and optionally * commit to IPA HW + * @rules: [inout] set of filtering rules to add * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) +{ + return ipa3_add_flt_rule_usr(rules, false); +} + +/** + * ipa3_add_flt_rule_usr() - Add the specified filtering rules to + * SW and optionally commit to IPA HW + * @rules: [inout] set of filtering rules to add + * @user_only: [in] indicate rules installed by userspace + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa3_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only) { int i; int result; @@ -1120,12 +1137,14 @@ int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) */ if (ipa3_ctx->ipa_fltrt_not_hashable) rules->rules[i].rule.hashable = false; - result = __ipa_add_ep_flt_rule(rules->ip, rules->ep, + result = __ipa_add_ep_flt_rule(rules->ip, + rules->ep, &rules->rules[i].rule, rules->rules[i].at_rear, - &rules->rules[i].flt_rule_hdl); - } else - result = -1; + &rules->rules[i].flt_rule_hdl, + user_only); + } else + result = -1; if (result) { IPAERR_RL("failed to add flt rule %d\n", i); @@ -1376,18 +1395,20 @@ int ipa3_commit_flt(enum ipa_ip_type ip) * ipa3_reset_flt() - Reset the current SW filtering table of specified type * (does not commit to HW) * @ip: [in] the family of routing tables + * @user_only: [in] indicate rules deleted by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa3_reset_flt(enum ipa_ip_type ip) +int ipa3_reset_flt(enum ipa_ip_type ip, bool user_only) { struct ipa3_flt_tbl *tbl; struct ipa3_flt_entry *entry; struct ipa3_flt_entry *next; int i; int id; + int rule_id; if (ip >= IPA_IP_MAX) { IPAERR_RL("bad parm\n"); @@ -1407,21 +1428,27 @@ int ipa3_reset_flt(enum ipa_ip_type ip) mutex_unlock(&ipa3_ctx->lock); return -EFAULT; } - list_del(&entry->link); - entry->tbl->rule_cnt--; - if (entry->rt_tbl) - entry->rt_tbl->ref_cnt--; - /* if rule id was allocated from idr, remove it */ - if ((entry->rule_id < ipahal_get_rule_id_hi_bit()) && - (entry->rule_id >= ipahal_get_low_rule_id())) - idr_remove(entry->tbl->rule_ids, - entry->rule_id); - entry->cookie = 0; - id = entry->id; - kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); - - /* remove the handle from the database */ - ipa3_id_remove(id); + + if (!user_only || + entry->ipacm_installed) { + list_del(&entry->link); + entry->tbl->rule_cnt--; + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + /* if rule id was allocated from idr, remove */ + rule_id = entry->rule_id; + id = entry->id; + if ((rule_id < ipahal_get_rule_id_hi_bit()) && + (rule_id >= ipahal_get_low_rule_id())) + idr_remove(entry->tbl->rule_ids, + rule_id); + entry->cookie = 0; + kmem_cache_free(ipa3_ctx->flt_rule_cache, + entry); + + /* remove the handle from the database */ + ipa3_id_remove(id); + } } } mutex_unlock(&ipa3_ctx->lock); @@ -1447,14 +1474,14 @@ void ipa3_install_dflt_flt_rules(u32 ipa_ep_idx) tbl = &ipa3_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v4]; rule.action = IPA_PASS_TO_EXCEPTION; __ipa_add_flt_rule(tbl, IPA_IP_v4, &rule, true, - &ep->dflt_flt4_rule_hdl); + &ep->dflt_flt4_rule_hdl, false); ipa3_ctx->ctrl->ipa3_commit_flt(IPA_IP_v4); tbl->sticky_rear = true; tbl = &ipa3_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v6]; rule.action = IPA_PASS_TO_EXCEPTION; __ipa_add_flt_rule(tbl, IPA_IP_v6, &rule, true, - &ep->dflt_flt6_rule_hdl); + &ep->dflt_flt6_rule_hdl, false); ipa3_ctx->ctrl->ipa3_commit_flt(IPA_IP_v6); tbl->sticky_rear = true; mutex_unlock(&ipa3_ctx->lock); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index 7f4282a30ac8..0a165957073d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -321,7 +321,7 @@ int __ipa_commit_hdr_v3_0(void) } static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, - bool add_ref_hdr) + bool add_ref_hdr, bool user_only) { struct ipa3_hdr_entry *hdr_entry; struct ipa3_hdr_proc_ctx_entry *entry; @@ -367,6 +367,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, if (add_ref_hdr) hdr_entry->ref_cnt++; entry->cookie = IPA_PROC_HDR_COOKIE; + entry->ipacm_installed = user_only; needed_len = ipahal_get_proc_ctx_needed_len(proc_ctx->type); @@ -403,6 +404,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, */ offset->offset = htbl->end; offset->bin = bin; + offset->ipacm_installed = user_only; htbl->end += ipa_hdr_proc_ctx_bin_sz[bin]; list_add(&offset->link, &htbl->head_offset_list[bin]); @@ -411,6 +413,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, offset = list_first_entry(&htbl->head_free_offset_list[bin], struct ipa3_hdr_proc_ctx_offset_entry, link); + offset->ipacm_installed = user_only; list_move(&offset->link, &htbl->head_offset_list[bin]); } @@ -448,7 +451,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, } -static int __ipa_add_hdr(struct ipa_hdr_add *hdr) +static int __ipa_add_hdr(struct ipa_hdr_add *hdr, bool user) { struct ipa3_hdr_entry *entry; struct ipa_hdr_offset_entry *offset = NULL; @@ -481,6 +484,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid; entry->eth2_ofst = hdr->eth2_ofst; entry->cookie = IPA_HDR_COOKIE; + entry->ipacm_installed = user; if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0]) bin = IPA_HDR_BIN0; @@ -532,6 +536,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) list_add(&offset->link, &htbl->head_offset_list[bin]); entry->offset_entry = offset; + offset->ipacm_installed = user; } } else { entry->is_hdr_proc_ctx = false; @@ -540,6 +545,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) struct ipa_hdr_offset_entry, link); list_move(&offset->link, &htbl->head_offset_list[bin]); entry->offset_entry = offset; + offset->ipacm_installed = user; } list_add(&entry->link, &htbl->head_hdr_entry_list); @@ -571,7 +577,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) IPADBG("adding processing context for header %s\n", hdr->name); proc_ctx.type = IPA_HDR_PROC_NONE; proc_ctx.hdr_hdl = id; - if (__ipa_add_hdr_proc_ctx(&proc_ctx, false)) { + if (__ipa_add_hdr_proc_ctx(&proc_ctx, false, user)) { IPAERR("failed to add hdr proc ctx\n"); goto fail_add_proc_ctx; } @@ -732,6 +738,21 @@ int __ipa3_del_hdr(u32 hdr_hdl, bool by_user) * Note: Should not be called from atomic context */ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs) +{ + return ipa3_add_hdr_usr(hdrs, false); +} + +/** + * ipa3_add_hdr_usr() - add the specified headers to SW + * and optionally commit them to IPA HW + * @hdrs: [inout] set of headers to add + * @user_only: [in] indicate installed from user + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa3_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only) { int i; int result = -EFAULT; @@ -745,7 +766,7 @@ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs) IPADBG("adding %d headers to IPA driver internal data struct\n", hdrs->num_hdrs); for (i = 0; i < hdrs->num_hdrs; i++) { - if (__ipa_add_hdr(&hdrs->hdr[i])) { + if (__ipa_add_hdr(&hdrs->hdr[i], user_only)) { IPAERR_RL("failed to add hdr %d\n", i); hdrs->hdr[i].status = -1; } else { @@ -826,12 +847,14 @@ int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls) * ipa3_add_hdr_proc_ctx() - add the specified headers to SW * and optionally commit them to IPA HW * @proc_ctxs: [inout] set of processing context headers to add + * @user_only: [in] indicate installed by user-space module * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) +int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only) { int i; int result = -EFAULT; @@ -845,7 +868,8 @@ int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) IPADBG("adding %d header processing contextes to IPA driver\n", proc_ctxs->num_proc_ctxs); for (i = 0; i < proc_ctxs->num_proc_ctxs; i++) { - if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], true)) { + if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], + true, user_only)) { IPAERR_RL("failed to add hdr pric ctx %d\n", i); proc_ctxs->proc_ctx[i].status = -1; } else { @@ -960,11 +984,12 @@ int ipa3_commit_hdr(void) * ipa3_reset_hdr() - reset the current header table in SW (does not commit to * HW) * + * @user_only: [in] indicate delete rules installed by userspace * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa3_reset_hdr(void) +int ipa3_reset_hdr(bool user_only) { struct ipa3_hdr_entry *entry; struct ipa3_hdr_entry *next; @@ -980,9 +1005,9 @@ int ipa3_reset_hdr(void) * issue a reset on the routing module since routing rules point to * header table entries */ - if (ipa3_reset_rt(IPA_IP_v4)) + if (ipa3_reset_rt(IPA_IP_v4, user_only)) IPAERR("fail to reset v4 rt\n"); - if (ipa3_reset_rt(IPA_IP_v6)) + if (ipa3_reset_rt(IPA_IP_v6, user_only)) IPAERR("fail to reset v4 rt\n"); mutex_lock(&ipa3_ctx->lock); @@ -1011,21 +1036,23 @@ int ipa3_reset_hdr(void) WARN_ON_RATELIMIT_IPA(1); return -EFAULT; } - if (entry->is_hdr_proc_ctx) { - dma_unmap_single(ipa3_ctx->pdev, - entry->phys_base, - entry->hdr_len, - DMA_TO_DEVICE); - entry->proc_ctx = NULL; - } - list_del(&entry->link); - entry->ref_cnt = 0; - entry->cookie = 0; - /* remove the handle from the database */ - ipa3_id_remove(entry->id); - kmem_cache_free(ipa3_ctx->hdr_cache, entry); + if (!user_only || entry->ipacm_installed) { + if (entry->is_hdr_proc_ctx) { + dma_unmap_single(ipa3_ctx->pdev, + entry->phys_base, + entry->hdr_len, + DMA_TO_DEVICE); + entry->proc_ctx = NULL; + } + list_del(&entry->link); + entry->ref_cnt = 0; + entry->cookie = 0; + /* remove the handle from the database */ + ipa3_id_remove(entry->id); + kmem_cache_free(ipa3_ctx->hdr_cache, entry); + } } for (i = 0; i < IPA_HDR_BIN_MAX; i++) { list_for_each_entry_safe(off_entry, off_next, @@ -1039,14 +1066,23 @@ int ipa3_reset_hdr(void) if (off_entry->offset == 0) continue; - list_del(&off_entry->link); - kmem_cache_free(ipa3_ctx->hdr_offset_cache, off_entry); + if (!user_only || + off_entry->ipacm_installed) { + list_del(&off_entry->link); + kmem_cache_free(ipa3_ctx->hdr_offset_cache, + off_entry); + } } list_for_each_entry_safe(off_entry, off_next, &ipa3_ctx->hdr_tbl.head_free_offset_list[i], link) { - list_del(&off_entry->link); - kmem_cache_free(ipa3_ctx->hdr_offset_cache, off_entry); + + if (!user_only || + off_entry->ipacm_installed) { + list_del(&off_entry->link); + kmem_cache_free(ipa3_ctx->hdr_offset_cache, + off_entry); + } } } /* there is one header of size 8 */ @@ -1065,30 +1101,43 @@ int ipa3_reset_hdr(void) WARN_ON_RATELIMIT_IPA(1); return -EFAULT; } - list_del(&ctx_entry->link); - ctx_entry->ref_cnt = 0; - ctx_entry->cookie = 0; - /* remove the handle from the database */ - ipa3_id_remove(ctx_entry->id); - kmem_cache_free(ipa3_ctx->hdr_proc_ctx_cache, ctx_entry); + if (!user_only || + ctx_entry->ipacm_installed) { + list_del(&ctx_entry->link); + ctx_entry->ref_cnt = 0; + ctx_entry->cookie = 0; + /* remove the handle from the database */ + ipa3_id_remove(ctx_entry->id); + kmem_cache_free(ipa3_ctx->hdr_proc_ctx_cache, + ctx_entry); + } } for (i = 0; i < IPA_HDR_PROC_CTX_BIN_MAX; i++) { list_for_each_entry_safe(ctx_off_entry, ctx_off_next, &ipa3_ctx->hdr_proc_ctx_tbl.head_offset_list[i], link) { - list_del(&ctx_off_entry->link); - kmem_cache_free(ipa3_ctx->hdr_proc_ctx_offset_cache, + if (!user_only || + ctx_off_entry->ipacm_installed) { + list_del(&ctx_off_entry->link); + kmem_cache_free( + ipa3_ctx->hdr_proc_ctx_offset_cache, ctx_off_entry); + } } list_for_each_entry_safe(ctx_off_entry, ctx_off_next, &ipa3_ctx->hdr_proc_ctx_tbl.head_free_offset_list[i], link) { - list_del(&ctx_off_entry->link); - kmem_cache_free(ipa3_ctx->hdr_proc_ctx_offset_cache, - ctx_off_entry); + + if (!user_only || + ctx_off_entry->ipacm_installed) { + list_del(&ctx_off_entry->link); + kmem_cache_free( + ipa3_ctx->hdr_proc_ctx_offset_cache, + ctx_off_entry); + } } } ipa3_ctx->hdr_proc_ctx_tbl.end = 0; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index c71d9448186d..4bba8e7b0a20 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -264,6 +264,7 @@ struct ipa_smmu_cb_ctx { * @prio: rule 10bit priority which defines the order of the rule * among other rules at the same integrated table * @rule_id: rule 10bit ID to be returned in packet status + * @ipacm_installed: indicate if installed by ipacm */ struct ipa3_flt_entry { struct list_head link; @@ -275,6 +276,7 @@ struct ipa3_flt_entry { int id; u16 prio; u16 rule_id; + bool ipacm_installed; }; /** @@ -331,6 +333,7 @@ struct ipa3_rt_tbl { * @is_eth2_ofst_valid: is eth2_ofst field valid? * @eth2_ofst: offset to start of Ethernet-II/802.3 header * @user_deleted: is the header deleted by the user? + * @ipacm_installed: indicate if installed by ipacm */ struct ipa3_hdr_entry { struct list_head link; @@ -349,6 +352,7 @@ struct ipa3_hdr_entry { u8 is_eth2_ofst_valid; u16 eth2_ofst; bool user_deleted; + bool ipacm_installed; }; /** @@ -372,11 +376,13 @@ struct ipa3_hdr_tbl { * @link: entry's link in global processing context header offset entries list * @offset: the offset * @bin: bin + * @ipacm_installed: indicate if installed by ipacm */ struct ipa3_hdr_proc_ctx_offset_entry { struct list_head link; u32 offset; u32 bin; + bool ipacm_installed; }; /** @@ -390,6 +396,7 @@ struct ipa3_hdr_proc_ctx_offset_entry { * @ref_cnt: reference counter of routing table * @id: processing context header entry id * @user_deleted: is the hdr processing context deleted by the user? + * @ipacm_installed: indicate if installed by ipacm */ struct ipa3_hdr_proc_ctx_entry { struct list_head link; @@ -401,6 +408,7 @@ struct ipa3_hdr_proc_ctx_entry { u32 ref_cnt; int id; bool user_deleted; + bool ipacm_installed; }; /** @@ -456,6 +464,8 @@ struct ipa3_flt_tbl { * @prio: rule 10bit priority which defines the order of the rule * among other rules at the integrated same table * @rule_id: rule 10bit ID to be returned in packet status + * @rule_id_valid: indicate if rule_id_valid valid or not? + * @ipacm_installed: indicate if installed by ipacm */ struct ipa3_rt_entry { struct list_head link; @@ -469,6 +479,7 @@ struct ipa3_rt_entry { u16 prio; u16 rule_id; u16 rule_id_valid; + bool ipacm_installed; }; /** @@ -910,9 +921,9 @@ struct ipa3_nat_mem { }; /** -* struct ipa3_ipv6ct_mem - IPA IPv6 connection tracking memory description -* @dev: the memory device structure -*/ + * struct ipa3_ipv6ct_mem - IPA IPv6 connection tracking memory description + * @dev: the memory device structure + */ struct ipa3_ipv6ct_mem { struct ipa3_nat_ipv6ct_common_mem dev; }; @@ -1360,6 +1371,8 @@ struct ipa3_context { struct list_head msg_list; struct list_head pull_msg_list; struct mutex msg_lock; + struct list_head msg_wlan_client_list; + struct mutex msg_wlan_client_lock; wait_queue_head_t msg_waitq; enum ipa_hw_type ipa_hw_type; enum ipa3_hw_mode ipa3_hw_mode; @@ -1797,13 +1810,15 @@ int ipa3_cfg_ep_ctrl(u32 clnt_hdl, const struct ipa_ep_cfg_ctrl *ep_ctrl); */ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs); +int ipa3_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool by_user); + int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls); int ipa3_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user); int ipa3_commit_hdr(void); -int ipa3_reset_hdr(void); +int ipa3_reset_hdr(bool user_only); int ipa3_get_hdr(struct ipa_ioc_get_hdr *lookup); @@ -1814,7 +1829,8 @@ int ipa3_copy_hdr(struct ipa_ioc_copy_hdr *copy); /* * Header Processing Context */ -int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs); +int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only); int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls); @@ -1826,6 +1842,9 @@ int ipa3_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, */ int ipa3_add_rt_rule(struct ipa_ioc_add_rt_rule *rules); +int ipa3_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, + bool user_only); + int ipa3_add_rt_rule_ext(struct ipa_ioc_add_rt_rule_ext *rules); int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules); @@ -1834,7 +1853,7 @@ int ipa3_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls); int ipa3_commit_rt(enum ipa_ip_type ip); -int ipa3_reset_rt(enum ipa_ip_type ip); +int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only); int ipa3_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup); @@ -1849,6 +1868,9 @@ int ipa3_mdfy_rt_rule(struct ipa_ioc_mdfy_rt_rule *rules); */ int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules); +int ipa3_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, + bool user_only); + int ipa3_add_flt_rule_after(struct ipa_ioc_add_flt_rule_after *rules); int ipa3_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls); @@ -1857,7 +1879,7 @@ int ipa3_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *rules); int ipa3_commit_flt(enum ipa_ip_type ip); -int ipa3_reset_flt(enum ipa_ip_type ip); +int ipa3_reset_flt(enum ipa_ip_type ip, bool user_only); /* * NAT @@ -1888,6 +1910,7 @@ int ipa3_nat_mdfy_pdn(struct ipa_ioc_nat_pdn_entry *mdfy_pdn); */ int ipa3_send_msg(struct ipa_msg_meta *meta, void *buff, ipa_msg_free_fn callback); +int ipa3_resend_wlan_msg(void); int ipa3_register_pull_msg(struct ipa_msg_meta *meta, ipa_msg_pull_fn callback); int ipa3_deregister_pull_msg(struct ipa_msg_meta *meta); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c index ff804294520b..72b5a21c9e15 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c @@ -14,6 +14,7 @@ #include #include #include "ipa_i.h" +#include struct ipa3_intf { char name[IPA_RESOURCE_NAME_MAX]; @@ -386,6 +387,105 @@ static void ipa3_send_msg_free(void *buff, u32 len, u32 type) kfree(buff); } +static int wlan_msg_process(struct ipa_msg_meta *meta, void *buff) +{ + struct ipa3_push_msg *msg_dup; + struct ipa_wlan_msg_ex *event_ex_cur_con = NULL; + struct ipa_wlan_msg_ex *event_ex_list = NULL; + struct ipa_wlan_msg *event_ex_cur_discon = NULL; + void *data_dup = NULL; + struct ipa3_push_msg *entry; + struct ipa3_push_msg *next; + int cnt = 0, total = 0, max = 0; + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint8_t mac2[IPA_MAC_ADDR_SIZE]; + + if (meta->msg_type == WLAN_CLIENT_CONNECT_EX) { + /* debug print */ + event_ex_cur_con = buff; + for (cnt = 0; cnt < event_ex_cur_con->num_of_attribs; cnt++) { + if (event_ex_cur_con->attribs[cnt].attrib_type == + WLAN_HDR_ATTRIB_MAC_ADDR) { + IPADBG("%02x:%02x:%02x:%02x:%02x:%02x,(%d)\n", + event_ex_cur_con->attribs[cnt].u.mac_addr[0], + event_ex_cur_con->attribs[cnt].u.mac_addr[1], + event_ex_cur_con->attribs[cnt].u.mac_addr[2], + event_ex_cur_con->attribs[cnt].u.mac_addr[3], + event_ex_cur_con->attribs[cnt].u.mac_addr[4], + event_ex_cur_con->attribs[cnt].u.mac_addr[5], + meta->msg_type); + } + } + + mutex_lock(&ipa3_ctx->msg_wlan_client_lock); + msg_dup = kzalloc(sizeof(*msg_dup), GFP_KERNEL); + if (msg_dup == NULL) { + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + return -ENOMEM; + } + msg_dup->meta = *meta; + if (meta->msg_len > 0 && buff) { + data_dup = kmalloc(meta->msg_len, GFP_KERNEL); + if (data_dup == NULL) { + kfree(msg_dup); + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + return -ENOMEM; + } + memcpy(data_dup, buff, meta->msg_len); + msg_dup->buff = data_dup; + msg_dup->callback = ipa3_send_msg_free; + } else { + IPAERR("msg_len %d\n", meta->msg_len); + kfree(msg_dup); + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + return -ENOMEM; + } + list_add_tail(&msg_dup->link, &ipa3_ctx->msg_wlan_client_list); + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + } + + /* remove the cache */ + if (meta->msg_type == WLAN_CLIENT_DISCONNECT) { + /* debug print */ + event_ex_cur_discon = buff; + IPADBG("Mac %pM, msg %d\n", + event_ex_cur_discon->mac_addr, + meta->msg_type); + memcpy(mac2, + event_ex_cur_discon->mac_addr, + sizeof(mac2)); + + mutex_lock(&ipa3_ctx->msg_wlan_client_lock); + list_for_each_entry_safe(entry, next, + &ipa3_ctx->msg_wlan_client_list, + link) { + event_ex_list = entry->buff; + max = event_ex_list->num_of_attribs; + for (cnt = 0; cnt < max; cnt++) { + memcpy(mac, + event_ex_list->attribs[cnt].u.mac_addr, + sizeof(mac)); + if (event_ex_list->attribs[cnt].attrib_type == + WLAN_HDR_ATTRIB_MAC_ADDR) { + pr_debug("%pM\n", mac); + + /* compare to delete one*/ + if (memcmp(mac2, mac, + sizeof(mac)) == 0) { + IPADBG("clean %d\n", total); + list_del(&entry->link); + kfree(entry); + break; + } + } + } + total++; + } + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + } + return 0; +} + /** * ipa3_send_msg() - Send "message" from kernel client to IPA driver * @meta: [in] message meta-data @@ -437,6 +537,11 @@ int ipa3_send_msg(struct ipa_msg_meta *meta, void *buff, mutex_lock(&ipa3_ctx->msg_lock); list_add_tail(&msg->link, &ipa3_ctx->msg_list); + /* support for softap client event cache */ + if (wlan_msg_process(meta, buff)) + IPAERR("wlan_msg_process failed\n"); + + /* unlock only after process */ mutex_unlock(&ipa3_ctx->msg_lock); IPA_STATS_INC_CNT(ipa3_ctx->stats.msg_w[meta->msg_type]); @@ -447,6 +552,65 @@ int ipa3_send_msg(struct ipa_msg_meta *meta, void *buff, return 0; } +/** + * ipa3_resend_wlan_msg() - Resend cached "message" to IPACM + * + * resend wlan client connect events to user-space + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa3_resend_wlan_msg(void) +{ + struct ipa_wlan_msg_ex *event_ex_list = NULL; + struct ipa3_push_msg *entry; + struct ipa3_push_msg *next; + int cnt = 0, total = 0; + struct ipa3_push_msg *msg; + void *data = NULL; + + IPADBG("\n"); + + mutex_lock(&ipa3_ctx->msg_wlan_client_lock); + list_for_each_entry_safe(entry, next, &ipa3_ctx->msg_wlan_client_list, + link) { + + event_ex_list = entry->buff; + for (cnt = 0; cnt < event_ex_list->num_of_attribs; cnt++) { + if (event_ex_list->attribs[cnt].attrib_type == + WLAN_HDR_ATTRIB_MAC_ADDR) { + IPADBG("%d-Mac %pM\n", total, + event_ex_list->attribs[cnt].u.mac_addr); + } + } + + msg = kzalloc(sizeof(*msg), GFP_KERNEL); + if (msg == NULL) { + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + return -ENOMEM; + } + msg->meta = entry->meta; + data = kmalloc(entry->meta.msg_len, GFP_KERNEL); + if (data == NULL) { + kfree(msg); + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + return -ENOMEM; + } + memcpy(data, entry->buff, entry->meta.msg_len); + msg->buff = data; + msg->callback = ipa3_send_msg_free; + mutex_lock(&ipa3_ctx->msg_lock); + list_add_tail(&msg->link, &ipa3_ctx->msg_list); + mutex_unlock(&ipa3_ctx->msg_lock); + wake_up(&ipa3_ctx->msg_waitq); + + total++; + } + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + return 0; +} + /** * ipa3_register_pull_msg() - register pull message type * @meta: [in] message meta-data diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c index adc153d24f15..5a29401114a8 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c @@ -1477,12 +1477,6 @@ int ipa3_nat_del_cmd(struct ipa_ioc_v4_nat_del *del) { struct ipa_ioc_nat_ipv6ct_table_del tmp; - if ((ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) && - (del->public_ip_addr == 0)) { - IPAERR_RL("Bad Parameter public IP address\n"); - return -EPERM; - } - tmp.table_index = del->table_index; return ipa3_del_nat_table(&tmp); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c index dfb94a683c28..654a3df0631e 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c @@ -585,6 +585,14 @@ int ipa3_qmi_filter_request_send(struct ipa_install_fltr_rule_req_msg_v01 *req) int rc; int i; + /* check if modem up */ + if (!ipa3_qmi_indication_fin || + !ipa3_qmi_modem_init_fin || + !ipa_q6_clnt) { + IPAWANDBG("modem QMI haven't up yet\n"); + return -EINVAL; + } + /* check if the filter rules from IPACM is valid */ if (req->filter_spec_list_len == 0) { IPAWANDBG("IPACM pass zero rules to Q6\n"); @@ -676,6 +684,14 @@ int ipa3_qmi_filter_request_ex_send( int rc; int i; + /* check if modem up */ + if (!ipa3_qmi_indication_fin || + !ipa3_qmi_modem_init_fin || + !ipa_q6_clnt) { + IPAWANDBG("modem QMI haven't up yet\n"); + return -EINVAL; + } + /* check if the filter rules from IPACM is valid */ if (req->filter_spec_ex_list_len == 0) { IPAWANDBG("IPACM pass zero rules to Q6\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index d2f0f9ced728..a0bd749dbd30 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -955,7 +955,7 @@ static int __ipa_create_rt_entry(struct ipa3_rt_entry **entry, const struct ipa_rt_rule *rule, struct ipa3_rt_tbl *tbl, struct ipa3_hdr_entry *hdr, struct ipa3_hdr_proc_ctx_entry *proc_ctx, - u16 rule_id) + u16 rule_id, bool user) { int id; @@ -981,6 +981,7 @@ static int __ipa_create_rt_entry(struct ipa3_rt_entry **entry, } } (*(entry))->rule_id = id; + (*(entry))->ipacm_installed = user; return 0; @@ -1026,7 +1027,7 @@ static int __ipa_finish_rt_rule_add(struct ipa3_rt_entry *entry, u32 *rule_hdl, static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, const struct ipa_rt_rule *rule, u8 at_rear, u32 *rule_hdl, - u16 rule_id) + u16 rule_id, bool user) { struct ipa3_rt_tbl *tbl; struct ipa3_rt_entry *entry; @@ -1055,7 +1056,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, } if (__ipa_create_rt_entry(&entry, rule, tbl, hdr, proc_ctx, - rule_id)) + rule_id, user)) goto error; if (at_rear) @@ -1086,7 +1087,7 @@ static int __ipa_add_rt_rule_after(struct ipa3_rt_tbl *tbl, if (__ipa_rt_validate_hndls(rule, &hdr, &proc_ctx)) goto error; - if (__ipa_create_rt_entry(&entry, rule, tbl, hdr, proc_ctx, 0)) + if (__ipa_create_rt_entry(&entry, rule, tbl, hdr, proc_ctx, 0, true)) goto error; list_add(&entry->link, &((*add_after_entry)->link)); @@ -1115,7 +1116,24 @@ static int __ipa_add_rt_rule_after(struct ipa3_rt_tbl *tbl, * * Note: Should not be called from atomic context */ + int ipa3_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) +{ + return ipa3_add_rt_rule_usr(rules, false); +} + +/** + * ipa3_add_rt_rule_usr() - Add the specified routing rules to SW and optionally + * commit to IPA HW + * @rules: [inout] set of routing rules to add + * @user_only: [in] indicate installed by userspace module + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ + +int ipa3_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only) { int i; int ret; @@ -1135,7 +1153,8 @@ int ipa3_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) &rules->rules[i].rule, rules->rules[i].at_rear, &rules->rules[i].rt_rule_hdl, - 0)) { + 0, + user_only)) { IPAERR("failed to add rt rule %d\n", i); rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED; } else { @@ -1183,7 +1202,7 @@ int ipa3_add_rt_rule_ext(struct ipa_ioc_add_rt_rule_ext *rules) &rules->rules[i].rule, rules->rules[i].at_rear, &rules->rules[i].rt_rule_hdl, - rules->rules[i].rule_id)) { + rules->rules[i].rule_id, true)) { IPAERR("failed to add rt rule %d\n", i); rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED; } else { @@ -1463,13 +1482,14 @@ int ipa3_commit_rt(enum ipa_ip_type ip) /** * ipa3_reset_rt() - reset the current SW routing table of specified type * (does not commit to HW) - * @ip: The family of routing tables + * @ip: [in] The family of routing tables + * @user_only: [in] indicate delete rules installed by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa3_reset_rt(enum ipa_ip_type ip) +int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only) { struct ipa3_rt_tbl *tbl; struct ipa3_rt_tbl *tbl_next; @@ -1479,6 +1499,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip) struct ipa3_rt_tbl_set *rset; u32 apps_start_idx; int id; + bool tbl_user = false; if (ip >= IPA_IP_MAX) { IPAERR_RL("bad param\n"); @@ -1496,7 +1517,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip) * issue a reset on the filtering module of same IP type since * filtering rules point to routing tables */ - if (ipa3_reset_flt(ip)) + if (ipa3_reset_flt(ip, user_only)) IPAERR_RL("fail to reset flt ip=%d\n", ip); set = &ipa3_ctx->rt_tbl_set[ip]; @@ -1504,6 +1525,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip) mutex_lock(&ipa3_ctx->lock); IPADBG("reset rt ip=%d\n", ip); list_for_each_entry_safe(tbl, tbl_next, &set->head_rt_tbl_list, link) { + tbl_user = false; list_for_each_entry_safe(rule, rule_next, &tbl->head_rt_rule_list, link) { if (ipa3_id_find(rule->id) == NULL) { @@ -1512,6 +1534,12 @@ int ipa3_reset_rt(enum ipa_ip_type ip) return -EFAULT; } + /* indicate if tbl used for user-specified rules*/ + if (rule->ipacm_installed) { + IPADBG("tbl_user %d, tbl-index %d\n", + tbl_user, tbl->id); + tbl_user = true; + } /* * for the "default" routing tbl, remove all but the * last rule @@ -1519,19 +1547,23 @@ int ipa3_reset_rt(enum ipa_ip_type ip) if (tbl->idx == apps_start_idx && tbl->rule_cnt == 1) continue; - list_del(&rule->link); - tbl->rule_cnt--; - if (rule->hdr) - __ipa3_release_hdr(rule->hdr->id); - else if (rule->proc_ctx) - __ipa3_release_hdr_proc_ctx(rule->proc_ctx->id); - rule->cookie = 0; - idr_remove(tbl->rule_ids, rule->rule_id); - id = rule->id; - kmem_cache_free(ipa3_ctx->rt_rule_cache, rule); - - /* remove the handle from the database */ - ipa3_id_remove(id); + if (!user_only || + rule->ipacm_installed) { + list_del(&rule->link); + tbl->rule_cnt--; + if (rule->hdr) + __ipa3_release_hdr(rule->hdr->id); + else if (rule->proc_ctx) + __ipa3_release_hdr_proc_ctx( + rule->proc_ctx->id); + rule->cookie = 0; + idr_remove(tbl->rule_ids, rule->rule_id); + id = rule->id; + kmem_cache_free(ipa3_ctx->rt_rule_cache, rule); + + /* remove the handle from the database */ + ipa3_id_remove(id); + } } if (ipa3_id_find(tbl->id) == NULL) { @@ -1543,26 +1575,30 @@ int ipa3_reset_rt(enum ipa_ip_type ip) /* do not remove the "default" routing tbl which has index 0 */ if (tbl->idx != apps_start_idx) { - tbl->rule_ids = NULL; - if (tbl->in_sys[IPA_RULE_HASHABLE] || - tbl->in_sys[IPA_RULE_NON_HASHABLE]) { - list_move(&tbl->link, &rset->head_rt_tbl_list); - clear_bit(tbl->idx, + if (!user_only || tbl_user) { + tbl->rule_ids = NULL; + if (tbl->in_sys[IPA_RULE_HASHABLE] || + tbl->in_sys[IPA_RULE_NON_HASHABLE]) { + list_move(&tbl->link, + &rset->head_rt_tbl_list); + clear_bit(tbl->idx, &ipa3_ctx->rt_idx_bitmap[ip]); - set->tbl_cnt--; - IPADBG("rst sys rt tbl_idx=%d tbl_cnt=%d\n", + set->tbl_cnt--; + IPADBG("rst tbl_idx=%d cnt=%d\n", tbl->idx, set->tbl_cnt); - } else { - list_del(&tbl->link); - set->tbl_cnt--; - clear_bit(tbl->idx, + } else { + list_del(&tbl->link); + set->tbl_cnt--; + clear_bit(tbl->idx, &ipa3_ctx->rt_idx_bitmap[ip]); - IPADBG("rst rt tbl_idx=%d tbl_cnt=%d\n", + IPADBG("rst rt tbl_idx=%d tbl_cnt=%d\n", tbl->idx, set->tbl_cnt); - kmem_cache_free(ipa3_ctx->rt_tbl_cache, tbl); + kmem_cache_free(ipa3_ctx->rt_tbl_cache, + tbl); + } + /* remove the handle from the database */ + ipa3_id_remove(id); } - /* remove the handle from the database */ - ipa3_id_remove(id); } } mutex_unlock(&ipa3_ctx->lock); @@ -1678,6 +1714,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) struct ipa3_hdr_proc_ctx_entry *proc_ctx = NULL; struct ipa3_hdr_entry *hdr_entry; struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry; + if (rtrule->rule.hdr_hdl) { hdr = ipa3_id_find(rtrule->rule.hdr_hdl); if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 4527986019c9..494085aab114 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -5084,6 +5084,7 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_cfg_ep_holb_by_client = ipa3_cfg_ep_holb_by_client; api_ctrl->ipa_cfg_ep_ctrl = ipa3_cfg_ep_ctrl; api_ctrl->ipa_add_hdr = ipa3_add_hdr; + api_ctrl->ipa_add_hdr_usr = ipa3_add_hdr_usr; api_ctrl->ipa_del_hdr = ipa3_del_hdr; api_ctrl->ipa_commit_hdr = ipa3_commit_hdr; api_ctrl->ipa_reset_hdr = ipa3_reset_hdr; @@ -5093,6 +5094,7 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_add_hdr_proc_ctx = ipa3_add_hdr_proc_ctx; api_ctrl->ipa_del_hdr_proc_ctx = ipa3_del_hdr_proc_ctx; api_ctrl->ipa_add_rt_rule = ipa3_add_rt_rule; + api_ctrl->ipa_add_rt_rule_usr = ipa3_add_rt_rule_usr; api_ctrl->ipa_del_rt_rule = ipa3_del_rt_rule; api_ctrl->ipa_commit_rt = ipa3_commit_rt; api_ctrl->ipa_reset_rt = ipa3_reset_rt; @@ -5101,6 +5103,7 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_query_rt_index = ipa3_query_rt_index; api_ctrl->ipa_mdfy_rt_rule = ipa3_mdfy_rt_rule; api_ctrl->ipa_add_flt_rule = ipa3_add_flt_rule; + api_ctrl->ipa_add_flt_rule_usr = ipa3_add_flt_rule_usr; api_ctrl->ipa_del_flt_rule = ipa3_del_flt_rule; api_ctrl->ipa_mdfy_flt_rule = ipa3_mdfy_flt_rule; api_ctrl->ipa_commit_flt = ipa3_commit_flt; diff --git a/include/linux/ipa.h b/include/linux/ipa.h index 40a848c24eda..ecdc4e7c0bf6 100644 --- a/include/linux/ipa.h +++ b/include/linux/ipa.h @@ -1206,11 +1206,13 @@ int ipa_cfg_ep_ctrl(u32 clnt_hdl, const struct ipa_ep_cfg_ctrl *ep_ctrl); */ int ipa_add_hdr(struct ipa_ioc_add_hdr *hdrs); +int ipa_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only); + int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls); int ipa_commit_hdr(void); -int ipa_reset_hdr(void); +int ipa_reset_hdr(bool user_only); int ipa_get_hdr(struct ipa_ioc_get_hdr *lookup); @@ -1221,7 +1223,8 @@ int ipa_copy_hdr(struct ipa_ioc_copy_hdr *copy); /* * Header Processing Context */ -int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs); +int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only); int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls); @@ -1230,11 +1233,13 @@ int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls); */ int ipa_add_rt_rule(struct ipa_ioc_add_rt_rule *rules); +int ipa_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only); + int ipa_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls); int ipa_commit_rt(enum ipa_ip_type ip); -int ipa_reset_rt(enum ipa_ip_type ip); +int ipa_reset_rt(enum ipa_ip_type ip, bool user_only); int ipa_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup); @@ -1249,13 +1254,15 @@ int ipa_mdfy_rt_rule(struct ipa_ioc_mdfy_rt_rule *rules); */ int ipa_add_flt_rule(struct ipa_ioc_add_flt_rule *rules); +int ipa_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only); + int ipa_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls); int ipa_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *rules); int ipa_commit_flt(enum ipa_ip_type ip); -int ipa_reset_flt(enum ipa_ip_type ip); +int ipa_reset_flt(enum ipa_ip_type ip, bool user_only); /* * NAT\IPv6CT @@ -1656,6 +1663,12 @@ static inline int ipa_add_hdr(struct ipa_ioc_add_hdr *hdrs) return -EPERM; } +static inline int ipa_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, + bool user_only) +{ + return -EPERM; +} + static inline int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls) { return -EPERM; @@ -1666,7 +1679,7 @@ static inline int ipa_commit_hdr(void) return -EPERM; } -static inline int ipa_reset_hdr(void) +static inline int ipa_reset_hdr(bool user_only) { return -EPERM; } @@ -1690,7 +1703,8 @@ static inline int ipa_copy_hdr(struct ipa_ioc_copy_hdr *copy) * Header Processing Context */ static inline int ipa_add_hdr_proc_ctx( - struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) + struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only) { return -EPERM; } @@ -1707,6 +1721,12 @@ static inline int ipa_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) return -EPERM; } +static inline int ipa_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, + bool user_only) +{ + return -EPERM; +} + static inline int ipa_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls) { return -EPERM; @@ -1717,7 +1737,7 @@ static inline int ipa_commit_rt(enum ipa_ip_type ip) return -EPERM; } -static inline int ipa_reset_rt(enum ipa_ip_type ip) +static inline int ipa_reset_rt(enum ipa_ip_type ip, bool user_only) { return -EPERM; } @@ -1750,6 +1770,12 @@ static inline int ipa_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) return -EPERM; } +static inline int ipa_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, + bool user_only) +{ + return -EPERM; +} + static inline int ipa_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls) { return -EPERM; @@ -1765,7 +1791,7 @@ static inline int ipa_commit_flt(enum ipa_ip_type ip) return -EPERM; } -static inline int ipa_reset_flt(enum ipa_ip_type ip) +static inline int ipa_reset_flt(enum ipa_ip_type ip, bool user_only) { return -EPERM; } diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index 9ced0f9d73e0..893caec1ca58 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -95,9 +95,11 @@ #define IPA_IOCTL_ALLOC_IPV6CT_TABLE 53 #define IPA_IOCTL_DEL_NAT_TABLE 54 #define IPA_IOCTL_DEL_IPV6CT_TABLE 55 -#define IPA_IOCTL_GET_VLAN_MODE 56 -#define IPA_IOCTL_ADD_BRIDGE_VLAN_MAPPING 57 -#define IPA_IOCTL_DEL_BRIDGE_VLAN_MAPPING 58 +#define IPA_IOCTL_CLEANUP 56 +#define IPA_IOCTL_QUERY_WLAN_CLIENT 57 +#define IPA_IOCTL_GET_VLAN_MODE 58 +#define IPA_IOCTL_ADD_BRIDGE_VLAN_MAPPING 59 +#define IPA_IOCTL_DEL_BRIDGE_VLAN_MAPPING 60 /** * max size of the header to be inserted @@ -2081,7 +2083,6 @@ struct ipa_ioc_bridge_vlan_mapping_info { #define IPA_IOC_GET_VLAN_MODE _IOWR(IPA_IOC_MAGIC, \ IPA_IOCTL_GET_VLAN_MODE, \ struct ipa_ioc_get_vlan_mode *) - #define IPA_IOC_ADD_BRIDGE_VLAN_MAPPING _IOWR(IPA_IOC_MAGIC, \ IPA_IOCTL_ADD_BRIDGE_VLAN_MAPPING, \ struct ipa_ioc_bridge_vlan_mapping_info) @@ -2089,7 +2090,10 @@ struct ipa_ioc_bridge_vlan_mapping_info { #define IPA_IOC_DEL_BRIDGE_VLAN_MAPPING _IOWR(IPA_IOC_MAGIC, \ IPA_IOCTL_DEL_BRIDGE_VLAN_MAPPING, \ struct ipa_ioc_bridge_vlan_mapping_info) - +#define IPA_IOC_CLEANUP _IO(IPA_IOC_MAGIC,\ + IPA_IOCTL_CLEANUP) +#define IPA_IOC_QUERY_WLAN_CLIENT _IO(IPA_IOC_MAGIC,\ + IPA_IOCTL_QUERY_WLAN_CLIENT) /* * unique magic number of the Tethering bridge ioctls */ -- GitLab From e92949dad844bfb655f5a2a7a6318414a3f18dac Mon Sep 17 00:00:00 2001 From: Jeevan Shriram Date: Mon, 25 Jun 2018 11:36:13 -0700 Subject: [PATCH 0765/1299] ARM: dts: msm: Update qtimer frequency on SDXPRAIRIE RUMI Update Qtimer frequency for the latest Rumi emulation (2.5) release for SDXPRAIRIE target. Change-Id: I4aab5cbedebc9c38d930444038f9506bbd318c70 Signed-off-by: Jeevan Shriram --- arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi index 4340663de4f3..7f755519de7a 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi @@ -14,10 +14,10 @@ &soc { timer { - clock-frequency = <96000>; + clock-frequency = <48000>; }; timer@17820000 { - clock-frequency = <96000>; + clock-frequency = <48000>; }; }; -- GitLab From 957cc168ad693e32045aaecf1297fe6569cc41d1 Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Wed, 20 Jun 2018 11:24:09 -0700 Subject: [PATCH 0766/1299] sched: restore all values for sched_{up,down}_migrate knobs in error case Now that the sched_{up,down}_migrate knobs accept multiple values depends on the number of clusters in the system, if any of the up migrate values is more than respective down migrate value, updating sched_{up,down}_migrate knobs are aborted by restoring only first value and returning an error to user. Instead of just restoring first value in the vector, restore all the values in case of error. Change-Id: If565fb951aa0c00d2dc4a8b4f1f7a90caf4d325f Signed-off-by: Satya Durga Srinivasu Prabhala --- kernel/sched/core.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 0232fd107c74..8d6358125852 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6840,12 +6840,11 @@ int sched_updown_migrate_handler(struct ctl_table *table, int write, { int ret, i; unsigned int *data = (unsigned int *)table->data; - unsigned int old_val; + unsigned int *old_val; static DEFINE_MUTEX(mutex); static int cap_margin_levels = -1; mutex_lock(&mutex); - old_val = *data; if (cap_margin_levels == -1 || table->maxlen != (sizeof(unsigned int) * cap_margin_levels)) { @@ -6854,25 +6853,36 @@ int sched_updown_migrate_handler(struct ctl_table *table, int write, } if (cap_margin_levels <= 0) { - mutex_unlock(&mutex); - return -EINVAL; + ret = -EINVAL; + goto unlock_mutex; } + old_val = kzalloc(table->maxlen, GFP_KERNEL); + if (!old_val) { + ret = -ENOMEM; + goto unlock_mutex; + } + + memcpy(old_val, data, table->maxlen); + ret = proc_douintvec_capacity(table, write, buffer, lenp, ppos); if (!ret && write) { for (i = 0; i < cap_margin_levels; i++) { if (sysctl_sched_capacity_margin_up[i] > sysctl_sched_capacity_margin_down[i]) { - *data = old_val; - mutex_unlock(&mutex); - return -EINVAL; + memcpy(data, old_val, table->maxlen); + ret = -EINVAL; + goto free_old_val; } } ret = sched_update_updown_migrate_values(data, cap_margin_levels, ret); } +free_old_val: + kfree(old_val); +unlock_mutex: mutex_unlock(&mutex); return ret; -- GitLab From 8468632e51bd16e27323dad8fa99948f4fcda409 Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Thu, 14 Jun 2018 18:28:35 -0700 Subject: [PATCH 0767/1299] drm/msm/sde: add cwb support for single ctl path MDSS hardware supports single CTL path starting SM8150 chipset. It needs mux configuration update starting for this hardware due to single CTL path. Change also includes ping-pong overflow irq handling for the additional ping-pong blocks in SM8150. Change-Id: I3f2ba272562b7f0967621b3b6aa029ef501b02db Signed-off-by: Prabhanjan Kandula --- drivers/gpu/drm/msm/sde/sde_encoder_phys.h | 6 +- drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c | 147 +++++++++++++++--- drivers/gpu/drm/msm/sde/sde_hw_catalog.c | 6 +- drivers/gpu/drm/msm/sde/sde_hw_catalog.h | 2 + drivers/gpu/drm/msm/sde/sde_hw_ctl.c | 34 ++++ drivers/gpu/drm/msm/sde/sde_hw_ctl.h | 8 + drivers/gpu/drm/msm/sde/sde_hw_interrupts.c | 9 +- drivers/gpu/drm/msm/sde/sde_hw_wb.c | 40 +++++ drivers/gpu/drm/msm/sde/sde_hw_wb.h | 12 ++ 9 files changed, 238 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 37735df1cd54..b814c37c0b6d 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -202,7 +202,9 @@ struct sde_encoder_phys_ops { * @INTR_IDX_RDPTR: Readpointer done unterrupt for cmd mode panel * @INTR_IDX_WB_DONE: Writeback done interrupt for WB * @INTR_IDX_PP2_OVFL: Pingpong overflow interrupt on PP2 for Concurrent WB - * @INTR_IDX_PP2_OVFL: Pingpong overflow interrupt on PP3 for Concurrent WB + * @INTR_IDX_PP3_OVFL: Pingpong overflow interrupt on PP3 for Concurrent WB + * @INTR_IDX_PP4_OVFL: Pingpong overflow interrupt on PP4 for Concurrent WB + * @INTR_IDX_PP5_OVFL: Pingpong overflow interrupt on PP5 for Concurrent WB * @INTR_IDX_AUTOREFRESH_DONE: Autorefresh done for cmd mode panel meaning * autorefresh has triggered a double buffer flip */ @@ -216,6 +218,8 @@ enum sde_intr_idx { INTR_IDX_WB_DONE, INTR_IDX_PP2_OVFL, INTR_IDX_PP3_OVFL, + INTR_IDX_PP4_OVFL, + INTR_IDX_PP5_OVFL, INTR_IDX_MAX, }; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c index a18271fbb1ac..4f4ae363c2e8 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c @@ -33,6 +33,11 @@ #define TO_S15D16(_x_) ((_x_) << 7) #define MULTIPLE_CONN_DETECTED(x) (x > 1) + +static const u32 cwb_irq_tbl[PINGPONG_MAX] = {SDE_NONE, SDE_NONE, + INTR_IDX_PP2_OVFL, INTR_IDX_PP3_OVFL, INTR_IDX_PP4_OVFL, + INTR_IDX_PP5_OVFL, SDE_NONE, SDE_NONE}; + /** * sde_rgb2yuv_601l - rgb to yuv color space conversion matrix * @@ -471,26 +476,66 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc, { struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); struct sde_hw_wb *hw_wb = wb_enc->hw_wb; - struct sde_hw_intf_cfg *intf_cfg = &phys_enc->intf_cfg; struct sde_hw_ctl *hw_ctl = phys_enc->hw_ctl; struct sde_crtc *crtc = to_sde_crtc(wb_enc->crtc); + struct sde_hw_pingpong *hw_pp = phys_enc->hw_pp; + bool need_merge = crtc->num_mixers > 1 ? true : false; + int i = 0; if (!phys_enc->in_clone_mode) { SDE_DEBUG("not in CWB mode. early return\n"); return; } - memset(intf_cfg, 0, sizeof(struct sde_hw_intf_cfg)); - intf_cfg->intf = SDE_NONE; - intf_cfg->wb = hw_wb->idx; + if (!hw_pp || !hw_ctl || !hw_wb || hw_pp->idx >= PINGPONG_MAX) { + SDE_ERROR("invalid hw resources - return\n"); + return; + } hw_ctl = crtc->mixers[0].hw_ctl; - if (hw_ctl && hw_ctl->ops.update_wb_cfg) { - hw_ctl->ops.update_wb_cfg(hw_ctl, intf_cfg, enable); - SDE_DEBUG("in CWB mode adding WB for CTL_%d\n", - hw_ctl->idx - CTL_0); + if (hw_ctl && hw_ctl->ops.setup_intf_cfg_v1 && + test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features)) { + struct sde_hw_intf_cfg_v1 intf_cfg = { 0, }; + + for (i = 0; i < crtc->num_mixers; i++) + intf_cfg.cwb[intf_cfg.cwb_count++] = + (enum sde_cwb)(hw_pp->idx + i); + + if (enable && hw_pp->merge_3d && (intf_cfg.merge_3d_count < + MAX_MERGE_3D_PER_CTL_V1) && need_merge) + intf_cfg.merge_3d[intf_cfg.merge_3d_count++] = + hw_pp->merge_3d->idx; + + if (hw_pp->ops.setup_3d_mode) + hw_pp->ops.setup_3d_mode(hw_pp, (enable && need_merge) ? + BLEND_3D_H_ROW_INT : 0); + + if (hw_wb->ops.bind_pingpong_blk) + hw_wb->ops.bind_pingpong_blk(hw_wb, enable, hw_pp->idx); + + if (hw_ctl->ops.update_cwb_cfg) { + hw_ctl->ops.update_cwb_cfg(hw_ctl, &intf_cfg); + SDE_DEBUG("in CWB mode on CTL_%d PP-%d merge3d:%d\n", + hw_ctl->idx - CTL_0, + hw_pp->idx - PINGPONG_0, + hw_pp->merge_3d ? + hw_pp->merge_3d->idx - MERGE_3D_0 : -1); + } + } else { + struct sde_hw_intf_cfg *intf_cfg = &phys_enc->intf_cfg; + + memset(intf_cfg, 0, sizeof(struct sde_hw_intf_cfg)); + intf_cfg->intf = SDE_NONE; + intf_cfg->wb = hw_wb->idx; + + if (hw_ctl && hw_ctl->ops.update_wb_cfg) { + hw_ctl->ops.update_wb_cfg(hw_ctl, intf_cfg, enable); + SDE_DEBUG("in CWB mode adding WB for CTL_%d\n", + hw_ctl->idx - CTL_0); + } } } + /** * sde_encoder_phys_wb_setup_cdp - setup chroma down prefetch block * @phys_enc: Pointer to physical encoder @@ -801,9 +846,15 @@ static void _sde_encoder_phys_wb_update_cwb_flush( struct sde_hw_wb *hw_wb; struct sde_hw_ctl *hw_ctl; struct sde_hw_cdm *hw_cdm; + struct sde_hw_pingpong *hw_pp; struct sde_crtc *crtc; struct sde_crtc_state *crtc_state; - int capture_point = 0; + int i = 0; + int cwb_capture_mode = 0; + enum sde_cwb cwb_idx = 0; + enum sde_cwb src_pp_idx = 0; + bool dspp_out = false; + bool need_merge = false; if (!phys_enc->in_clone_mode) { SDE_DEBUG("not in CWB mode. early return\n"); @@ -813,30 +864,59 @@ static void _sde_encoder_phys_wb_update_cwb_flush( wb_enc = to_sde_encoder_phys_wb(phys_enc); crtc = to_sde_crtc(wb_enc->crtc); crtc_state = to_sde_crtc_state(wb_enc->crtc->state); + cwb_capture_mode = sde_crtc_get_property(crtc_state, + CRTC_PROP_CAPTURE_OUTPUT); + hw_pp = phys_enc->hw_pp; hw_wb = wb_enc->hw_wb; hw_cdm = phys_enc->hw_cdm; /* In CWB mode, program actual source master sde_hw_ctl from crtc */ hw_ctl = crtc->mixers[0].hw_ctl; - if (!hw_ctl) { - SDE_DEBUG("[wb:%d] no ctl assigned for CWB\n", - hw_wb->idx - WB_0); + if (!hw_ctl || !hw_wb || !hw_pp) { + SDE_ERROR("[wb] HW resource not available for CWB\n"); return; } - capture_point = sde_crtc_get_property(crtc_state, - CRTC_PROP_CAPTURE_OUTPUT); + /* treating LM idx of primary display ctl path as source ping-pong idx*/ + src_pp_idx = (enum sde_cwb)crtc->mixers[0].hw_lm->idx; + cwb_idx = (enum sde_cwb)hw_pp->idx; + dspp_out = (cwb_capture_mode == CAPTURE_DSPP_OUT); + need_merge = (crtc->num_mixers > 1) ? true : false; - phys_enc->hw_mdptop->ops.set_cwb_ppb_cntl(phys_enc->hw_mdptop, - crtc->num_mixers == CRTC_DUAL_MIXERS, - capture_point == CAPTURE_DSPP_OUT); + if (src_pp_idx > LM_0 || ((cwb_idx + crtc->num_mixers) > CWB_MAX)) { + SDE_ERROR("invalid hw config for CWB\n"); + return; + } if (hw_ctl->ops.update_bitmask_wb) hw_ctl->ops.update_bitmask_wb(hw_ctl, hw_wb->idx, 1); if (hw_ctl->ops.update_bitmask_cdm && hw_cdm) hw_ctl->ops.update_bitmask_cdm(hw_ctl, hw_cdm->idx, 1); + + if (test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features)) { + for (i = 0; i < crtc->num_mixers; i++) { + cwb_idx = (enum sde_cwb) (hw_pp->idx + i); + src_pp_idx = (enum sde_cwb) (src_pp_idx + i); + + if (hw_wb->ops.program_cwb_ctrl) + hw_wb->ops.program_cwb_ctrl(hw_wb, cwb_idx, + src_pp_idx, dspp_out); + + if (hw_ctl->ops.update_bitmask_cwb) + hw_ctl->ops.update_bitmask_cwb(hw_ctl, + cwb_idx, 1); + } + + if (need_merge && hw_ctl->ops.update_bitmask_merge3d + && hw_pp && hw_pp->merge_3d) + hw_ctl->ops.update_bitmask_merge3d(hw_ctl, + hw_pp->merge_3d->idx, 1); + } else { + phys_enc->hw_mdptop->ops.set_cwb_ppb_cntl(phys_enc->hw_mdptop, + need_merge, dspp_out); + } } /** @@ -1035,6 +1115,7 @@ static void sde_encoder_phys_wb_irq_ctrl( struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys); int index = 0; + int pp = 0; if (!wb_enc) return; @@ -1042,21 +1123,25 @@ static void sde_encoder_phys_wb_irq_ctrl( if (wb_enc->bypass_irqreg) return; + pp = phys->hw_pp->idx - PINGPONG_0; + if ((pp + CRTC_DUAL_MIXERS) >= PINGPONG_MAX) { + SDE_ERROR("invalid pingpong index for WB or CWB\n"); + return; + } + if (enable) { sde_encoder_helper_register_irq(phys, INTR_IDX_WB_DONE); if (phys->in_clone_mode) { for (index = 0; index < CRTC_DUAL_MIXERS; index++) sde_encoder_helper_register_irq(phys, - index ? INTR_IDX_PP3_OVFL - : INTR_IDX_PP2_OVFL); + cwb_irq_tbl[index + pp]); } } else { sde_encoder_helper_unregister_irq(phys, INTR_IDX_WB_DONE); if (phys->in_clone_mode) { for (index = 0; index < CRTC_DUAL_MIXERS; index++) sde_encoder_helper_unregister_irq(phys, - index ? INTR_IDX_PP3_OVFL - : INTR_IDX_PP2_OVFL); + cwb_irq_tbl[index + pp]); } } } @@ -1733,6 +1818,26 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init( irq->cb.arg = wb_enc; irq->cb.func = sde_encoder_phys_cwb_ovflow; + irq = &phys_enc->irq[INTR_IDX_PP4_OVFL]; + INIT_LIST_HEAD(&irq->cb.list); + irq->name = "pp4_overflow"; + irq->hw_idx = CWB_4; + irq->irq_idx = -1; + irq->intr_type = SDE_IRQ_TYPE_CWB_OVERFLOW; + irq->intr_idx = INTR_IDX_PP4_OVFL; + irq->cb.arg = wb_enc; + irq->cb.func = sde_encoder_phys_cwb_ovflow; + + irq = &phys_enc->irq[INTR_IDX_PP5_OVFL]; + INIT_LIST_HEAD(&irq->cb.list); + irq->name = "pp5_overflow"; + irq->hw_idx = CWB_5; + irq->irq_idx = -1; + irq->intr_type = SDE_IRQ_TYPE_CWB_OVERFLOW; + irq->intr_idx = INTR_IDX_PP5_OVFL; + irq->cb.arg = wb_enc; + irq->cb.func = sde_encoder_phys_cwb_ovflow; + /* create internal buffer for disable logic */ if (_sde_encoder_phys_wb_init_internal_fb(wb_enc, DRM_FORMAT_RGB888, 2, 1, 6)) { diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c index b5c546cbb1a4..18500acc225e 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c @@ -1876,8 +1876,11 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) set_bit(SDE_WB_INPUT_CTRL, &wb->features); - if (sde_cfg->has_cwb_support) + if (sde_cfg->has_cwb_support) { set_bit(SDE_WB_HAS_CWB, &wb->features); + if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) + set_bit(SDE_WB_CWB_CTRL, &wb->features); + } for (j = 0; j < sde_cfg->mdp_count; j++) { sde_cfg->mdp[j].clk_ctrls[wb->clk_ctrl].reg_off = @@ -3567,6 +3570,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->vbif_qos_nlvl = 8; sde_cfg->ts_prefill_rev = 2; } else if (IS_SM8150_TARGET(hw_rev)) { + sde_cfg->has_cwb_support = true; sde_cfg->has_wb_ubwc = true; sde_cfg->has_qsync = true; sde_cfg->perf.min_prefill_lines = 24; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h index b337afca72d2..fe2817f489f2 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h @@ -329,6 +329,7 @@ enum { * @SDE_WB_INPUT_CTRL Writeback supports from which pp block input pixel * data arrives. * @SDE_WB_HAS_CWB Writeback block supports concurrent writeback + * @SDE_WB_CWB_CTRL Separate CWB control is available for configuring * @SDE_WB_MAX maximum value */ enum { @@ -349,6 +350,7 @@ enum { SDE_WB_CDP, SDE_WB_INPUT_CTRL, SDE_WB_HAS_CWB, + SDE_WB_CWB_CTRL, SDE_WB_MAX }; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c index 8d7402b0c87a..15258ff45d1e 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c @@ -954,6 +954,39 @@ static int sde_hw_ctl_reset_post_te_disable(struct sde_hw_ctl *ctx, return 0; } +static int sde_hw_ctl_update_cwb_cfg(struct sde_hw_ctl *ctx, + struct sde_hw_intf_cfg_v1 *cfg) +{ + int i; + u32 cwb_active = 0; + u32 merge_3d_active = 0; + u32 wb_active = 0; + struct sde_hw_blk_reg_map *c; + + if (!ctx) + return -EINVAL; + + c = &ctx->hw; + cwb_active = SDE_REG_READ(c, CTL_CWB_ACTIVE); + for (i = 0; i < cfg->cwb_count; i++) { + if (cfg->cwb[i]) + cwb_active |= BIT(cfg->cwb[i] - CWB_0); + } + + merge_3d_active = SDE_REG_READ(c, CTL_MERGE_3D_ACTIVE); + for (i = 0; i < cfg->merge_3d_count; i++) { + if (cfg->merge_3d[i]) + merge_3d_active |= BIT(cfg->merge_3d[i] - MERGE_3D_0); + } + + wb_active = BIT(2); + SDE_REG_WRITE(c, CTL_WB_ACTIVE, wb_active); + SDE_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active); + SDE_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active); + + return 0; +} + static int sde_hw_ctl_dsc_cfg(struct sde_hw_ctl *ctx, struct sde_ctl_dsc_cfg *cfg) { @@ -1098,6 +1131,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, ops->trigger_flush = sde_hw_ctl_trigger_flush_v1; ops->setup_intf_cfg_v1 = sde_hw_ctl_intf_cfg_v1; + ops->update_cwb_cfg = sde_hw_ctl_update_cwb_cfg; ops->setup_dsc_cfg = sde_hw_ctl_dsc_cfg; ops->update_bitmask_cdm = sde_hw_ctl_update_bitmask_cdm_v1; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h index a231e8a2f787..e55a173a7ff9 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h @@ -250,6 +250,14 @@ struct sde_hw_ctl_ops { int (*reset_post_te_disable)(struct sde_hw_ctl *ctx, struct sde_hw_intf_cfg_v1 *cfg, u32 merge_3d_idx); + /** update cwb for ctl_path + * @ctx : ctl path ctx pointer + * @cfg : interface config structure pointer + * @Return: error code + */ + int (*update_cwb_cfg)(struct sde_hw_ctl *ctx, + struct sde_hw_intf_cfg_v1 *cfg); + /** * Setup ctl_path interface config for SDE_CTL_ACTIVE_CFG * @ctx : ctl path ctx pointer diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c index ecf4a4ff99c1..0721493e2b1e 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c @@ -130,6 +130,8 @@ */ #define SDE_INTR_CWB_2_OVERFLOW BIT(14) #define SDE_INTR_CWB_3_OVERFLOW BIT(15) +#define SDE_INTR_CWB_4_OVERFLOW BIT(20) +#define SDE_INTR_CWB_5_OVERFLOW BIT(21) /** * Histogram VIG done interrupt status bit definitions @@ -390,9 +392,10 @@ static const struct sde_irq_type sde_irq_map[] = { SDE_INTR_PING_PONG_2_TEAR_DETECTED, 1}, { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_3, SDE_INTR_PING_PONG_3_TEAR_DETECTED, 1}, - /* irq_idx: 53-55 */ - { SDE_IRQ_TYPE_RESERVED, 0, 0, 1}, - { SDE_IRQ_TYPE_RESERVED, 0, 0, 1}, + /* irq_idx: 53-54 */ + { SDE_IRQ_TYPE_CWB_OVERFLOW, CWB_4, SDE_INTR_CWB_4_OVERFLOW, 1}, + { SDE_IRQ_TYPE_CWB_OVERFLOW, CWB_5, SDE_INTR_CWB_5_OVERFLOW, 1}, + /* irq_idx: 55 */ { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_S0, SDE_INTR_PING_PONG_S0_TEAR_DETECTED, 1}, /* irq_idx: 56-59 */ diff --git a/drivers/gpu/drm/msm/sde/sde_hw_wb.c b/drivers/gpu/drm/msm/sde/sde_hw_wb.c index 95edb3b1c61d..92c774867428 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_wb.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_wb.c @@ -55,6 +55,11 @@ #define WB_OUT_IMAGE_SIZE 0x2C0 #define WB_OUT_XY 0x2C4 +#define CWB_CTRL_SRC_SEL 0x0 +#define CWB_CTRL_MODE 0x4 +#define CWB_CTRL_BLK_SIZE 0x100 +#define CWB_CTRL_BASE_OFFSET 0x83000 + /* WB_QOS_CTRL */ #define WB_QOS_CTRL_DANGER_SAFE_EN BIT(0) @@ -78,6 +83,18 @@ static struct sde_wb_cfg *_wb_offset(enum sde_wb wb, return ERR_PTR(-EINVAL); } +static void _sde_hw_cwb_ctrl_init(struct sde_mdss_cfg *m, + void __iomem *addr, struct sde_hw_blk_reg_map *b) +{ + if (b) { + b->base_off = addr; + b->blk_off = CWB_CTRL_BASE_OFFSET; + b->length = CWB_CTRL_BLK_SIZE * m->pingpong_count; + b->hwversion = m->hwversion; + b->log_mask = SDE_DBG_MASK_WB; + } +} + static void sde_hw_wb_setup_outaddress(struct sde_hw_wb *ctx, struct sde_hw_wb_cfg *data) { @@ -262,6 +279,23 @@ static void sde_hw_wb_bind_pingpong_blk( SDE_REG_WRITE(c, WB_MUX, mux_cfg); } +static void sde_hw_wb_program_cwb_ctrl(struct sde_hw_wb *ctx, + const enum sde_cwb cur_idx, + const enum sde_cwb data_src, bool dspp_out) +{ + struct sde_hw_blk_reg_map *c; + u32 blk_base; + + if (!ctx) + return; + + c = &ctx->cwb_hw; + blk_base = CWB_CTRL_BLK_SIZE * (cur_idx - CWB_0); + + SDE_REG_WRITE(c, blk_base + CWB_CTRL_SRC_SEL, data_src - CWB_0); + SDE_REG_WRITE(c, blk_base + CWB_CTRL_MODE, dspp_out); +} + static void _setup_wb_ops(struct sde_hw_wb_ops *ops, unsigned long features) { @@ -283,6 +317,9 @@ static void _setup_wb_ops(struct sde_hw_wb_ops *ops, if (test_bit(SDE_WB_INPUT_CTRL, &features)) ops->bind_pingpong_blk = sde_hw_wb_bind_pingpong_blk; + + if (test_bit(SDE_WB_CWB_CTRL, &features)) + ops->program_cwb_ctrl = sde_hw_wb_program_cwb_ctrl; } static struct sde_hw_blk_ops sde_hw_ops = { @@ -330,6 +367,9 @@ struct sde_hw_wb *sde_hw_wb_init(enum sde_wb idx, sde_dbg_reg_register_dump_range(SDE_DBG_NAME, cfg->name, c->hw.blk_off, c->hw.blk_off + c->hw.length, c->hw.xin_id); + if (test_bit(SDE_WB_CWB_CTRL, &cfg->features)) + _sde_hw_cwb_ctrl_init(m, addr, &c->cwb_hw); + return c; blk_init_error: diff --git a/drivers/gpu/drm/msm/sde/sde_hw_wb.h b/drivers/gpu/drm/msm/sde/sde_hw_wb.h index c908ad058d46..268d0ef8b3d9 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_wb.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_wb.h @@ -137,6 +137,16 @@ struct sde_hw_wb_ops { void (*bind_pingpong_blk)(struct sde_hw_wb *ctx, bool enable, const enum sde_pingpong pp); + + /** + * program_cwb_ctrl - program cwb block configp + * @ctx: Pointer to wb context + * @pp_idx: Current CWB block index to poram + * @data_src: Source CWB/PingPong block index + * @dspp_out: Tap dspp output or default LM output + */ + void (*program_cwb_ctrl)(struct sde_hw_wb *ctx, const enum sde_cwb cwb, + const enum sde_cwb data_src, bool dspp_out); }; /** @@ -149,6 +159,7 @@ struct sde_hw_wb_ops { * @wb_hw_caps: hardware capabilities * @ops: function pointers * @hw_mdp: MDP top level hardware block + * @cwb_hw: CWB control hwio details */ struct sde_hw_wb { struct sde_hw_blk base; @@ -164,6 +175,7 @@ struct sde_hw_wb { struct sde_hw_wb_ops ops; struct sde_hw_mdp *hw_mdp; + struct sde_hw_blk_reg_map cwb_hw; }; /** -- GitLab From c4b98f6473c93884012401786a2a707113eaf524 Mon Sep 17 00:00:00 2001 From: Lianjun Huang Date: Sat, 16 Jun 2018 22:59:46 +0800 Subject: [PATCH 0768/1299] ANDROID: sdcardfs: fix potential crash when reserved_mb is not zero sdcardfs_mkdir() calls check_min_free_space(). When reserved_mb is not zero, a negative dentry will be passed to ext4_statfs() at last and ext4_statfs() will crash. The parent dentry is positive. So we use the parent dentry to check free space. Change-Id: I80ab9623fe59ba911f4cc9f0e029a1c6f7ee421b Signed-off-by: Lianjun Huang --- fs/sdcardfs/inode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index b43258684fb9..2de5a4dffa22 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -270,6 +270,7 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode struct dentry *lower_dentry; struct vfsmount *lower_mnt; struct dentry *lower_parent_dentry = NULL; + struct dentry *parent_dentry = NULL; struct path lower_path; struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); const struct cred *saved_cred = NULL; @@ -289,11 +290,14 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir)); /* check disk space */ - if (!check_min_free_space(dentry, 0, 1)) { + parent_dentry = dget_parent(dentry); + if (!check_min_free_space(parent_dentry, 0, 1)) { pr_err("sdcardfs: No minimum free space.\n"); err = -ENOSPC; + dput(parent_dentry); goto out_revert; } + dput(parent_dentry); /* the lower_dentry is negative here */ sdcardfs_get_lower_path(dentry, &lower_path); -- GitLab From 1b189876d3d5b38c0df302cca4a1746cf61fbf6e Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Mon, 25 Jun 2018 10:33:19 +0300 Subject: [PATCH 0769/1299] msm: ipa4: initialize IPAHAL at ipa_pre_init() At virtual platforms, SMMU is not used so IPA HAL initialization can be done during ipa_pre_init() instead of ipa_post_init(). IPAHAL need to be initialized at ipa_pre_init() on virtual platforms as it is used to load IPA firmwares. CRx-fixed: 2266802 Change-Id: I00201ab6386639ede06a7ba9ac022834f5244e56 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 40 +++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 771654d6aa5d..3f1525121115 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -4562,12 +4562,19 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, /* move proxy vote for modem on ipa3_post_init */ if (ipa3_ctx->ipa_hw_type != IPA_HW_v4_0) ipa3_proxy_clk_vote(); - /* SMMU was already attached if used, safe to do allocations */ - if (ipahal_init(ipa3_ctx->ipa_hw_type, ipa3_ctx->mmio, - ipa3_ctx->pdev)) { - IPAERR("fail to init ipahal\n"); - result = -EFAULT; - goto fail_ipahal; + + /* + * In Virtual mode, IPAHAL initialized at pre_init as + * there is no SMMU. In normal mode need to wait until + * SMMU is attached and thus initialization done here. + */ + if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL) { + if (ipahal_init(ipa3_ctx->ipa_hw_type, ipa3_ctx->mmio, + ipa3_ctx->pdev)) { + IPAERR("fail to init ipahal\n"); + result = -EFAULT; + goto fail_ipahal; + } } result = ipa3_init_hw(); @@ -4797,9 +4804,9 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, ipa3_free_dma_task_for_gsi(); fail_dma_task: fail_init_hw: - ipahal_destroy(); + if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL) + ipahal_destroy(); fail_ipahal: - return result; } @@ -5252,6 +5259,20 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, goto fail_remap; } + /* + * In Virtual mode, IPAHAL used to load the firmwares + * and there is no SMMU so IPAHAL is initialized here. + */ + if (ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_VIRTUAL) { + if (ipahal_init(ipa3_ctx->ipa_hw_type, + ipa3_ctx->mmio, + &(ipa3_ctx->master_pdev->dev))) { + IPAERR("fail to init ipahal\n"); + result = -EFAULT; + goto fail_ipahal_init; + } + } + mutex_init(&ipa3_ctx->ipa3_active_clients.mutex); IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, "PROXY_CLK_VOTE"); @@ -5538,6 +5559,9 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, fail_create_transport_wq: destroy_workqueue(ipa3_ctx->power_mgmt_wq); fail_init_hw: + if (ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_VIRTUAL) + ipahal_destroy(); +fail_ipahal_init: iounmap(ipa3_ctx->mmio); fail_remap: ipa3_disable_clks(); -- GitLab From 584b975af0d29c461920acb4d512f70b0bbe3661 Mon Sep 17 00:00:00 2001 From: Xiangning Yu Date: Thu, 7 Jun 2018 13:39:59 +0800 Subject: [PATCH 0770/1299] bonding: re-evaluate force_primary when the primary slave name changes [ Upstream commit eb55bbf865d9979098c6a7a17cbdb41237ece951 ] There is a timing issue under active-standy mode, when bond_enslave() is called, bond->params.primary might not be initialized yet. Any time the primary slave string changes, bond->force_primary should be set to true to make sure the primary becomes the active slave. Signed-off-by: Xiangning Yu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_options.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 5931aa2fe997..61084ba69a99 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -1142,6 +1142,7 @@ static int bond_option_primary_set(struct bonding *bond, slave->dev->name); rcu_assign_pointer(bond->primary_slave, slave); strcpy(bond->params.primary, slave->dev->name); + bond->force_primary = true; bond_select_active_slave(bond); goto out; } -- GitLab From 6e48ee025dc9a20cfe3fdc5a268cb0b971d58a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 8 Jun 2018 09:15:24 +0200 Subject: [PATCH 0771/1299] cdc_ncm: avoid padding beyond end of skb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 49c2c3f246e2fc3009039e31a826333dcd0283cd ] Commit 4a0e3e989d66 ("cdc_ncm: Add support for moving NDP to end of NCM frame") added logic to reserve space for the NDP at the end of the NTB/skb. This reservation did not take the final alignment of the NDP into account, causing us to reserve too little space. Additionally the padding prior to NDP addition did not ensure there was enough space for the NDP. The NTB/skb with the NDP appended would then exceed the configured max size. This caused the final padding of the NTB to use a negative count, padding to almost INT_MAX, and resulting in: [60103.825970] BUG: unable to handle kernel paging request at ffff9641f2004000 [60103.825998] IP: __memset+0x24/0x30 [60103.826001] PGD a6a06067 P4D a6a06067 PUD 4f65a063 PMD 72003063 PTE 0 [60103.826013] Oops: 0002 [#1] SMP NOPTI [60103.826018] Modules linked in: (removed( [60103.826158] CPU: 0 PID: 5990 Comm: Chrome_DevTools Tainted: G O 4.14.0-3-amd64 #1 Debian 4.14.17-1 [60103.826162] Hardware name: LENOVO 20081 BIOS 41CN28WW(V2.04) 05/03/2012 [60103.826166] task: ffff964193484fc0 task.stack: ffffb2890137c000 [60103.826171] RIP: 0010:__memset+0x24/0x30 [60103.826174] RSP: 0000:ffff964316c03b68 EFLAGS: 00010216 [60103.826178] RAX: 0000000000000000 RBX: 00000000fffffffd RCX: 000000001ffa5000 [60103.826181] RDX: 0000000000000005 RSI: 0000000000000000 RDI: ffff9641f2003ffc [60103.826184] RBP: ffff964192f6c800 R08: 00000000304d434e R09: ffff9641f1d2c004 [60103.826187] R10: 0000000000000002 R11: 00000000000005ae R12: ffff9642e6957a80 [60103.826190] R13: ffff964282ff2ee8 R14: 000000000000000d R15: ffff9642e4843900 [60103.826194] FS: 00007f395aaf6700(0000) GS:ffff964316c00000(0000) knlGS:0000000000000000 [60103.826197] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [60103.826200] CR2: ffff9641f2004000 CR3: 0000000013b0c000 CR4: 00000000000006f0 [60103.826204] Call Trace: [60103.826212] [60103.826225] cdc_ncm_fill_tx_frame+0x5e3/0x740 [cdc_ncm] [60103.826236] cdc_ncm_tx_fixup+0x57/0x70 [cdc_ncm] [60103.826246] usbnet_start_xmit+0x5d/0x710 [usbnet] [60103.826254] ? netif_skb_features+0x119/0x250 [60103.826259] dev_hard_start_xmit+0xa1/0x200 [60103.826267] sch_direct_xmit+0xf2/0x1b0 [60103.826273] __dev_queue_xmit+0x5e3/0x7c0 [60103.826280] ? ip_finish_output2+0x263/0x3c0 [60103.826284] ip_finish_output2+0x263/0x3c0 [60103.826289] ? ip_output+0x6c/0xe0 [60103.826293] ip_output+0x6c/0xe0 [60103.826298] ? ip_forward_options+0x1a0/0x1a0 [60103.826303] tcp_transmit_skb+0x516/0x9b0 [60103.826309] tcp_write_xmit+0x1aa/0xee0 [60103.826313] ? sch_direct_xmit+0x71/0x1b0 [60103.826318] tcp_tasklet_func+0x177/0x180 [60103.826325] tasklet_action+0x5f/0x110 [60103.826332] __do_softirq+0xde/0x2b3 [60103.826337] irq_exit+0xae/0xb0 [60103.826342] do_IRQ+0x81/0xd0 [60103.826347] common_interrupt+0x98/0x98 [60103.826351] [60103.826355] RIP: 0033:0x7f397bdf2282 [60103.826358] RSP: 002b:00007f395aaf57d8 EFLAGS: 00000206 ORIG_RAX: ffffffffffffff6e [60103.826362] RAX: 0000000000000000 RBX: 00002f07bc6d0900 RCX: 00007f39752d7fe7 [60103.826365] RDX: 0000000000000022 RSI: 0000000000000147 RDI: 00002f07baea02c0 [60103.826368] RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000 [60103.826371] R10: 00000000ffffffff R11: 0000000000000000 R12: 00002f07baea02c0 [60103.826373] R13: 00002f07bba227a0 R14: 00002f07bc6d090c R15: 0000000000000000 [60103.826377] Code: 90 90 90 90 90 90 90 0f 1f 44 00 00 49 89 f9 48 89 d1 83 e2 07 48 c1 e9 03 40 0f b6 f6 48 b8 01 01 01 01 01 01 01 01 48 0f af c6 48 ab 89 d1 f3 aa 4c 89 c8 c3 90 49 89 f9 40 88 f0 48 89 d1 [60103.826442] RIP: __memset+0x24/0x30 RSP: ffff964316c03b68 [60103.826444] CR2: ffff9641f2004000 Commit e1069bbfcf3b ("net: cdc_ncm: Reduce memory use when kernel memory low") made this bug much more likely to trigger by reducing the NTB size under memory pressure. Link: https://bugs.debian.org/893393 Reported-by: Горбешко Богдан Reported-and-tested-by: Dennis Wassenberg Cc: Enrico Mioso Fixes: 4a0e3e989d66 ("cdc_ncm: Add support for moving NDP to end of NCM frame") Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/cdc_ncm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 9e1b74590682..f5316ab68a0a 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1124,7 +1124,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) * accordingly. Otherwise, we should check here. */ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) - delayed_ndp_size = ctx->max_ndp_size; + delayed_ndp_size = ALIGN(ctx->max_ndp_size, ctx->tx_ndp_modulus); else delayed_ndp_size = 0; @@ -1285,7 +1285,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) /* If requested, put NDP at end of frame. */ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data; - cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size); + cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size - ctx->max_ndp_size); nth16->wNdpIndex = cpu_to_le16(skb_out->len); skb_put_data(skb_out, ctx->delayed_ndp16, ctx->max_ndp_size); -- GitLab From 6bcc27abfa62161ef7dae18dfe1bce70865b2aa8 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 11 Jun 2018 02:02:54 +0300 Subject: [PATCH 0772/1299] ipv6: allow PMTU exceptions to local routes [ Upstream commit 0975764684487bf3f7a47eef009e750ea41bd514 ] IPVS setups with local client and remote tunnel server need to create exception for the local virtual IP. What we do is to change PMTU from 64KB (on "lo") to 1460 in the common case. Suggested-by: Martin KaFai Lau Fixes: 45e4fd26683c ("ipv6: Only create RTF_CACHE routes after encountering pmtu exception") Fixes: 7343ff31ebf0 ("ipv6: Don't create clones of host routes.") Signed-off-by: Julian Anastasov Acked-by: David Ahern Acked-by: Martin KaFai Lau Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 375b20d5bbd7..60efd326014b 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1476,9 +1476,6 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, const struct in6_addr *daddr, *saddr; struct rt6_info *rt6 = (struct rt6_info *)dst; - if (rt6->rt6i_flags & RTF_LOCAL) - return; - if (dst_metric_locked(dst, RTAX_MTU)) return; -- GitLab From 73c0eab8d2158ef08120e979ce96f4fd80bc4488 Mon Sep 17 00:00:00 2001 From: Zhouyang Jia Date: Mon, 11 Jun 2018 13:26:35 +0800 Subject: [PATCH 0773/1299] net: dsa: add error handling for pskb_trim_rcsum [ Upstream commit 349b71d6f427ff8211adf50839dbbff3f27c1805 ] When pskb_trim_rcsum fails, the lack of error-handling code may cause unexpected results. This patch adds error-handling code after calling pskb_trim_rcsum. Signed-off-by: Zhouyang Jia Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/dsa/tag_trailer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c index fcc9aa72877d..374d586b4a2c 100644 --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c @@ -79,7 +79,8 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev, if (unlikely(ds->cpu_port_mask & BIT(source_port))) return NULL; - pskb_trim_rcsum(skb, skb->len - 4); + if (pskb_trim_rcsum(skb, skb->len - 4)) + return NULL; skb->dev = ds->ports[source_port].netdev; -- GitLab From 81d159444da5b4dc7fee9182b5f8596b84722789 Mon Sep 17 00:00:00 2001 From: Davide Caratti Date: Fri, 8 Jun 2018 05:02:31 +0200 Subject: [PATCH 0774/1299] net/sched: act_simple: fix parsing of TCA_DEF_DATA [ Upstream commit 8d499533e0bc02d44283dbdab03142b599b8ba16 ] use nla_strlcpy() to avoid copying data beyond the length of TCA_DEF_DATA netlink attribute, in case it is less than SIMP_MAX_DATA and it does not end with '\0' character. v2: fix errors in the commit message, thanks Hangbin Liu Fixes: fa1b1cff3d06 ("net_cls_act: Make act_simple use of netlink policy.") Signed-off-by: Davide Caratti Reviewed-by: Simon Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/act_simple.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index b5f80e675783..f3ed63aa4111 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c @@ -53,22 +53,22 @@ static void tcf_simp_release(struct tc_action *a, int bind) kfree(d->tcfd_defdata); } -static int alloc_defdata(struct tcf_defact *d, char *defdata) +static int alloc_defdata(struct tcf_defact *d, const struct nlattr *defdata) { d->tcfd_defdata = kzalloc(SIMP_MAX_DATA, GFP_KERNEL); if (unlikely(!d->tcfd_defdata)) return -ENOMEM; - strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); + nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); return 0; } -static void reset_policy(struct tcf_defact *d, char *defdata, +static void reset_policy(struct tcf_defact *d, const struct nlattr *defdata, struct tc_defact *p) { spin_lock_bh(&d->tcf_lock); d->tcf_action = p->action; memset(d->tcfd_defdata, 0, SIMP_MAX_DATA); - strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); + nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); spin_unlock_bh(&d->tcf_lock); } @@ -87,7 +87,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, struct tcf_defact *d; bool exists = false; int ret = 0, err; - char *defdata; if (nla == NULL) return -EINVAL; @@ -110,8 +109,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, return -EINVAL; } - defdata = nla_data(tb[TCA_DEF_DATA]); - if (!exists) { ret = tcf_idr_create(tn, parm->index, est, a, &act_simp_ops, bind, false); @@ -119,7 +116,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, return ret; d = to_defact(*a); - ret = alloc_defdata(d, defdata); + ret = alloc_defdata(d, tb[TCA_DEF_DATA]); if (ret < 0) { tcf_idr_release(*a, bind); return ret; @@ -133,7 +130,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, if (!ovr) return -EEXIST; - reset_policy(d, defdata, parm); + reset_policy(d, tb[TCA_DEF_DATA], parm); } if (ret == ACT_P_CREATED) -- GitLab From 39f4ae01c1d6c6891b46d6cb1f3f869823bac21a Mon Sep 17 00:00:00 2001 From: Frank van der Linden Date: Tue, 12 Jun 2018 23:09:37 +0000 Subject: [PATCH 0775/1299] tcp: verify the checksum of the first data segment in a new connection [ Upstream commit 4fd44a98ffe0d048246efef67ed640fdf2098a62 ] commit 079096f103fa ("tcp/dccp: install syn_recv requests into ehash table") introduced an optimization for the handling of child sockets created for a new TCP connection. But this optimization passes any data associated with the last ACK of the connection handshake up the stack without verifying its checksum, because it calls tcp_child_process(), which in turn calls tcp_rcv_state_process() directly. These lower-level processing functions do not do any checksum verification. Insert a tcp_checksum_complete call in the TCP_NEW_SYN_RECEIVE path to fix this. Fixes: 079096f103fa ("tcp/dccp: install syn_recv requests into ehash table") Signed-off-by: Frank van der Linden Signed-off-by: Eric Dumazet Tested-by: Balbir Singh Reviewed-by: Balbir Singh Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_ipv4.c | 4 ++++ net/ipv6/tcp_ipv6.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index cab4b935e474..a95ccdceb797 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1675,6 +1675,10 @@ int tcp_v4_rcv(struct sk_buff *skb) reqsk_put(req); goto discard_it; } + if (tcp_checksum_complete(skb)) { + reqsk_put(req); + goto csum_error; + } if (unlikely(sk->sk_state != TCP_LISTEN)) { inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 237cc6187c5a..35e8aef9ceed 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1453,6 +1453,10 @@ static int tcp_v6_rcv(struct sk_buff *skb) reqsk_put(req); goto discard_it; } + if (tcp_checksum_complete(skb)) { + reqsk_put(req); + goto csum_error; + } if (unlikely(sk->sk_state != TCP_LISTEN)) { inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup; -- GitLab From 91717ffc9057f38a0203a40ef36ae2e482fd7cbe Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 7 Jun 2018 13:39:49 -0700 Subject: [PATCH 0776/1299] socket: close race condition between sock_close() and sockfs_setattr() [ Upstream commit 6d8c50dcb029872b298eea68cc6209c866fd3e14 ] fchownat() doesn't even hold refcnt of fd until it figures out fd is really needed (otherwise is ignored) and releases it after it resolves the path. This means sock_close() could race with sockfs_setattr(), which leads to a NULL pointer dereference since typically we set sock->sk to NULL in ->release(). As pointed out by Al, this is unique to sockfs. So we can fix this in socket layer by acquiring inode_lock in sock_close() and checking against NULL in sockfs_setattr(). sock_release() is called in many places, only the sock_close() path matters here. And fortunately, this should not affect normal sock_close() as it is only called when the last fd refcnt is gone. It only affects sock_close() with a parallel sockfs_setattr() in progress, which is not common. Fixes: 86741ec25462 ("net: core: Add a UID field to struct sock.") Reported-by: shankarapailoor Cc: Tetsuo Handa Cc: Lorenzo Colitti Cc: Al Viro Signed-off-by: Cong Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/socket.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/net/socket.c b/net/socket.c index 43d2f17f5eea..8b2bef6cfe42 100644 --- a/net/socket.c +++ b/net/socket.c @@ -538,7 +538,10 @@ static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr) if (!err && (iattr->ia_valid & ATTR_UID)) { struct socket *sock = SOCKET_I(d_inode(dentry)); - sock->sk->sk_uid = iattr->ia_uid; + if (sock->sk) + sock->sk->sk_uid = iattr->ia_uid; + else + err = -ENOENT; } return err; @@ -588,12 +591,16 @@ EXPORT_SYMBOL(sock_alloc); * an inode not a file. */ -void sock_release(struct socket *sock) +static void __sock_release(struct socket *sock, struct inode *inode) { if (sock->ops) { struct module *owner = sock->ops->owner; + if (inode) + inode_lock(inode); sock->ops->release(sock); + if (inode) + inode_unlock(inode); sock->ops = NULL; module_put(owner); } @@ -608,6 +615,11 @@ void sock_release(struct socket *sock) } sock->file = NULL; } + +void sock_release(struct socket *sock) +{ + __sock_release(sock, NULL); +} EXPORT_SYMBOL(sock_release); void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags) @@ -1122,7 +1134,7 @@ static int sock_mmap(struct file *file, struct vm_area_struct *vma) static int sock_close(struct inode *inode, struct file *filp) { - sock_release(SOCKET_I(inode)); + __sock_release(SOCKET_I(inode), inode); return 0; } -- GitLab From 2e5d3168821d2ae523ebab5dd5df6a38f728b0d7 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Fri, 8 Jun 2018 11:35:40 +0200 Subject: [PATCH 0777/1299] udp: fix rx queue len reported by diag and proc interface [ Upstream commit 6c206b20092a3623184cff9470dba75d21507874 ] After commit 6b229cf77d68 ("udp: add batching to udp_rmem_release()") the sk_rmem_alloc field does not measure exactly anymore the receive queue length, because we batch the rmem release. The issue is really apparent only after commit 0d4a6608f68c ("udp: do rmem bulk free even if the rx sk queue is empty"): the user space can easily check for an empty socket with not-0 queue length reported by the 'ss' tool or the procfs interface. We need to use a custom UDP helper to report the correct queue length, taking into account the forward allocation deficit. Reported-by: trevor.francis@46labs.com Fixes: 6b229cf77d68 ("UDP: add batching to udp_rmem_release()") Signed-off-by: Paolo Abeni Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/transp_v6.h | 11 +++++++++-- include/net/udp.h | 5 +++++ net/ipv4/udp.c | 2 +- net/ipv4/udp_diag.c | 2 +- net/ipv6/datagram.c | 6 +++--- net/ipv6/udp.c | 3 ++- 6 files changed, 21 insertions(+), 8 deletions(-) diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index c4f5caaf3778..f6a3543e5247 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -45,8 +45,15 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg, struct flowi6 *fl6, struct ipcm6_cookie *ipc6, struct sockcm_cookie *sockc); -void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, - __u16 srcp, __u16 destp, int bucket); +void __ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, + __u16 srcp, __u16 destp, int rqueue, int bucket); +static inline void +ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, __u16 srcp, + __u16 destp, int bucket) +{ + __ip6_dgram_sock_seq_show(seq, sp, srcp, destp, sk_rmem_alloc_get(sp), + bucket); +} #define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006) diff --git a/include/net/udp.h b/include/net/udp.h index 6c759c8594e2..18391015233e 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -244,6 +244,11 @@ static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb, return htons((((u64) hash * (max - min)) >> 32) + min); } +static inline int udp_rqueue_get(struct sock *sk) +{ + return sk_rmem_alloc_get(sk) - READ_ONCE(udp_sk(sk)->forward_deficit); +} + /* net/ipv4/udp.c */ void udp_destruct_sock(struct sock *sk); void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b0ad62bd38f7..5752bf7593dc 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2720,7 +2720,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f, " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d", bucket, src, srcp, dest, destp, sp->sk_state, sk_wmem_alloc_get(sp), - sk_rmem_alloc_get(sp), + udp_rqueue_get(sp), 0, 0L, 0, from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), 0, sock_i_ino(sp), diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index d0390d844ac8..d9ad986c7b2c 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c @@ -163,7 +163,7 @@ static int udp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, void *info) { - r->idiag_rqueue = sk_rmem_alloc_get(sk); + r->idiag_rqueue = udp_rqueue_get(sk); r->idiag_wqueue = sk_wmem_alloc_get(sk); } diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 287112da3c06..453dc3726199 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -1026,8 +1026,8 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, } EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl); -void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, - __u16 srcp, __u16 destp, int bucket) +void __ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, + __u16 srcp, __u16 destp, int rqueue, int bucket) { const struct in6_addr *dest, *src; @@ -1043,7 +1043,7 @@ void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, dest->s6_addr32[2], dest->s6_addr32[3], destp, sp->sk_state, sk_wmem_alloc_get(sp), - sk_rmem_alloc_get(sp), + rqueue, 0, 0L, 0, from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), 0, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 0146dcdc5c40..330d5ea8451b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1503,7 +1503,8 @@ int udp6_seq_show(struct seq_file *seq, void *v) struct inet_sock *inet = inet_sk(v); __u16 srcp = ntohs(inet->inet_sport); __u16 destp = ntohs(inet->inet_dport); - ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket); + __ip6_dgram_sock_seq_show(seq, v, srcp, destp, + udp_rqueue_get(v), bucket); } return 0; } -- GitLab From 5320e035d7bbdade3755f90dc9b55ee542edc4d3 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Wed, 6 Jun 2018 11:23:01 -0400 Subject: [PATCH 0778/1299] net: in virtio_net_hdr only add VLAN_HLEN to csum_start if payload holds vlan [ Upstream commit fd3a88625844907151737fc3b4201676effa6d27 ] Tun, tap, virtio, packet and uml vector all use struct virtio_net_hdr to communicate packet metadata to userspace. For skbuffs with vlan, the first two return the packet as it may have existed on the wire, inserting the VLAN tag in the user buffer. Then virtio_net_hdr.csum_start needs to be adjusted by VLAN_HLEN bytes. Commit f09e2249c4f5 ("macvtap: restore vlan header on user read") added this feature to macvtap. Commit 3ce9b20f1971 ("macvtap: Fix csum_start when VLAN tags are present") then fixed up csum_start. Virtio, packet and uml do not insert the vlan header in the user buffer. When introducing virtio_net_hdr_from_skb to deduplicate filling in the virtio_net_hdr, the variant from macvtap which adds VLAN_HLEN was applied uniformly, breaking csum offset for packets with vlan on virtio and packet. Make insertion of VLAN_HLEN optional. Convert the callers to pass it when needed. Fixes: e858fae2b0b8f4 ("virtio_net: use common code for virtio_net_hdr and skb GSO conversion") Fixes: 1276f24eeef2 ("packet: use common code for virtio_net_hdr and skb GSO conversion") Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/tap.c | 5 ++++- drivers/net/tun.c | 3 ++- drivers/net/virtio_net.c | 3 ++- include/linux/virtio_net.h | 11 ++++------- net/packet/af_packet.c | 4 ++-- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/net/tap.c b/drivers/net/tap.c index bfd4ded0a53f..773a3fea8f0e 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -777,13 +777,16 @@ static ssize_t tap_put_user(struct tap_queue *q, int total; if (q->flags & IFF_VNET_HDR) { + int vlan_hlen = skb_vlan_tag_present(skb) ? VLAN_HLEN : 0; struct virtio_net_hdr vnet_hdr; + vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz); if (iov_iter_count(iter) < vnet_hdr_len) return -EINVAL; if (virtio_net_hdr_from_skb(skb, &vnet_hdr, - tap_is_little_endian(q), true)) + tap_is_little_endian(q), true, + vlan_hlen)) BUG(); if (copy_to_iter(&vnet_hdr, sizeof(vnet_hdr), iter) != diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 3d9ad11e4f28..cb17ffadfc30 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1648,7 +1648,8 @@ static ssize_t tun_put_user(struct tun_struct *tun, return -EINVAL; if (virtio_net_hdr_from_skb(skb, &gso, - tun_is_little_endian(tun), true)) { + tun_is_little_endian(tun), true, + vlan_hlen)) { struct skb_shared_info *sinfo = skb_shinfo(skb); pr_err("unexpected GSO type: " "0x%x, gso_size %d, hdr_len %d\n", diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 9e93e7a5df7e..910c46b47769 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1237,7 +1237,8 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) hdr = skb_vnet_hdr(skb); if (virtio_net_hdr_from_skb(skb, &hdr->hdr, - virtio_is_little_endian(vi->vdev), false)) + virtio_is_little_endian(vi->vdev), false, + 0)) BUG(); if (vi->mergeable_rx_bufs) diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index f144216febc6..9397628a1967 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -58,7 +58,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, struct virtio_net_hdr *hdr, bool little_endian, - bool has_data_valid) + bool has_data_valid, + int vlan_hlen) { memset(hdr, 0, sizeof(*hdr)); /* no info leak */ @@ -83,12 +84,8 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, if (skb->ip_summed == CHECKSUM_PARTIAL) { hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; - if (skb_vlan_tag_present(skb)) - hdr->csum_start = __cpu_to_virtio16(little_endian, - skb_checksum_start_offset(skb) + VLAN_HLEN); - else - hdr->csum_start = __cpu_to_virtio16(little_endian, - skb_checksum_start_offset(skb)); + hdr->csum_start = __cpu_to_virtio16(little_endian, + skb_checksum_start_offset(skb) + vlan_hlen); hdr->csum_offset = __cpu_to_virtio16(little_endian, skb->csum_offset); } else if (has_data_valid && diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 7806e166669a..4fe2e34522d6 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2046,7 +2046,7 @@ static int packet_rcv_vnet(struct msghdr *msg, const struct sk_buff *skb, return -EINVAL; *len -= sizeof(vnet_hdr); - if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true)) + if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true, 0)) return -EINVAL; return memcpy_to_msg(msg, (void *)&vnet_hdr, sizeof(vnet_hdr)); @@ -2313,7 +2313,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, if (do_vnet) { if (virtio_net_hdr_from_skb(skb, h.raw + macoff - sizeof(struct virtio_net_hdr), - vio_le(), true)) { + vio_le(), true, 0)) { spin_lock(&sk->sk_receive_queue.lock); goto drop_n_account; } -- GitLab From 244c10f9bfa35b59e4acf61a0fb15a94f6110991 Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Wed, 6 Jun 2018 21:32:51 +0000 Subject: [PATCH 0779/1299] hv_netvsc: Fix a network regression after ifdown/ifup [ Upstream commit 52acf73b6e9a6962045feb2ba5a8921da2201915 ] Recently people reported the NIC stops working after "ifdown eth0; ifup eth0". It turns out in this case the TX queues are not enabled, after the refactoring of the common detach logic: when the NIC has sub-channels, usually we enable all the TX queues after all sub-channels are set up: see rndis_set_subchannel() -> netif_device_attach(), but in the case of "ifdown eth0; ifup eth0" where the number of channels doesn't change, we also must make sure the TX queues are enabled. The patch fixes the regression. Fixes: 7b2ee50c0cd5 ("hv_netvsc: common detach logic") Signed-off-by: Dexuan Cui Cc: Stephen Hemminger Cc: K. Y. Srinivasan Cc: Haiyang Zhang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/hyperv/netvsc_drv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 3a7241c8713c..6890478a0851 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -123,8 +123,10 @@ static int netvsc_open(struct net_device *net) } rdev = nvdev->extension; - if (!rdev->link_state) + if (!rdev->link_state) { netif_carrier_on(net); + netif_tx_wake_all_queues(net); + } if (vf_netdev) { /* Setting synthetic device up transparently sets -- GitLab From 5e8a5c30546f731b20591eb8cffc7db299286d05 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 15 Jun 2018 03:07:45 +0200 Subject: [PATCH 0780/1299] tls: fix use-after-free in tls_push_record [ Upstream commit a447da7d00410278c90d3576782a43f8b675d7be ] syzkaller managed to trigger a use-after-free in tls like the following: BUG: KASAN: use-after-free in tls_push_record.constprop.15+0x6a2/0x810 [tls] Write of size 1 at addr ffff88037aa08000 by task a.out/2317 CPU: 3 PID: 2317 Comm: a.out Not tainted 4.17.0+ #144 Hardware name: LENOVO 20FBCTO1WW/20FBCTO1WW, BIOS N1FET47W (1.21 ) 11/28/2016 Call Trace: dump_stack+0x71/0xab print_address_description+0x6a/0x280 kasan_report+0x258/0x380 ? tls_push_record.constprop.15+0x6a2/0x810 [tls] tls_push_record.constprop.15+0x6a2/0x810 [tls] tls_sw_push_pending_record+0x2e/0x40 [tls] tls_sk_proto_close+0x3fe/0x710 [tls] ? tcp_check_oom+0x4c0/0x4c0 ? tls_write_space+0x260/0x260 [tls] ? kmem_cache_free+0x88/0x1f0 inet_release+0xd6/0x1b0 __sock_release+0xc0/0x240 sock_close+0x11/0x20 __fput+0x22d/0x660 task_work_run+0x114/0x1a0 do_exit+0x71a/0x2780 ? mm_update_next_owner+0x650/0x650 ? handle_mm_fault+0x2f5/0x5f0 ? __do_page_fault+0x44f/0xa50 ? mm_fault_error+0x2d0/0x2d0 do_group_exit+0xde/0x300 __x64_sys_exit_group+0x3a/0x50 do_syscall_64+0x9a/0x300 ? page_fault+0x8/0x30 entry_SYSCALL_64_after_hwframe+0x44/0xa9 This happened through fault injection where aead_req allocation in tls_do_encryption() eventually failed and we returned -ENOMEM from the function. Turns out that the use-after-free is triggered from tls_sw_sendmsg() in the second tls_push_record(). The error then triggers a jump to waiting for memory in sk_stream_wait_memory() resp. returning immediately in case of MSG_DONTWAIT. What follows is the trim_both_sgl(sk, orig_size), which drops elements from the sg list added via tls_sw_sendmsg(). Now the use-after-free gets triggered when the socket is being closed, where tls_sk_proto_close() callback is invoked. The tls_complete_pending_work() will figure that there's a pending closed tls record to be flushed and thus calls into the tls_push_pending_closed_record() from there. ctx->push_pending_record() is called from the latter, which is the tls_sw_push_pending_record() from sw path. This again calls into tls_push_record(). And here the tls_fill_prepend() will panic since the buffer address has been freed earlier via trim_both_sgl(). One way to fix it is to move the aead request allocation out of tls_do_encryption() early into tls_push_record(). This means we don't prep the tls header and advance state to the TLS_PENDING_CLOSED_RECORD before allocation which could potentially fail happened. That fixes the issue on my side. Fixes: 3c4d7559159b ("tls: kernel TLS support") Reported-by: syzbot+5c74af81c547738e1684@syzkaller.appspotmail.com Reported-by: syzbot+709f2810a6a05f11d4d3@syzkaller.appspotmail.com Signed-off-by: Daniel Borkmann Acked-by: Dave Watson Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/tls/tls_sw.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 83f886d7c1f8..3c86614462f6 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -211,18 +211,12 @@ static void tls_free_both_sg(struct sock *sk) } static int tls_do_encryption(struct tls_context *tls_ctx, - struct tls_sw_context *ctx, size_t data_len, - gfp_t flags) + struct tls_sw_context *ctx, + struct aead_request *aead_req, + size_t data_len) { - unsigned int req_size = sizeof(struct aead_request) + - crypto_aead_reqsize(ctx->aead_send); - struct aead_request *aead_req; int rc; - aead_req = kzalloc(req_size, flags); - if (!aead_req) - return -ENOMEM; - ctx->sg_encrypted_data[0].offset += tls_ctx->prepend_size; ctx->sg_encrypted_data[0].length -= tls_ctx->prepend_size; @@ -235,7 +229,6 @@ static int tls_do_encryption(struct tls_context *tls_ctx, ctx->sg_encrypted_data[0].offset -= tls_ctx->prepend_size; ctx->sg_encrypted_data[0].length += tls_ctx->prepend_size; - kfree(aead_req); return rc; } @@ -244,8 +237,14 @@ static int tls_push_record(struct sock *sk, int flags, { struct tls_context *tls_ctx = tls_get_ctx(sk); struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx); + struct aead_request *req; int rc; + req = kzalloc(sizeof(struct aead_request) + + crypto_aead_reqsize(ctx->aead_send), sk->sk_allocation); + if (!req) + return -ENOMEM; + sg_mark_end(ctx->sg_plaintext_data + ctx->sg_plaintext_num_elem - 1); sg_mark_end(ctx->sg_encrypted_data + ctx->sg_encrypted_num_elem - 1); @@ -261,15 +260,14 @@ static int tls_push_record(struct sock *sk, int flags, tls_ctx->pending_open_record_frags = 0; set_bit(TLS_PENDING_CLOSED_RECORD, &tls_ctx->flags); - rc = tls_do_encryption(tls_ctx, ctx, ctx->sg_plaintext_size, - sk->sk_allocation); + rc = tls_do_encryption(tls_ctx, ctx, req, ctx->sg_plaintext_size); if (rc < 0) { /* If we are called from write_space and * we fail, we need to set this SOCK_NOSPACE * to trigger another write_space in the future. */ set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); - return rc; + goto out_req; } free_sg(sk, ctx->sg_plaintext_data, &ctx->sg_plaintext_num_elem, @@ -284,6 +282,8 @@ static int tls_push_record(struct sock *sk, int flags, tls_err_abort(sk); tls_advance_record_sn(sk, tls_ctx); +out_req: + kfree(req); return rc; } -- GitLab From 84f4d2c6dabef6622f4d22a592cf4d1dca9e7dae Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 19 Oct 2017 15:46:45 -0400 Subject: [PATCH 0781/1299] NFSv4.1: Fix up replays of interrupted requests commit 3be0f80b5fe9c16eca2d538f799b94ca8aa59433 upstream. If the previous request on a slot was interrupted before it was processed by the server, then our slot sequence number may be out of whack, and so we try the next operation using the old sequence number. The problem with this, is that not all servers check to see that the client is replaying the same operations as previously when they decide to go to the replay cache, and so instead of the expected error of NFS4ERR_SEQ_FALSE_RETRY, we get a replay of the old reply, which could (if the operations match up) be mistaken by the client for a new reply. To fix this, we attempt to send a COMPOUND containing only the SEQUENCE op in order to resync our slot sequence number. Cc: Olga Kornievskaia [olga.kornievskaia@gmail.com: fix an Oops] Signed-off-by: Trond Myklebust Signed-off-by: Anna Schumaker Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4_fs.h | 2 +- fs/nfs/nfs4proc.c | 148 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 103 insertions(+), 47 deletions(-) diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index dcfcf7fd7438..a73144b3cb8c 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -465,7 +465,7 @@ extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid); extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid); extern void nfs_release_seqid(struct nfs_seqid *seqid); extern void nfs_free_seqid(struct nfs_seqid *seqid); -extern int nfs4_setup_sequence(const struct nfs_client *client, +extern int nfs4_setup_sequence(struct nfs_client *client, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, struct rpc_task *task); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ae8f43d270d6..8ff98bbe479b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -96,6 +96,10 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, struct nfs_open_context *ctx, struct nfs4_label *ilabel, struct nfs4_label *olabel); #ifdef CONFIG_NFS_V4_1 +static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, + struct rpc_cred *cred, + struct nfs4_slot *slot, + bool is_privileged); static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *, struct rpc_cred *); static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *, @@ -641,13 +645,14 @@ static int nfs40_sequence_done(struct rpc_task *task, #if defined(CONFIG_NFS_V4_1) -static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) +static void nfs41_release_slot(struct nfs4_slot *slot) { struct nfs4_session *session; struct nfs4_slot_table *tbl; - struct nfs4_slot *slot = res->sr_slot; bool send_new_highest_used_slotid = false; + if (!slot) + return; tbl = slot->table; session = tbl->session; @@ -673,13 +678,18 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) send_new_highest_used_slotid = false; out_unlock: spin_unlock(&tbl->slot_tbl_lock); - res->sr_slot = NULL; if (send_new_highest_used_slotid) nfs41_notify_server(session->clp); if (waitqueue_active(&tbl->slot_waitq)) wake_up_all(&tbl->slot_waitq); } +static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) +{ + nfs41_release_slot(res->sr_slot); + res->sr_slot = NULL; +} + static int nfs41_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res) { @@ -707,13 +717,6 @@ static int nfs41_sequence_process(struct rpc_task *task, /* Check the SEQUENCE operation status */ switch (res->sr_status) { case 0: - /* If previous op on slot was interrupted and we reused - * the seq# and got a reply from the cache, then retry - */ - if (task->tk_status == -EREMOTEIO && interrupted) { - ++slot->seq_nr; - goto retry_nowait; - } /* Update the slot's sequence and clientid lease timer */ slot->seq_done = 1; clp = session->clp; @@ -747,16 +750,16 @@ static int nfs41_sequence_process(struct rpc_task *task, * The slot id we used was probably retired. Try again * using a different slot id. */ + if (slot->seq_nr < slot->table->target_highest_slotid) + goto session_recover; goto retry_nowait; case -NFS4ERR_SEQ_MISORDERED: /* * Was the last operation on this sequence interrupted? * If so, retry after bumping the sequence number. */ - if (interrupted) { - ++slot->seq_nr; - goto retry_nowait; - } + if (interrupted) + goto retry_new_seq; /* * Could this slot have been previously retired? * If so, then the server may be expecting seq_nr = 1! @@ -765,10 +768,11 @@ static int nfs41_sequence_process(struct rpc_task *task, slot->seq_nr = 1; goto retry_nowait; } - break; + goto session_recover; case -NFS4ERR_SEQ_FALSE_RETRY: - ++slot->seq_nr; - goto retry_nowait; + if (interrupted) + goto retry_new_seq; + goto session_recover; default: /* Just update the slot sequence no. */ slot->seq_done = 1; @@ -778,6 +782,11 @@ static int nfs41_sequence_process(struct rpc_task *task, dprintk("%s: Error %d free the slot \n", __func__, res->sr_status); out_noaction: return ret; +session_recover: + nfs4_schedule_session_recovery(session, res->sr_status); + goto retry_nowait; +retry_new_seq: + ++slot->seq_nr; retry_nowait: if (rpc_restart_call_prepare(task)) { nfs41_sequence_free_slot(res); @@ -854,6 +863,17 @@ static const struct rpc_call_ops nfs41_call_sync_ops = { .rpc_call_done = nfs41_call_sync_done, }; +static void +nfs4_sequence_process_interrupted(struct nfs_client *client, + struct nfs4_slot *slot, struct rpc_cred *cred) +{ + struct rpc_task *task; + + task = _nfs41_proc_sequence(client, cred, slot, true); + if (!IS_ERR(task)) + rpc_put_task_async(task); +} + #else /* !CONFIG_NFS_V4_1 */ static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res) @@ -874,9 +894,34 @@ int nfs4_sequence_done(struct rpc_task *task, } EXPORT_SYMBOL_GPL(nfs4_sequence_done); +static void +nfs4_sequence_process_interrupted(struct nfs_client *client, + struct nfs4_slot *slot, struct rpc_cred *cred) +{ + WARN_ON_ONCE(1); + slot->interrupted = 0; +} + #endif /* !CONFIG_NFS_V4_1 */ -int nfs4_setup_sequence(const struct nfs_client *client, +static +void nfs4_sequence_attach_slot(struct nfs4_sequence_args *args, + struct nfs4_sequence_res *res, + struct nfs4_slot *slot) +{ + if (!slot) + return; + slot->privileged = args->sa_privileged ? 1 : 0; + args->sa_slot = slot; + + res->sr_slot = slot; + res->sr_timestamp = jiffies; + res->sr_status_flags = 0; + res->sr_status = 1; + +} + +int nfs4_setup_sequence(struct nfs_client *client, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, struct rpc_task *task) @@ -894,29 +939,28 @@ int nfs4_setup_sequence(const struct nfs_client *client, task->tk_timeout = 0; } - spin_lock(&tbl->slot_tbl_lock); - /* The state manager will wait until the slot table is empty */ - if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged) - goto out_sleep; + for (;;) { + spin_lock(&tbl->slot_tbl_lock); + /* The state manager will wait until the slot table is empty */ + if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged) + goto out_sleep; + + slot = nfs4_alloc_slot(tbl); + if (IS_ERR(slot)) { + /* Try again in 1/4 second */ + if (slot == ERR_PTR(-ENOMEM)) + task->tk_timeout = HZ >> 2; + goto out_sleep; + } + spin_unlock(&tbl->slot_tbl_lock); - slot = nfs4_alloc_slot(tbl); - if (IS_ERR(slot)) { - /* Try again in 1/4 second */ - if (slot == ERR_PTR(-ENOMEM)) - task->tk_timeout = HZ >> 2; - goto out_sleep; + if (likely(!slot->interrupted)) + break; + nfs4_sequence_process_interrupted(client, + slot, task->tk_msg.rpc_cred); } - spin_unlock(&tbl->slot_tbl_lock); - - slot->privileged = args->sa_privileged ? 1 : 0; - args->sa_slot = slot; - res->sr_slot = slot; - if (session) { - res->sr_timestamp = jiffies; - res->sr_status_flags = 0; - res->sr_status = 1; - } + nfs4_sequence_attach_slot(args, res, slot); trace_nfs4_setup_sequence(session, args); out_start: @@ -8151,6 +8195,7 @@ static const struct rpc_call_ops nfs41_sequence_ops = { static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred, + struct nfs4_slot *slot, bool is_privileged) { struct nfs4_sequence_data *calldata; @@ -8164,15 +8209,18 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, .callback_ops = &nfs41_sequence_ops, .flags = RPC_TASK_ASYNC | RPC_TASK_TIMEOUT, }; + struct rpc_task *ret; + ret = ERR_PTR(-EIO); if (!atomic_inc_not_zero(&clp->cl_count)) - return ERR_PTR(-EIO); + goto out_err; + + ret = ERR_PTR(-ENOMEM); calldata = kzalloc(sizeof(*calldata), GFP_NOFS); - if (calldata == NULL) { - nfs_put_client(clp); - return ERR_PTR(-ENOMEM); - } + if (calldata == NULL) + goto out_put_clp; nfs4_init_sequence(&calldata->args, &calldata->res, 0); + nfs4_sequence_attach_slot(&calldata->args, &calldata->res, slot); if (is_privileged) nfs4_set_sequence_privileged(&calldata->args); msg.rpc_argp = &calldata->args; @@ -8180,7 +8228,15 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, calldata->clp = clp; task_setup_data.callback_data = calldata; - return rpc_run_task(&task_setup_data); + ret = rpc_run_task(&task_setup_data); + if (IS_ERR(ret)) + goto out_err; + return ret; +out_put_clp: + nfs_put_client(clp); +out_err: + nfs41_release_slot(slot); + return ret; } static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags) @@ -8190,7 +8246,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) return -EAGAIN; - task = _nfs41_proc_sequence(clp, cred, false); + task = _nfs41_proc_sequence(clp, cred, NULL, false); if (IS_ERR(task)) ret = PTR_ERR(task); else @@ -8204,7 +8260,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) struct rpc_task *task; int ret; - task = _nfs41_proc_sequence(clp, cred, true); + task = _nfs41_proc_sequence(clp, cred, NULL, true); if (IS_ERR(task)) { ret = PTR_ERR(task); goto out; -- GitLab From f70af46a52b3c354643c92e8a59b34a86472559d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sat, 12 May 2018 19:55:00 -0400 Subject: [PATCH 0782/1299] ext4: fix hole length detection in ext4_ind_map_blocks() commit 2ee3ee06a8fd792765fa3267ddf928997797eec5 upstream. When ext4_ind_map_blocks() computes a length of a hole, it doesn't count with the fact that mapped offset may be somewhere in the middle of the completely empty subtree. In such case it will return too large length of the hole which then results in lseek(SEEK_DATA) to end up returning an incorrect offset beyond the end of the hole. Fix the problem by correctly taking offset within a subtree into account when computing a length of a hole. Fixes: facab4d9711e7aa3532cb82643803e8f1b9518e8 CC: stable@vger.kernel.org Reported-by: Jeff Mahoney Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/ext4/indirect.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index c32802c956d5..bf7fa1507e81 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -561,10 +561,16 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, unsigned epb = inode->i_sb->s_blocksize / sizeof(u32); int i; - /* Count number blocks in a subtree under 'partial' */ - count = 1; - for (i = 0; partial + i != chain + depth - 1; i++) - count *= epb; + /* + * Count number blocks in a subtree under 'partial'. At each + * level we count number of complete empty subtrees beyond + * current offset and then descend into the subtree only + * partially beyond current offset. + */ + count = 0; + for (i = partial - chain + 1; i < depth; i++) + count = count * epb + (epb - offsets[i] - 1); + count++; /* Fill in size of a hole we found */ map->m_pblk = 0; map->m_len = min_t(unsigned int, map->m_len, count); -- GitLab From bd713edfc85d20ba6a8ea970c0f542774084a4d2 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Sun, 13 May 2018 19:28:35 -0400 Subject: [PATCH 0783/1299] ext4: update mtime in ext4_punch_hole even if no blocks are released commit eee597ac931305eff3d3fd1d61d6aae553bc0984 upstream. Currently in ext4_punch_hole we're going to skip the mtime update if there are no actual blocks to release. However we've actually modified the file by zeroing the partial block so the mtime should be updated. Moreover the sync and datasync handling is skipped as well, which is also wrong. Fix it. Signed-off-by: Lukas Czerner Signed-off-by: Theodore Ts'o Reported-by: Joe Habermann Cc: Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 09014c3c4207..90c485ea11fa 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4246,28 +4246,28 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) EXT4_BLOCK_SIZE_BITS(sb); stop_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb); - /* If there are no blocks to remove, return now */ - if (first_block >= stop_block) - goto out_stop; + /* If there are blocks to remove, do it */ + if (stop_block > first_block) { - down_write(&EXT4_I(inode)->i_data_sem); - ext4_discard_preallocations(inode); + down_write(&EXT4_I(inode)->i_data_sem); + ext4_discard_preallocations(inode); - ret = ext4_es_remove_extent(inode, first_block, - stop_block - first_block); - if (ret) { - up_write(&EXT4_I(inode)->i_data_sem); - goto out_stop; - } + ret = ext4_es_remove_extent(inode, first_block, + stop_block - first_block); + if (ret) { + up_write(&EXT4_I(inode)->i_data_sem); + goto out_stop; + } - if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) - ret = ext4_ext_remove_space(inode, first_block, - stop_block - 1); - else - ret = ext4_ind_remove_space(handle, inode, first_block, - stop_block); + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) + ret = ext4_ext_remove_space(inode, first_block, + stop_block - 1); + else + ret = ext4_ind_remove_space(handle, inode, first_block, + stop_block); - up_write(&EXT4_I(inode)->i_data_sem); + up_write(&EXT4_I(inode)->i_data_sem); + } if (IS_SYNC(inode)) ext4_handle_sync(handle); -- GitLab From e81d371dac30019816a1c5a3a2c4c44bb3c68558 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 22 May 2018 16:15:24 -0400 Subject: [PATCH 0784/1299] ext4: do not allow external inodes for inline data commit 117166efb1ee8f13c38f9e96b258f16d4923f888 upstream. The inline data feature was implemented before we added support for external inodes for xattrs. It makes no sense to support that combination, but the problem is that there are a number of extended attribute checks that are skipped if e_value_inum is non-zero. Unfortunately, the inline data code is completely e_value_inum unaware, and attempts to interpret the xattr fields as if it were an inline xattr --- at which point, Hilarty Ensues. This addresses CVE-2018-11412. https://bugzilla.kernel.org/show_bug.cgi?id=199803 Reported-by: Jann Horn Reviewed-by: Andreas Dilger Signed-off-by: Theodore Ts'o Fixes: e50e5129f384 ("ext4: xattr-in-inode support") Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inline.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index fd9501977f1c..8f5dc243effd 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -150,6 +150,12 @@ int ext4_find_inline_data_nolock(struct inode *inode) goto out; if (!is.s.not_found) { + if (is.s.here->e_value_inum) { + EXT4_ERROR_INODE(inode, "inline data xattr refers " + "to an external xattr inode"); + error = -EFSCORRUPTED; + goto out; + } EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - (void *)ext4_raw_inode(&is.iloc)); EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + -- GitLab From 02d45ec6e770dcad4a48ad185feff588e3dcedc2 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 22 May 2018 17:14:07 -0400 Subject: [PATCH 0785/1299] ext4: bubble errors from ext4_find_inline_data_nolock() up to ext4_iget() commit eb9b5f01c33adebc31cbc236c02695f605b0e417 upstream. If ext4_find_inline_data_nolock() returns an error it needs to get reflected up to ext4_iget(). In order to fix this, ext4_iget_extra_inode() needs to return an error (and not return void). This is related to "ext4: do not allow external inodes for inline data" (which fixes CVE-2018-11412) in that in the errors=continue case, it would be useful to for userspace to receive an error indicating that file system is corrupted. Signed-off-by: Theodore Ts'o Reviewed-by: Andreas Dilger Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 90c485ea11fa..bd6453e78992 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4634,19 +4634,21 @@ static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, } } -static inline void ext4_iget_extra_inode(struct inode *inode, +static inline int ext4_iget_extra_inode(struct inode *inode, struct ext4_inode *raw_inode, struct ext4_inode_info *ei) { __le32 *magic = (void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize; + if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize + sizeof(__le32) <= EXT4_INODE_SIZE(inode->i_sb) && *magic == cpu_to_le32(EXT4_XATTR_MAGIC)) { ext4_set_inode_state(inode, EXT4_STATE_XATTR); - ext4_find_inline_data_nolock(inode); + return ext4_find_inline_data_nolock(inode); } else EXT4_I(inode)->i_inline_off = 0; + return 0; } int ext4_get_projid(struct inode *inode, kprojid_t *projid) @@ -4826,7 +4828,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ei->i_extra_isize = sizeof(struct ext4_inode) - EXT4_GOOD_OLD_INODE_SIZE; } else { - ext4_iget_extra_inode(inode, raw_inode, ei); + ret = ext4_iget_extra_inode(inode, raw_inode, ei); + if (ret) + goto bad_inode; } } -- GitLab From 21542545990c5aba4b919ac0f8c8ae6a408b49d4 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 23 May 2018 11:31:03 -0400 Subject: [PATCH 0786/1299] ext4: correctly handle a zero-length xattr with a non-zero e_value_offs commit 8a2b307c21d4b290e3cbe33f768f194286d07c23 upstream. Ext4 will always create ext4 extended attributes which do not have a value (where e_value_size is zero) with e_value_offs set to zero. In most places e_value_offs will not be used in a substantive way if e_value_size is zero. There was one exception to this, which is in ext4_xattr_set_entry(), where if there is a maliciously crafted file system where there is an extended attribute with e_value_offs is non-zero and e_value_size is 0, the attempt to remove this xattr will result in a negative value getting passed to memmove, leading to the following sadness: [ 41.225365] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null) [ 44.538641] BUG: unable to handle kernel paging request at ffff9ec9a3000000 [ 44.538733] IP: __memmove+0x81/0x1a0 [ 44.538755] PGD 1249bd067 P4D 1249bd067 PUD 1249c1067 PMD 80000001230000e1 [ 44.538793] Oops: 0003 [#1] SMP PTI [ 44.539074] CPU: 0 PID: 1470 Comm: poc Not tainted 4.16.0-rc1+ #1 ... [ 44.539475] Call Trace: [ 44.539832] ext4_xattr_set_entry+0x9e7/0xf80 ... [ 44.539972] ext4_xattr_block_set+0x212/0xea0 ... [ 44.540041] ext4_xattr_set_handle+0x514/0x610 [ 44.540065] ext4_xattr_set+0x7f/0x120 [ 44.540090] __vfs_removexattr+0x4d/0x60 [ 44.540112] vfs_removexattr+0x75/0xe0 [ 44.540132] removexattr+0x4d/0x80 ... [ 44.540279] path_removexattr+0x91/0xb0 [ 44.540300] SyS_removexattr+0xf/0x20 [ 44.540322] do_syscall_64+0x71/0x120 [ 44.540344] entry_SYSCALL_64_after_hwframe+0x21/0x86 https://bugzilla.kernel.org/show_bug.cgi?id=199347 This addresses CVE-2018-10840. Reported-by: "Xu, Wen" Signed-off-by: Theodore Ts'o Reviewed-by: Andreas Dilger Cc: stable@kernel.org Fixes: dec214d00e0d7 ("ext4: xattr inode deduplication") Signed-off-by: Greg Kroah-Hartman --- fs/ext4/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 1718354e6322..ed1cf24a7831 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1687,7 +1687,7 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, /* No failures allowed past this point. */ - if (!s->not_found && here->e_value_offs) { + if (!s->not_found && here->e_value_size && here->e_value_offs) { /* Remove the old value. */ void *first_val = s->base + min_offs; size_t offs = le16_to_cpu(here->e_value_offs); -- GitLab From f3233cb2485ce482cc2285354dcfca90094442ac Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 25 May 2018 12:51:25 -0400 Subject: [PATCH 0787/1299] ext4: fix fencepost error in check for inode count overflow during resize commit 4f2f76f751433908364ccff82f437a57d0e6e9b7 upstream. ext4_resize_fs() has an off-by-one bug when checking whether growing of a filesystem will not overflow inode count. As a result it allows a filesystem with 8192 inodes per group to grow to 64TB which overflows inode count to 0 and makes filesystem unusable. Fix it. Cc: stable@vger.kernel.org Fixes: 3f8a6411fbada1fa482276591e037f3b1adcf55b Reported-by: Jaco Kroon Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- fs/ext4/resize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 1dac59c24792..823c0b82dfeb 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -1905,7 +1905,7 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) return 0; n_group = ext4_get_group_number(sb, n_blocks_count - 1); - if (n_group > (0xFFFFFFFFUL / EXT4_INODES_PER_GROUP(sb))) { + if (n_group >= (0xFFFFFFFFUL / EXT4_INODES_PER_GROUP(sb))) { ext4_warning(sb, "resize would cause inodes_count overflow"); return -EINVAL; } -- GitLab From c81a6be9da6d9fd9264cf759f2676b07d0727b41 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 7 May 2018 19:10:31 +0900 Subject: [PATCH 0788/1299] driver core: Don't ignore class_dir_create_and_add() failure. commit 84d0c27d6233a9ba0578b20f5a09701eb66cee42 upstream. syzbot is hitting WARN() at kernfs_add_one() [1]. This is because kernfs_create_link() is confused by previous device_add() call which continued without setting dev->kobj.parent field when get_device_parent() failed by memory allocation fault injection. Fix this by propagating the error from class_dir_create_and_add() to the calllers of get_device_parent(). [1] https://syzkaller.appspot.com/bug?id=fae0fb607989ea744526d1c082a5b8de6529116f Signed-off-by: Tetsuo Handa Reported-by: syzbot Cc: Greg Kroah-Hartman Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index c8501cdb95f4..a359934ffd85 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1461,7 +1461,7 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj) dir = kzalloc(sizeof(*dir), GFP_KERNEL); if (!dir) - return NULL; + return ERR_PTR(-ENOMEM); dir->class = class; kobject_init(&dir->kobj, &class_dir_ktype); @@ -1471,7 +1471,7 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj) retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name); if (retval < 0) { kobject_put(&dir->kobj); - return NULL; + return ERR_PTR(retval); } return &dir->kobj; } @@ -1778,6 +1778,10 @@ int device_add(struct device *dev) parent = get_device(dev->parent); kobj = get_device_parent(dev, parent); + if (IS_ERR(kobj)) { + error = PTR_ERR(kobj); + goto parent_error; + } if (kobj) dev->kobj.parent = kobj; @@ -1876,6 +1880,7 @@ int device_add(struct device *dev) kobject_del(&dev->kobj); Error: cleanup_glue_dir(dev, glue_dir); +parent_error: put_device(parent); name_error: kfree(dev->p); @@ -2695,6 +2700,11 @@ int device_move(struct device *dev, struct device *new_parent, device_pm_lock(); new_parent = get_device(new_parent); new_parent_kobj = get_device_parent(dev, new_parent); + if (IS_ERR(new_parent_kobj)) { + error = PTR_ERR(new_parent_kobj); + put_device(new_parent); + goto out; + } pr_debug("device: '%s': %s: moving to '%s'\n", dev_name(dev), __func__, new_parent ? dev_name(new_parent) : ""); -- GitLab From 55d29ff48222c89a7ca03b8eacb7d4f62fd651be Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Tue, 22 May 2018 15:02:12 -0700 Subject: [PATCH 0789/1299] Btrfs: fix clone vs chattr NODATASUM race commit b5c40d598f5408bd0ca22dfffa82f03cd9433f23 upstream. In btrfs_clone_files(), we must check the NODATASUM flag while the inodes are locked. Otherwise, it's possible that btrfs_ioctl_setflags() will change the flags after we check and we can end up with a party checksummed file. The race window is only a few instructions in size, between the if and the locks which is: 3834 if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode)) 3835 return -EISDIR; where the setflags must be run and toggle the NODATASUM flag (provided the file size is 0). The clone will block on the inode lock, segflags takes the inode lock, changes flags, releases log and clone continues. Not impossible but still needs a lot of bad luck to hit unintentionally. Fixes: 0e7b824c4ef9 ("Btrfs: don't make a file partly checksummed through file clone") CC: stable@vger.kernel.org # 4.4+ Signed-off-by: Omar Sandoval Reviewed-by: Nikolay Borisov Reviewed-by: David Sterba [ update changelog ] Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/ioctl.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 2763f3184ac5..677f5a17935e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -3861,11 +3861,6 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src, src->i_sb != inode->i_sb) return -EXDEV; - /* don't make the dst file partly checksummed */ - if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) != - (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) - return -EINVAL; - if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode)) return -EISDIR; @@ -3875,6 +3870,13 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src, inode_lock(src); } + /* don't make the dst file partly checksummed */ + if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) != + (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { + ret = -EINVAL; + goto out_unlock; + } + /* determine range to clone */ ret = -EINVAL; if (off + len > src->i_size || off + len < off) -- GitLab From 5f7e3b5b96f8b787e95bfd91636261fd32d80dc2 Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Tue, 22 May 2018 15:44:01 -0700 Subject: [PATCH 0790/1299] Btrfs: fix memory and mount leak in btrfs_ioctl_rm_dev_v2() commit fd4e994bd1f9dc9628e168a7f619bf69f6984635 upstream. If we have invalid flags set, when we error out we must drop our writer counter and free the buffer we allocated for the arguments. This bug is trivially reproduced with the following program on 4.7+: #include #include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { struct btrfs_ioctl_vol_args_v2 vol_args = { .flags = UINT64_MAX, }; int ret; int fd; if (argc != 2) { fprintf(stderr, "usage: %s PATH\n", argv[0]); return EXIT_FAILURE; } fd = open(argv[1], O_WRONLY); if (fd == -1) { perror("open"); return EXIT_FAILURE; } ret = ioctl(fd, BTRFS_IOC_RM_DEV_V2, &vol_args); if (ret == -1) perror("ioctl"); close(fd); return EXIT_SUCCESS; } When unmounting the filesystem, we'll hit the WARN_ON(mnt_get_writers(mnt)) in cleanup_mnt() and also may prevent the filesystem to be remounted read-only as the writer count will stay lifted. Fixes: 6b526ed70cf1 ("btrfs: introduce device delete by devid") CC: stable@vger.kernel.org # 4.9+ Signed-off-by: Omar Sandoval Reviewed-by: Su Yue Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/ioctl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 677f5a17935e..7303ba108112 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2682,8 +2682,10 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg) } /* Check for compatibility reject unknown flags */ - if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED) - return -EOPNOTSUPP; + if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED) { + ret = -EOPNOTSUPP; + goto out; + } if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; -- GitLab From 4cb8942042bde6b58cac0c76d12a24b62ab0c76c Mon Sep 17 00:00:00 2001 From: Su Yue Date: Wed, 30 May 2018 16:48:56 +0800 Subject: [PATCH 0791/1299] btrfs: return error value if create_io_em failed in cow_file_range commit 090a127afa8f73e9618d4058d6755f7ec7453dd6 upstream. In cow_file_range(), create_io_em() may fail, but its return value is not recorded. Then return value may be 0 even it failed which is a wrong behavior. Let cow_file_range() return PTR_ERR(em) if create_io_em() failed. Fixes: 6f9994dbabe5 ("Btrfs: create a helper to create em for IO") CC: stable@vger.kernel.org # 4.11+ Signed-off-by: Su Yue Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/inode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8ecbac3b862e..3a07900971c3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1027,8 +1027,10 @@ static noinline int cow_file_range(struct inode *inode, ram_size, /* ram_bytes */ BTRFS_COMPRESS_NONE, /* compress_type */ BTRFS_ORDERED_REGULAR /* type */); - if (IS_ERR(em)) + if (IS_ERR(em)) { + ret = PTR_ERR(em); goto out_reserve; + } free_extent_map(em); ret = btrfs_add_ordered_extent(inode, start, ins.objectid, -- GitLab From b1cf23c2c8db7c73d3ae684fa13d0a28631d1768 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Tue, 5 Jun 2018 12:36:56 +0800 Subject: [PATCH 0792/1299] btrfs: scrub: Don't use inode pages for device replace commit ac0b4145d662a3b9e34085dea460fb06ede9b69b upstream. [BUG] Btrfs can create compressed extent without checksum (even though it shouldn't), and if we then try to replace device containing such extent, the result device will contain all the uncompressed data instead of the compressed one. Test case already submitted to fstests: https://patchwork.kernel.org/patch/10442353/ [CAUSE] When handling compressed extent without checksum, device replace will goe into copy_nocow_pages() function. In that function, btrfs will get all inodes referring to this data extents and then use find_or_create_page() to get pages direct from that inode. The problem here is, pages directly from inode are always uncompressed. And for compressed data extent, they mismatch with on-disk data. Thus this leads to corrupted compressed data extent written to replace device. [FIX] In this attempt, we could just remove the "optimization" branch, and let unified scrub_pages() to handle it. Although scrub_pages() won't bother reusing page cache, it will be a little slower, but it does the correct csum checking and won't cause such data corruption caused by "optimization". Note about the fix: this is the minimal fix that can be backported to older stable trees without conflicts. The whole callchain from copy_nocow_pages() can be deleted, and will be in followup patches. Fixes: ff023aac3119 ("Btrfs: add code to scrub to copy read data to another disk") CC: stable@vger.kernel.org # 4.4+ Reported-by: James Harvey Reviewed-by: James Harvey Signed-off-by: Qu Wenruo [ remove code removal, add note why ] Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/scrub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 24613b4e224c..936d58ca2b49 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -2775,7 +2775,7 @@ static int scrub_extent(struct scrub_ctx *sctx, u64 logical, u64 len, have_csum = scrub_find_csum(sctx, logical, csum); if (have_csum == 0) ++sctx->stat.no_csum; - if (sctx->is_dev_replace && !have_csum) { + if (0 && sctx->is_dev_replace && !have_csum) { ret = copy_nocow_pages(sctx, logical, l, mirror_num, physical_for_dev_replace); -- GitLab From ff7eb857eeca10368f43343ac8c5e6f39250adeb Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Wed, 30 May 2018 12:33:07 +0800 Subject: [PATCH 0793/1299] ALSA: hda/realtek - Enable mic-mute hotkey for several Lenovo AIOs commit 986376b68dcc95bb7df60ad30c2353c1f7578fa5 upstream. We have several Lenovo AIOs like M810z, M820z and M920z, they have the same design for mic-mute hotkey and led and they use the same codec with the same pin configuration, so use the pin conf table to apply fix to all of them. Fixes: 29693efcea0f ("ALSA: hda - Fix micmute hotkey problem for a lenovo AIO machine") Cc: Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6ae061183eff..2a8aa2bc5c30 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6439,7 +6439,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x3138, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), - SND_PCI_QUIRK(0x17aa, 0x3112, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), @@ -6610,6 +6609,11 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x12, 0x90a60140}, {0x14, 0x90170110}, {0x21, 0x02211020}), + SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, + {0x12, 0x90a60140}, + {0x14, 0x90170110}, + {0x19, 0x02a11030}, + {0x21, 0x02211020}), SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, {0x12, 0x90a60140}, {0x14, 0x90170150}, -- GitLab From 03701e42cc19323b9624fb7d12b855a8c5ef440e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 18 May 2018 12:14:32 +0200 Subject: [PATCH 0794/1299] ALSA: hda/conexant - Add fixup for HP Z2 G4 workstation commit f16041df4c360eccacfe90f96673b37829e4c959 upstream. HP Z2 G4 requires the same workaround as other HP machines that have no mic-pin detection. Cc: Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 5b4dbcec6de8..091cb7a9ce08 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -965,6 +965,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO), SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), -- GitLab From a3eb20df0e23e23c6604fbff4d6c5a6c610f7dbc Mon Sep 17 00:00:00 2001 From: Bo Chen Date: Thu, 31 May 2018 15:35:18 -0700 Subject: [PATCH 0795/1299] ALSA: hda - Handle kzalloc() failure in snd_hda_attach_pcm_stream() commit a3aa60d511746bd6c0d0366d4eb90a7998bcde8b upstream. When 'kzalloc()' fails in 'snd_hda_attach_pcm_stream()', a new pcm instance is created without setting its operators via 'snd_pcm_set_ops()'. Following operations on the new pcm instance can trigger kernel null pointer dereferences and cause kernel oops. This bug was found with my work on building a gray-box fault-injection tool for linux-kernel-module binaries. A kernel null pointer dereference was confirmed from line 'substream->ops->open()' in function 'snd_pcm_open_substream()' in file 'sound/core/pcm_native.c'. This patch fixes the bug by calling 'snd_device_free()' in the error handling path of 'kzalloc()', which removes the new pcm instance from the snd card before returns with an error code. Signed-off-by: Bo Chen Cc: Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_controller.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index d1eb14842340..a12e594d4e3b 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -748,8 +748,10 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, return err; strlcpy(pcm->name, cpcm->name, sizeof(pcm->name)); apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); - if (apcm == NULL) + if (apcm == NULL) { + snd_device_free(chip->card, pcm); return -ENOMEM; + } apcm->chip = chip; apcm->pcm = pcm; apcm->codec = codec; -- GitLab From e6c9fd8cf7d05e8be07cfc741108440477deb5b6 Mon Sep 17 00:00:00 2001 From: Dennis Wassenberg Date: Tue, 12 Jun 2018 07:10:59 +0200 Subject: [PATCH 0796/1299] ALSA: hda: add dock and led support for HP EliteBook 830 G5 commit 2861751f67b91e1d24e68010ced96614fb3140f4 upstream. This patch adds missing initialisation for HP 2013 UltraSlim Dock Line-In/Out PINs and activates keyboard mute/micmute leds for HP EliteBook 830 G5 Signed-off-by: Dennis Wassenberg Cc: Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 091cb7a9ce08..2de00401627e 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -959,6 +959,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK), + SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE), SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC), SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO), -- GitLab From c5c00990f75daa8cb50d6d26f2c5db8b9f3a50dc Mon Sep 17 00:00:00 2001 From: Dennis Wassenberg Date: Tue, 12 Jun 2018 07:11:11 +0200 Subject: [PATCH 0797/1299] ALSA: hda: add dock and led support for HP ProBook 640 G4 commit 7eef32c1ef895a3a96463f9cbd04203007cd5555 upstream. This patch adds missing initialisation for HP 2013 UltraSlim Dock Line-In/Out PINs and activates keyboard mute/micmute leds for HP ProBook 640 G4 Signed-off-by: Dennis Wassenberg Cc: Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 2de00401627e..ba9a7e552183 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -960,6 +960,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK), + SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE), SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC), SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO), -- GitLab From e0b510a4170e220d978a6cfbe25e634193fffbfa Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 27 Apr 2018 09:37:08 -0700 Subject: [PATCH 0798/1299] x86/MCE: Fix stack out-of-bounds write in mce-inject.c: Flags_read() commit 985c78d3ff8e9c74450fa2bb08eb55e680d999ca upstream. Each of the strings that we want to put into the buf[MAX_FLAG_OPT_SIZE] in flags_read() is two characters long. But the sprintf() adds a trailing newline and will add a terminating NUL byte. So MAX_FLAG_OPT_SIZE needs to be 4. sprintf() calls vsnprintf() and *that* does return: " * The return value is the number of characters which would * be generated for the given input, excluding the trailing * '\0', as per ISO C99." Note the "excluding". Reported-by: Dmitry Vyukov Signed-off-by: Tony Luck Signed-off-by: Borislav Petkov Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Cc: linux-edac Link: http://lkml.kernel.org/r/20180427163707.ktaiysvbk3yhk4wm@agluck-desk Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce-inject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c index 231ad23b24a9..8fec687b3e44 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c @@ -48,7 +48,7 @@ static struct dentry *dfs_inj; static u8 n_banks; -#define MAX_FLAG_OPT_SIZE 3 +#define MAX_FLAG_OPT_SIZE 4 #define NBCFG 0x44 enum injection_type { -- GitLab From dcde75924f25c21f6eb6e394782e930ed439dda5 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 19 May 2018 02:04:55 -0500 Subject: [PATCH 0799/1299] smb3: fix various xid leaks commit cfe89091644c441a1ade6dae6d2e47b715648615 upstream. Fix a few cases where we were not freeing the xid which led to active requests being non-zero at unmount time. Signed-off-by: Steve French CC: Stable Reviewed-by: Ronnie Sahlberg Signed-off-by: Greg Kroah-Hartman --- fs/cifs/smb2ops.c | 63 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 839327f75e3d..9f1613c01189 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1571,8 +1571,11 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb, oparms.create_options = 0; utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); - if (!utf16_path) - return ERR_PTR(-ENOMEM); + if (!utf16_path) { + rc = -ENOMEM; + free_xid(xid); + return ERR_PTR(rc); + } oparms.tcon = tcon; oparms.desired_access = READ_CONTROL; @@ -1630,8 +1633,11 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen, access_flags = WRITE_DAC; utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); - if (!utf16_path) - return -ENOMEM; + if (!utf16_path) { + rc = -ENOMEM; + free_xid(xid); + return rc; + } oparms.tcon = tcon; oparms.desired_access = access_flags; @@ -1691,15 +1697,21 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, /* if file not oplocked can't be sure whether asking to extend size */ if (!CIFS_CACHE_READ(cifsi)) - if (keep_size == false) - return -EOPNOTSUPP; + if (keep_size == false) { + rc = -EOPNOTSUPP; + free_xid(xid); + return rc; + } /* * Must check if file sparse since fallocate -z (zero range) assumes * non-sparse allocation */ - if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) - return -EOPNOTSUPP; + if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) { + rc = -EOPNOTSUPP; + free_xid(xid); + return rc; + } /* * need to make sure we are not asked to extend the file since the SMB3 @@ -1708,8 +1720,11 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, * which for a non sparse file would zero the newly extended range */ if (keep_size == false) - if (i_size_read(inode) < offset + len) - return -EOPNOTSUPP; + if (i_size_read(inode) < offset + len) { + rc = -EOPNOTSUPP; + free_xid(xid); + return rc; + } cifs_dbg(FYI, "offset %lld len %lld", offset, len); @@ -1743,8 +1758,11 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, /* Need to make file sparse, if not already, before freeing range. */ /* Consider adding equivalent for compressed since it could also work */ - if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) - return -EOPNOTSUPP; + if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) { + rc = -EOPNOTSUPP; + free_xid(xid); + return rc; + } cifs_dbg(FYI, "offset %lld len %lld", offset, len); @@ -1776,8 +1794,10 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, /* if file not oplocked can't be sure whether asking to extend size */ if (!CIFS_CACHE_READ(cifsi)) - if (keep_size == false) - return -EOPNOTSUPP; + if (keep_size == false) { + free_xid(xid); + return rc; + } /* * Files are non-sparse by default so falloc may be a no-op @@ -1786,14 +1806,16 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, */ if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) { if (keep_size == true) - return 0; + rc = 0; /* check if extending file */ else if (i_size_read(inode) >= off + len) /* not extending file and already not sparse */ - return 0; + rc = 0; /* BB: in future add else clause to extend file */ else - return -EOPNOTSUPP; + rc = -EOPNOTSUPP; + free_xid(xid); + return rc; } if ((keep_size == true) || (i_size_read(inode) >= off + len)) { @@ -1805,8 +1827,11 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, * ie potentially making a few extra pages at the beginning * or end of the file non-sparse via set_sparse is harmless. */ - if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) - return -EOPNOTSUPP; + if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) { + rc = -EOPNOTSUPP; + free_xid(xid); + return rc; + } rc = smb2_set_sparse(xid, tcon, cfile, inode, false); } -- GitLab From ae62f35def75922782c7d2bdc9f7ca2097c3adce Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 31 May 2018 15:19:25 -0500 Subject: [PATCH 0800/1299] smb3: on reconnect set PreviousSessionId field commit b2adf22fdfba85a6701c481faccdbbb3a418ccfc upstream. The server detects reconnect by the (non-zero) value in PreviousSessionId of SMB2/SMB3 SessionSetup request, but this behavior regressed due to commit 166cea4dc3a4f66f020cfb9286225ecd228ab61d ("SMB2: Separate RawNTLMSSP authentication from SMB2_sess_setup") CC: Stable CC: Sachin Prabhu Signed-off-by: Steve French Reviewed-by: Ronnie Sahlberg Signed-off-by: Greg Kroah-Hartman --- fs/cifs/smb2pdu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 49779d952cd5..70eeaa2925bb 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1182,6 +1182,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, sess_data->ses = ses; sess_data->buf0_type = CIFS_NO_BUFFER; sess_data->nls_cp = (struct nls_table *) nls_cp; + sess_data->previous_session = ses->Suid; while (sess_data->func) sess_data->func(sess_data); -- GitLab From 2a8737336dbd3906ec33c391a7b0f57d2f760d55 Mon Sep 17 00:00:00 2001 From: Mark Syms Date: Thu, 24 May 2018 09:47:31 +0100 Subject: [PATCH 0801/1299] CIFS: 511c54a2f69195b28afb9dd119f03787b1625bb4 adds a check for session expiry commit d81243c697ffc71f983736e7da2db31a8be0001f upstream. Handle this additional status in the same way as SESSION_EXPIRED. Signed-off-by: Mark Syms Signed-off-by: Steve French CC: Stable Signed-off-by: Greg Kroah-Hartman --- fs/cifs/smb2ops.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 9f1613c01189..36bc9a7eb8ea 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1256,10 +1256,11 @@ smb2_is_session_expired(char *buf) { struct smb2_sync_hdr *shdr = get_sync_hdr(buf); - if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED) + if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED && + shdr->Status != STATUS_USER_SESSION_DELETED) return false; - cifs_dbg(FYI, "Session expired\n"); + cifs_dbg(FYI, "Session expired or deleted\n"); return true; } -- GitLab From ffb179cfbcf66da752524983a702e8adbaf462b7 Mon Sep 17 00:00:00 2001 From: Shirish Pargaonkar Date: Mon, 4 Jun 2018 06:46:22 -0500 Subject: [PATCH 0802/1299] cifs: For SMB2 security informaion query, check for minimum sized security descriptor instead of sizeof FileAllInformation class commit ee25c6dd7b05113783ce1f4fab6b30fc00d29b8d upstream. Validate_buf () function checks for an expected minimum sized response passed to query_info() function. For security information, the size of a security descriptor can be smaller (one subauthority, no ACEs) than the size of the structure that defines FileInfoClass of FileAllInformation. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199725 Cc: Signed-off-by: Shirish Pargaonkar Reviewed-by: Noah Morrison Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifsacl.h | 14 ++++++++++++++ fs/cifs/smb2pdu.c | 3 +-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 4f3884835267..dd95a6fa24bf 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h @@ -98,4 +98,18 @@ struct cifs_ace { struct cifs_sid sid; /* ie UUID of user or group who gets these perms */ } __attribute__((packed)); +/* + * Minimum security identifier can be one for system defined Users + * and Groups such as NULL SID and World or Built-in accounts such + * as Administrator and Guest and consists of + * Revision + Num (Sub)Auths + Authority + Domain (one Subauthority) + */ +#define MIN_SID_LEN (1 + 1 + 6 + 4) /* in bytes */ + +/* + * Minimum security descriptor can be one without any SACL and DACL and can + * consist of revision, type, and two sids of minimum size for owner and group + */ +#define MIN_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + (2 * MIN_SID_LEN)) + #endif /* _CIFSACL_H */ diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 70eeaa2925bb..5247b40e57f6 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -2279,8 +2279,7 @@ SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon, return query_info(xid, tcon, persistent_fid, volatile_fid, 0, SMB2_O_INFO_SECURITY, additional_info, - SMB2_MAX_BUFFER_SIZE, - sizeof(struct smb2_file_all_info), data, plen); + SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen); } int -- GitLab From edee2e826640c1ba54d51914b1699bc24a1f32c9 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 16 May 2018 14:51:17 -0400 Subject: [PATCH 0803/1299] nbd: fix nbd device deletion commit 8364da4751cf22201d74933d5e634176f44ed407 upstream. This fixes a use after free bug, we shouldn't be doing disk->queue right after we do del_gendisk(disk). Save the queue and do the cleanup after the del_gendisk. Fixes: c6a4759ea0c9 ("nbd: add device refcounting") cc: stable@vger.kernel.org Signed-off-by: Josef Bacik Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/nbd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 86258b00a1d4..7a2101030683 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -173,9 +173,12 @@ static const struct device_attribute pid_attr = { static void nbd_dev_remove(struct nbd_device *nbd) { struct gendisk *disk = nbd->disk; + struct request_queue *q; + if (disk) { + q = disk->queue; del_gendisk(disk); - blk_cleanup_queue(disk->queue); + blk_cleanup_queue(q); blk_mq_free_tag_set(&nbd->tag_set); disk->private_data = NULL; put_disk(disk); -- GitLab From a477d00557f59a20de6398a20808998ce97dce08 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 16 May 2018 14:51:18 -0400 Subject: [PATCH 0804/1299] nbd: update size when connected commit c3f7c9397609705ef848cc98a5fb429b3e90c3c4 upstream. I messed up changing the size of an NBD device while it was connected by not actually updating the device or doing the uevent. Fix this by updating everything if we're connected and we change the size. cc: stable@vger.kernel.org Fixes: 639812a ("nbd: don't set the device size until we're connected") Signed-off-by: Josef Bacik Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/nbd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 7a2101030683..7dc01bbb851f 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -246,6 +246,8 @@ static void nbd_size_set(struct nbd_device *nbd, loff_t blocksize, struct nbd_config *config = nbd->config; config->blksize = blocksize; config->bytesize = blocksize * nr_blocks; + if (nbd->task_recv != NULL) + nbd_size_update(nbd); } static void nbd_complete_rq(struct request *req) -- GitLab From 00946218ffe376ff3234ff3c81cd4193e3ca95e2 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 16 May 2018 14:51:19 -0400 Subject: [PATCH 0805/1299] nbd: use bd_set_size when updating disk size commit 9e2b19675d1338d2a38e99194756f2db44a081df upstream. When we stopped relying on the bdev everywhere I broke updating the block device size on the fly, which ceph relies on. We can't just do set_capacity, we also have to do bd_set_size so things like parted will notice the device size change. Fixes: 29eaadc ("nbd: stop using the bdev everywhere") cc: stable@vger.kernel.org Signed-off-by: Josef Bacik Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/nbd.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 7dc01bbb851f..6fb64e73bc96 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -234,9 +234,18 @@ static void nbd_size_clear(struct nbd_device *nbd) static void nbd_size_update(struct nbd_device *nbd) { struct nbd_config *config = nbd->config; + struct block_device *bdev = bdget_disk(nbd->disk, 0); + blk_queue_logical_block_size(nbd->disk->queue, config->blksize); blk_queue_physical_block_size(nbd->disk->queue, config->blksize); set_capacity(nbd->disk, config->bytesize >> 9); + if (bdev) { + if (bdev->bd_disk) + bd_set_size(bdev, config->bytesize); + else + bdev->bd_invalidated = 1; + bdput(bdev); + } kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); } @@ -1114,7 +1123,6 @@ static int nbd_start_device_ioctl(struct nbd_device *nbd, struct block_device *b if (ret) return ret; - bd_set_size(bdev, config->bytesize); if (max_part) bdev->bd_invalidated = 1; mutex_unlock(&nbd->config_lock); -- GitLab From ba502bf2be45f37f38581353af8897a91493f33a Mon Sep 17 00:00:00 2001 From: Roman Pen Date: Sun, 10 Jun 2018 22:38:24 +0200 Subject: [PATCH 0806/1299] blk-mq: reinit q->tag_set_list entry only after grace period commit a347c7ad8edf4c5685154f3fdc3c12fc1db800ba upstream. It is not allowed to reinit q->tag_set_list list entry while RCU grace period has not completed yet, otherwise the following soft lockup in blk_mq_sched_restart() happens: [ 1064.252652] watchdog: BUG: soft lockup - CPU#12 stuck for 23s! [fio:9270] [ 1064.254445] task: ffff99b912e8b900 task.stack: ffffa6d54c758000 [ 1064.254613] RIP: 0010:blk_mq_sched_restart+0x96/0x150 [ 1064.256510] Call Trace: [ 1064.256664] [ 1064.256824] blk_mq_free_request+0xea/0x100 [ 1064.256987] msg_io_conf+0x59/0xd0 [ibnbd_client] [ 1064.257175] complete_rdma_req+0xf2/0x230 [ibtrs_client] [ 1064.257340] ? ibtrs_post_recv_empty+0x4d/0x70 [ibtrs_core] [ 1064.257502] ibtrs_clt_rdma_done+0xd1/0x1e0 [ibtrs_client] [ 1064.257669] ib_create_qp+0x321/0x380 [ib_core] [ 1064.257841] ib_process_cq_direct+0xbd/0x120 [ib_core] [ 1064.258007] irq_poll_softirq+0xb7/0xe0 [ 1064.258165] __do_softirq+0x106/0x2a2 [ 1064.258328] irq_exit+0x92/0xa0 [ 1064.258509] do_IRQ+0x4a/0xd0 [ 1064.258660] common_interrupt+0x7a/0x7a [ 1064.258818] Meanwhile another context frees other queue but with the same set of shared tags: [ 1288.201183] INFO: task bash:5910 blocked for more than 180 seconds. [ 1288.201833] bash D 0 5910 5820 0x00000000 [ 1288.202016] Call Trace: [ 1288.202315] schedule+0x32/0x80 [ 1288.202462] schedule_timeout+0x1e5/0x380 [ 1288.203838] wait_for_completion+0xb0/0x120 [ 1288.204137] __wait_rcu_gp+0x125/0x160 [ 1288.204287] synchronize_sched+0x6e/0x80 [ 1288.204770] blk_mq_free_queue+0x74/0xe0 [ 1288.204922] blk_cleanup_queue+0xc7/0x110 [ 1288.205073] ibnbd_clt_unmap_device+0x1bc/0x280 [ibnbd_client] [ 1288.205389] ibnbd_clt_unmap_dev_store+0x169/0x1f0 [ibnbd_client] [ 1288.205548] kernfs_fop_write+0x109/0x180 [ 1288.206328] vfs_write+0xb3/0x1a0 [ 1288.206476] SyS_write+0x52/0xc0 [ 1288.206624] do_syscall_64+0x68/0x1d0 [ 1288.206774] entry_SYSCALL_64_after_hwframe+0x3d/0xa2 What happened is the following: 1. There are several MQ queues with shared tags. 2. One queue is about to be freed and now task is in blk_mq_del_queue_tag_set(). 3. Other CPU is in blk_mq_sched_restart() and loops over all queues in tag list in order to find hctx to restart. Because linked list entry was modified in blk_mq_del_queue_tag_set() without proper waiting for a grace period, blk_mq_sched_restart() never ends, spining in list_for_each_entry_rcu_rr(), thus soft lockup. Fix is simple: reinit list entry after an RCU grace period elapsed. Fixes: Fixes: 705cda97ee3a ("blk-mq: Make it safe to use RCU to iterate over blk_mq_tag_set.tag_list") Cc: stable@vger.kernel.org Cc: Sagi Grimberg Cc: linux-block@vger.kernel.org Reviewed-by: Christoph Hellwig Reviewed-by: Ming Lei Reviewed-by: Bart Van Assche Signed-off-by: Roman Pen Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-mq.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 74c35513ada5..49979c095f31 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2252,7 +2252,6 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q) mutex_lock(&set->tag_list_lock); list_del_rcu(&q->tag_set_list); - INIT_LIST_HEAD(&q->tag_set_list); if (list_is_singular(&set->tag_list)) { /* just transitioned to unshared */ set->flags &= ~BLK_MQ_F_TAG_SHARED; @@ -2260,8 +2259,8 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q) blk_mq_update_tag_set_depth(set, false); } mutex_unlock(&set->tag_list_lock); - synchronize_rcu(); + INIT_LIST_HEAD(&q->tag_set_list); } static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set, -- GitLab From 67b46304b92b6bbb165817abe8700a2ec1aa8305 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 23 May 2018 10:56:32 -0700 Subject: [PATCH 0807/1299] bdi: Move cgroup bdi_writeback to a dedicated low concurrency workqueue commit f183464684190bacbfb14623bd3e4e51b7575b4c upstream. From 0aa2e9b921d6db71150633ff290199554f0842a8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 23 May 2018 10:29:00 -0700 cgwb_release() punts the actual release to cgwb_release_workfn() on system_wq. Depending on the number of cgroups or block devices, there can be a lot of cgwb_release_workfn() in flight at the same time. We're periodically seeing close to 256 kworkers getting stuck with the following stack trace and overtime the entire system gets stuck. [] _synchronize_rcu_expedited.constprop.72+0x2fc/0x330 [] synchronize_rcu_expedited+0x24/0x30 [] bdi_unregister+0x53/0x290 [] release_bdi+0x89/0xc0 [] wb_exit+0x85/0xa0 [] cgwb_release_workfn+0x54/0xb0 [] process_one_work+0x150/0x410 [] worker_thread+0x6d/0x520 [] kthread+0x12c/0x160 [] ret_from_fork+0x29/0x40 [] 0xffffffffffffffff The events leading to the lockup are... 1. A lot of cgwb_release_workfn() is queued at the same time and all system_wq kworkers are assigned to execute them. 2. They all end up calling synchronize_rcu_expedited(). One of them wins and tries to perform the expedited synchronization. 3. However, that invovles queueing rcu_exp_work to system_wq and waiting for it. Because #1 is holding all available kworkers on system_wq, rcu_exp_work can't be executed. cgwb_release_workfn() is waiting for synchronize_rcu_expedited() which in turn is waiting for cgwb_release_workfn() to free up some of the kworkers. We shouldn't be scheduling hundreds of cgwb_release_workfn() at the same time. There's nothing to be gained from that. This patch updates cgwb release path to use a dedicated percpu workqueue with @max_active of 1. While this resolves the problem at hand, it might be a good idea to isolate rcu_exp_work to its own workqueue too as it can be used from various paths and is prone to this sort of indirect A-A deadlocks. Signed-off-by: Tejun Heo Cc: "Paul E. McKenney" Cc: stable@vger.kernel.org Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- mm/backing-dev.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/mm/backing-dev.c b/mm/backing-dev.c index dee049a0ec5b..6774e0369ebe 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -409,6 +409,7 @@ static void wb_exit(struct bdi_writeback *wb) * protected. */ static DEFINE_SPINLOCK(cgwb_lock); +static struct workqueue_struct *cgwb_release_wq; /** * wb_congested_get_create - get or create a wb_congested @@ -519,7 +520,7 @@ static void cgwb_release(struct percpu_ref *refcnt) { struct bdi_writeback *wb = container_of(refcnt, struct bdi_writeback, refcnt); - schedule_work(&wb->release_work); + queue_work(cgwb_release_wq, &wb->release_work); } static void cgwb_kill(struct bdi_writeback *wb) @@ -783,6 +784,21 @@ static void cgwb_bdi_register(struct backing_dev_info *bdi) spin_unlock_irq(&cgwb_lock); } +static int __init cgwb_init(void) +{ + /* + * There can be many concurrent release work items overwhelming + * system_wq. Put them in a separate wq and limit concurrency. + * There's no point in executing many of these in parallel. + */ + cgwb_release_wq = alloc_workqueue("cgwb_release", 0, 1); + if (!cgwb_release_wq) + return -ENOMEM; + + return 0; +} +subsys_initcall(cgwb_init); + #else /* CONFIG_CGROUP_WRITEBACK */ static int cgwb_bdi_init(struct backing_dev_info *bdi) -- GitLab From c3c77b5db39350c8d64c85102138ab9ba6066815 Mon Sep 17 00:00:00 2001 From: Tao Wang Date: Sat, 26 May 2018 15:16:48 +0800 Subject: [PATCH 0808/1299] cpufreq: Fix new policy initialization during limits updates via sysfs commit c7d1f119c48f64bebf0fa1e326af577c6152fe30 upstream. If the policy limits are updated via cpufreq_update_policy() and subsequently via sysfs, the limits stored in user_policy may be set incorrectly. For example, if both min and max are set via sysfs to the maximum available frequency, user_policy.min and user_policy.max will also be the maximum. If a policy notifier triggered by cpufreq_update_policy() lowers both the min and the max at this point, that change is not reflected by the user_policy limits, so if the max is updated again via sysfs to the same lower value, then user_policy.max will be lower than user_policy.min which shouldn't happen. In particular, if one of the policy CPUs is then taken offline and back online, cpufreq_set_policy() will fail for it due to a failing limits check. To prevent that from happening, initialize the min and max fields of the new_policy object to the ones stored in user_policy that were previously set via sysfs. Signed-off-by: Kevin Wangtao Acked-by: Viresh Kumar [ rjw: Subject & changelog ] Cc: All applicable Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/cpufreq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 789fc3a8289f..93754300cb57 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -693,6 +693,8 @@ static ssize_t store_##file_name \ struct cpufreq_policy new_policy; \ \ memcpy(&new_policy, policy, sizeof(*policy)); \ + new_policy.min = policy->user_policy.min; \ + new_policy.max = policy->user_policy.max; \ \ ret = sscanf(buf, "%u", &new_policy.object); \ if (ret != 1) \ -- GitLab From 1404d2e5dd3647d9bec8960c7dc90aea7cbd8b63 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Fri, 8 Jun 2018 09:07:33 +0800 Subject: [PATCH 0809/1299] cpufreq: governors: Fix long idle detection logic in load calculation commit 7592019634f8473f0b0973ce79297183077bdbc2 upstream. According to current code implementation, detecting the long idle period is done by checking if the interval between two adjacent utilization update handlers is long enough. Although this mechanism can detect if the idle period is long enough (no utilization hooks invoked during idle period), it might not cover a corner case: if the task has occupied the CPU for too long which causes no context switches during that period, then no utilization handler will be launched until this high prio task is scheduled out. As a result, the idle_periods field might be calculated incorrectly because it regards the 100% load as 0% and makes the conservative governor who uses this field confusing. Change the detection to compare the idle_time with sampling_rate directly. Reported-by: Artem S. Tashkinov Signed-off-by: Chen Yu Acked-by: Viresh Kumar Cc: All applicable Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/cpufreq_governor.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index ca38229b045a..43e14bb512c8 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -165,7 +165,7 @@ unsigned int dbs_update(struct cpufreq_policy *policy) * calls, so the previous load value can be used then. */ load = j_cdbs->prev_load; - } else if (unlikely(time_elapsed > 2 * sampling_rate && + } else if (unlikely((int)idle_time > 2 * sampling_rate && j_cdbs->prev_load)) { /* * If the CPU had gone completely idle and a task has @@ -185,10 +185,8 @@ unsigned int dbs_update(struct cpufreq_policy *policy) * clear prev_load to guarantee that the load will be * computed again next time. * - * Detecting this situation is easy: the governor's - * utilization update handler would not have run during - * CPU-idle periods. Hence, an unusually large - * 'time_elapsed' (as compared to the sampling rate) + * Detecting this situation is easy: an unusually large + * 'idle_time' (as compared to the sampling rate) * indicates this scenario. */ load = j_cdbs->prev_load; @@ -217,8 +215,8 @@ unsigned int dbs_update(struct cpufreq_policy *policy) j_cdbs->prev_load = load; } - if (time_elapsed > 2 * sampling_rate) { - unsigned int periods = time_elapsed / sampling_rate; + if (unlikely((int)idle_time > 2 * sampling_rate)) { + unsigned int periods = idle_time / sampling_rate; if (periods < idle_periods) idle_periods = periods; -- GitLab From 27c0f1e5d94d90ef07a3c33fe20996c403fbbf9e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 29 May 2018 12:13:24 +0300 Subject: [PATCH 0810/1299] libata: zpodd: small read overflow in eject_tray() commit 18c9a99bce2a57dfd7e881658703b5d7469cc7b9 upstream. We read from the cdb[] buffer in ata_exec_internal_sg(). It has to be ATAPI_CDB_LEN (16) bytes long, but this buffer is only 12 bytes. Fixes: 213342053db5 ("libata: handle power transition of ODD") Signed-off-by: Dan Carpenter Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-zpodd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c index de4ddd0e8550..b3ed8f9953a8 100644 --- a/drivers/ata/libata-zpodd.c +++ b/drivers/ata/libata-zpodd.c @@ -35,7 +35,7 @@ struct zpodd { static int eject_tray(struct ata_device *dev) { struct ata_taskfile tf; - static const char cdb[] = { GPCMD_START_STOP_UNIT, + static const char cdb[ATAPI_CDB_LEN] = { GPCMD_START_STOP_UNIT, 0, 0, 0, 0x02, /* LoEj */ 0, 0, 0, 0, 0, 0, 0, -- GitLab From 0667483adeeefdedd21cc636cd224632d5570980 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 31 May 2018 13:21:07 +0200 Subject: [PATCH 0811/1299] libata: Drop SanDisk SD7UB3Q*G1001 NOLPM quirk commit 2cfce3a86b64b53f0a70e92a6a659c720c319b45 upstream. Commit 184add2ca23c ("libata: Apply NOLPM quirk for SanDisk SD7UB3Q*G1001 SSDs") disabled LPM for SanDisk SD7UB3Q*G1001 SSDs. This has lead to several reports of users of that SSD where LPM was working fine and who know have a significantly increased idle power consumption on their laptops. Likely there is another problem on the T450s from the original reporter which gets exposed by the uncore reaching deeper sleep states (higher PC-states) due to LPM being enabled. The problem as reported, a hardfreeze about once a day, already did not sound like it would be caused by LPM and the reports of the SSD working fine confirm this. The original reporter is ok with dropping the quirk. A X250 user has reported the same hard freeze problem and for him the problem went away after unrelated updates, I suspect some GPU driver stack changes fixed things. TL;DR: The original reporters problem were triggered by LPM but not an LPM issue, so drop the quirk for the SSD in question. BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1583207 Cc: stable@vger.kernel.org Cc: Richard W.M. Jones Cc: Lorenzo Dalrio Reported-by: Lorenzo Dalrio Signed-off-by: Hans de Goede Signed-off-by: Tejun Heo Acked-by: "Richard W.M. Jones" Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-core.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 71008dbabe98..cad2530a5b52 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4543,9 +4543,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { ATA_HORKAGE_ZERO_AFTER_TRIM | ATA_HORKAGE_NOLPM, }, - /* Sandisk devices which are known to not handle LPM well */ - { "SanDisk SD7UB3Q*G1001", NULL, ATA_HORKAGE_NOLPM, }, - /* devices that don't properly handle queued TRIM commands */ { "Micron_M500IT_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, -- GitLab From e6ef46cb8f01b67266a1adc1c323b5b67086b8e8 Mon Sep 17 00:00:00 2001 From: Stefan Potyra Date: Wed, 2 May 2018 10:55:31 +0200 Subject: [PATCH 0812/1299] w1: mxc_w1: Enable clock before calling clk_get_rate() on it commit 955bc61328dc0a297fb3baccd84e9d3aee501ed8 upstream. According to the API, you may only call clk_get_rate() after actually enabling it. Found by Linux Driver Verification project (linuxtesting.org). Fixes: a5fd9139f74c ("w1: add 1-wire master driver for i.MX27 / i.MX31") Signed-off-by: Stefan Potyra Acked-by: Evgeniy Polyakov Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/mxc_w1.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index 74f2e6e6202a..8851d441e5fd 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -112,6 +112,10 @@ static int mxc_w1_probe(struct platform_device *pdev) if (IS_ERR(mdev->clk)) return PTR_ERR(mdev->clk); + err = clk_prepare_enable(mdev->clk); + if (err) + return err; + clkrate = clk_get_rate(mdev->clk); if (clkrate < 10000000) dev_warn(&pdev->dev, @@ -125,12 +129,10 @@ static int mxc_w1_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mdev->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(mdev->regs)) - return PTR_ERR(mdev->regs); - - err = clk_prepare_enable(mdev->clk); - if (err) - return err; + if (IS_ERR(mdev->regs)) { + err = PTR_ERR(mdev->regs); + goto out_disable_clk; + } /* Software reset 1-Wire module */ writeb(MXC_W1_RESET_RST, mdev->regs + MXC_W1_RESET); @@ -146,8 +148,12 @@ static int mxc_w1_probe(struct platform_device *pdev) err = w1_add_master_device(&mdev->bus_master); if (err) - clk_disable_unprepare(mdev->clk); + goto out_disable_clk; + return 0; + +out_disable_clk: + clk_disable_unprepare(mdev->clk); return err; } -- GitLab From 2d58a9ac892a2c08480a113f1fb0f55dbf85e2bb Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 8 Jun 2018 09:07:32 -0700 Subject: [PATCH 0813/1299] x86/intel_rdt: Enable CMT and MBM on new Skylake stepping commit 1d9f3e20a56d33e55748552aeec597f58542f92d upstream. New stepping of Skylake has fixes for cache occupancy and memory bandwidth monitoring. Update the code to enable these by default on newer steppings. Signed-off-by: Tony Luck Signed-off-by: Thomas Gleixner Cc: Fenghua Yu Cc: stable@vger.kernel.org # v4.14 Cc: Vikas Shivappa Link: https://lkml.kernel.org/r/20180608160732.9842-1-tony.luck@intel.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/intel_rdt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 18dd8f22e353..665d0f6cd62f 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -773,6 +773,8 @@ static __init void rdt_quirks(void) case INTEL_FAM6_SKYLAKE_X: if (boot_cpu_data.x86_stepping <= 4) set_rdt_options("!cmt,!mbmtotal,!mbmlocal,!l3cat"); + else + set_rdt_options("!l3cat"); } } -- GitLab From b8511dbff2639db94baad73ab912bd6f22afea14 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 13 Feb 2018 11:09:40 +0200 Subject: [PATCH 0814/1299] iwlwifi: fw: harden page loading code commit 9039d985811d5b109b58b202b7594fd24e433fed upstream. The page loading code trusts the data provided in the firmware images a bit too much and may cause a buffer overflow or copy unknown data if the block sizes don't match what we expect. To prevent potential problems, harden the code by checking if the sizes we are copying are what we expect. Cc: stable@vger.kernel.org Signed-off-by: Luca Coelho Signed-off-by: Greg Kroah-Hartman --- .../net/wireless/intel/iwlwifi/fw/paging.c | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/paging.c b/drivers/net/wireless/intel/iwlwifi/fw/paging.c index 1610722b8099..747eef82cefd 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/paging.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/paging.c @@ -8,6 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -174,7 +176,7 @@ static int iwl_alloc_fw_paging_mem(struct iwl_fw_runtime *fwrt, static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt, const struct fw_img *image) { - int sec_idx, idx; + int sec_idx, idx, ret; u32 offset = 0; /* @@ -201,17 +203,23 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt, */ if (sec_idx >= image->num_sec - 1) { IWL_ERR(fwrt, "Paging: Missing CSS and/or paging sections\n"); - iwl_free_fw_paging(fwrt); - return -EINVAL; + ret = -EINVAL; + goto err; } /* copy the CSS block to the dram */ IWL_DEBUG_FW(fwrt, "Paging: load paging CSS to FW, sec = %d\n", sec_idx); + if (image->sec[sec_idx].len > fwrt->fw_paging_db[0].fw_paging_size) { + IWL_ERR(fwrt, "CSS block is larger than paging size\n"); + ret = -EINVAL; + goto err; + } + memcpy(page_address(fwrt->fw_paging_db[0].fw_paging_block), image->sec[sec_idx].data, - fwrt->fw_paging_db[0].fw_paging_size); + image->sec[sec_idx].len); dma_sync_single_for_device(fwrt->trans->dev, fwrt->fw_paging_db[0].fw_paging_phys, fwrt->fw_paging_db[0].fw_paging_size, @@ -232,6 +240,14 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt, for (idx = 1; idx < fwrt->num_of_paging_blk; idx++) { struct iwl_fw_paging *block = &fwrt->fw_paging_db[idx]; + if (block->fw_paging_size > image->sec[sec_idx].len - offset) { + IWL_ERR(fwrt, + "Paging: paging size is larger than remaining data in block %d\n", + idx); + ret = -EINVAL; + goto err; + } + memcpy(page_address(block->fw_paging_block), image->sec[sec_idx].data + offset, block->fw_paging_size); @@ -242,19 +258,32 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt, IWL_DEBUG_FW(fwrt, "Paging: copied %d paging bytes to block %d\n", - fwrt->fw_paging_db[idx].fw_paging_size, - idx); + block->fw_paging_size, idx); + + offset += block->fw_paging_size; - offset += fwrt->fw_paging_db[idx].fw_paging_size; + if (offset > image->sec[sec_idx].len) { + IWL_ERR(fwrt, + "Paging: offset goes over section size\n"); + ret = -EINVAL; + goto err; + } } /* copy the last paging block */ if (fwrt->num_of_pages_in_last_blk > 0) { struct iwl_fw_paging *block = &fwrt->fw_paging_db[idx]; + if (image->sec[sec_idx].len - offset > block->fw_paging_size) { + IWL_ERR(fwrt, + "Paging: last block is larger than paging size\n"); + ret = -EINVAL; + goto err; + } + memcpy(page_address(block->fw_paging_block), image->sec[sec_idx].data + offset, - FW_PAGING_SIZE * fwrt->num_of_pages_in_last_blk); + image->sec[sec_idx].len - offset); dma_sync_single_for_device(fwrt->trans->dev, block->fw_paging_phys, block->fw_paging_size, @@ -266,6 +295,10 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt, } return 0; + +err: + iwl_free_fw_paging(fwrt); + return ret; } static int iwl_save_fw_paging(struct iwl_fw_runtime *fwrt, -- GitLab From f7e4328c37007c43e005af1b3ed268149f8abb32 Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Thu, 31 May 2018 16:36:58 +0000 Subject: [PATCH 0815/1299] orangefs: set i_size on new symlink commit f6a4b4c9d07dda90c7c29dae96d6119ac6425dca upstream. As long as a symlink inode remains in-core, the destination (and therefore size) will not be re-fetched from the server, as it cannot change. The original implementation of the attribute cache assumed that setting the expiry time in the past was sufficient to cause a re-fetch of all attributes on the next getattr. That does not work in this case. The bug manifested itself as follows. When the command sequence touch foo; ln -s foo bar; ls -l bar is run, the output was lrwxrwxrwx. 1 fedora fedora 4906 Apr 24 19:10 bar -> foo However, after a re-mount, ls -l bar produces lrwxrwxrwx. 1 fedora fedora 3 Apr 24 19:10 bar -> foo After this commit, even before a re-mount, the output is lrwxrwxrwx. 1 fedora fedora 3 Apr 24 19:10 bar -> foo Reported-by: Becky Ligon Signed-off-by: Martin Brandenburg Fixes: 71680c18c8f2 ("orangefs: Cache getattr results.") Cc: stable@vger.kernel.org Cc: hubcap@omnibond.com Signed-off-by: Mike Marshall Signed-off-by: Greg Kroah-Hartman --- fs/orangefs/namei.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c index f8f3c73d2664..05b3abbdbc4b 100644 --- a/fs/orangefs/namei.c +++ b/fs/orangefs/namei.c @@ -314,6 +314,13 @@ static int orangefs_symlink(struct inode *dir, ret = PTR_ERR(inode); goto out; } + /* + * This is necessary because orangefs_inode_getattr will not + * re-read symlink size as it is impossible for it to change. + * Invalidating the cache does not help. orangefs_new_inode + * does not set the correct size (it does not know symname). + */ + inode->i_size = strlen(symname); gossip_debug(GOSSIP_NAME_DEBUG, "Assigned symlink inode new number of %pU\n", -- GitLab From e3e6bd6a14761942a93ffef884f954764ddca39e Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Thu, 31 May 2018 16:37:00 +0000 Subject: [PATCH 0816/1299] orangefs: report attributes_mask and attributes for statx commit 7f54910fa8dfe504f2e1563f4f6ddc3294dfbf3a upstream. OrangeFS formerly failed to set attributes_mask with the result that software could not see immutable and append flags present in the filesystem. Reported-by: Becky Ligon Signed-off-by: Martin Brandenburg Fixes: 68a24a6cc4a6 ("orangefs: implement statx") Cc: stable@vger.kernel.org Cc: hubcap@omnibond.com Signed-off-by: Mike Marshall Signed-off-by: Greg Kroah-Hartman --- fs/orangefs/inode.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c index 28825a5b6d09..902b72dac41a 100644 --- a/fs/orangefs/inode.c +++ b/fs/orangefs/inode.c @@ -269,6 +269,13 @@ int orangefs_getattr(const struct path *path, struct kstat *stat, else stat->result_mask = STATX_BASIC_STATS & ~STATX_SIZE; + + stat->attributes_mask = STATX_ATTR_IMMUTABLE | + STATX_ATTR_APPEND; + if (inode->i_flags & S_IMMUTABLE) + stat->attributes |= STATX_ATTR_IMMUTABLE; + if (inode->i_flags & S_APPEND) + stat->attributes |= STATX_ATTR_APPEND; } return ret; } -- GitLab From ab17de60ceaa10ef48f39afe9753f63f0fc80037 Mon Sep 17 00:00:00 2001 From: Even Xu Date: Fri, 12 Feb 2016 04:11:34 +0800 Subject: [PATCH 0817/1299] HID: intel_ish-hid: ipc: register more pm callbacks to support hibernation commit ebeaa367548e9e92dd9374b9464ff6e7d157117b upstream. Current ISH driver only registers suspend/resume PM callbacks which don't support hibernation (suspend to disk). Basically after hiberation, the ISH can't resume properly and user may not see sensor events (for example: screen rotation may not work). User will not see a crash or panic or anything except the following message in log: hid-sensor-hub 001F:8086:22D8.0001: timeout waiting for response from ISHTP device So this patch adds support for S4/hiberbation to ISH by using the SIMPLE_DEV_PM_OPS() MACRO instead of struct dev_pm_ops directly. The suspend and resume functions will now be used for both suspend to RAM and hibernation. If power management is disabled, SIMPLE_DEV_PM_OPS will do nothing, the suspend and resume related functions won't be used, so mark them as __maybe_unused to clarify that this is the intended behavior, and remove #ifdefs for power management. Cc: stable@vger.kernel.org Signed-off-by: Even Xu Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/intel-ish-hid/ipc/pci-ish.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index 20d824f74f99..90d7be08fea0 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c @@ -204,8 +204,7 @@ static void ish_remove(struct pci_dev *pdev) kfree(ishtp_dev); } -#ifdef CONFIG_PM -static struct device *ish_resume_device; +static struct device __maybe_unused *ish_resume_device; /* 50ms to get resume response */ #define WAIT_FOR_RESUME_ACK_MS 50 @@ -219,7 +218,7 @@ static struct device *ish_resume_device; * in that case a simple resume message is enough, others we need * a reset sequence. */ -static void ish_resume_handler(struct work_struct *work) +static void __maybe_unused ish_resume_handler(struct work_struct *work) { struct pci_dev *pdev = to_pci_dev(ish_resume_device); struct ishtp_device *dev = pci_get_drvdata(pdev); @@ -261,7 +260,7 @@ static void ish_resume_handler(struct work_struct *work) * * Return: 0 to the pm core */ -static int ish_suspend(struct device *device) +static int __maybe_unused ish_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct ishtp_device *dev = pci_get_drvdata(pdev); @@ -287,7 +286,7 @@ static int ish_suspend(struct device *device) return 0; } -static DECLARE_WORK(resume_work, ish_resume_handler); +static __maybe_unused DECLARE_WORK(resume_work, ish_resume_handler); /** * ish_resume() - ISH resume callback * @device: device pointer @@ -296,7 +295,7 @@ static DECLARE_WORK(resume_work, ish_resume_handler); * * Return: 0 to the pm core */ -static int ish_resume(struct device *device) +static int __maybe_unused ish_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct ishtp_device *dev = pci_get_drvdata(pdev); @@ -310,21 +309,14 @@ static int ish_resume(struct device *device) return 0; } -static const struct dev_pm_ops ish_pm_ops = { - .suspend = ish_suspend, - .resume = ish_resume, -}; -#define ISHTP_ISH_PM_OPS (&ish_pm_ops) -#else -#define ISHTP_ISH_PM_OPS NULL -#endif /* CONFIG_PM */ +static SIMPLE_DEV_PM_OPS(ish_pm_ops, ish_suspend, ish_resume); static struct pci_driver ish_driver = { .name = KBUILD_MODNAME, .id_table = ish_pci_tbl, .probe = ish_probe, .remove = ish_remove, - .driver.pm = ISHTP_ISH_PM_OPS, + .driver.pm = &ish_pm_ops, }; module_pci_driver(ish_driver); -- GitLab From d37c95f529115230421ee91a9553558321cca4e8 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 12 Jun 2018 13:42:46 -0700 Subject: [PATCH 0818/1299] HID: wacom: Correct logical maximum Y for 2nd-gen Intuos Pro large commit d471b6b22d37bf9928c6d0202bdaaf76583b8b61 upstream. The HID descriptor for the 2nd-gen Intuos Pro large (PTH-860) contains a typo which defines an incorrect logical maximum Y value. This causes a small portion of the bottom of the tablet to become unusable (both because the area is below the "bottom" of the tablet and because 'wacom_wac_event' ignores out-of-range values). It also results in a skewed aspect ratio. To fix this, we add a quirk to 'wacom_usage_mapping' which overwrites the data with the correct value. Signed-off-by: Jason Gerecke CC: stable@vger.kernel.org # v4.10+ Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/wacom_sys.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 69afd7968d9c..18d5b99d13f1 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -284,6 +284,14 @@ static void wacom_usage_mapping(struct hid_device *hdev, } } + /* 2nd-generation Intuos Pro Large has incorrect Y maximum */ + if (hdev->vendor == USB_VENDOR_ID_WACOM && + hdev->product == 0x0358 && + WACOM_PEN_FIELD(field) && + wacom_equivalent_usage(usage->hid) == HID_GD_Y) { + field->logical_maximum = 43200; + } + switch (usage->hid) { case HID_GD_X: features->x_max = field->logical_maximum; -- GitLab From 7446344baafba2f23da58ac837b86770ec977b90 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sat, 12 May 2018 00:33:10 +0300 Subject: [PATCH 0819/1299] vhost: fix info leak due to uninitialized memory commit 670ae9caaca467ea1bfd325cb2a5c98ba87f94ad upstream. struct vhost_msg within struct vhost_msg_node is copied to userspace. Unfortunately it turns out on 64 bit systems vhost_msg has padding after type which gcc doesn't initialize, leaking 4 uninitialized bytes to userspace. This padding also unfortunately means 32 bit users of this interface are broken on a 64 bit kernel which will need to be fixed separately. Fixes: CVE-2018-1118 Cc: stable@vger.kernel.org Reported-by: Kevin Easton Signed-off-by: Michael S. Tsirkin Reported-by: syzbot+87cfa083e727a224754b@syzkaller.appspotmail.com Signed-off-by: Michael S. Tsirkin Signed-off-by: Greg Kroah-Hartman --- drivers/vhost/vhost.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 50e48afd88ff..244e5256c526 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -2382,6 +2382,9 @@ struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type) struct vhost_msg_node *node = kmalloc(sizeof *node, GFP_KERNEL); if (!node) return NULL; + + /* Make sure all padding within the structure is initialized. */ + memset(&node->msg, 0, sizeof node->msg); node->vq = vq; node->msg.type = type; return node; -- GitLab From 250edf9580f7cba70efdcca4137089bd060f5090 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Thu, 7 Jun 2018 17:11:01 -0700 Subject: [PATCH 0820/1299] fs/binfmt_misc.c: do not allow offset overflow commit 5cc41e099504b77014358b58567c5ea6293dd220 upstream. WHen registering a new binfmt_misc handler, it is possible to overflow the offset to get a negative value, which might crash the system, or possibly leak kernel data. Here is a crash log when 2500000000 was used as an offset: BUG: unable to handle kernel paging request at ffff989cfd6edca0 IP: load_misc_binary+0x22b/0x470 [binfmt_misc] PGD 1ef3e067 P4D 1ef3e067 PUD 0 Oops: 0000 [#1] SMP NOPTI Modules linked in: binfmt_misc kvm_intel ppdev kvm irqbypass joydev input_leds serio_raw mac_hid parport_pc qemu_fw_cfg parpy CPU: 0 PID: 2499 Comm: bash Not tainted 4.15.0-22-generic #24-Ubuntu Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.1-1 04/01/2014 RIP: 0010:load_misc_binary+0x22b/0x470 [binfmt_misc] Call Trace: search_binary_handler+0x97/0x1d0 do_execveat_common.isra.34+0x667/0x810 SyS_execve+0x31/0x40 do_syscall_64+0x73/0x130 entry_SYSCALL_64_after_hwframe+0x3d/0xa2 Use kstrtoint instead of simple_strtoul. It will work as the code already set the delimiter byte to '\0' and we only do it when the field is not empty. Tested with offsets -1, 2500000000, UINT_MAX and INT_MAX. Also tested with examples documented at Documentation/admin-guide/binfmt-misc.rst and other registrations from packages on Ubuntu. Link: http://lkml.kernel.org/r/20180529135648.14254-1-cascardo@canonical.com Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Thadeu Lima de Souza Cascardo Reviewed-by: Andrew Morton Cc: Alexander Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/binfmt_misc.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index a7c5a9861bef..8311e8ed76de 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -387,8 +387,13 @@ static Node *create_entry(const char __user *buffer, size_t count) s = strchr(p, del); if (!s) goto einval; - *s++ = '\0'; - e->offset = simple_strtoul(p, &p, 10); + *s = '\0'; + if (p != s) { + int r = kstrtoint(p, 10, &e->offset); + if (r != 0 || e->offset < 0) + goto einval; + } + p = s; if (*p++) goto einval; pr_debug("register: offset: %#x\n", e->offset); @@ -428,7 +433,8 @@ static Node *create_entry(const char __user *buffer, size_t count) if (e->mask && string_unescape_inplace(e->mask, UNESCAPE_HEX) != e->size) goto einval; - if (e->size + e->offset > BINPRM_BUF_SIZE) + if (e->size > BINPRM_BUF_SIZE || + BINPRM_BUF_SIZE - e->size < e->offset) goto einval; pr_debug("register: magic/mask length: %i\n", e->size); if (USE_DEBUG) { -- GitLab From 1d26c112959f91e28dadee942877e32b91596d76 Mon Sep 17 00:00:00 2001 From: Vlastimil Babka Date: Thu, 7 Jun 2018 17:09:29 -0700 Subject: [PATCH 0821/1299] mm, page_alloc: do not break __GFP_THISNODE by zonelist reset commit 7810e6781e0fcbca78b91cf65053f895bf59e85f upstream. In __alloc_pages_slowpath() we reset zonelist and preferred_zoneref for allocations that can ignore memory policies. The zonelist is obtained from current CPU's node. This is a problem for __GFP_THISNODE allocations that want to allocate on a different node, e.g. because the allocating thread has been migrated to a different CPU. This has been observed to break SLAB in our 4.4-based kernel, because there it relies on __GFP_THISNODE working as intended. If a slab page is put on wrong node's list, then further list manipulations may corrupt the list because page_to_nid() is used to determine which node's list_lock should be locked and thus we may take a wrong lock and race. Current SLAB implementation seems to be immune by luck thanks to commit 511e3a058812 ("mm/slab: make cache_grow() handle the page allocated on arbitrary node") but there may be others assuming that __GFP_THISNODE works as promised. We can fix it by simply removing the zonelist reset completely. There is actually no reason to reset it, because memory policies and cpusets don't affect the zonelist choice in the first place. This was different when commit 183f6371aac2 ("mm: ignore mempolicies when using ALLOC_NO_WATERMARK") introduced the code, as mempolicies provided their own restricted zonelists. We might consider this for 4.17 although I don't know if there's anything currently broken. SLAB is currently not affected, but in kernels older than 4.7 that don't yet have 511e3a058812 ("mm/slab: make cache_grow() handle the page allocated on arbitrary node") it is. That's at least 4.4 LTS. Older ones I'll have to check. So stable backports should be more important, but will have to be reviewed carefully, as the code went through many changes. BTW I think that also the ac->preferred_zoneref reset is currently useless if we don't also reset ac->nodemask from a mempolicy to NULL first (which we probably should for the OOM victims etc?), but I would leave that for a separate patch. Link: http://lkml.kernel.org/r/20180525130853.13915-1-vbabka@suse.cz Signed-off-by: Vlastimil Babka Fixes: 183f6371aac2 ("mm: ignore mempolicies when using ALLOC_NO_WATERMARK") Acked-by: Mel Gorman Cc: Michal Hocko Cc: David Rientjes Cc: Joonsoo Kim Cc: Vlastimil Babka Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page_alloc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 1d7693c35424..59ccf455fcbd 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3981,7 +3981,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, * orientated. */ if (!(alloc_flags & ALLOC_CPUSET) || reserve_flags) { - ac->zonelist = node_zonelist(numa_node_id(), gfp_mask); ac->preferred_zoneref = first_zones_zonelist(ac->zonelist, ac->high_zoneidx, ac->nodemask); } -- GitLab From a26899e0baa4de07caf97f5e4d7298240e98fd0e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 26 Jun 2018 08:06:33 +0800 Subject: [PATCH 0822/1299] Linux 4.14.52 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a33376204c17..e2e4009bbfed 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 51 +SUBLEVEL = 52 EXTRAVERSION = NAME = Petit Gorille -- GitLab From 58d26de620d651ca6719ce16de38caf5dfef5f9a Mon Sep 17 00:00:00 2001 From: Aditya Degwekar Date: Mon, 25 Jun 2018 18:11:26 -0700 Subject: [PATCH 0823/1299] defconfig: sm8150: Enable support for UVC devices Enable USB Video Class (UVC) device support and media drivers for USB bus for enabling video input devices, such as camera streamers over USB Change-Id: I2a7508c5501ef157e2bf46cf4be0b355d84af697 Signed-off-by: Aditya Degwekar --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 2 ++ arch/arm64/configs/vendor/sm8150_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 9fb85b7fe1c1..dcc85fb1f204 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -369,6 +369,8 @@ CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_VIDEO_ADV_DEBUG=y CONFIG_VIDEO_FIXED_MINOR_RANGES=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=y CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_SPECTRA_CAMERA=y CONFIG_MSM_VIDC_V4L2=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index c4873fb06ba4..e99ee1d8dc1f 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -384,6 +384,8 @@ CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_VIDEO_ADV_DEBUG=y CONFIG_VIDEO_FIXED_MINOR_RANGES=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=y CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_SPECTRA_CAMERA=y CONFIG_MSM_VIDC_V4L2=y -- GitLab From 54a81c5fb62f59d0b66855fc43204cd1a4ebda7e Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Mon, 25 Jun 2018 18:53:23 -0700 Subject: [PATCH 0824/1299] msm: ipa4: fix client register and deregister for usb Register all USB protocols instead of the first one. Use pm Deregister if pm is configured. Start as 1 for a valid pm handle for clients since 0 is commonly used for debug purposes. Change-Id: I5c816f03dc458144f4d7c56bd03ac5355a8b7f92 Signed-off-by: Michael Adisumarta Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa_pm.c | 9 +++++---- drivers/platform/msm/ipa/ipa_v3/ipa_pm.h | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c index bffadfb7147e..34065cf8c2ed 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c @@ -242,7 +242,7 @@ static int calculate_throughput(void) struct ipa_pm_client *client; /* Create a basic array to hold throughputs*/ - for (i = 0, n = 0; i < IPA_PM_MAX_CLIENTS; i++) { + for (i = 1, n = 0; i < IPA_PM_MAX_CLIENTS; i++) { client = ipa_pm_ctx->clients[i]; if (client != NULL && IPA_PM_STATE_ACTIVE(client->state)) { /* default case */ @@ -498,7 +498,8 @@ static int find_next_open_array_element(const char *name) n = -ENOBUFS; - for (i = IPA_PM_MAX_CLIENTS - 1; i >= 0; i--) { + /* 0 is not a valid handle */ + for (i = IPA_PM_MAX_CLIENTS - 1; i >= 1; i--) { if (ipa_pm_ctx->clients[i] == NULL) { n = i; continue; @@ -1063,7 +1064,7 @@ int ipa_pm_deactivate_all_deferred(void) return -EINVAL; } - for (i = 0; i < IPA_PM_MAX_CLIENTS; i++) { + for (i = 1; i < IPA_PM_MAX_CLIENTS; i++) { client = ipa_pm_ctx->clients[i]; if (client == NULL) @@ -1304,7 +1305,7 @@ int ipa_pm_stat(char *buf, int size) cnt += result; - for (i = 0; i < IPA_PM_MAX_CLIENTS; i++) { + for (i = 1; i < IPA_PM_MAX_CLIENTS; i++) { client = ipa_pm_ctx->clients[i]; if (client == NULL) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h index 38e082f35e6f..47a03f938243 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,7 +16,7 @@ #include /* internal to ipa */ -#define IPA_PM_MAX_CLIENTS 12 /* actual max is value -1 since we start from 1*/ +#define IPA_PM_MAX_CLIENTS 32 /* actual max is value -1 since we start from 1*/ #define IPA_PM_MAX_EX_CL 64 #define IPA_PM_THRESHOLD_MAX 5 #define IPA_PM_EXCEPTION_MAX 2 -- GitLab From 7ddb6e89e837939708ed9042bf12fe6087ccc92a Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 22 Jun 2018 13:46:53 +0530 Subject: [PATCH 0825/1299] ARM: dts: msm: Update LPM parameters for sm8150 Update various LPM parameters such as latency, time overhead, energy overhead and steady state power. Also update prediction parameters for CPUs and cluster level prediction. Change-Id: Ide895c4e382e5fbf80bf1ab6ea2c1e4c3f4077b9 Signed-off-by: Maulik Shah --- arch/arm64/boot/dts/qcom/sm8150-pm.dtsi | 61 ++++++++----------------- 1 file changed, 20 insertions(+), 41 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-pm.dtsi b/arch/arm64/boot/dts/qcom/sm8150-pm.dtsi index b01b389bbc0f..838b17dfeba0 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-pm.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-pm.dtsi @@ -22,6 +22,7 @@ #address-cells = <1>; #size-cells = <0>; label = "L3"; + qcom,clstr-tmr-add = <1000>; qcom,psci-mode-shift = <4>; qcom,psci-mode-mask = <0xfff>; @@ -35,39 +36,14 @@ qcom,time-overhead = <99>; }; - qcom,pm-cluster-level@1 { /* D4 */ + qcom,pm-cluster-level@1 { /* LLCC off, AOSS sleep */ reg = <1>; - label = "l3-pc"; - qcom,psci-mode = <0x4>; - qcom,latency-us = <4562>; - qcom,ss-power = <408>; - qcom,energy-overhead = <2421840>; - qcom,time-overhead = <5376>; - qcom,min-child-idx = <2>; - qcom,is-reset; - }; - - qcom,pm-cluster-level@2 { /* Cx off */ - reg = <2>; - label = "cx-off"; - qcom,psci-mode = <0x224>; - qcom,latency-us = <5562>; - qcom,ss-power = <308>; - qcom,energy-overhead = <2521840>; - qcom,time-overhead = <6376>; - qcom,min-child-idx = <2>; - qcom,is-reset; - qcom,notify-rpm; - }; - - qcom,pm-cluster-level@3 { /* LLCC off, AOSS sleep */ - reg = <3>; label = "llcc-off"; qcom,psci-mode = <0xC24>; qcom,latency-us = <6562>; qcom,ss-power = <108>; - qcom,energy-overhead = <2621840>; - qcom,time-overhead = <7376>; + qcom,energy-overhead = <4000000>; + qcom,time-overhead = <5000>; qcom,min-child-idx = <2>; qcom,is-reset; qcom,notify-rpm; @@ -78,6 +54,9 @@ #size-cells = <0>; qcom,psci-mode-shift = <0>; qcom,psci-mode-mask = <0xf>; + qcom,ref-stddev = <500>; + qcom,tmr-add = <1000>; + qcom,ref-premature-cnt = <1>; qcom,cpu = <&CPU0 &CPU1 &CPU2 &CPU3>; qcom,pm-cpu-level@0 { /* C1 */ @@ -85,19 +64,19 @@ label = "wfi"; qcom,psci-cpu-mode = <0x1>; qcom,latency-us = <43>; - qcom,ss-power = <454>; - qcom,energy-overhead = <38639>; - qcom,time-overhead = <83>; + qcom,ss-power = <150>; + qcom,energy-overhead = <10000>; + qcom,time-overhead = <100>; }; qcom,pm-cpu-level@1 { /* C3 */ reg = <1>; label = "pc"; qcom,psci-cpu-mode = <0x3>; - qcom,latency-us = <612>; - qcom,ss-power = <436>; - qcom,energy-overhead = <418225>; - qcom,time-overhead = <885>; + qcom,latency-us = <461>; + qcom,ss-power = <100>; + qcom,energy-overhead = <400000>; + qcom,time-overhead = <500>; qcom,is-reset; qcom,use-broadcast-timer; }; @@ -106,10 +85,10 @@ reg = <2>; label = "rail-pc"; qcom,psci-cpu-mode = <0x4>; - qcom,latency-us = <700>; - qcom,ss-power = <400>; - qcom,energy-overhead = <428225>; - qcom,time-overhead = <1000>; + qcom,latency-us = <531>; + qcom,ss-power = <73>; + qcom,energy-overhead = <500000>; + qcom,time-overhead = <600>; qcom,is-reset; qcom,use-broadcast-timer; }; @@ -136,7 +115,7 @@ reg = <1>; label = "pc"; qcom,psci-cpu-mode = <0x3>; - qcom,latency-us = <612>; + qcom,latency-us = <621>; qcom,ss-power = <436>; qcom,energy-overhead = <418225>; qcom,time-overhead = <885>; @@ -148,7 +127,7 @@ reg = <2>; label = "rail-pc"; qcom,psci-cpu-mode = <0x4>; - qcom,latency-us = <700>; + qcom,latency-us = <1061>; qcom,ss-power = <400>; qcom,energy-overhead = <428225>; qcom,time-overhead = <1000>; -- GitLab From b27eceadfbd91c34ed1b857e5dc9081516efda52 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Thu, 21 Jun 2018 11:48:23 +0530 Subject: [PATCH 0826/1299] drivers: cpuidle: lpm-levels: Correctly check for list empty Correctly check for list empty condition to get least cluster latency. Change-Id: I56f11e4a80c24d337ee231f6d0bc461a90f1a2ea Signed-off-by: Maulik Shah --- drivers/cpuidle/lpm-levels.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index c7865bc273c6..ced301631e3a 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -156,7 +156,7 @@ static uint32_t least_cluster_latency(struct lpm_cluster *cluster, uint32_t latency = 0; int i; - if (!cluster->list.next) { + if (list_empty(&cluster->list)) { for (i = 0; i < cluster->nlevels; i++) { level = &cluster->levels[i]; pwr_params = &level->pwr; -- GitLab From 57c337d4e0d959c5ae6c1098404acad80c4117db Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Fri, 22 Jun 2018 16:09:37 +0530 Subject: [PATCH 0827/1299] ARM: dts: msm: Add memshare for sm8150 Memshare driver allocates and share the memory with the modem clients for their use. The device tree information for memshare driver on sm8150 are added to specify client details. Change-Id: Ib8b467ac2c95931e689cdbaf11b84ebd10f29414 Signed-off-by: Manoj Prabhu B --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index c5529cfd06d3..cd43e0c4206b 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -2103,6 +2103,33 @@ }; }; + qcom,memshare { + compatible = "qcom,memshare"; + + qcom,client_1 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <0>; + qcom,allocate-boot-time; + label = "modem"; + }; + + qcom,client_2 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <2>; + label = "modem"; + }; + + mem_client_3_size: qcom,client_3 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x500000>; + qcom,client-id = <1>; + qcom,allocate-boot-time; + label = "modem"; + }; + }; + qcom,sps { compatible = "qcom,msm_sps_4k"; qcom,pipe-attr-ee; -- GitLab From eeba79ca7794ec533d9659fdc3424d4d2cc59c7d Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Fri, 22 Jun 2018 21:49:35 +0530 Subject: [PATCH 0828/1299] defconfig: arm: msm: Enable memshare driver on sm8150 The patch enables memshare driver compilation necessary for allocation of memory for the clients requesting. Change-Id: I5386b9a2781e0ab42e9c078af9ef97715e9ffb7b Signed-off-by: Manoj Prabhu B --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 9fb85b7fe1c1..d9f91b7ccfd8 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -548,6 +548,7 @@ CONFIG_MSM_EVENT_TIMER=y CONFIG_MSM_PM=y CONFIG_MSM_QBT1000=y CONFIG_QCOM_FSA4480_I2C=y +CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_MSM_PERFORMANCE=y CONFIG_QMP_DEBUGFS_CLIENT=y CONFIG_QCOM_SMP2P_SLEEPSTATE=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index c4873fb06ba4..9b1c7c3b11d1 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -574,6 +574,7 @@ CONFIG_MSM_EVENT_TIMER=y CONFIG_MSM_PM=y CONFIG_MSM_QBT1000=y CONFIG_QCOM_FSA4480_I2C=y +CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_MSM_PERFORMANCE=y CONFIG_QMP_DEBUGFS_CLIENT=y CONFIG_QCOM_SMP2P_SLEEPSTATE=y -- GitLab From 38c0344dde75109ed9594e192b5019a561d1896e Mon Sep 17 00:00:00 2001 From: Mohit Aggarwal Date: Fri, 22 Jun 2018 12:05:15 +0530 Subject: [PATCH 0829/1299] diag: Update mask pointers after reallocation Currently, mask pointers are not updated in case peripherals are supporting more mask tables. The patch updates the mask pointers properly. Change-Id: I1360c722076fca0215e0ccd28247c4741a1ebd88 Signed-off-by: Mohit Aggarwal Signed-off-by: Manoj Prabhu B --- drivers/char/diag/diag_masks.c | 20 +++++++++++++------- drivers/char/diag/diagfwd_cntl.c | 23 ++++++++++++++++++++--- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index 14177c6cb460..caf76181f228 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -922,10 +922,12 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED : DIAG_CTRL_MASK_ALL_DISABLED; for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { - mutex_lock(&mask->lock); - memset(mask->ptr, req->rt_mask, - mask->range * sizeof(uint32_t)); - mutex_unlock(&mask->lock); + if (mask && mask->ptr) { + mutex_lock(&mask->lock); + memset(mask->ptr, req->rt_mask, + mask->range * sizeof(uint32_t)); + mutex_unlock(&mask->lock); + } } mutex_unlock(&driver->msg_mask_lock); mutex_unlock(&mask_info->lock); @@ -1337,6 +1339,8 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len, mutex_lock(&mask_info->lock); for (i = 0; i < MAX_EQUIP_ID && !status; i++, mask++) { + if (!mask || !mask->ptr) + continue; if (mask->equip_id != req->equip_id) continue; mutex_lock(&mask->lock); @@ -1464,9 +1468,11 @@ static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len, return -EINVAL; } for (i = 0; i < MAX_EQUIP_ID; i++, mask++) { - mutex_lock(&mask->lock); - memset(mask->ptr, 0, mask->range); - mutex_unlock(&mask->lock); + if (mask && mask->ptr) { + mutex_lock(&mask->lock); + memset(mask->ptr, 0, mask->range); + mutex_unlock(&mask->lock); + } } mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED; mutex_unlock(&driver->md_session_lock); diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c index 704b945a026b..10da2c717088 100644 --- a/drivers/char/diag/diagfwd_cntl.c +++ b/drivers/char/diag/diagfwd_cntl.c @@ -445,8 +445,8 @@ static void process_last_event_report(uint8_t *buf, uint32_t len, header = (struct diag_ctrl_last_event_report *)ptr; event_size = ((header->event_last_id / 8) + 1); if (event_size >= driver->event_mask_size) { - pr_debug("diag: In %s, receiving event mask size more that Apps can handle\n", - __func__); + DIAG_LOG(DIAG_DEBUG_MASKS, + "diag: receiving event mask size more that Apps can handle\n"); temp = krealloc(driver->event_mask->ptr, event_size, GFP_KERNEL); if (!temp) { @@ -560,6 +560,10 @@ static void process_ssid_range_report(uint8_t *buf, uint32_t len, mask_ptr = (struct diag_msg_mask_t *)msg_mask.ptr; found = 0; for (j = 0; j < driver->msg_mask_tbl_count; j++, mask_ptr++) { + if (!mask_ptr || !ssid_range) { + found = 1; + break; + } if (mask_ptr->ssid_first != ssid_range->ssid_first) continue; mutex_lock(&mask_ptr->lock); @@ -578,6 +582,8 @@ static void process_ssid_range_report(uint8_t *buf, uint32_t len, new_size = (driver->msg_mask_tbl_count + 1) * sizeof(struct diag_msg_mask_t); + DIAG_LOG(DIAG_DEBUG_MASKS, + "diag: receiving msg mask size more that Apps can handle\n"); temp = krealloc(msg_mask.ptr, new_size, GFP_KERNEL); if (!temp) { pr_err("diag: In %s, Unable to add new ssid table to msg mask, ssid first: %d, last: %d\n", @@ -586,6 +592,7 @@ static void process_ssid_range_report(uint8_t *buf, uint32_t len, continue; } msg_mask.ptr = temp; + mask_ptr = (struct diag_msg_mask_t *)msg_mask.ptr; err = diag_create_msg_mask_table_entry(mask_ptr, ssid_range); if (err) { pr_err("diag: In %s, Unable to create a new msg mask table entry, first: %d last: %d err: %d\n", @@ -625,6 +632,10 @@ static void diag_build_time_mask_update(uint8_t *buf, num_items = range->ssid_last - range->ssid_first + 1; for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) { + if (!build_mask) { + found = 1; + break; + } if (build_mask->ssid_first != range->ssid_first) continue; found = 1; @@ -635,7 +646,8 @@ static void diag_build_time_mask_update(uint8_t *buf, __func__); } dest_ptr = build_mask->ptr; - for (j = 0; j < build_mask->range; j++, mask_ptr++, dest_ptr++) + for (j = 0; (j < build_mask->range) && mask_ptr && dest_ptr; + j++, mask_ptr++, dest_ptr++) *(uint32_t *)dest_ptr |= *mask_ptr; mutex_unlock(&build_mask->lock); break; @@ -643,8 +655,12 @@ static void diag_build_time_mask_update(uint8_t *buf, if (found) goto end; + new_size = (driver->bt_msg_mask_tbl_count + 1) * sizeof(struct diag_msg_mask_t); + DIAG_LOG(DIAG_DEBUG_MASKS, + "diag: receiving build time mask size more that Apps can handle\n"); + temp = krealloc(driver->build_time_mask->ptr, new_size, GFP_KERNEL); if (!temp) { pr_err("diag: In %s, unable to create a new entry for build time mask\n", @@ -652,6 +668,7 @@ static void diag_build_time_mask_update(uint8_t *buf, goto end; } driver->build_time_mask->ptr = temp; + build_mask = (struct diag_msg_mask_t *)driver->build_time_mask->ptr; err = diag_create_msg_mask_table_entry(build_mask, range); if (err) { pr_err("diag: In %s, Unable to create a new msg mask table entry, err: %d\n", -- GitLab From 71f6efba5950c724bbd0b9272569ad8fc0bebcfd Mon Sep 17 00:00:00 2001 From: Lingutla Chandrasekhar Date: Tue, 26 Jun 2018 09:52:17 +0530 Subject: [PATCH 0830/1299] ARM: dts: msm: add cpu dmips capacity for qcs405 Add cpu's dmips per mhz for capacity calculations, these are used in scheduler. Change-Id: Ie3cede9c430d9e9433fc656d700aa7412ff18669 Signed-off-by: Lingutla Chandrasekhar --- arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi b/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi index ed48793d348c..cc237fdeccf0 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi @@ -42,6 +42,7 @@ compatible = "arm,cortex-a53"; reg = <0x100>; enable-method = "psci"; + capacity-dmips-mhz = <1024>; sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; @@ -66,6 +67,7 @@ compatible = "arm,cortex-a53"; reg = <0x101>; enable-method = "psci"; + capacity-dmips-mhz = <1024>; sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; @@ -84,6 +86,7 @@ compatible = "arm,cortex-a53"; reg = <0x102>; enable-method = "psci"; + capacity-dmips-mhz = <1024>; sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; @@ -102,6 +105,7 @@ compatible = "arm,cortex-a53"; reg = <0x103>; enable-method = "psci"; + capacity-dmips-mhz = <1024>; sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>; next-level-cache = <&L2_1>; #cooling-cells = <2>; -- GitLab From bccde84744a8892c4859199a5d06f5cbb2a21eae Mon Sep 17 00:00:00 2001 From: Sayali Lokhande Date: Mon, 14 May 2018 22:05:32 +0530 Subject: [PATCH 0831/1299] ARM: dts: msm: Add UFS support for sm6150 Enable ufs support for sm6150 rumi platform. Change-Id: I22587f0c625d800f2848a9d29b0ddb45606f166b Signed-off-by: Sayali Lokhande --- arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi | 46 ++++++++++++ arch/arm64/boot/dts/qcom/sm6150-rumi.dtsi | 34 +++++++++ arch/arm64/boot/dts/qcom/sm6150.dtsi | 73 ++++++++++++++++++++ 3 files changed, 153 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi index 1126ddac9394..5e62775e0761 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi @@ -20,6 +20,52 @@ interrupt-controller; #interrupt-cells = <2>; + ufs_dev_reset_assert: ufs_dev_reset_assert { + config { + pins = "ufs_reset"; + bias-pull-down; /* default: pull down */ + /* + * UFS_RESET driver strengths are having + * different values/steps compared to typical + * GPIO drive strengths. + * + * Following table clarifies: + * + * HDRV value | UFS_RESET | Typical GPIO + * (dec) | (mA) | (mA) + * 0 | 0.8 | 2 + * 1 | 1.55 | 4 + * 2 | 2.35 | 6 + * 3 | 3.1 | 8 + * 4 | 3.9 | 10 + * 5 | 4.65 | 12 + * 6 | 5.4 | 14 + * 7 | 6.15 | 16 + * + * POR value for UFS_RESET HDRV is 3 which means + * 3.1mA and we want to use that. Hence just + * specify 8mA to "drive-strength" binding and + * that should result into writing 3 to HDRV + * field. + */ + drive-strength = <8>; /* default: 3.1 mA */ + output-low; /* active low reset */ + }; + }; + + ufs_dev_reset_deassert: ufs_dev_reset_deassert { + config { + pins = "ufs_reset"; + bias-pull-down; /* default: pull down */ + /* + * default: 3.1 mA + * check comments under ufs_dev_reset_assert + */ + drive-strength = <8>; + output-high; /* active low reset */ + }; + }; + /* QUPv3_0 South SE mappings */ /* SE 0 pin mappings */ qupv3_se0_2uart_pins: qupv3_se0_2uart_pins { diff --git a/arch/arm64/boot/dts/qcom/sm6150-rumi.dtsi b/arch/arm64/boot/dts/qcom/sm6150-rumi.dtsi index 51ec825cb9ef..3d8b2bddefea 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-rumi.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-rumi.dtsi @@ -72,6 +72,40 @@ status = "disabled"; }; +&ufsphy_mem { + compatible = "qcom,ufs-phy-qrbtc-sdm845"; + + vdda-phy-supply = <&pm6150_l4>; /* 0.88v */ + vdda-pll-supply = <&pm6150_l11>; /* 1.2v */ + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + + status = "ok"; +}; + +&ufshc_mem { + limit-tx-hs-gear = <1>; + limit-rx-hs-gear = <1>; + scsi-cmd-timeout = <300000>; + + vdd-hba-supply = <&ufs_phy_gdsc>; + vdd-hba-fixed-regulator; + vcc-supply = <&pm6150l_l11>; + vccq2-supply = <&pm6150_l12>; + vcc-max-microamp = <600000>; + vccq2-max-microamp = <600000>; + + qcom,vddp-ref-clk-supply = <&pm6150l_l3>; + qcom,vddp-ref-clk-max-microamp = <100>; + qcom,vddp-ref-clk-min-uV = <1232000>; + qcom,vddp-ref-clk-max-uV = <1260000>; + + qcom,disable-lpm; + rpm-level = <0>; + spm-level = <0>; + status = "ok"; +}; + &spmi_bus { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index 5d2ebe110a6b..e285a6f5e2c3 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -32,6 +32,7 @@ interrupt-parent = <&pdc>; aliases { + ufshc1 = &ufshc_mem; /* Embedded UFS slot */ serial0 = &qupv3_se0_2uart; sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ sdhc2 = &sdhc_2; /* SDC2 SD Card slot */ @@ -1041,6 +1042,78 @@ status = "disabled"; }; + ufsphy_mem: ufsphy_mem@1d87000 { + reg = <0x1d87000 0xdb8>; /* PHY regs */ + reg-names = "phy_mem"; + #phy-cells = <0>; + + lanes-per-direction = <1>; + + clock-names = "ref_clk_src", + "ref_clk", + "ref_aux_clk"; + clocks = <&clock_rpmh RPMH_CXO_CLK>, + <&clock_gcc GCC_UFS_MEM_CLKREF_CLK>, + <&clock_gcc GCC_UFS_PHY_PHY_AUX_CLK>; + + status = "disabled"; + }; + + ufshc_mem: ufshc@1d84000 { + compatible = "qcom,ufshc"; + reg = <0x1d84000 0x3000>; + interrupts = <0 265 0>; + phys = <&ufsphy_mem>; + phy-names = "ufsphy"; + + lanes-per-direction = <1>; + dev-ref-clk-freq = <0>; /* 19.2 MHz */ + spm-level = <5>; + + clock-names = + "core_clk", + "bus_aggr_clk", + "iface_clk", + "core_clk_unipro", + "core_clk_ice", + "ref_clk", + "tx_lane0_sync_clk", + "rx_lane0_sync_clk"; + clocks = + <&clock_gcc GCC_UFS_PHY_AXI_CLK>, + <&clock_gcc GCC_AGGRE_UFS_PHY_AXI_CLK>, + <&clock_gcc GCC_UFS_PHY_AHB_CLK>, + <&clock_gcc GCC_UFS_PHY_UNIPRO_CORE_CLK>, + <&clock_gcc GCC_UFS_PHY_ICE_CORE_CLK>, + <&clock_rpmh RPMH_CXO_CLK>, + <&clock_gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>, + <&clock_gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>; + freq-table-hz = + <37500000 300000000>, + <0 0>, + <0 0>, + <37500000 300000000>, + <75000000 300000000>, + <0 0>, + <0 0>, + <0 0>; + + /* PM QoS */ + qcom,pm-qos-cpu-groups = <0x3f 0xC0>; + qcom,pm-qos-cpu-group-latency-us = <67 67>; + qcom,pm-qos-default-cpu = <0>; + + pinctrl-names = "dev-reset-assert", "dev-reset-deassert"; + pinctrl-0 = <&ufs_dev_reset_assert>; + pinctrl-1 = <&ufs_dev_reset_deassert>; + + resets = <&clock_gcc GCC_UFS_PHY_BCR>; + reset-names = "core_reset"; + non-removable; + + status = "disabled"; + }; + spmi_bus: qcom,spmi@c440000 { compatible = "qcom,spmi-pmic-arb"; reg = <0xc440000 0x2300>, -- GitLab From 1cf9b916b664a167d9033f6a6e7443b810f4ab2b Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Wed, 4 Mar 2015 16:38:28 +0530 Subject: [PATCH 0832/1299] mm: vmpressure: allow in-kernel clients to subscribe for events Currently, vmpressure is tied to memcg and its events are available only to userspace clients. This patch removes the dependency on CONFIG_MEMCG and adds a mechanism for in-kernel clients to subscribe for vmpressure events (in fact raw vmpressure values are delivered instead of vmpressure levels, to provide clients more flexibility to take actions on custom pressure levels which are not currently defined by vmpressure module). Change-Id: I38010f166546e8d7f12f5f355b5dbfd6ba04d587 Signed-off-by: Vinayak Menon --- include/linux/vmpressure.h | 12 ++-- mm/Makefile | 4 +- mm/vmpressure.c | 138 ++++++++++++++++++++++++++++++------- 3 files changed, 121 insertions(+), 33 deletions(-) diff --git a/include/linux/vmpressure.h b/include/linux/vmpressure.h index 61e6fddfb26f..1b8a21c3757a 100644 --- a/include/linux/vmpressure.h +++ b/include/linux/vmpressure.h @@ -29,11 +29,13 @@ struct vmpressure { struct mem_cgroup; -#ifdef CONFIG_MEMCG +extern int vmpressure_notifier_register(struct notifier_block *nb); +extern int vmpressure_notifier_unregister(struct notifier_block *nb); extern void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, unsigned long scanned, unsigned long reclaimed); extern void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio); +#ifdef CONFIG_MEMCG extern void vmpressure_init(struct vmpressure *vmpr); extern void vmpressure_cleanup(struct vmpressure *vmpr); extern struct vmpressure *memcg_to_vmpressure(struct mem_cgroup *memcg); @@ -44,9 +46,9 @@ extern int vmpressure_register_event(struct mem_cgroup *memcg, extern void vmpressure_unregister_event(struct mem_cgroup *memcg, struct eventfd_ctx *eventfd); #else -static inline void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, - unsigned long scanned, unsigned long reclaimed) {} -static inline void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, - int prio) {} +static inline struct vmpressure *memcg_to_vmpressure(struct mem_cgroup *memcg) +{ + return NULL; +} #endif /* CONFIG_MEMCG */ #endif /* __LINUX_VMPRESSURE_H */ diff --git a/mm/Makefile b/mm/Makefile index 5a2b9505e413..3243322fb58f 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -39,7 +39,7 @@ obj-y := filemap.o mempool.o oom_kill.o \ mm_init.o mmu_context.o percpu.o slab_common.o \ compaction.o vmacache.o swap_slots.o \ interval_tree.o list_lru.o workingset.o \ - debug.o $(mmu-y) showmem.o + debug.o $(mmu-y) showmem.o vmpressure.o obj-y += init-mm.o @@ -77,7 +77,7 @@ obj-$(CONFIG_MIGRATION) += migrate.o obj-$(CONFIG_QUICKLIST) += quicklist.o obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o khugepaged.o obj-$(CONFIG_PAGE_COUNTER) += page_counter.o -obj-$(CONFIG_MEMCG) += memcontrol.o vmpressure.o +obj-$(CONFIG_MEMCG) += memcontrol.o obj-$(CONFIG_MEMCG_SWAP) += swap_cgroup.o obj-$(CONFIG_CGROUP_HUGETLB) += hugetlb_cgroup.o obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o diff --git a/mm/vmpressure.c b/mm/vmpressure.c index afb5beadd219..d3b694a89271 100644 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include /* @@ -49,6 +51,24 @@ static const unsigned long vmpressure_win = SWAP_CLUSTER_MAX * 16; static const unsigned int vmpressure_level_med = 60; static const unsigned int vmpressure_level_critical = 95; +static struct vmpressure global_vmpressure; +static BLOCKING_NOTIFIER_HEAD(vmpressure_notifier); + +int vmpressure_notifier_register(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&vmpressure_notifier, nb); +} + +int vmpressure_notifier_unregister(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&vmpressure_notifier, nb); +} + +static void vmpressure_notify(unsigned long pressure) +{ + blocking_notifier_call_chain(&vmpressure_notifier, pressure, NULL); +} + /* * When there are too little pages left to scan, vmpressure() may miss the * critical pressure as number of pages will be less than "window size". @@ -75,6 +95,7 @@ static struct vmpressure *work_to_vmpressure(struct work_struct *work) return container_of(work, struct vmpressure, work); } +#ifdef CONFIG_MEMCG static struct vmpressure *vmpressure_parent(struct vmpressure *vmpr) { struct cgroup_subsys_state *css = vmpressure_to_css(vmpr); @@ -85,6 +106,12 @@ static struct vmpressure *vmpressure_parent(struct vmpressure *vmpr) return NULL; return memcg_to_vmpressure(memcg); } +#else +static struct vmpressure *vmpressure_parent(struct vmpressure *vmpr) +{ + return NULL; +} +#endif enum vmpressure_levels { VMPRESSURE_LOW = 0, @@ -121,7 +148,7 @@ static enum vmpressure_levels vmpressure_level(unsigned long pressure) return VMPRESSURE_LOW; } -static enum vmpressure_levels vmpressure_calc_level(unsigned long scanned, +static unsigned long vmpressure_calc_pressure(unsigned long scanned, unsigned long reclaimed) { unsigned long scale = scanned + reclaimed; @@ -148,7 +175,7 @@ static enum vmpressure_levels vmpressure_calc_level(unsigned long scanned, pr_debug("%s: %3lu (s: %lu r: %lu)\n", __func__, pressure, scanned, reclaimed); - return vmpressure_level(pressure); + return pressure; } struct vmpressure_event { @@ -186,6 +213,7 @@ static void vmpressure_work_fn(struct work_struct *work) struct vmpressure *vmpr = work_to_vmpressure(work); unsigned long scanned; unsigned long reclaimed; + unsigned long pressure; enum vmpressure_levels level; bool ancestor = false; bool signalled = false; @@ -210,7 +238,8 @@ static void vmpressure_work_fn(struct work_struct *work) vmpr->tree_reclaimed = 0; spin_unlock(&vmpr->sr_lock); - level = vmpressure_calc_level(scanned, reclaimed); + pressure = vmpressure_calc_pressure(scanned, reclaimed); + level = vmpressure_level(pressure); do { if (vmpressure_event(vmpr, level, ancestor, signalled)) @@ -219,28 +248,8 @@ static void vmpressure_work_fn(struct work_struct *work) } while ((vmpr = vmpressure_parent(vmpr))); } -/** - * vmpressure() - Account memory pressure through scanned/reclaimed ratio - * @gfp: reclaimer's gfp mask - * @memcg: cgroup memory controller handle - * @tree: legacy subtree mode - * @scanned: number of pages scanned - * @reclaimed: number of pages reclaimed - * - * This function should be called from the vmscan reclaim path to account - * "instantaneous" memory pressure (scanned/reclaimed ratio). The raw - * pressure index is then further refined and averaged over time. - * - * If @tree is set, vmpressure is in traditional userspace reporting - * mode: @memcg is considered the pressure root and userspace is - * notified of the entire subtree's reclaim efficiency. - * - * If @tree is not set, reclaim efficiency is recorded for @memcg, and - * only in-kernel users are notified. - * - * This function does not return any value. - */ -void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, +#ifdef CONFIG_MEMCG +static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree, unsigned long scanned, unsigned long reclaimed) { struct vmpressure *vmpr = memcg_to_vmpressure(memcg); @@ -281,6 +290,7 @@ void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, schedule_work(&vmpr->work); } else { enum vmpressure_levels level; + unsigned long pressure; /* For now, no users for root-level efficiency */ if (!memcg || memcg == root_mem_cgroup) @@ -296,7 +306,8 @@ void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, vmpr->scanned = vmpr->reclaimed = 0; spin_unlock(&vmpr->sr_lock); - level = vmpressure_calc_level(scanned, reclaimed); + pressure = vmpressure_calc_pressure(scanned, reclaimed); + level = vmpressure_level(pressure); if (level > VMPRESSURE_LOW) { /* @@ -311,6 +322,74 @@ void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, } } } +#else +static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree, + unsigned long scanned, unsigned long reclaimed) +{ +} +#endif + +static void vmpressure_global(gfp_t gfp, unsigned long scanned, + unsigned long reclaimed) +{ + struct vmpressure *vmpr = &global_vmpressure; + unsigned long pressure; + + if (!(gfp & (__GFP_HIGHMEM | __GFP_MOVABLE | __GFP_IO | __GFP_FS))) + return; + + if (!scanned) + return; + + spin_lock(&vmpr->sr_lock); + vmpr->scanned += scanned; + vmpr->reclaimed += reclaimed; + scanned = vmpr->scanned; + reclaimed = vmpr->reclaimed; + spin_unlock(&vmpr->sr_lock); + + if (scanned < vmpressure_win) + return; + + spin_lock(&vmpr->sr_lock); + vmpr->scanned = 0; + vmpr->reclaimed = 0; + spin_unlock(&vmpr->sr_lock); + + pressure = vmpressure_calc_pressure(scanned, reclaimed); + vmpressure_notify(pressure); +} + +/** + * vmpressure() - Account memory pressure through scanned/reclaimed ratio + * @gfp: reclaimer's gfp mask + * @memcg: cgroup memory controller handle + * @tree: legacy subtree mode + * @scanned: number of pages scanned + * @reclaimed: number of pages reclaimed + * + * This function should be called from the vmscan reclaim path to account + * "instantaneous" memory pressure (scanned/reclaimed ratio). The raw + * pressure index is then further refined and averaged over time. + * + * If @tree is set, vmpressure is in traditional userspace reporting + * mode: @memcg is considered the pressure root and userspace is + * notified of the entire subtree's reclaim efficiency. + * + * If @tree is not set, reclaim efficiency is recorded for @memcg, and + * only in-kernel users are notified. + * + * This function does not return any value. + */ +void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, + unsigned long scanned, unsigned long reclaimed) +{ + if (!memcg && tree) + vmpressure_global(gfp, scanned, reclaimed); + + if (IS_ENABLED(CONFIG_MEMCG)) + vmpressure_memcg(gfp, memcg, tree, scanned, reclaimed); +} /** * vmpressure_prio() - Account memory pressure through reclaimer priority level @@ -491,3 +570,10 @@ void vmpressure_cleanup(struct vmpressure *vmpr) */ flush_work(&vmpr->work); } + +static int vmpressure_global_init(void) +{ + vmpressure_init(&global_vmpressure); + return 0; +} +late_initcall(vmpressure_global_init); -- GitLab From 16ef91359c6141170a1d98ef2405012dce08d00a Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Fri, 9 Jan 2015 18:36:55 +0530 Subject: [PATCH 0833/1299] mm: prevent to write out dirty page in CMA by may_writepage Now, local variable references in shrink_page_list is PAGEREF_RECLAIM_CLEAN as default. It is for preventing to reclaim dirty pages when CMA try to migrate pages. Strictly speaking, we don't need it because CMA already didn't allow to write out by .may_writepage = 0 in reclaim_clean_pages_from_list. Morever, it has a problem to prevent anonymous pages's swap out when we use force_reclaim = true in shrink_page_list(ex, per process reclaim can do it) So this patch makes references's default value to PAGEREF_RECLAIM and declare .may_writepage = 0 of scan_control in CMA part to make code more clear. Change-Id: I5edc3c955d106ecebc4949ce27daf5b7b7a18089 Cc: Marek Szyprowski Cc: Mel Gorman Reported-by: Minkyung Kim Signed-off-by: Minchan Kim Patch-mainline: linux-mm @ 9 May 2013 16:21:23 [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- mm/vmscan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index cfc335d220e3..ac7e419c4f22 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -983,7 +983,7 @@ static unsigned long shrink_page_list(struct list_head *page_list, struct address_space *mapping; struct page *page; int may_enter_fs; - enum page_references references = PAGEREF_RECLAIM_CLEAN; + enum page_references references = PAGEREF_RECLAIM; bool dirty, writeback; cond_resched(); @@ -1378,6 +1378,8 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, .gfp_mask = GFP_KERNEL, .priority = DEF_PRIORITY, .may_unmap = 1, + /* Doesn't allow to write out dirty page */ + .may_writepage = 0, }; unsigned long ret; struct page *page, *next; -- GitLab From e6caa6025c64f7019eae808309d2d4b1abfdc5ad Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Thu, 9 May 2013 16:21:24 +0900 Subject: [PATCH 0834/1299] mm: Per process reclaim These day, there are many platforms available in the embedded market and they are smarter than kernel which has very limited information about working set so they want to involve memory management more heavily like android's lowmemory killer and ashmem or recent many lowmemory notifier. One of the simple imagine scenario about userspace's intelligence is that platform can manage tasks as forground and background so it would be better to reclaim background's task pages for end-user's *responsibility* although it has frequent referenced pages. This patch adds new knob "reclaim under proc//" so task manager can reclaim any target process anytime, anywhere. It could give another method to platform for using memory efficiently. It can avoid process killing for getting free memory, which was really terrible experience because I lost my best score of game I had ever after I switch the phone call while I enjoyed the game. Reclaim file-backed pages only. echo file > /proc/PID/reclaim Reclaim anonymous pages only. echo anon > /proc/PID/reclaim Reclaim all pages echo all > /proc/PID/reclaim Change-Id: Iabdb7bc2ef3dc4d94e3ea005fbe18f4cd06739ab Signed-off-by: Minchan Kim Patch-mainline: linux-mm @ 9 May 2013 16:21:24 [vinmenon@codeaurora.org: trivial merge conflict fixes, and minor tweak of the commit msg] Signed-off-by: Vinayak Menon --- fs/proc/base.c | 3 ++ fs/proc/internal.h | 1 + fs/proc/task_mmu.c | 121 +++++++++++++++++++++++++++++++++++++++++++ include/linux/rmap.h | 4 ++ mm/Kconfig | 13 +++++ mm/vmscan.c | 56 ++++++++++++++++++++ 6 files changed, 198 insertions(+) diff --git a/fs/proc/base.c b/fs/proc/base.c index 292cf94949cf..7d6cc5f3af24 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3162,6 +3162,9 @@ static const struct pid_entry tgid_base_stuff[] = { REG("mounts", S_IRUGO, proc_mounts_operations), REG("mountinfo", S_IRUGO, proc_mountinfo_operations), REG("mountstats", S_IRUSR, proc_mountstats_operations), +#ifdef CONFIG_PROCESS_RECLAIM + REG("reclaim", 0200, proc_reclaim_operations), +#endif #ifdef CONFIG_PROC_PAGE_MONITOR REG("clear_refs", S_IWUSR, proc_clear_refs_operations), REG("smaps", S_IRUGO, proc_pid_smaps_operations), diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 5e55186858c9..c5d76327262b 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -199,6 +199,7 @@ struct pde_opener { extern const struct inode_operations proc_link_inode_operations; extern const struct inode_operations proc_pid_link_inode_operations; +extern const struct file_operations proc_reclaim_operations; extern void proc_init_inodecache(void); void set_proc_pid_nlink(void); diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 587bc1613170..109dbb519f3a 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -1642,6 +1643,126 @@ const struct file_operations proc_pagemap_operations = { }; #endif /* CONFIG_PROC_PAGE_MONITOR */ +#ifdef CONFIG_PROCESS_RECLAIM +static int reclaim_pte_range(pmd_t *pmd, unsigned long addr, + unsigned long end, struct mm_walk *walk) +{ + struct vm_area_struct *vma = walk->private; + pte_t *pte, ptent; + spinlock_t *ptl; + struct page *page; + LIST_HEAD(page_list); + int isolated; + + split_huge_pmd(vma, addr, pmd); + if (pmd_trans_unstable(pmd)) + return 0; +cont: + isolated = 0; + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; pte++, addr += PAGE_SIZE) { + ptent = *pte; + if (!pte_present(ptent)) + continue; + + page = vm_normal_page(vma, addr, ptent); + if (!page) + continue; + + if (isolate_lru_page(page)) + continue; + + list_add(&page->lru, &page_list); + inc_node_page_state(page, NR_ISOLATED_ANON + + page_is_file_cache(page)); + isolated++; + if (isolated >= SWAP_CLUSTER_MAX) + break; + } + pte_unmap_unlock(pte - 1, ptl); + reclaim_pages_from_list(&page_list); + if (addr != end) + goto cont; + + cond_resched(); + return 0; +} + +enum reclaim_type { + RECLAIM_FILE, + RECLAIM_ANON, + RECLAIM_ALL, + RECLAIM_RANGE, +}; + +static ssize_t reclaim_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct task_struct *task; + char buffer[PROC_NUMBUF]; + struct mm_struct *mm; + struct vm_area_struct *vma; + enum reclaim_type type; + char *type_buf; + + memset(buffer, 0, sizeof(buffer)); + if (count > sizeof(buffer) - 1) + count = sizeof(buffer) - 1; + + if (copy_from_user(buffer, buf, count)) + return -EFAULT; + + type_buf = strstrip(buffer); + if (!strcmp(type_buf, "file")) + type = RECLAIM_FILE; + else if (!strcmp(type_buf, "anon")) + type = RECLAIM_ANON; + else if (!strcmp(type_buf, "all")) + type = RECLAIM_ALL; + else + return -EINVAL; + + task = get_proc_task(file->f_path.dentry->d_inode); + if (!task) + return -ESRCH; + + mm = get_task_mm(task); + if (mm) { + struct mm_walk reclaim_walk = { + .pmd_entry = reclaim_pte_range, + .mm = mm, + }; + + down_read(&mm->mmap_sem); + for (vma = mm->mmap; vma; vma = vma->vm_next) { + reclaim_walk.private = vma; + + if (is_vm_hugetlb_page(vma)) + continue; + + if (type == RECLAIM_ANON && vma->vm_file) + continue; + if (type == RECLAIM_FILE && !vma->vm_file) + continue; + + walk_page_range(vma->vm_start, vma->vm_end, + &reclaim_walk); + } + flush_tlb_mm(mm); + up_read(&mm->mmap_sem); + mmput(mm); + } + put_task_struct(task); + + return count; +} + +const struct file_operations proc_reclaim_operations = { + .write = reclaim_write, + .llseek = noop_llseek, +}; +#endif + #ifdef CONFIG_NUMA struct numa_maps { diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 505a29e8c16d..5c5e8f488bb9 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -12,6 +12,10 @@ #include #include +extern int isolate_lru_page(struct page *page); +extern void putback_lru_page(struct page *page); +extern unsigned long reclaim_pages_from_list(struct list_head *page_list); + /* * The anon_vma heads a list of private "related" vmas, to scan if * an anonymous page pointing to this anon_vma needs to be unmapped: diff --git a/mm/Kconfig b/mm/Kconfig index d099a3e2a3e8..d434484680d4 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -807,3 +807,16 @@ config HAVE_LOW_MEMORY_KILLER Say 'y' if you have a user/kernel low memory killer and thus you want page allocator to provide sufficient time before it triggers Out of Memory killer. + +config PROCESS_RECLAIM + bool "Enable process reclaim" + depends on PROC_FS + default y + help + It allows to reclaim pages of the process by /proc/pid/reclaim. + + (echo file > /proc/PID/reclaim) reclaims file-backed pages only. + (echo anon > /proc/PID/reclaim) reclaims anonymous pages only. + (echo all > /proc/PID/reclaim) reclaims all pages. + + Any other value is ignored. diff --git a/mm/vmscan.c b/mm/vmscan.c index ac7e419c4f22..b2ff2827f3b9 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1400,6 +1400,62 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, return ret; } +#ifdef CONFIG_PROCESS_RECLAIM +static unsigned long shrink_page(struct page *page, + struct zone *zone, + struct scan_control *sc, + enum ttu_flags ttu_flags, + bool force_reclaim, + struct list_head *ret_pages) +{ + int reclaimed; + LIST_HEAD(page_list); + + list_add(&page->lru, &page_list); + + reclaimed = shrink_page_list(&page_list, zone->zone_pgdat, sc, + ttu_flags, NULL, force_reclaim); + if (!reclaimed) + list_splice(&page_list, ret_pages); + + return reclaimed; +} + +unsigned long reclaim_pages_from_list(struct list_head *page_list) +{ + struct scan_control sc = { + .gfp_mask = GFP_KERNEL, + .priority = DEF_PRIORITY, + .may_writepage = 1, + .may_unmap = 1, + .may_swap = 1, + }; + + LIST_HEAD(ret_pages); + struct page *page; + unsigned long nr_reclaimed = 0; + + while (!list_empty(page_list)) { + page = lru_to_page(page_list); + list_del(&page->lru); + + ClearPageActive(page); + nr_reclaimed += shrink_page(page, page_zone(page), &sc, + TTU_IGNORE_ACCESS, true, &ret_pages); + } + + while (!list_empty(&ret_pages)) { + page = lru_to_page(&ret_pages); + list_del(&page->lru); + dec_node_page_state(page, NR_ISOLATED_ANON + + page_is_file_cache(page)); + putback_lru_page(page); + } + + return nr_reclaimed; +} +#endif + /* * Attempt to remove the specified page from its LRU. Only take this page * if it is of the appropriate PageActive status. Pages which are being -- GitLab From 54d3ac19a0375e92a1dc8c02bc93aac074c56613 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Thu, 9 May 2013 16:21:25 +0900 Subject: [PATCH 0835/1299] mm: make shrink_page_list with pages work from multiple zones Shrink_page_list expects all pages come from a same zone but it's too limited to use. This patch removes the dependency so next patch can use shrink_page_list with pages from multiple zones. Change-Id: I34469b7f0a79f2b79e30e40033ba8b3e1dd5f2d0 Signed-off-by: Minchan Kim Patch-mainline: linux-mm @ 9 May 2013 16:21:25 [vinmenon@codeaurora.org: changes for node based lrus. shrink_page_list expects all pages come from same node.] Signed-off-by: Vinayak Menon --- mm/vmscan.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index b2ff2827f3b9..874ace6683ef 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -995,6 +995,8 @@ static unsigned long shrink_page_list(struct list_head *page_list, goto keep; VM_BUG_ON_PAGE(PageActive(page), page); + if (pgdat) + VM_BUG_ON_PAGE(page_pgdat(page) != pgdat, page); sc->nr_scanned++; @@ -1083,7 +1085,8 @@ static unsigned long shrink_page_list(struct list_head *page_list, /* Case 1 above */ if (current_is_kswapd() && PageReclaim(page) && - test_bit(PGDAT_WRITEBACK, &pgdat->flags)) { + (pgdat && + test_bit(PGDAT_WRITEBACK, &pgdat->flags))) { nr_immediate++; goto activate_locked; @@ -1205,7 +1208,8 @@ static unsigned long shrink_page_list(struct list_head *page_list, */ if (page_is_file_cache(page) && (!current_is_kswapd() || !PageReclaim(page) || - !test_bit(PGDAT_DIRTY, &pgdat->flags))) { + (pgdat && + !test_bit(PGDAT_DIRTY, &pgdat->flags)))) { /* * Immediately reclaim when written back. * Similar in principal to deactivate_page() -- GitLab From fc50cf4478bc05231238a4e89f9e64a63514e29a Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Thu, 9 May 2013 16:21:26 +0900 Subject: [PATCH 0836/1299] mm: Remove shrink_page By previous patch, shrink_page_list can handle pages from multiple zone so let's remove shrink_page. Change-Id: I3526377aa6ee6142b8f3ec63396e7ada1e442505 Signed-off-by: Minchan Kim Patch-mainline: linux-mm @ 22 Apr 2013 17:45:03 [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- mm/vmscan.c | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 874ace6683ef..f106704514cc 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1335,6 +1335,13 @@ static unsigned long shrink_page_list(struct list_head *page_list, (*get_compound_page_dtor(page))(page); } else list_add(&page->lru, &free_pages); + /* + * If pagelist are from multiple nodes, we should decrease + * NR_ISOLATED_ANON + x on freed pages in here. + */ + if (!pgdat) + dec_node_page_state(page, NR_ISOLATED_ANON + + page_is_file_cache(page)); continue; activate_locked: @@ -1405,26 +1412,6 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, } #ifdef CONFIG_PROCESS_RECLAIM -static unsigned long shrink_page(struct page *page, - struct zone *zone, - struct scan_control *sc, - enum ttu_flags ttu_flags, - bool force_reclaim, - struct list_head *ret_pages) -{ - int reclaimed; - LIST_HEAD(page_list); - - list_add(&page->lru, &page_list); - - reclaimed = shrink_page_list(&page_list, zone->zone_pgdat, sc, - ttu_flags, NULL, force_reclaim); - if (!reclaimed) - list_splice(&page_list, ret_pages); - - return reclaimed; -} - unsigned long reclaim_pages_from_list(struct list_head *page_list) { struct scan_control sc = { @@ -1435,21 +1422,17 @@ unsigned long reclaim_pages_from_list(struct list_head *page_list) .may_swap = 1, }; - LIST_HEAD(ret_pages); + unsigned long nr_reclaimed; struct page *page; - unsigned long nr_reclaimed = 0; - - while (!list_empty(page_list)) { - page = lru_to_page(page_list); - list_del(&page->lru); + list_for_each_entry(page, page_list, lru) ClearPageActive(page); - nr_reclaimed += shrink_page(page, page_zone(page), &sc, - TTU_IGNORE_ACCESS, true, &ret_pages); - } - while (!list_empty(&ret_pages)) { - page = lru_to_page(&ret_pages); + nr_reclaimed = shrink_page_list(page_list, NULL, &sc, + TTU_IGNORE_ACCESS, NULL, true); + + while (!list_empty(page_list)) { + page = lru_to_page(page_list); list_del(&page->lru); dec_node_page_state(page, NR_ISOLATED_ANON + page_is_file_cache(page)); -- GitLab From 434fe4e62b1761cc5e80563a0676f4fb69ef678d Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Thu, 9 May 2013 16:21:27 +0900 Subject: [PATCH 0837/1299] mm: Enhance per process reclaim to consider shared pages Some pages could be shared by several processes. (ex, libc) In case of that, it's too bad to reclaim them from the beginnig. This patch causes VM to keep them on memory until last task try to reclaim them so shared pages will be reclaimed only if all of task has gone swapping out. This feature doesn't handle non-linear mapping on ramfs because it's very time-consuming and doesn't make sure of reclaiming and not common. Change-Id: I7e5f34f2e947f5db6d405867fe2ad34863ca40f7 Signed-off-by: Sangseok Lee Signed-off-by: Minchan Kim Patch-mainline: linux-mm @ 9 May 2013 16:21:27 [vinmenon@codeaurora.org: trivial merge conflict fixes + changes to make the patch work with 4.14 kernel + Avoid targetted reclaim from ksm since vma_address(page) is not valid for a ksm page] Signed-off-by: Vinayak Menon --- fs/proc/task_mmu.c | 2 +- include/linux/rmap.h | 9 ++++++--- mm/ksm.c | 1 + mm/memory-failure.c | 2 +- mm/migrate.c | 4 ++-- mm/rmap.c | 23 ++++++++++++++++++++++- mm/vmscan.c | 13 +++++++++++-- 7 files changed, 44 insertions(+), 10 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 109dbb519f3a..abb5e7062f07 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1680,7 +1680,7 @@ static int reclaim_pte_range(pmd_t *pmd, unsigned long addr, break; } pte_unmap_unlock(pte - 1, ptl); - reclaim_pages_from_list(&page_list); + reclaim_pages_from_list(&page_list, vma); if (addr != end) goto cont; diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 5c5e8f488bb9..7268a54b8956 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -14,7 +14,8 @@ extern int isolate_lru_page(struct page *page); extern void putback_lru_page(struct page *page); -extern unsigned long reclaim_pages_from_list(struct list_head *page_list); +extern unsigned long reclaim_pages_from_list(struct list_head *page_list, + struct vm_area_struct *vma); /* * The anon_vma heads a list of private "related" vmas, to scan if @@ -207,7 +208,8 @@ static inline void page_dup_rmap(struct page *page, bool compound) int page_referenced(struct page *, int is_locked, struct mem_cgroup *memcg, unsigned long *vm_flags); -bool try_to_unmap(struct page *, enum ttu_flags flags); +bool try_to_unmap(struct page *page, enum ttu_flags flags, + struct vm_area_struct *vma); /* Avoid racy checks */ #define PVMW_SYNC (1 << 0) @@ -273,6 +275,7 @@ int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma); */ struct rmap_walk_control { void *arg; + struct vm_area_struct *target_vma; /* * Return false if page table scanning in rmap_walk should be stopped. * Otherwise, return true. @@ -301,7 +304,7 @@ static inline int page_referenced(struct page *page, int is_locked, return 0; } -#define try_to_unmap(page, refs) false +#define try_to_unmap(page, refs, vma) false static inline int page_mkclean(struct page *page) { diff --git a/mm/ksm.c b/mm/ksm.c index fdc8746ebcb4..b524e4efbe91 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -2552,6 +2552,7 @@ void rmap_walk_ksm(struct page *page, struct rmap_walk_control *rwc) stable_node = page_stable_node(page); if (!stable_node) return; + again: hlist_for_each_entry(rmap_item, &stable_node->hlist, hlist) { struct anon_vma *anon_vma = rmap_item->anon_vma; diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 1cd3b3569af8..a9f6e138e4f2 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -994,7 +994,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, if (kill) collect_procs(hpage, &tokill, flags & MF_ACTION_REQUIRED); - unmap_success = try_to_unmap(hpage, ttu); + unmap_success = try_to_unmap(hpage, ttu, NULL); if (!unmap_success) pr_err("Memory failure: %#lx: failed to unmap page (mapcount=%d)\n", pfn, page_mapcount(hpage)); diff --git a/mm/migrate.c b/mm/migrate.c index 6149dc62a0f1..0ff14c3825d3 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1080,7 +1080,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage, VM_BUG_ON_PAGE(PageAnon(page) && !PageKsm(page) && !anon_vma, page); try_to_unmap(page, - TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS); + TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS, NULL); page_was_mapped = 1; } @@ -1305,7 +1305,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, if (page_mapped(hpage)) { try_to_unmap(hpage, - TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS); + TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS, NULL); page_was_mapped = 1; } diff --git a/mm/rmap.c b/mm/rmap.c index 5d657329191e..c481b646ed8a 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -1590,19 +1590,24 @@ static int page_mapcount_is_zero(struct page *page) * try_to_unmap - try to remove all page table mappings to a page * @page: the page to get unmapped * @flags: action and flags + * @vma : target vma for reclaim * * Tries to remove all the page table entries which are mapping this * page, used in the pageout path. Caller must hold the page lock. + * If @vma is not NULL, this function try to remove @page from only @vma + * without peeking all mapped vma for @page. * * If unmap is successful, return true. Otherwise, false. */ -bool try_to_unmap(struct page *page, enum ttu_flags flags) +bool try_to_unmap(struct page *page, enum ttu_flags flags, + struct vm_area_struct *vma) { struct rmap_walk_control rwc = { .rmap_one = try_to_unmap_one, .arg = (void *)flags, .done = page_mapcount_is_zero, .anon_lock = page_lock_anon_vma_read, + .target_vma = vma, }; /* @@ -1646,6 +1651,7 @@ void try_to_munlock(struct page *page) .arg = (void *)TTU_MUNLOCK, .done = page_not_mapped, .anon_lock = page_lock_anon_vma_read, + .target_vma = NULL, }; @@ -1707,6 +1713,12 @@ static void rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc, pgoff_t pgoff_start, pgoff_end; struct anon_vma_chain *avc; + if (rwc->target_vma) { + unsigned long address = vma_address(page, rwc->target_vma); + + rwc->rmap_one(page, rwc->target_vma, address, rwc->arg); + } + if (locked) { anon_vma = page_anon_vma(page); /* anon_vma disappear under us? */ @@ -1714,6 +1726,7 @@ static void rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc, } else { anon_vma = rmap_walk_anon_lock(page, rwc); } + if (!anon_vma) return; @@ -1758,6 +1771,7 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc, struct address_space *mapping = page_mapping(page); pgoff_t pgoff_start, pgoff_end; struct vm_area_struct *vma; + unsigned long address; /* * The page lock not only makes sure that page->mapping cannot @@ -1774,6 +1788,13 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc, pgoff_end = pgoff_start + hpage_nr_pages(page) - 1; if (!locked) i_mmap_lock_read(mapping); + + if (rwc->target_vma) { + address = vma_address(page, rwc->target_vma); + rwc->rmap_one(page, rwc->target_vma, address, rwc->arg); + goto done; + } + vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff_start, pgoff_end) { unsigned long address = vma_address(page, vma); diff --git a/mm/vmscan.c b/mm/vmscan.c index f106704514cc..4ce5b4d8778f 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -116,6 +116,13 @@ struct scan_control { /* Number of pages freed so far during a call to shrink_zones() */ unsigned long nr_reclaimed; + + /* + * Reclaim pages from a vma. If the page is shared by other tasks + * it is zapped from a vma without reclaim so it ends up remaining + * on memory until last task zap it. + */ + struct vm_area_struct *target_vma; }; #ifdef ARCH_HAS_PREFETCH @@ -1189,7 +1196,7 @@ static unsigned long shrink_page_list(struct list_head *page_list, if (unlikely(PageTransHuge(page))) flags |= TTU_SPLIT_HUGE_PMD; - if (!try_to_unmap(page, flags)) { + if (!try_to_unmap(page, flags, sc->target_vma)) { nr_unmap_fail++; goto activate_locked; } @@ -1412,7 +1419,8 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, } #ifdef CONFIG_PROCESS_RECLAIM -unsigned long reclaim_pages_from_list(struct list_head *page_list) +unsigned long reclaim_pages_from_list(struct list_head *page_list, + struct vm_area_struct *vma) { struct scan_control sc = { .gfp_mask = GFP_KERNEL, @@ -1420,6 +1428,7 @@ unsigned long reclaim_pages_from_list(struct list_head *page_list) .may_writepage = 1, .may_unmap = 1, .may_swap = 1, + .target_vma = vma, }; unsigned long nr_reclaimed; -- GitLab From 62478c622aa2020149645882d185a47802bd92fc Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Thu, 9 May 2013 16:21:28 +0900 Subject: [PATCH 0838/1299] mm: Support address range reclaim This patch adds address range reclaim of a process. The requirement is following as, Like webkit1, it uses a address space for handling multi tabs. IOW, it uses *one* process model so all tabs shares address space of the process. In such scenario, per-process reclaim is rather coarse-grained so this patch supports more fine-grained reclaim for being able to reclaim target address range of the process. For reclaim target range, you should use following format. echo [addr] [size-byte] > /proc/pid/reclaim The addr should be page-aligned. So now reclaim konb's interface is following as. echo file > /proc/pid/reclaim reclaim file-backed pages only echo anon > /proc/pid/reclaim reclaim anonymous pages only echo all > /proc/pid/reclaim reclaim all pages echo 0x100000 8K > /proc/pid/reclaim reclaim pages in (0x100000 - 0x102000) Change-Id: I111131d31be1cfcfa246617b634a9a8bc4078098 Signed-off-by: Minchan Kim Patch-mainline: linux-mm @ 9 May 2013 08:39:01 [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- fs/proc/task_mmu.c | 86 ++++++++++++++++++++++++++++++++++++++-------- mm/Kconfig | 3 ++ 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index abb5e7062f07..2f7e1e90a9e6 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -1699,11 +1700,14 @@ static ssize_t reclaim_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct task_struct *task; - char buffer[PROC_NUMBUF]; + char buffer[200]; struct mm_struct *mm; struct vm_area_struct *vma; enum reclaim_type type; char *type_buf; + struct mm_walk reclaim_walk = {}; + unsigned long start = 0; + unsigned long end = 0; memset(buffer, 0, sizeof(buffer)); if (count > sizeof(buffer) - 1) @@ -1719,42 +1723,94 @@ static ssize_t reclaim_write(struct file *file, const char __user *buf, type = RECLAIM_ANON; else if (!strcmp(type_buf, "all")) type = RECLAIM_ALL; + else if (isdigit(*type_buf)) + type = RECLAIM_RANGE; else - return -EINVAL; + goto out_err; + + if (type == RECLAIM_RANGE) { + char *token; + unsigned long long len, len_in, tmp; + + token = strsep(&type_buf, " "); + if (!token) + goto out_err; + tmp = memparse(token, &token); + if (tmp & ~PAGE_MASK || tmp > ULONG_MAX) + goto out_err; + start = tmp; + + token = strsep(&type_buf, " "); + if (!token) + goto out_err; + len_in = memparse(token, &token); + len = (len_in + ~PAGE_MASK) & PAGE_MASK; + if (len > ULONG_MAX) + goto out_err; + /* + * Check to see whether len was rounded up from small -ve + * to zero. + */ + if (len_in && !len) + goto out_err; + + end = start + len; + if (end < start) + goto out_err; + } task = get_proc_task(file->f_path.dentry->d_inode); if (!task) return -ESRCH; mm = get_task_mm(task); - if (mm) { - struct mm_walk reclaim_walk = { - .pmd_entry = reclaim_pte_range, - .mm = mm, - }; + if (!mm) + goto out; - down_read(&mm->mmap_sem); - for (vma = mm->mmap; vma; vma = vma->vm_next) { - reclaim_walk.private = vma; + reclaim_walk.mm = mm; + reclaim_walk.pmd_entry = reclaim_pte_range; + + down_read(&mm->mmap_sem); + if (type == RECLAIM_RANGE) { + vma = find_vma(mm, start); + while (vma) { + if (vma->vm_start > end) + break; + if (is_vm_hugetlb_page(vma)) + continue; + reclaim_walk.private = vma; + walk_page_range(max(vma->vm_start, start), + min(vma->vm_end, end), + &reclaim_walk); + vma = vma->vm_next; + } + } else { + for (vma = mm->mmap; vma; vma = vma->vm_next) { if (is_vm_hugetlb_page(vma)) continue; if (type == RECLAIM_ANON && vma->vm_file) continue; + if (type == RECLAIM_FILE && !vma->vm_file) continue; + reclaim_walk.private = vma; walk_page_range(vma->vm_start, vma->vm_end, - &reclaim_walk); + &reclaim_walk); } - flush_tlb_mm(mm); - up_read(&mm->mmap_sem); - mmput(mm); } - put_task_struct(task); + flush_tlb_mm(mm); + up_read(&mm->mmap_sem); + mmput(mm); +out: + put_task_struct(task); return count; + +out_err: + return -EINVAL; } const struct file_operations proc_reclaim_operations = { diff --git a/mm/Kconfig b/mm/Kconfig index d434484680d4..17ad9d7de090 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -819,4 +819,7 @@ config PROCESS_RECLAIM (echo anon > /proc/PID/reclaim) reclaims anonymous pages only. (echo all > /proc/PID/reclaim) reclaims all pages. + (echo addr size-byte > /proc/PID/reclaim) reclaims pages in + (addr, addr + size-bytes) of the process. + Any other value is ignored. -- GitLab From 57b0c2767c62b4031d8037d62681ee2509fb587b Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Thu, 9 May 2013 16:21:29 +0900 Subject: [PATCH 0839/1299] add documentation about reclaim knob on proc.txt This patch adds stuff about new reclaim field in proc.txt Change-Id: I1718fad12ec078e204e7a59769ce70fad7708756 Acked-by: Rob Landley Signed-off-by: Minchan Kim Patch-mainline: linux-mm @ 9 May 2013 16:21:29 [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- Documentation/filesystems/proc.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 99ca8e30a4ca..112e96ee1ab3 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -139,6 +139,7 @@ Table 1-1: Process specific entries in /proc maps Memory maps to executables and library files (2.4) mem Memory held by this process root Link to the root directory of this process + reclaim Reclaim pages in this process stat Process status statm Process memory status information status Process status in human readable form @@ -538,6 +539,25 @@ current value: Any other value written to /proc/PID/clear_refs will have no effect. +The file /proc/PID/reclaim is used to reclaim pages in this process. +To reclaim file-backed pages, + > echo file > /proc/PID/reclaim + +To reclaim anonymous pages, + > echo anon > /proc/PID/reclaim + +To reclaim all pages, + > echo all > /proc/PID/reclaim + +Also, you can specify address range of process so part of address space +will be reclaimed. The format is following as + > echo addr size-byte > /proc/PID/reclaim + +NOTE: addr should be page-aligned. + +Below is example which try to reclaim 2M from 0x100000. + > echo 0x100000 2M > /proc/PID/reclaim + The /proc/pid/pagemap gives the PFN, which can be used to find the pageflags using /proc/kpageflags and number of times a page is mapped using /proc/kpagecount. For detailed explanation, see Documentation/vm/pagemap.txt. -- GitLab From 206500ab836562f606200a4ca70a12db882b1454 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Tue, 26 Jun 2018 11:36:30 +0530 Subject: [PATCH 0840/1299] ARM: dts: msm: Add USB DLOAD cookie device node on QCS405 Linux USB DIAG driver needs to update PID and serial number with IMEM memory to avoid DIAG port hopping while performing RAMDUMP collection over USB. Hence add device node entry with IMEM driver for USB dload cookie imem start address and size. Change-Id: I8cb2a25bf642d39dd5c40b9d4c6874438298db30 Signed-off-by: Sriharsha Allenki --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index ee07feb6e9aa..254e65c540a9 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -424,6 +424,11 @@ compatible = "qcom,msm-imem-pil"; reg = <0x94c 200>; }; + + diag_dload@c8 { + compatible = "qcom,msm-imem-diag-dload"; + reg = <0xc8 200>; + }; }; qcom,lpass@c000000 { -- GitLab From 3ee4870d2ac128b96d6a52b307edb05bf5a57465 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Mon, 25 Jun 2018 15:20:23 +0530 Subject: [PATCH 0841/1299] Documentation: sound: Add documentation for use-pinctrl property Add documentation for new property added for audio clock driver. Change-Id: I6b75f947ef2098fb3a0366bc69add7cff99185d5 Signed-off-by: Laxminath Kasam --- Documentation/devicetree/bindings/sound/qcom-audio-dev.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index 6ca0b64acfe4..a4744c4b0e15 100644 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -384,6 +384,9 @@ Optional properties: - qcom,mclk-clk-reg: Indicate the register address for mclk. + - qcom,use-pinctrl: Indicates pinctrl required or not for this + clock node. + * audio_slimslave Required properties: -- GitLab From 10ab228207c8513b1949246234da57ed7bd0163d Mon Sep 17 00:00:00 2001 From: Fei Mao Date: Tue, 26 Jun 2018 15:03:38 +0800 Subject: [PATCH 0842/1299] Revert "input: touchscreen: shutdown ST touch's power supply when suspend" This reverts commit 0085ca6d09abaf939ba9546439a7a277fba8a5d4. DVDD is always on. And keep both these two LDOs on when suspend. Change-Id: I3a49cd6e719181eafbd83877586f7aaecd9649e7 Signed-off-by: Fei Mao --- drivers/input/touchscreen/st/fts.c | 53 ++++-------------------------- 1 file changed, 7 insertions(+), 46 deletions(-) diff --git a/drivers/input/touchscreen/st/fts.c b/drivers/input/touchscreen/st/fts.c index e30f6e4a5dfd..3f63203263b2 100644 --- a/drivers/input/touchscreen/st/fts.c +++ b/drivers/input/touchscreen/st/fts.c @@ -3835,47 +3835,6 @@ static int fts_mode_handler(struct fts_ts_info *info, int force) return res; } -int fts_chip_power_switch(struct fts_ts_info *info, int on) -{ - int error = 0; - - logError(0, "%s %s:will set power mode %d...\n", tag, __func__, on); - if (on == 0) { - if (info->pwr_reg) { - error = regulator_disable(info->pwr_reg); - if (error < 0) - logError(1, "%s %s: Failed to disable DVDD\n", - tag, __func__); - } - - if (info->bus_reg) { - error = regulator_disable(info->bus_reg); - if (error < 0) - logError(1, "%s %s: Failed to disable AVDD\n", - tag, __func__); - - } - if (info->bdata->reset_gpio != GPIO_NOT_DEFINED) - gpio_set_value(info->bdata->reset_gpio, 0); - } else if (on == 1) { - if (info->bus_reg) { - error = regulator_enable(info->bus_reg); - if (error < 0) - logError(1, "%s %s: Failed to enable AVDD\n", - tag, __func__); - } - if (info->pwr_reg) { - error = regulator_enable(info->pwr_reg); - if (error < 0) - logError(1, "%s %s: Failed to enable DVDD\n", - tag, __func__); - } - - } - - return error; -} - static void fts_resume_work(struct work_struct *work) { @@ -3886,19 +3845,22 @@ static void fts_resume_work(struct work_struct *work) __pm_wakeup_event(&info->wakeup_source, HZ); info->resume_bit = 1; - fts_chip_power_switch(info, 1); #ifdef USE_NOISE_PARAM readNoiseParameters(noise_params); #endif - cleanUp(1); + fts_system_reset(); + #ifdef USE_NOISE_PARAM writeNoiseParameters(noise_params); #endif release_all_touches(info); + fts_mode_handler(info, 0); info->sensor_sleep = false; + + fts_enableInterrupt(); } @@ -3913,12 +3875,11 @@ static void fts_suspend_work(struct work_struct *work) info->resume_bit = 0; fts_mode_handler(info, 0); + release_all_touches(info); info->sensor_sleep = true; - fts_disableInterrupt(); - fts_chip_power_switch(info, 0); - + fts_enableInterrupt(); } -- GitLab From 81f0cf8f6a28210455073dc27f3784d7e4aee5a0 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Mon, 25 Jun 2018 15:22:35 +0530 Subject: [PATCH 0843/1299] ARM: dts: msm: Add use-pinctrl for clock nodes on sm8150 and qcs405 For LPASS or PMI clock nodes of audio-ref-clk need to specify qcom,use-pinctrl property with value 1 if pinctrl is used. Update clock nodes with this property that uses pinctrl. CRs-Fixed: 2259784 Change-Id: Icf4985362f6f4bab637b8390d79a548147b6346f Signed-off-by: Laxminath Kasam --- arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi | 1 + arch/arm64/boot/dts/qcom/sdmshrike-audio-overlay.dtsi | 1 + arch/arm64/boot/dts/qcom/sm8150-audio-overlay.dtsi | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi b/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi index fa2f21d561bc..9bfe109bda2e 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi @@ -25,6 +25,7 @@ clock_audio: audio_ext_clk { compatible = "qcom,audio-ref-clk"; qcom,codec-ext-clk-src = <0>; + qcom,use-pinctrl = <1>; pinctrl-names = "active", "sleep"; pinctrl-0 = <&tasha_mclk_default>; pinctrl-1 = <&tasha_mclk_default>; diff --git a/arch/arm64/boot/dts/qcom/sdmshrike-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdmshrike-audio-overlay.dtsi index d8a0f4e06c40..4e0d024e8494 100644 --- a/arch/arm64/boot/dts/qcom/sdmshrike-audio-overlay.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmshrike-audio-overlay.dtsi @@ -125,6 +125,7 @@ qcom,codec-ext-clk-src = <2>; qcom,codec-lpass-ext-clk-freq = <19200000>; qcom,codec-lpass-clk-id = <278>; + qcom,use-pinctrl = <1>; pinctrl-names = "active", "sleep"; pinctrl-0 = <&quin_mi2s_mclk_active>; pinctrl-1 = <&quin_mi2s_mclk_sleep>; diff --git a/arch/arm64/boot/dts/qcom/sm8150-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sm8150-audio-overlay.dtsi index dbb6a385e9ad..ae00fc4d03b4 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-audio-overlay.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-audio-overlay.dtsi @@ -120,6 +120,7 @@ qcom,codec-ext-clk-src = <2>; qcom,codec-lpass-ext-clk-freq = <19200000>; qcom,codec-lpass-clk-id = <278>; + qcom,use-pinctrl = <1>; pinctrl-names = "active", "sleep"; pinctrl-0 = <&quin_mi2s_mclk_active>; pinctrl-1 = <&quin_mi2s_mclk_sleep>; -- GitLab From 4534459fa27f0a846b0a6c989feb65a62d74442c Mon Sep 17 00:00:00 2001 From: Narender Ankam Date: Fri, 1 Jun 2018 13:53:20 +0530 Subject: [PATCH 0844/1299] clk: qcom: mdss: add support for DSI 28LPM PLL Add upstream support to program the DSI 28LPM PLL to drive DSI byte and pxl clks. Change-Id: I08e7b49cce7f30094b619374f5e4cf186397c4cc Signed-off-by: Narender Ankam --- .../devicetree/bindings/fb/mdss-pll.txt | 28 +- drivers/clk/qcom/mdss/Makefile | 2 + drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c | 617 +++++++++++----- .../clk/qcom/mdss/mdss-dsi-pll-28nm-util.c | 693 ++++++++++++++++++ drivers/clk/qcom/mdss/mdss-dsi-pll-28nm.h | 72 ++ drivers/clk/qcom/mdss/mdss-dsi-pll-util.c | 587 --------------- drivers/clk/qcom/mdss/mdss-dsi-pll.h | 7 +- drivers/clk/qcom/mdss/mdss-pll.c | 6 + drivers/clk/qcom/mdss/mdss-pll.h | 5 + include/dt-bindings/clock/mdss-28nm-pll-clk.h | 31 + 10 files changed, 1263 insertions(+), 785 deletions(-) create mode 100644 drivers/clk/qcom/mdss/mdss-dsi-pll-28nm-util.c create mode 100644 drivers/clk/qcom/mdss/mdss-dsi-pll-28nm.h delete mode 100644 drivers/clk/qcom/mdss/mdss-dsi-pll-util.c create mode 100644 include/dt-bindings/clock/mdss-28nm-pll-clk.h diff --git a/Documentation/devicetree/bindings/fb/mdss-pll.txt b/Documentation/devicetree/bindings/fb/mdss-pll.txt index 6b9238c4bf30..4583f4e8d364 100644 --- a/Documentation/devicetree/bindings/fb/mdss-pll.txt +++ b/Documentation/devicetree/bindings/fb/mdss-pll.txt @@ -1,20 +1,24 @@ Qualcomm Technologies, Inc. MDSS pll for DSI/EDP/HDMI -mdss-pll is a pll controller device which supports pll devices that are -compatiable with MIPI display serial interface specification, HDMI and edp. +mdss-pll is a pll controller device which supports pll devices that +are compatible with MIPI display serial interface specification, +HDMI and edp. Required properties: - compatible: Compatible name used in the driver. Should be one of: - "qcom,mdss_dsi_pll_8916", "qcom,mdss_dsi_pll_8939", - "qcom,mdss_dsi_pll_8974", "qcom,mdss_dsi_pll_8994", - "qcom,mdss_dsi_pll_8994", "qcom,mdss_dsi_pll_8909", - "qcom,mdss_hdmi_pll", "qcom,mdss_hdmi_pll_8994", - "qcom,mdss_dsi_pll_8992", "qcom,mdss_hdmi_pll_8992", - "qcom,mdss_dsi_pll_8996", "qcom,mdss_hdmi_pll_8996", - "qcom,mdss_hdmi_pll_8996_v2", "qcom,mdss_dsi_pll_8996_v2", - "qcom,mdss_hdmi_pll_8996_v3", "qcom,mdss_dsi_pll_8952", - "qcom,mdss_dsi_pll_8937", "qcom,mdss_hdmi_pll_8996_v3_1p8", - "qcom,mdss_dsi_pll_8953" + "qcom,mdss_dsi_pll_8916", "qcom,mdss_dsi_pll_8939", + "qcom,mdss_dsi_pll_8974", "qcom,mdss_dsi_pll_8994", + "qcom,mdss_dsi_pll_8994", "qcom,mdss_dsi_pll_8909", + "qcom,mdss_hdmi_pll", "qcom,mdss_hdmi_pll_8994", + "qcom,mdss_dsi_pll_8992", "qcom,mdss_hdmi_pll_8992", + "qcom,mdss_dsi_pll_8996", "qcom,mdss_hdmi_pll_8996", + "qcom,mdss_hdmi_pll_8996_v2", "qcom,mdss_dsi_pll_8996_v2", + "qcom,mdss_hdmi_pll_8996_v3", "qcom,mdss_hdmi_pll_8996_v3_1p8", + "qcom,mdss_edp_pll_8996_v3", "qcom,mdss_edp_pll_8996_v3_1p8", + "qcom,mdss_dsi_pll_10nm", "qcom,mdss_dp_pll_8998", + "qcom,mdss_hdmi_pll_8998", "qcom,mdss_dp_pll_10nm", + "qcom,mdss_dsi_pll_7nm", "qcom,mdss_dp_pll_7nm", + "qcom,mdss_dsi_pll_28lpm" - cell-index: Specifies the controller used - reg: offset and length of the register set for the device. - reg-names : names to refer to register sets related to this device diff --git a/drivers/clk/qcom/mdss/Makefile b/drivers/clk/qcom/mdss/Makefile index 6d100b5ed197..06c011f76a8f 100644 --- a/drivers/clk/qcom/mdss/Makefile +++ b/drivers/clk/qcom/mdss/Makefile @@ -6,3 +6,5 @@ obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dp-pll-10nm-util.o obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-7nm.o obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dp-pll-7nm.o obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dp-pll-7nm-util.o +obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-28lpm.o +obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-28nm-util.o diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c index f6c7e287b8ca..ae688cbd5d60 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,21 +16,20 @@ #include #include #include -#include -#include -#include -#include +#include #include "mdss-pll.h" #include "mdss-dsi-pll.h" +#include "mdss-dsi-pll-28nm.h" #define VCO_DELAY_USEC 1000 -static struct clk_div_ops fixed_2div_ops; -static const struct clk_ops byte_mux_clk_ops; -static const struct clk_ops pixel_clk_src_ops; -static const struct clk_ops byte_clk_src_ops; -static const struct clk_ops analog_postdiv_clk_ops; +enum { + DSI_PLL_0, + DSI_PLL_1, + DSI_PLL_MAX +}; + static struct lpfr_cfg lpfr_lut_struct[] = { {479500000, 8}, {480000000, 11}, @@ -44,263 +43,519 @@ static struct lpfr_cfg lpfr_lut_struct[] = { {750000000, 11}, }; -static int vco_set_rate_lpm(struct clk *c, unsigned long rate) +static void dsi_pll_sw_reset(struct mdss_pll_resources *rsc) { - int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - /* * DSI PLL software reset. Add HW recommended delays after toggling * the software reset bit off and back on. */ - MDSS_PLL_REG_W(dsi_pll_res->pll_base, + MDSS_PLL_REG_W(rsc->pll_base, DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01); - udelay(1000); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, + ndelay(500); + MDSS_PLL_REG_W(rsc->pll_base, DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00); - udelay(1000); +} + +static void dsi_pll_toggle_lock_detect( + struct mdss_pll_resources *rsc) +{ + /* DSI PLL toggle lock detect setting */ + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x04); + ndelay(500); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x05); + udelay(512); +} - rc = vco_set_rate(vco, rate); +static int dsi_pll_check_lock_status( + struct mdss_pll_resources *rsc) +{ + int rc = 0; + + rc = dsi_pll_lock_status(rsc); + if (rc) + pr_debug("PLL Locked\n"); + else + pr_err("PLL failed to lock\n"); - mdss_pll_resource_enable(dsi_pll_res, false); return rc; } -static int dsi_pll_enable_seq_8916(struct mdss_pll_resources *dsi_pll_res) + +static int dsi_pll_enable_seq_gf2(struct mdss_pll_resources *rsc) { int pll_locked = 0; + dsi_pll_sw_reset(rsc); + /* - * DSI PLL software reset. Add HW recommended delays after toggling - * the software reset bit off and back on. + * GF PART 2 PLL power up sequence. + * Add necessary delays recommended by hardware. */ - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01); - ndelay(500); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x04); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05); + udelay(3); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f); + udelay(500); + + dsi_pll_toggle_lock_detect(rsc); + + pll_locked = dsi_pll_check_lock_status(rsc); + return pll_locked ? 0 : -EINVAL; +} + +static int dsi_pll_enable_seq_gf1(struct mdss_pll_resources *rsc) +{ + int pll_locked = 0; + dsi_pll_sw_reset(rsc); /* - * PLL power up sequence. + * GF PART 1 PLL power up sequence. * Add necessary delays recommended by hardware. */ - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34); - ndelay(500); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, + + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x14); + MDSS_PLL_REG_W(rsc->pll_base, DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01); - ndelay(500); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, + MDSS_PLL_REG_W(rsc->pll_base, DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05); - ndelay(500); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, + udelay(3); + MDSS_PLL_REG_W(rsc->pll_base, DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f); - ndelay(500); + udelay(500); - /* DSI PLL toggle lock detect setting */ - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x04); - ndelay(500); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x05); - udelay(512); + dsi_pll_toggle_lock_detect(rsc); - pll_locked = dsi_pll_lock_status(dsi_pll_res); + pll_locked = dsi_pll_check_lock_status(rsc); + return pll_locked ? 0 : -EINVAL; +} - if (pll_locked) - pr_debug("PLL Locked\n"); - else - pr_err("PLL failed to lock\n"); +static int dsi_pll_enable_seq_tsmc(struct mdss_pll_resources *rsc) +{ + int pll_locked = 0; + dsi_pll_sw_reset(rsc); + /* + * TSMC PLL power up sequence. + * Add necessary delays recommended by hardware. + */ + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f); + udelay(500); + + dsi_pll_toggle_lock_detect(rsc); + + pll_locked = dsi_pll_check_lock_status(rsc); return pll_locked ? 0 : -EINVAL; } -/* Op structures */ - -static const struct clk_ops clk_ops_dsi_vco = { - .set_rate = vco_set_rate_lpm, - .round_rate = vco_round_rate, - .handoff = vco_handoff, - .prepare = vco_prepare, - .unprepare = vco_unprepare, +static struct regmap_config dsi_pll_28lpm_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xF4, }; +static struct regmap_bus analog_postdiv_regmap_bus = { + .reg_write = analog_postdiv_reg_write, + .reg_read = analog_postdiv_reg_read, +}; -static struct clk_div_ops fixed_4div_ops = { - .set_div = fixed_4div_set_div, - .get_div = fixed_4div_get_div, +static struct regmap_bus byteclk_src_mux_regmap_bus = { + .reg_write = byteclk_mux_write_sel, + .reg_read = byteclk_mux_read_sel, }; -static struct clk_div_ops analog_postdiv_ops = { - .set_div = analog_set_div, - .get_div = analog_get_div, +static struct regmap_bus pclk_src_regmap_bus = { + .reg_write = pixel_clk_set_div, + .reg_read = pixel_clk_get_div, }; -static struct clk_div_ops digital_postdiv_ops = { - .set_div = digital_set_div, - .get_div = digital_get_div, +static const struct clk_ops clk_ops_vco_28lpm = { + .recalc_rate = vco_28nm_recalc_rate, + .set_rate = vco_28nm_set_rate, + .round_rate = vco_28nm_round_rate, + .prepare = vco_28nm_prepare, + .unprepare = vco_28nm_unprepare, }; -static struct clk_mux_ops byte_mux_ops = { - .set_mux_sel = set_byte_mux_sel, - .get_mux_sel = get_byte_mux_sel, +static struct dsi_pll_vco_clk dsi0pll_vco_clk = { + .ref_clk_rate = 19200000UL, + .min_rate = 350000000UL, + .max_rate = 750000000UL, + .pll_en_seq_cnt = 9, + .pll_enable_seqs[0] = dsi_pll_enable_seq_tsmc, + .pll_enable_seqs[1] = dsi_pll_enable_seq_tsmc, + .pll_enable_seqs[2] = dsi_pll_enable_seq_tsmc, + .pll_enable_seqs[3] = dsi_pll_enable_seq_gf1, + .pll_enable_seqs[4] = dsi_pll_enable_seq_gf1, + .pll_enable_seqs[5] = dsi_pll_enable_seq_gf1, + .pll_enable_seqs[6] = dsi_pll_enable_seq_gf2, + .pll_enable_seqs[7] = dsi_pll_enable_seq_gf2, + .pll_enable_seqs[8] = dsi_pll_enable_seq_gf2, + .lpfr_lut_size = 10, + .lpfr_lut = lpfr_lut_struct, + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_vco_clk", + .parent_names = (const char *[]){"bi_tcxo"}, + .num_parents = 1, + .ops = &clk_ops_vco_28lpm, + .flags = CLK_GET_RATE_NOCACHE, + }, }; -static struct dsi_pll_vco_clk dsi_vco_clk_8916 = { - .ref_clk_rate = 19200000, - .min_rate = 350000000, - .max_rate = 750000000, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = dsi_pll_enable_seq_8916, +static struct dsi_pll_vco_clk dsi1pll_vco_clk = { + .ref_clk_rate = 19200000UL, + .min_rate = 350000000UL, + .max_rate = 750000000UL, + .pll_en_seq_cnt = 9, + .pll_enable_seqs[0] = dsi_pll_enable_seq_tsmc, + .pll_enable_seqs[1] = dsi_pll_enable_seq_tsmc, + .pll_enable_seqs[2] = dsi_pll_enable_seq_tsmc, + .pll_enable_seqs[3] = dsi_pll_enable_seq_gf1, + .pll_enable_seqs[4] = dsi_pll_enable_seq_gf1, + .pll_enable_seqs[5] = dsi_pll_enable_seq_gf1, + .pll_enable_seqs[6] = dsi_pll_enable_seq_gf2, + .pll_enable_seqs[7] = dsi_pll_enable_seq_gf2, + .pll_enable_seqs[8] = dsi_pll_enable_seq_gf2, .lpfr_lut_size = 10, .lpfr_lut = lpfr_lut_struct, - .c = { - .dbg_name = "dsi_vco_clk_8916", - .ops = &clk_ops_dsi_vco, - CLK_INIT(dsi_vco_clk_8916.c), + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_vco_clk", + .parent_names = (const char *[]){"bi_tcxo"}, + .num_parents = 1, + .ops = &clk_ops_vco_28lpm, + .flags = CLK_GET_RATE_NOCACHE, }, }; -static struct div_clk analog_postdiv_clk_8916 = { - .data = { - .max_div = 255, - .min_div = 1, +static struct clk_regmap_div dsi0pll_analog_postdiv = { + .reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, + .shift = 0, + .width = 4, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_analog_postdiv", + .parent_names = (const char *[]){"dsi0pll_vco_clk"}, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_regmap_div_ops, + }, }, - .ops = &analog_postdiv_ops, - .c = { - .parent = &dsi_vco_clk_8916.c, - .dbg_name = "analog_postdiv_clk", - .ops = &analog_postdiv_clk_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(analog_postdiv_clk_8916.c), +}; + +static struct clk_regmap_div dsi1pll_analog_postdiv = { + .reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, + .shift = 0, + .width = 4, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_analog_postdiv", + .parent_names = (const char *[]){"dsi1pll_vco_clk"}, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_regmap_div_ops, + }, }, }; -static struct div_clk indirect_path_div2_clk_8916 = { - .ops = &fixed_2div_ops, - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, +static struct clk_fixed_factor dsi0pll_indirect_path_src = { + .div = 2, + .mult = 1, + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_indirect_path_src", + .parent_names = (const char *[]){"dsi0pll_analog_postdiv"}, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, }, - .c = { - .parent = &analog_postdiv_clk_8916.c, - .dbg_name = "indirect_path_div2_clk", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(indirect_path_div2_clk_8916.c), +}; + +static struct clk_fixed_factor dsi1pll_indirect_path_src = { + .div = 2, + .mult = 1, + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_indirect_path_src", + .parent_names = (const char *[]){"dsi1pll_analog_postdiv"}, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, }, }; -static struct div_clk pixel_clk_src = { - .data = { - .max_div = 255, - .min_div = 1, +static struct clk_regmap_mux dsi0pll_byteclk_src_mux = { + .reg = DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, + .shift = 1, + .width = 1, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_byteclk_src_mux", + .parent_names = (const char *[]){ + "dsi0pll_vco_clk", + "dsi0pll_indirect_path_src"}, + .num_parents = 2, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_regmap_mux_closest_ops, + }, }, - .ops = &digital_postdiv_ops, - .c = { - .parent = &dsi_vco_clk_8916.c, - .dbg_name = "pixel_clk_src_8916", - .ops = &pixel_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(pixel_clk_src.c), +}; + +static struct clk_regmap_mux dsi1pll_byteclk_src_mux = { + .reg = DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, + .shift = 1, + .width = 1, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_byteclk_src_mux", + .parent_names = (const char *[]){ + "dsi1pll_vco_clk", + "dsi1pll_indirect_path_src"}, + .num_parents = 2, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_regmap_mux_closest_ops, + }, }, }; -static struct mux_clk byte_mux_8916 = { - .num_parents = 2, - .parents = (struct clk_src[]){ - {&dsi_vco_clk_8916.c, 0}, - {&indirect_path_div2_clk_8916.c, 1}, +static struct clk_fixed_factor dsi0pll_byteclk_src = { + .div = 4, + .mult = 1, + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_byteclk_src", + .parent_names = (const char *[]){ + "dsi0pll_byteclk_src_mux"}, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, }, - .ops = &byte_mux_ops, - .c = { - .parent = &dsi_vco_clk_8916.c, - .dbg_name = "byte_mux_8916", - .ops = &byte_mux_clk_ops, - CLK_INIT(byte_mux_8916.c), +}; + +static struct clk_fixed_factor dsi1pll_byteclk_src = { + .div = 4, + .mult = 1, + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_byteclk_src", + .parent_names = (const char *[]){ + "dsi1pll_byteclk_src_mux"}, + .num_parents = 1, + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .ops = &clk_fixed_factor_ops, }, }; -static struct div_clk byte_clk_src = { - .ops = &fixed_4div_ops, - .data = { - .min_div = 4, - .max_div = 4, +static struct clk_regmap_div dsi0pll_pclk_src = { + .reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, + .shift = 0, + .width = 8, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi0pll_pclk_src", + .parent_names = (const char *[]){"dsi0pll_vco_clk"}, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + .ops = &clk_regmap_div_ops, + }, }, - .c = { - .parent = &byte_mux_8916.c, - .dbg_name = "byte_clk_src_8916", - .ops = &byte_clk_src_ops, - CLK_INIT(byte_clk_src.c), +}; + +static struct clk_regmap_div dsi1pll_pclk_src = { + .reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, + .shift = 0, + .width = 8, + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dsi1pll_pclk_src", + .parent_names = (const char *[]){"dsi1pll_vco_clk"}, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + .ops = &clk_regmap_div_ops, + }, }, }; -static struct clk_lookup mdss_dsi_pllcc_8916[] = { - CLK_LIST(pixel_clk_src), - CLK_LIST(byte_clk_src), +static struct clk_hw *mdss_dsi_pllcc_28lpm[] = { + [VCO_CLK_0] = &dsi0pll_vco_clk.hw, + [ANALOG_POSTDIV_0_CLK] = &dsi0pll_analog_postdiv.clkr.hw, + [INDIRECT_PATH_SRC_0_CLK] = &dsi0pll_indirect_path_src.hw, + [BYTECLK_SRC_MUX_0_CLK] = &dsi0pll_byteclk_src_mux.clkr.hw, + [BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw, + [PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw, + [VCO_CLK_1] = &dsi1pll_vco_clk.hw, + [ANALOG_POSTDIV_1_CLK] = &dsi1pll_analog_postdiv.clkr.hw, + [INDIRECT_PATH_SRC_1_CLK] = &dsi1pll_indirect_path_src.hw, + [BYTECLK_SRC_MUX_1_CLK] = &dsi1pll_byteclk_src_mux.clkr.hw, + [BYTECLK_SRC_1_CLK] = &dsi1pll_byteclk_src.hw, + [PCLK_SRC_1_CLK] = &dsi1pll_pclk_src.clkr.hw, }; -int dsi_pll_clock_register_lpm(struct platform_device *pdev, +int dsi_pll_clock_register_28lpm(struct platform_device *pdev, struct mdss_pll_resources *pll_res) { - int rc; - - if (!pdev || !pdev->dev.of_node) { - pr_err("Invalid input parameters\n"); + int rc = 0, ndx, i; + struct clk *clk; + struct clk_onecell_data *clk_data; + int num_clks = ARRAY_SIZE(mdss_dsi_pllcc_28lpm); + struct regmap *rmap; + + int const ssc_freq_min = 30000; /* min. recommended freq. value */ + int const ssc_freq_max = 33000; /* max. recommended freq. value */ + int const ssc_ppm_max = 5000; /* max. recommended ppm */ + + if (!pdev || !pdev->dev.of_node || + !pll_res || !pll_res->pll_base) { + pr_err("Invalid params\n"); return -EINVAL; } - if (!pll_res || !pll_res->pll_base) { - pr_err("Invalid PLL resources\n"); - return -EPROBE_DEFER; + ndx = pll_res->index; + + if (ndx >= DSI_PLL_MAX) { + pr_err("pll index(%d) NOT supported\n", ndx); + return -EINVAL; } - /* Set client data to mux, div and vco clocks */ - byte_clk_src.priv = pll_res; - pixel_clk_src.priv = pll_res; - byte_mux_8916.priv = pll_res; - indirect_path_div2_clk_8916.priv = pll_res; - analog_postdiv_clk_8916.priv = pll_res; - dsi_vco_clk_8916.priv = pll_res; pll_res->vco_delay = VCO_DELAY_USEC; - /* Set clock source operations */ - pixel_clk_src_ops = clk_ops_slave_div; - pixel_clk_src_ops.prepare = dsi_pll_div_prepare; + if (pll_res->ssc_en) { + if (!pll_res->ssc_freq || (pll_res->ssc_freq < ssc_freq_min) || + (pll_res->ssc_freq > ssc_freq_max)) { + pll_res->ssc_freq = ssc_freq_min; + pr_debug("SSC frequency out of recommended range. Set to default=%d\n", + pll_res->ssc_freq); + } - analog_postdiv_clk_ops = clk_ops_div; - analog_postdiv_clk_ops.prepare = dsi_pll_div_prepare; + if (!pll_res->ssc_ppm || (pll_res->ssc_ppm > ssc_ppm_max)) { + pll_res->ssc_ppm = ssc_ppm_max; + pr_debug("SSC PPM out of recommended range. Set to default=%d\n", + pll_res->ssc_ppm); + } + } - byte_clk_src_ops = clk_ops_div; - byte_clk_src_ops.prepare = dsi_pll_div_prepare; + clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; - byte_mux_clk_ops = clk_ops_gen_mux; - byte_mux_clk_ops.prepare = dsi_pll_mux_prepare; + clk_data->clks = devm_kzalloc(&pdev->dev, (num_clks * + sizeof(struct clk *)), GFP_KERNEL); + if (!clk_data->clks) { + devm_kfree(&pdev->dev, clk_data); + return -ENOMEM; + } + clk_data->clk_num = num_clks; + + /* Establish client data */ + if (ndx == 0) { + rmap = devm_regmap_init(&pdev->dev, &byteclk_src_mux_regmap_bus, + pll_res, &dsi_pll_28lpm_config); + if (IS_ERR(rmap)) { + pr_err("regmap init failed for DSI clock:%d\n", + pll_res->index); + return -EINVAL; + } + dsi0pll_byteclk_src_mux.clkr.regmap = rmap; + + rmap = devm_regmap_init(&pdev->dev, &analog_postdiv_regmap_bus, + pll_res, &dsi_pll_28lpm_config); + if (IS_ERR(rmap)) { + pr_err("regmap init failed for DSI clock:%d\n", + pll_res->index); + return -EINVAL; + } + dsi0pll_analog_postdiv.clkr.regmap = rmap; + + rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, + pll_res, &dsi_pll_28lpm_config); + if (IS_ERR(rmap)) { + pr_err("regmap init failed for DSI clock:%d\n", + pll_res->index); + return -EINVAL; + } + dsi0pll_pclk_src.clkr.regmap = rmap; + + dsi0pll_vco_clk.priv = pll_res; + for (i = VCO_CLK_0; i <= PCLK_SRC_0_CLK; i++) { + clk = devm_clk_register(&pdev->dev, + mdss_dsi_pllcc_28lpm[i]); + if (IS_ERR(clk)) { + pr_err("clk registration failed for DSI clock:%d\n", + pll_res->index); + rc = -EINVAL; + goto clk_register_fail; + } + clk_data->clks[i] = clk; - if (pll_res->target_id == MDSS_PLL_TARGET_8916 || - pll_res->target_id == MDSS_PLL_TARGET_8939 || - pll_res->target_id == MDSS_PLL_TARGET_8909) { - rc = of_msm_clock_register(pdev->dev.of_node, - mdss_dsi_pllcc_8916, ARRAY_SIZE(mdss_dsi_pllcc_8916)); - if (rc) { - pr_err("Clock register failed\n"); - rc = -EPROBE_DEFER; } + + rc = of_clk_add_provider(pdev->dev.of_node, + of_clk_src_onecell_get, clk_data); + } else { - pr_err("Invalid target ID\n"); - rc = -EINVAL; + rmap = devm_regmap_init(&pdev->dev, &byteclk_src_mux_regmap_bus, + pll_res, &dsi_pll_28lpm_config); + if (IS_ERR(rmap)) { + pr_err("regmap init failed for DSI clock:%d\n", + pll_res->index); + return -EINVAL; + } + dsi1pll_byteclk_src_mux.clkr.regmap = rmap; + + rmap = devm_regmap_init(&pdev->dev, &analog_postdiv_regmap_bus, + pll_res, &dsi_pll_28lpm_config); + if (IS_ERR(rmap)) { + pr_err("regmap init failed for DSI clock:%d\n", + pll_res->index); + return -EINVAL; + } + dsi1pll_analog_postdiv.clkr.regmap = rmap; + + rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, + pll_res, &dsi_pll_28lpm_config); + if (IS_ERR(rmap)) { + pr_err("regmap init failed for DSI clock:%d\n", + pll_res->index); + return -EINVAL; + } + dsi1pll_pclk_src.clkr.regmap = rmap; + + dsi1pll_vco_clk.priv = pll_res; + for (i = VCO_CLK_1; i <= PCLK_SRC_1_CLK; i++) { + clk = devm_clk_register(&pdev->dev, + mdss_dsi_pllcc_28lpm[i]); + if (IS_ERR(clk)) { + pr_err("clk registration failed for DSI clock:%d\n", + pll_res->index); + rc = -EINVAL; + goto clk_register_fail; + } + clk_data->clks[i] = clk; + + } + + rc = of_clk_add_provider(pdev->dev.of_node, + of_clk_src_onecell_get, clk_data); } + if (!rc) { + pr_info("Registered DSI PLL ndx=%d, clocks successfully", ndx); - if (!rc) - pr_info("Registered DSI PLL clocks successfully\n"); + return rc; + } +clk_register_fail: + devm_kfree(&pdev->dev, clk_data->clks); + devm_kfree(&pdev->dev, clk_data); return rc; } diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm-util.c new file mode 100644 index 000000000000..4e23eb939c77 --- /dev/null +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm-util.c @@ -0,0 +1,693 @@ +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include + +#include "mdss-pll.h" +#include "mdss-dsi-pll.h" +#include "mdss-dsi-pll-28nm.h" + +#define DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG (0x0) +#define DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG (0x0008) +#define DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG (0x000C) +#define DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG (0x0014) +#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG (0x0024) +#define DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG (0x002C) +#define DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG (0x0030) +#define DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG (0x0034) +#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0 (0x0038) +#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1 (0x003C) +#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2 (0x0040) +#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3 (0x0044) +#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4 (0x0048) +#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG0 (0x004C) +#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG1 (0x0050) +#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG2 (0x0054) +#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG3 (0x0058) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0 (0x006C) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG2 (0x0074) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3 (0x0078) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4 (0x007C) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG5 (0x0080) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6 (0x0084) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7 (0x0088) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8 (0x008C) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9 (0x0090) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10 (0x0094) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11 (0x0098) +#define DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG (0x009C) +#define DSI_PHY_PLL_UNIPHY_PLL_STATUS (0x00C0) + +#define DSI_PLL_POLL_DELAY_US 50 +#define DSI_PLL_POLL_TIMEOUT_US 500 + +int analog_postdiv_reg_read(void *context, unsigned int reg, + unsigned int *div) +{ + int rc = 0; + struct mdss_pll_resources *rsc = context; + + if (is_gdsc_disabled(rsc)) + return 0; + + rc = mdss_pll_resource_enable(rsc, true); + if (rc) { + pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); + return rc; + } + + *div = MDSS_PLL_REG_R(rsc->pll_base, reg); + + /** + * Common clock framework the divider value is interpreted as one less + * hence we return one less for all dividers except when zero + */ + if (*div != 0) + *div -= 1; + + pr_debug("analog_postdiv div = %d\n", *div); + + (void)mdss_pll_resource_enable(rsc, false); + return rc; +} + +int analog_postdiv_reg_write(void *context, unsigned int reg, + unsigned int div) +{ + int rc = 0; + struct mdss_pll_resources *rsc = context; + + rc = mdss_pll_resource_enable(rsc, true); + if (rc) { + pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); + return rc; + } + + pr_debug("analog_postdiv div = %d\n", div); + + /** + * In common clock framework the divider value provided is one less and + * and hence adjusting the divider value by one prior to writing it to + * hardware + */ + div++; + + MDSS_PLL_REG_W(rsc->pll_base, reg, div); + + (void)mdss_pll_resource_enable(rsc, false); + return rc; +} + +int byteclk_mux_read_sel(void *context, unsigned int reg, + unsigned int *val) +{ + int rc = 0; + struct mdss_pll_resources *rsc = context; + + if (is_gdsc_disabled(rsc)) + return 0; + + rc = mdss_pll_resource_enable(rsc, true); + if (rc) { + pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); + return rc; + } + + *val = ((MDSS_PLL_REG_R(rsc->pll_base, reg) & BIT(1)) >> 1); + pr_debug("byteclk mux mode = %s", *val ? "indirect" : "direct"); + + (void)mdss_pll_resource_enable(rsc, false); + return rc; +} + +int byteclk_mux_write_sel(void *context, unsigned int reg, + unsigned int val) +{ + int rc = 0; + u32 reg_val = 0; + struct mdss_pll_resources *rsc = context; + + rc = mdss_pll_resource_enable(rsc, true); + if (rc) { + pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); + return rc; + } + + pr_debug("byteclk mux set to %s mode\n", val ? "indirect" : "direct"); + + reg_val = MDSS_PLL_REG_R(rsc->pll_base, reg); + reg_val &= ~0x02; + reg_val |= (val << 1); + + MDSS_PLL_REG_W(rsc->pll_base, reg, reg_val); + + (void)mdss_pll_resource_enable(rsc, false); + + return rc; +} + +int pixel_clk_get_div(void *context, unsigned int reg, + unsigned int *div) +{ + int rc = 0; + struct mdss_pll_resources *rsc = context; + + if (is_gdsc_disabled(rsc)) + return 0; + + rc = mdss_pll_resource_enable(rsc, true); + if (rc) { + pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); + return rc; + } + + *div = MDSS_PLL_REG_R(rsc->pll_base, reg); + + /** + *Common clock framework the divider value is interpreted as one less + * hence we return one less for all dividers except when zero + */ + if (*div != 0) + *div -= 1; + + pr_debug("pclk_src div = %d\n", *div); + + (void)mdss_pll_resource_enable(rsc, false); + return rc; +} + +int pixel_clk_set_div(void *context, unsigned int reg, + unsigned int div) +{ + int rc = 0; + struct mdss_pll_resources *rsc = context; + + rc = mdss_pll_resource_enable(rsc, true); + if (rc) { + pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); + return rc; + } + + pr_debug("pclk_src div = %d\n", div); + + /** + * In common clock framework the divider value provided is one less and + * and hence adjusting the divider value by one prior to writing it to + * hardware + */ + div++; + + MDSS_PLL_REG_W(rsc->pll_base, reg, div); + + (void)mdss_pll_resource_enable(rsc, false); + return rc; +} + +int dsi_pll_lock_status(struct mdss_pll_resources *rsc) +{ + u32 status; + int pll_locked; + + /* poll for PLL ready status */ + if (readl_poll_timeout_atomic((rsc->pll_base + + DSI_PHY_PLL_UNIPHY_PLL_STATUS), + status, + ((status & BIT(0)) == 1), + DSI_PLL_POLL_DELAY_US, + DSI_PLL_POLL_TIMEOUT_US)) { + pr_debug("DSI PLL status=%x failed to Lock\n", status); + pll_locked = 0; + } else { + pll_locked = 1; + } + + return pll_locked; +} + +static int pll_28nm_vco_rate_calc(struct dsi_pll_vco_clk *vco, + struct mdss_dsi_vco_calc *vco_calc, unsigned long vco_clk_rate) +{ + s32 rem; + s64 frac_n_mode, ref_doubler_en_b; + s64 ref_clk_to_pll, div_fb, frac_n_value; + int i; + + /* Configure the Loop filter resistance */ + for (i = 0; i < vco->lpfr_lut_size; i++) + if (vco_clk_rate <= vco->lpfr_lut[i].vco_rate) + break; + if (i == vco->lpfr_lut_size) { + pr_err("unable to get loop filter resistance. vco=%ld\n", + vco_clk_rate); + return -EINVAL; + } + vco_calc->lpfr_lut_res = vco->lpfr_lut[i].r; + + div_s64_rem(vco_clk_rate, vco->ref_clk_rate, &rem); + if (rem) { + vco_calc->refclk_cfg = 0x1; + frac_n_mode = 1; + ref_doubler_en_b = 0; + } else { + vco_calc->refclk_cfg = 0x0; + frac_n_mode = 0; + ref_doubler_en_b = 1; + } + + pr_debug("refclk_cfg = %lld\n", vco_calc->refclk_cfg); + + ref_clk_to_pll = ((vco->ref_clk_rate * 2 * (vco_calc->refclk_cfg)) + + (ref_doubler_en_b * vco->ref_clk_rate)); + + div_fb = div_s64_rem(vco_clk_rate, ref_clk_to_pll, &rem); + frac_n_value = div_s64(((s64)rem * (1 << 16)), ref_clk_to_pll); + vco_calc->gen_vco_clk = vco_clk_rate; + + pr_debug("ref_clk_to_pll = %lld\n", ref_clk_to_pll); + pr_debug("div_fb = %lld\n", div_fb); + pr_debug("frac_n_value = %lld\n", frac_n_value); + + pr_debug("Generated VCO Clock: %lld\n", vco_calc->gen_vco_clk); + rem = 0; + if (frac_n_mode) { + vco_calc->sdm_cfg0 = 0; + vco_calc->sdm_cfg1 = (div_fb & 0x3f) - 1; + vco_calc->sdm_cfg3 = div_s64_rem(frac_n_value, 256, &rem); + vco_calc->sdm_cfg2 = rem; + } else { + vco_calc->sdm_cfg0 = (0x1 << 5); + vco_calc->sdm_cfg0 |= (div_fb & 0x3f) - 1; + vco_calc->sdm_cfg1 = 0; + vco_calc->sdm_cfg2 = 0; + vco_calc->sdm_cfg3 = 0; + } + + pr_debug("sdm_cfg0=%lld\n", vco_calc->sdm_cfg0); + pr_debug("sdm_cfg1=%lld\n", vco_calc->sdm_cfg1); + pr_debug("sdm_cfg2=%lld\n", vco_calc->sdm_cfg2); + pr_debug("sdm_cfg3=%lld\n", vco_calc->sdm_cfg3); + + vco_calc->cal_cfg11 = div_s64_rem(vco_calc->gen_vco_clk, + 256 * 1000000, &rem); + vco_calc->cal_cfg10 = rem / 1000000; + pr_debug("cal_cfg10=%lld, cal_cfg11=%lld\n", + vco_calc->cal_cfg10, vco_calc->cal_cfg11); + + return 0; +} + +static void pll_28nm_ssc_param_calc(struct dsi_pll_vco_clk *vco, + struct mdss_dsi_vco_calc *vco_calc) +{ + struct mdss_pll_resources *rsc = vco->priv; + s64 ppm_freq, incr, spread_freq, div_rf, frac_n_value; + s32 rem; + + if (!rsc->ssc_en) { + pr_debug("DSI PLL SSC not enabled\n"); + return; + } + + vco_calc->ssc.kdiv = DIV_ROUND_CLOSEST(vco->ref_clk_rate, + 1000000) - 1; + vco_calc->ssc.triang_steps = DIV_ROUND_CLOSEST(vco->ref_clk_rate, + rsc->ssc_freq * (vco_calc->ssc.kdiv + 1)); + ppm_freq = div_s64(vco_calc->gen_vco_clk * rsc->ssc_ppm, + 1000000); + incr = div64_s64(ppm_freq * 65536, vco->ref_clk_rate * 2 * + vco_calc->ssc.triang_steps); + + vco_calc->ssc.triang_inc_7_0 = incr & 0xff; + vco_calc->ssc.triang_inc_9_8 = (incr >> 8) & 0x3; + + if (!rsc->ssc_center) + spread_freq = vco_calc->gen_vco_clk - ppm_freq; + else + spread_freq = vco_calc->gen_vco_clk - (ppm_freq / 2); + + div_rf = div_s64(spread_freq, 2 * vco->ref_clk_rate); + vco_calc->ssc.dc_offset = (div_rf - 1); + + div_s64_rem(spread_freq, 2 * vco->ref_clk_rate, &rem); + frac_n_value = div_s64((s64)rem * 65536, 2 * vco->ref_clk_rate); + + vco_calc->ssc.freq_seed_7_0 = frac_n_value & 0xff; + vco_calc->ssc.freq_seed_15_8 = (frac_n_value >> 8) & 0xff; +} + +static void pll_28nm_vco_config(struct dsi_pll_vco_clk *vco, + struct mdss_dsi_vco_calc *vco_calc) +{ + struct mdss_pll_resources *rsc = vco->priv; + void __iomem *pll_base = rsc->pll_base; + u32 vco_delay_us = rsc->vco_delay; + bool ssc_en = rsc->ssc_en; + + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG, + vco_calc->lpfr_lut_res); + + /* Loop filter capacitance values : c1 and c2 */ + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG, 0x70); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG, 0x15); + + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG, 0x02); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3, 0x2b); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4, 0x66); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d); + + if (!ssc_en) { + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1, + (u32)(vco_calc->sdm_cfg1 & 0xff)); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2, + (u32)(vco_calc->sdm_cfg2 & 0xff)); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3, + (u32)(vco_calc->sdm_cfg3 & 0xff)); + } else { + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1, + (u32)vco_calc->ssc.dc_offset); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2, + (u32)vco_calc->ssc.freq_seed_7_0); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3, + (u32)vco_calc->ssc.freq_seed_15_8); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG0, + (u32)vco_calc->ssc.kdiv); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG1, + (u32)vco_calc->ssc.triang_inc_7_0); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG2, + (u32)vco_calc->ssc.triang_inc_9_8); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG3, + (u32)vco_calc->ssc.triang_steps); + } + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4, 0x00); + + /* Add hardware recommended delay for correct PLL configuration */ + if (vco_delay_us) + udelay(vco_delay_us); + + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG, + (u32)vco_calc->refclk_cfg); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG, 0x71); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0, + (u32)vco_calc->sdm_cfg0); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x30); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x00); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9, 0x00); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10, + (u32)(vco_calc->cal_cfg10 & 0xff)); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11, + (u32)(vco_calc->cal_cfg11 & 0xff)); + MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG, 0x20); +} + +static int vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate) +{ + struct mdss_dsi_vco_calc vco_calc = {0}; + int rc = 0; + + rc = pll_28nm_vco_rate_calc(vco, &vco_calc, rate); + if (rc) { + pr_err("vco rate calculation failed\n"); + return rc; + } + + pll_28nm_ssc_param_calc(vco, &vco_calc); + pll_28nm_vco_config(vco, &vco_calc); + + return 0; +} + +static unsigned long vco_get_rate(struct dsi_pll_vco_clk *vco) +{ + struct mdss_pll_resources *rsc = vco->priv; + int rc; + u32 sdm0, doubler, sdm_byp_div; + u64 vco_rate; + u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3; + u64 ref_clk = vco->ref_clk_rate; + + if (is_gdsc_disabled(rsc)) + return 0; + + rc = mdss_pll_resource_enable(rsc, true); + if (rc) { + pr_err("Failed to enable mdss dsi pll resources\n"); + return rc; + } + + /* Check to see if the ref clk doubler is enabled */ + doubler = MDSS_PLL_REG_R(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG) & BIT(0); + ref_clk += (doubler * vco->ref_clk_rate); + + /* see if it is integer mode or sdm mode */ + sdm0 = MDSS_PLL_REG_R(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0); + if (sdm0 & BIT(6)) { + /* integer mode */ + sdm_byp_div = (MDSS_PLL_REG_R(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0) & 0x3f) + 1; + vco_rate = ref_clk * sdm_byp_div; + } else { + /* sdm mode */ + sdm_dc_off = MDSS_PLL_REG_R(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1) & 0xFF; + pr_debug("sdm_dc_off = %d\n", sdm_dc_off); + sdm2 = MDSS_PLL_REG_R(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2) & 0xFF; + sdm3 = MDSS_PLL_REG_R(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3) & 0xFF; + sdm_freq_seed = (sdm3 << 8) | sdm2; + pr_debug("sdm_freq_seed = %d\n", sdm_freq_seed); + + vco_rate = (ref_clk * (sdm_dc_off + 1)) + + mult_frac(ref_clk, sdm_freq_seed, BIT(16)); + pr_debug("vco rate = %lld", vco_rate); + } + + pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); + + mdss_pll_resource_enable(rsc, false); + + return (unsigned long)vco_rate; +} + +static int dsi_pll_enable(struct dsi_pll_vco_clk *vco) +{ + int i, rc; + struct mdss_pll_resources *rsc = vco->priv; + + rc = mdss_pll_resource_enable(rsc, true); + if (rc) { + pr_err("failed to enable dsi pll(%d) resources\n", + rsc->index); + return rc; + } + + /* Try all enable sequences until one succeeds */ + for (i = 0; i < vco->pll_en_seq_cnt; i++) { + rc = vco->pll_enable_seqs[i](rsc); + pr_debug("DSI PLL %s after sequence #%d\n", + rc ? "unlocked" : "locked", i + 1); + if (!rc) + break; + } + + if (rc) { + mdss_pll_resource_enable(rsc, false); + pr_err("DSI PLL failed to lock\n"); + } + rsc->pll_on = true; + + return rc; +} + +static void dsi_pll_disable(struct dsi_pll_vco_clk *vco) +{ + struct mdss_pll_resources *rsc = vco->priv; + + if (!rsc->pll_on && + mdss_pll_resource_enable(rsc, true)) { + pr_err("failed to enable dsi pll(%d) resources\n", + rsc->index); + return; + } + + rsc->handoff_resources = false; + + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x00); + + mdss_pll_resource_enable(rsc, false); + rsc->pll_on = false; + + pr_debug("DSI PLL Disabled\n"); +} + +int vco_28nm_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); + struct mdss_pll_resources *rsc = vco->priv; + int rc; + + if (!rsc) { + pr_err("pll resource not found\n"); + return -EINVAL; + } + + if (rsc->pll_on) + return 0; + + pr_debug("ndx=%d, rate=%lu\n", rsc->index, rate); + + rc = mdss_pll_resource_enable(rsc, true); + if (rc) { + pr_err("failed to enable mdss dsi pll(%d), rc=%d\n", + rsc->index, rc); + return rc; + } + + /* + * DSI PLL software reset. Add HW recommended delays after toggling + * the software reset bit off and back on. + */ + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01); + udelay(1000); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00); + udelay(1000); + + rc = vco_set_rate(vco, rate); + + mdss_pll_resource_enable(rsc, false); + + return 0; +} + +long vco_28nm_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long rrate = rate; + struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); + + if (rate < vco->min_rate) + rrate = vco->min_rate; + if (rate > vco->max_rate) + rrate = vco->max_rate; + + *parent_rate = rrate; + + return rrate; +} + +unsigned long vco_28nm_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); + struct mdss_pll_resources *rsc = vco->priv; + int rc; + u64 vco_rate = 0; + + if (!rsc) { + pr_err("dsi pll resources not available\n"); + return 0; + } + + if (is_gdsc_disabled(rsc)) + return 0; + + rc = mdss_pll_resource_enable(rsc, true); + if (rc) { + pr_err("failed to enable dsi pll(%d) resources\n", + rsc->index); + return 0; + } + + if (dsi_pll_lock_status(rsc)) { + rsc->handoff_resources = true; + rsc->pll_on = true; + vco_rate = vco_get_rate(vco); + } else { + mdss_pll_resource_enable(rsc, false); + } + + return (unsigned long)vco_rate; +} + +int vco_28nm_prepare(struct clk_hw *hw) +{ + int rc = 0; + struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); + struct mdss_pll_resources *rsc = vco->priv; + + if (!rsc) { + pr_err("dsi pll resources not available\n"); + return -EINVAL; + } + + if ((rsc->vco_cached_rate != 0) + && (rsc->vco_cached_rate == clk_hw_get_rate(hw))) { + rc = hw->init->ops->set_rate(hw, rsc->vco_cached_rate, + rsc->vco_cached_rate); + if (rc) { + pr_err("pll(%d ) set_rate failed. rc=%d\n", + rsc->index, rc); + goto error; + } + + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, + rsc->cached_postdiv1); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, + rsc->cached_postdiv3); + MDSS_PLL_REG_W(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, + rsc->cached_vreg_cfg); + } + + rc = dsi_pll_enable(vco); + +error: + return rc; +} + +void vco_28nm_unprepare(struct clk_hw *hw) +{ + struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); + struct mdss_pll_resources *rsc = vco->priv; + + if (!rsc) { + pr_err("dsi pll resources not available\n"); + return; + } + + rsc->cached_postdiv1 = MDSS_PLL_REG_R(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG); + rsc->cached_postdiv3 = MDSS_PLL_REG_R(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG); + rsc->cached_vreg_cfg = MDSS_PLL_REG_R(rsc->pll_base, + DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG); + + rsc->vco_cached_rate = clk_hw_get_rate(hw); + + dsi_pll_disable(vco); +} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm.h b/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm.h new file mode 100644 index 000000000000..b2ab4196ce47 --- /dev/null +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm.h @@ -0,0 +1,72 @@ +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __MDSS_DSI_PLL_28NM_H +#define __MDSS_DSI_PLL_28NM_H + +#define DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG (0x0020) +#define DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2 (0x0064) +#define DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG (0x0068) +#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1 (0x0070) + +#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG (0x0004) +#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG (0x0028) +#define DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG (0x0010) + +struct ssc_params { + s32 kdiv; + s64 triang_inc_7_0; + s64 triang_inc_9_8; + s64 triang_steps; + s64 dc_offset; + s64 freq_seed_7_0; + s64 freq_seed_15_8; +}; + +struct mdss_dsi_vco_calc { + s64 sdm_cfg0; + s64 sdm_cfg1; + s64 sdm_cfg2; + s64 sdm_cfg3; + s64 cal_cfg10; + s64 cal_cfg11; + s64 refclk_cfg; + s64 gen_vco_clk; + u32 lpfr_lut_res; + struct ssc_params ssc; +}; + +unsigned long vco_28nm_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate); +int vco_28nm_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate); +long vco_28nm_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate); +int vco_28nm_prepare(struct clk_hw *hw); +void vco_28nm_unprepare(struct clk_hw *hw); + +int analog_postdiv_reg_write(void *context, + unsigned int reg, unsigned int div); +int analog_postdiv_reg_read(void *context, + unsigned int reg, unsigned int *div); +int byteclk_mux_write_sel(void *context, + unsigned int reg, unsigned int val); +int byteclk_mux_read_sel(void *context, + unsigned int reg, unsigned int *val); +int pixel_clk_set_div(void *context, + unsigned int reg, unsigned int div); +int pixel_clk_get_div(void *context, + unsigned int reg, unsigned int *div); + +int dsi_pll_lock_status(struct mdss_pll_resources *rsc); +#endif /* __MDSS_DSI_PLL_28NM_H */ diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-util.c deleted file mode 100644 index 4e66b7837eb8..000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-util.c +++ /dev/null @@ -1,587 +0,0 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" - -#define DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG (0x0) -#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG (0x0004) -#define DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG (0x0008) -#define DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG (0x000C) -#define DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG (0x0010) -#define DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG (0x0014) -#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG (0x0024) -#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG (0x0028) -#define DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG (0x002C) -#define DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG (0x0030) -#define DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG (0x0034) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0 (0x0038) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1 (0x003C) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2 (0x0040) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3 (0x0044) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4 (0x0048) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0 (0x006C) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG2 (0x0074) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3 (0x0078) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4 (0x007C) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG5 (0x0080) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6 (0x0084) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7 (0x0088) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8 (0x008C) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9 (0x0090) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10 (0x0094) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11 (0x0098) -#define DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG (0x009C) -#define DSI_PHY_PLL_UNIPHY_PLL_STATUS (0x00C0) - -#define DSI_PLL_POLL_DELAY_US 50 -#define DSI_PLL_POLL_TIMEOUT_US 500 - -int set_byte_mux_sel(struct mux_clk *clk, int sel) -{ - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - pr_debug("byte mux set to %s mode\n", sel ? "indirect" : "direct"); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, (sel << 1)); - - return 0; -} - -int get_byte_mux_sel(struct mux_clk *clk) -{ - int mux_mode, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - mux_mode = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG) & BIT(1); - - pr_debug("byte mux mode = %s", mux_mode ? "indirect" : "direct"); - mdss_pll_resource_enable(dsi_pll_res, false); - - return !!mux_mode; -} - -int dsi_pll_div_prepare(struct clk *c) -{ - struct div_clk *div = to_div_clk(c); - /* Restore the divider's value */ - return div->ops->set_div(div, div->data.div); -} - -int dsi_pll_mux_prepare(struct clk *c) -{ - struct mux_clk *mux = to_mux_clk(c); - int i, rc, sel = 0; - struct mdss_pll_resources *dsi_pll_res = mux->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - for (i = 0; i < mux->num_parents; i++) - if (mux->parents[i].src == c->parent) { - sel = mux->parents[i].sel; - break; - } - - if (i == mux->num_parents) { - pr_err("Failed to select the parent clock\n"); - rc = -EINVAL; - goto error; - } - - /* Restore the mux source select value */ - rc = mux->ops->set_mux_sel(mux, sel); - -error: - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int fixed_4div_set_div(struct div_clk *clk, int div) -{ - int rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG, (div - 1)); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int fixed_4div_get_div(struct div_clk *clk) -{ - int div = 0, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - div = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG); - - mdss_pll_resource_enable(dsi_pll_res, false); - return div + 1; -} - -int digital_set_div(struct div_clk *clk, int div) -{ - int rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, (div - 1)); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int digital_get_div(struct div_clk *clk) -{ - int div = 0, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - div = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG); - - mdss_pll_resource_enable(dsi_pll_res, false); - return div + 1; -} - -int analog_set_div(struct div_clk *clk, int div) -{ - int rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, div - 1); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int analog_get_div(struct div_clk *clk) -{ - int div = 0, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(clk->priv, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - div = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG) + 1; - - mdss_pll_resource_enable(dsi_pll_res, false); - - return div; -} - -int dsi_pll_lock_status(struct mdss_pll_resources *dsi_pll_res) -{ - u32 status; - int pll_locked; - - /* poll for PLL ready status */ - if (readl_poll_timeout_atomic((dsi_pll_res->pll_base + - DSI_PHY_PLL_UNIPHY_PLL_STATUS), - status, - ((status & BIT(0)) == 1), - DSI_PLL_POLL_DELAY_US, - DSI_PLL_POLL_TIMEOUT_US)) { - pr_debug("DSI PLL status=%x failed to Lock\n", status); - pll_locked = 0; - } else { - pll_locked = 1; - } - - return pll_locked; -} - -int vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate) -{ - s64 vco_clk_rate = rate; - s32 rem; - s64 refclk_cfg, frac_n_mode, ref_doubler_en_b; - s64 ref_clk_to_pll, div_fbx1000, frac_n_value; - s64 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3; - s64 gen_vco_clk, cal_cfg10, cal_cfg11; - u32 res; - int i; - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - /* Configure the Loop filter resistance */ - for (i = 0; i < vco->lpfr_lut_size; i++) - if (vco_clk_rate <= vco->lpfr_lut[i].vco_rate) - break; - if (i == vco->lpfr_lut_size) { - pr_err("unable to get loop filter resistance. vco=%ld\n", rate); - return -EINVAL; - } - res = vco->lpfr_lut[i].r; - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG, res); - - /* Loop filter capacitance values : c1 and c2 */ - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG, 0x70); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG, 0x15); - - div_s64_rem(vco_clk_rate, vco->ref_clk_rate, &rem); - if (rem) { - refclk_cfg = 0x1; - frac_n_mode = 1; - ref_doubler_en_b = 0; - } else { - refclk_cfg = 0x0; - frac_n_mode = 0; - ref_doubler_en_b = 1; - } - - pr_debug("refclk_cfg = %lld\n", refclk_cfg); - - ref_clk_to_pll = ((vco->ref_clk_rate * 2 * (refclk_cfg)) - + (ref_doubler_en_b * vco->ref_clk_rate)); - div_fbx1000 = div_s64((vco_clk_rate * 1000), ref_clk_to_pll); - - div_s64_rem(div_fbx1000, 1000, &rem); - frac_n_value = div_s64((rem * (1 << 16)), 1000); - gen_vco_clk = div_s64(div_fbx1000 * ref_clk_to_pll, 1000); - - pr_debug("ref_clk_to_pll = %lld\n", ref_clk_to_pll); - pr_debug("div_fb = %lld\n", div_fbx1000); - pr_debug("frac_n_value = %lld\n", frac_n_value); - - pr_debug("Generated VCO Clock: %lld\n", gen_vco_clk); - rem = 0; - if (frac_n_mode) { - sdm_cfg0 = (0x0 << 5); - sdm_cfg0 |= (0x0 & 0x3f); - sdm_cfg1 = (div_s64(div_fbx1000, 1000) & 0x3f) - 1; - sdm_cfg3 = div_s64_rem(frac_n_value, 256, &rem); - sdm_cfg2 = rem; - } else { - sdm_cfg0 = (0x1 << 5); - sdm_cfg0 |= (div_s64(div_fbx1000, 1000) & 0x3f) - 1; - sdm_cfg1 = (0x0 & 0x3f); - sdm_cfg2 = 0; - sdm_cfg3 = 0; - } - - pr_debug("sdm_cfg0=%lld\n", sdm_cfg0); - pr_debug("sdm_cfg1=%lld\n", sdm_cfg1); - pr_debug("sdm_cfg2=%lld\n", sdm_cfg2); - pr_debug("sdm_cfg3=%lld\n", sdm_cfg3); - - cal_cfg11 = div_s64_rem(gen_vco_clk, 256 * 1000000, &rem); - cal_cfg10 = rem / 1000000; - pr_debug("cal_cfg10=%lld, cal_cfg11=%lld\n", cal_cfg10, cal_cfg11); - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG, 0x02); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3, 0x2b); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4, 0x66); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d); - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1, (u32)(sdm_cfg1 & 0xff)); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2, (u32)(sdm_cfg2 & 0xff)); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3, (u32)(sdm_cfg3 & 0xff)); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4, 0x00); - - /* Add hardware recommended delay for correct PLL configuration */ - if (dsi_pll_res->vco_delay) - udelay(dsi_pll_res->vco_delay); - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG, (u32)refclk_cfg); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG, 0x71); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0, (u32)sdm_cfg0); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x30); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x00); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10, (u32)(cal_cfg10 & 0xff)); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11, (u32)(cal_cfg11 & 0xff)); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG, 0x20); - - return 0; -} - -unsigned long vco_get_rate(struct clk *c) -{ - u32 sdm0, doubler, sdm_byp_div; - u64 vco_rate; - u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - u64 ref_clk = vco->ref_clk_rate; - int rc; - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - /* Check to see if the ref clk doubler is enabled */ - doubler = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG) & BIT(0); - ref_clk += (doubler * vco->ref_clk_rate); - - /* see if it is integer mode or sdm mode */ - sdm0 = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0); - if (sdm0 & BIT(6)) { - /* integer mode */ - sdm_byp_div = (MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0) & 0x3f) + 1; - vco_rate = ref_clk * sdm_byp_div; - } else { - /* sdm mode */ - sdm_dc_off = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1) & 0xFF; - pr_debug("sdm_dc_off = %d\n", sdm_dc_off); - sdm2 = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2) & 0xFF; - sdm3 = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3) & 0xFF; - sdm_freq_seed = (sdm3 << 8) | sdm2; - pr_debug("sdm_freq_seed = %d\n", sdm_freq_seed); - - vco_rate = (ref_clk * (sdm_dc_off + 1)) + - mult_frac(ref_clk, sdm_freq_seed, BIT(16)); - pr_debug("vco rate = %lld", vco_rate); - } - - pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); - - mdss_pll_resource_enable(dsi_pll_res, false); - - return (unsigned long)vco_rate; -} - -static int dsi_pll_enable(struct clk *c) -{ - int i, rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - /* Try all enable sequences until one succeeds */ - for (i = 0; i < vco->pll_en_seq_cnt; i++) { - rc = vco->pll_enable_seqs[i](dsi_pll_res); - pr_debug("DSI PLL %s after sequence #%d\n", - rc ? "unlocked" : "locked", i + 1); - if (!rc) - break; - } - - if (rc) { - mdss_pll_resource_enable(dsi_pll_res, false); - pr_err("DSI PLL failed to lock\n"); - } - dsi_pll_res->pll_on = true; - - return rc; -} - -static void dsi_pll_disable(struct clk *c) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (!dsi_pll_res->pll_on && - mdss_pll_resource_enable(dsi_pll_res, true)) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return; - } - - dsi_pll_res->handoff_resources = false; - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x00); - - mdss_pll_resource_enable(dsi_pll_res, false); - dsi_pll_res->pll_on = false; - - pr_debug("DSI PLL Disabled\n"); -} - -long vco_round_rate(struct clk *c, unsigned long rate) -{ - unsigned long rrate = rate; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - return rrate; -} - -enum handoff vco_handoff(struct clk *c) -{ - int rc; - enum handoff ret = HANDOFF_DISABLED_CLK; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return HANDOFF_DISABLED_CLK; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return ret; - } - - if (dsi_pll_lock_status(dsi_pll_res)) { - dsi_pll_res->handoff_resources = true; - dsi_pll_res->pll_on = true; - c->rate = vco_get_rate(c); - ret = HANDOFF_ENABLED_CLK; - } else { - mdss_pll_resource_enable(dsi_pll_res, false); - } - - return ret; -} - -int vco_prepare(struct clk *c) -{ - int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (!dsi_pll_res) { - pr_err("Dsi pll resources are not available\n"); - return -EINVAL; - } - - if ((dsi_pll_res->vco_cached_rate != 0) - && (dsi_pll_res->vco_cached_rate == c->rate)) { - rc = c->ops->set_rate(c, dsi_pll_res->vco_cached_rate); - if (rc) { - pr_err("vco_set_rate failed. rc=%d\n", rc); - goto error; - } - } - - rc = dsi_pll_enable(c); - -error: - return rc; -} - -void vco_unprepare(struct clk *c) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (!dsi_pll_res) { - pr_err("Dsi pll resources are not available\n"); - return; - } - - dsi_pll_res->vco_cached_rate = c->rate; - dsi_pll_disable(c); -} - diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll.h b/drivers/clk/qcom/mdss/mdss-dsi-pll.h index 1edcb8afc11c..42d3a1188ccc 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll.h +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll.h @@ -17,11 +17,6 @@ #include "mdss-pll.h" #define MAX_DSI_PLL_EN_SEQS 10 -#define DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG (0x0020) -#define DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2 (0x0064) -#define DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG (0x0068) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1 (0x0070) - /* Register offsets for 20nm PHY PLL */ #define MMSS_DSI_PHY_PLL_PLL_CNTRL (0x0014) #define MMSS_DSI_PHY_PLL_PLL_BKG_KVCO_CAL_EN (0x002C) @@ -51,6 +46,8 @@ int dsi_pll_clock_register_10nm(struct platform_device *pdev, int dsi_pll_clock_register_7nm(struct platform_device *pdev, struct mdss_pll_resources *pll_res); +int dsi_pll_clock_register_28lpm(struct platform_device *pdev, + struct mdss_pll_resources *pll_res); static inline struct dsi_pll_vco_clk *to_vco_clk_hw(struct clk_hw *hw) { diff --git a/drivers/clk/qcom/mdss/mdss-pll.c b/drivers/clk/qcom/mdss/mdss-pll.c index d31d7c2a7f0a..8ff3567f1f15 100644 --- a/drivers/clk/qcom/mdss/mdss-pll.c +++ b/drivers/clk/qcom/mdss/mdss-pll.c @@ -133,6 +133,8 @@ static int mdss_pll_resource_parse(struct platform_device *pdev, pll_res->pll_interface_type = MDSS_DP_PLL_7NM; else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_7nm")) pll_res->pll_interface_type = MDSS_DSI_PLL_7NM; + else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_28lpm")) + pll_res->pll_interface_type = MDSS_DSI_PLL_28LPM; else goto err; @@ -167,6 +169,9 @@ static int mdss_pll_clock_register(struct platform_device *pdev, case MDSS_DP_PLL_7NM: rc = dp_pll_clock_register_7nm(pdev, pll_res); break; + case MDSS_DSI_PLL_28LPM: + rc = dsi_pll_clock_register_28lpm(pdev, pll_res); + break; case MDSS_UNKNOWN_PLL: default: rc = -EINVAL; @@ -397,6 +402,7 @@ static const struct of_device_id mdss_pll_dt_match[] = { {.compatible = "qcom,mdss_dp_pll_10nm"}, {.compatible = "qcom,mdss_dsi_pll_7nm"}, {.compatible = "qcom,mdss_dp_pll_7nm"}, + {.compatible = "qcom,mdss_dsi_pll_28lpm"}, {} }; diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h index 9652176bd953..48c57f79eb5e 100644 --- a/drivers/clk/qcom/mdss/mdss-pll.h +++ b/drivers/clk/qcom/mdss/mdss-pll.h @@ -45,6 +45,7 @@ enum { MDSS_DP_PLL_10NM, MDSS_DSI_PLL_7NM, MDSS_DP_PLL_7NM, + MDSS_DSI_PLL_28LPM, MDSS_UNKNOWN_PLL, }; @@ -108,6 +109,10 @@ struct mdss_pll_resources { u32 cached_cfg1; u32 cached_outdiv; + u32 cached_postdiv1; + u32 cached_postdiv3; + u32 cached_vreg_cfg; + /* dsi/edp/hmdi pll interface type */ u32 pll_interface_type; diff --git a/include/dt-bindings/clock/mdss-28nm-pll-clk.h b/include/dt-bindings/clock/mdss-28nm-pll-clk.h new file mode 100644 index 000000000000..45e12ca5f923 --- /dev/null +++ b/include/dt-bindings/clock/mdss-28nm-pll-clk.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MDSS_28NM_PLL_CLK_H +#define __MDSS_28NM_PLL_CLK_H + +/* DSI PLL clocks */ +#define VCO_CLK_0 0 +#define ANALOG_POSTDIV_0_CLK 1 +#define INDIRECT_PATH_SRC_0_CLK 2 +#define BYTECLK_SRC_MUX_0_CLK 3 +#define BYTECLK_SRC_0_CLK 4 +#define PCLK_SRC_0_CLK 5 +#define VCO_CLK_1 6 +#define ANALOG_POSTDIV_1_CLK 7 +#define INDIRECT_PATH_SRC_1_CLK 8 +#define BYTECLK_SRC_MUX_1_CLK 9 +#define BYTECLK_SRC_1_CLK 10 +#define PCLK_SRC_1_CLK 11 + +#endif -- GitLab From aa43014b7bd22d908a7b07ae591d1fd834dd0ff7 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Tue, 26 Jun 2018 13:02:30 +0530 Subject: [PATCH 0845/1299] msm: kgsl: Add out of bound check for gmu register access Read/write operation to out of gmu register address space will not give the expected results. Add a check to allow the access to gmu registers only. Change-Id: Ifb88c1966137531daa5c7a58c70a9bdf0a584b23 Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/kgsl_gmu_core.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/msm/kgsl_gmu_core.c b/drivers/gpu/msm/kgsl_gmu_core.c index 06887ecd8f3a..3979a93839a2 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.c +++ b/drivers/gpu/msm/kgsl_gmu_core.c @@ -193,6 +193,11 @@ void gmu_core_regread(struct kgsl_device *device, unsigned int offsetwords, { struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); + if (!gmu_core_is_register_offset(device, offsetwords)) { + WARN(1, "Out of bounds register read: 0x%x\n", offsetwords); + return; + } + if (gmu_core_ops && gmu_core_ops->regread) gmu_core_ops->regread(device, offsetwords, value); else @@ -204,6 +209,11 @@ void gmu_core_regwrite(struct kgsl_device *device, unsigned int offsetwords, { struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); + if (!gmu_core_is_register_offset(device, offsetwords)) { + WARN(1, "Out of bounds register write: 0x%x\n", offsetwords); + return; + } + if (gmu_core_ops && gmu_core_ops->regwrite) gmu_core_ops->regwrite(device, offsetwords, value); } @@ -214,6 +224,11 @@ void gmu_core_regrmw(struct kgsl_device *device, { unsigned int val = 0; + if (!gmu_core_is_register_offset(device, offsetwords)) { + WARN(1, "Out of bounds register rmw: 0x%x\n", offsetwords); + return; + } + gmu_core_regread(device, offsetwords, &val); val &= ~mask; gmu_core_regwrite(device, offsetwords, val | bits); -- GitLab From 0b4f73c9b47436aa8256cb6af3b131a0e4c27189 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Wed, 15 Nov 2017 18:38:55 +0530 Subject: [PATCH 0846/1299] Revert "mm: memory: reduce fault_around_bytes" This reverts commit 23f8a2f5f2e0. fault_around_bytes were reduced as it was found to cause reclaim issues. The reclaim issues were mainly because of faultaround producing young ptes. The following patches will make faultaround produce old ptes. Thus revert the fault_around_bytes to its original value. Change-Id: If9a385eead5a5d7a0d40fed41ddf4753e15d2998 Signed-off-by: Vinayak Menon --- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index 36f74787fd2c..d140ba280c1e 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3654,7 +3654,7 @@ int finish_fault(struct vm_fault *vmf) } static unsigned long fault_around_bytes __read_mostly = - rounddown_pow_of_two(4096); + rounddown_pow_of_two(65536); #ifdef CONFIG_DEBUG_FS static int fault_around_bytes_get(void *data, u64 *val) -- GitLab From 822051c914bd93de7d85d442f42ac1f30f1c5616 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Wed, 20 Jun 2018 21:45:06 +0300 Subject: [PATCH 0847/1299] msm: gsi: Adapt GSI registers to support GSI version 2.5 GSI version 2.5 introduces changes to some of the configuration registers. Some are added, some deleted and others changed. This change adapt the registers accordingly and removes unused ones. CRs-Fixed: 2264509 Change-Id: I598b90cd6ef876ae10071f401a5bc30f8886f82b Signed-off-by: Ghanim Fodi --- drivers/platform/msm/gsi/gsi.c | 24 +- drivers/platform/msm/gsi/gsi_reg.h | 981 ++--------------------------- 2 files changed, 69 insertions(+), 936 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 71fb666862cf..0e5b5371df18 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -721,10 +721,10 @@ static uint32_t gsi_get_max_channels(enum gsi_ver ver) break; case GSI_VER_2_5: reg = gsi_readl(gsi_ctx->base + - GSI_V2_2_EE_n_GSI_HW_PARAM_2_OFFS(gsi_ctx->per.ee)); + GSI_V2_5_EE_n_GSI_HW_PARAM_2_OFFS(gsi_ctx->per.ee)); reg = (reg & - GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_BMSK) >> - GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_SHFT; + GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_BMSK) >> + GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_SHFT; break; } @@ -778,10 +778,10 @@ static uint32_t gsi_get_max_event_rings(enum gsi_ver ver) break; case GSI_VER_2_5: reg = gsi_readl(gsi_ctx->base + - GSI_V2_2_EE_n_GSI_HW_PARAM_2_OFFS(gsi_ctx->per.ee)); + GSI_V2_5_EE_n_GSI_HW_PARAM_2_OFFS(gsi_ctx->per.ee)); reg = (reg & - GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_BMSK) >> - GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_SHFT; + GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_BMSK) >> + GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_SHFT; break; } @@ -3032,13 +3032,16 @@ static void gsi_configure_ieps(void *base, enum gsi_ver ver) gsi_writel(4, gsi_base + GSI_GSI_IRAM_PTR_CH_EMPTY_OFFS); gsi_writel(5, gsi_base + GSI_GSI_IRAM_PTR_EE_GENERIC_CMD_OFFS); gsi_writel(6, gsi_base + GSI_GSI_IRAM_PTR_EVENT_GEN_COMP_OFFS); - gsi_writel(7, gsi_base + GSI_GSI_IRAM_PTR_INT_MOD_STOPPED_OFFS); + gsi_writel(7, gsi_base + GSI_GSI_IRAM_PTR_INT_MOD_STOPED_OFFS); gsi_writel(8, gsi_base + GSI_GSI_IRAM_PTR_PERIPH_IF_TLV_IN_0_OFFS); gsi_writel(9, gsi_base + GSI_GSI_IRAM_PTR_PERIPH_IF_TLV_IN_2_OFFS); gsi_writel(10, gsi_base + GSI_GSI_IRAM_PTR_PERIPH_IF_TLV_IN_1_OFFS); gsi_writel(11, gsi_base + GSI_GSI_IRAM_PTR_NEW_RE_OFFS); gsi_writel(12, gsi_base + GSI_GSI_IRAM_PTR_READ_ENG_COMP_OFFS); gsi_writel(13, gsi_base + GSI_GSI_IRAM_PTR_TIMER_EXPIRED_OFFS); + gsi_writel(14, gsi_base + GSI_GSI_IRAM_PTR_EV_DB_OFFS); + gsi_writel(15, gsi_base + GSI_GSI_IRAM_PTR_UC_GP_INT_OFFS); + gsi_writel(16, gsi_base + GSI_GSI_IRAM_PTR_WRITE_ENG_COMP_OFFS); if (ver >= GSI_VER_2_5) gsi_writel(17, @@ -3149,7 +3152,6 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size, enum gsi_ver ver) GSI_GSI_CFG_GSI_PWR_CLPS_BMSK) | ((0 << GSI_GSI_CFG_BP_MTRIX_DISABLE_SHFT) & GSI_GSI_CFG_BP_MTRIX_DISABLE_BMSK)); - gsi_writel(value, gsi_base + GSI_GSI_CFG_OFFS); } else { value = (((1 << GSI_GSI_CFG_GSI_ENABLE_SHFT) & GSI_GSI_CFG_GSI_ENABLE_BMSK) | @@ -3159,9 +3161,13 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size, enum gsi_ver ver) GSI_GSI_CFG_DOUBLE_MCS_CLK_FREQ_BMSK) | ((0 << GSI_GSI_CFG_UC_IS_MCS_SHFT) & GSI_GSI_CFG_UC_IS_MCS_BMSK)); - gsi_writel(value, gsi_base + GSI_GSI_CFG_OFFS); } + /* GSI frequency is peripheral frequency divided by 3 (2+1) */ + if (ver >= GSI_VER_2_5) + value |= ((2 << GSI_V2_5_GSI_CFG_SLEEP_CLK_DIV_SHFT) & + GSI_V2_5_GSI_CFG_SLEEP_CLK_DIV_BMSK); + gsi_writel(value, gsi_base + GSI_GSI_CFG_OFFS); iounmap(gsi_base); return 0; diff --git a/drivers/platform/msm/gsi/gsi_reg.h b/drivers/platform/msm/gsi/gsi_reg.h index d32f8009ecbb..ec2e886fb2d7 100644 --- a/drivers/platform/msm/gsi/gsi_reg.h +++ b/drivers/platform/msm/gsi/gsi_reg.h @@ -16,7 +16,8 @@ #define GSI_GSI_CFG_OFFS \ (GSI_GSI_REG_BASE_OFFS + 0x00000000) -#define GSI_GSI_CFG_RMSK 0xf +#define GSI_V2_5_GSI_CFG_SLEEP_CLK_DIV_BMSK 0xf00 +#define GSI_V2_5_GSI_CFG_SLEEP_CLK_DIV_SHFT 0x8 #define GSI_GSI_CFG_BP_MTRIX_DISABLE_BMSK 0x20 #define GSI_GSI_CFG_BP_MTRIX_DISABLE_SHFT 0x5 #define GSI_GSI_CFG_GSI_PWR_CLPS_BMSK 0x10 @@ -35,18 +36,6 @@ #define GSI_GSI_MCS_CFG_MCS_ENABLE_BMSK 0x1 #define GSI_GSI_MCS_CFG_MCS_ENABLE_SHFT 0x0 -#define GSI_GSI_MANAGER_MCS_CODE_VER_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000008) -#define GSI_GSI_MANAGER_MCS_CODE_VER_RMSK 0xffffffff -#define GSI_GSI_MANAGER_MCS_CODE_VER_VER_BMSK 0xffffffff -#define GSI_GSI_MANAGER_MCS_CODE_VER_VER_SHFT 0x0 - -#define GSI_GSI_ZEROS_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000010) -#define GSI_GSI_ZEROS_RMSK 0xffffffff -#define GSI_GSI_ZEROS_ZEROS_BMSK 0xffffffff -#define GSI_GSI_ZEROS_ZEROS_SHFT 0x0 - #define GSI_GSI_PERIPH_BASE_ADDR_LSB_OFFS \ (GSI_GSI_REG_BASE_OFFS + 0x00000018) #define GSI_GSI_PERIPH_BASE_ADDR_LSB_RMSK 0xffffffff @@ -59,136 +48,6 @@ #define GSI_GSI_PERIPH_BASE_ADDR_MSB_BASE_ADDR_BMSK 0xffffffff #define GSI_GSI_PERIPH_BASE_ADDR_MSB_BASE_ADDR_SHFT 0x0 -#define GSI_GSI_MOQA_CFG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000030) -#define GSI_GSI_MOQA_CFG_RMSK 0xffffff -#define GSI_GSI_MOQA_CFG_CLIENT_OOWR_BMSK 0xff0000 -#define GSI_GSI_MOQA_CFG_CLIENT_OOWR_SHFT 0x10 -#define GSI_GSI_MOQA_CFG_CLIENT_OORD_BMSK 0xff00 -#define GSI_GSI_MOQA_CFG_CLIENT_OORD_SHFT 0x8 -#define GSI_GSI_MOQA_CFG_CLIENT_REQ_PRIO_BMSK 0xff -#define GSI_GSI_MOQA_CFG_CLIENT_REQ_PRIO_SHFT 0x0 - -#define GSI_GSI_REE_CFG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000038) -#define GSI_GSI_REE_CFG_RMSK 0xff01 -#define GSI_GSI_REE_CFG_MAX_BURST_SIZE_BMSK 0xff00 -#define GSI_GSI_REE_CFG_MAX_BURST_SIZE_SHFT 0x8 -#define GSI_GSI_REE_CFG_MOVE_TO_ESC_CLR_MODE_TRSH_BMSK 0x1 -#define GSI_GSI_REE_CFG_MOVE_TO_ESC_CLR_MODE_TRSH_SHFT 0x0 - -#define GSI_GSI_SHRAM_WR_WRR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000050) -#define GSI_GSI_SHRAM_WR_WRR_RMSK 0xffff -#define GSI_GSI_SHRAM_WR_WRR_CLIENT3_WR_WEIGHT_BMSK 0xf000 -#define GSI_GSI_SHRAM_WR_WRR_CLIENT3_WR_WEIGHT_SHFT 0xc -#define GSI_GSI_SHRAM_WR_WRR_CLIENT2_WR_WEIGHT_BMSK 0xf00 -#define GSI_GSI_SHRAM_WR_WRR_CLIENT2_WR_WEIGHT_SHFT 0x8 -#define GSI_GSI_SHRAM_WR_WRR_CLIENT1_WR_WEIGHT_BMSK 0xf0 -#define GSI_GSI_SHRAM_WR_WRR_CLIENT1_WR_WEIGHT_SHFT 0x4 -#define GSI_GSI_SHRAM_WR_WRR_CLIENT0_WR_WEIGHT_BMSK 0xf -#define GSI_GSI_SHRAM_WR_WRR_CLIENT0_WR_WEIGHT_SHFT 0x0 - -#define GSI_GSI_SHRAM_RD_WRR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000058) -#define GSI_GSI_SHRAM_RD_WRR_RMSK 0xffffff -#define GSI_GSI_SHRAM_RD_WRR_ACH_SHRAM_RD_WEIGHT_BMSK 0xf00000 -#define GSI_GSI_SHRAM_RD_WRR_ACH_SHRAM_RD_WEIGHT_SHFT 0x14 -#define GSI_GSI_SHRAM_RD_WRR_IE_SHRAM_RD_WEIGHT_BMSK 0xf0000 -#define GSI_GSI_SHRAM_RD_WRR_IE_SHRAM_RD_WEIGHT_SHFT 0x10 -#define GSI_GSI_SHRAM_RD_WRR_CSR_SHRAM_RD_WEIGHT_BMSK 0xf000 -#define GSI_GSI_SHRAM_RD_WRR_CSR_SHRAM_RD_WEIGHT_SHFT 0xc -#define GSI_GSI_SHRAM_RD_WRR_RE_CNTXT_SHRAM_RD_WEIGHT_BMSK 0xf00 -#define GSI_GSI_SHRAM_RD_WRR_RE_CNTXT_SHRAM_RD_WEIGHT_SHFT 0x8 -#define GSI_GSI_SHRAM_RD_WRR_MCS_LD_SHRAM_RD_WEIGHT_BMSK 0xf0 -#define GSI_GSI_SHRAM_RD_WRR_MCS_LD_SHRAM_RD_WEIGHT_SHFT 0x4 -#define GSI_GSI_SHRAM_RD_WRR_EV_ENG_SHRAM_RD_WEIGHT_BMSK 0xf -#define GSI_GSI_SHRAM_RD_WRR_EV_ENG_SHRAM_RD_WEIGHT_SHFT 0x0 - -#define GSI_GSI_CGC_CTRL_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000060) -#define GSI_GSI_CGC_CTRL_RMSK 0x3f -#define GSI_GSI_CGC_CTRL_REGION_12_HW_CGC_EN_BMSK 0x800 -#define GSI_GSI_CGC_CTRL_REGION_12_HW_CGC_EN_SHFT 0xb -#define GSI_GSI_CGC_CTRL_REGION_11_HW_CGC_EN_BMSK0x400 -#define GSI_GSI_CGC_CTRL_REGION_11_HW_CGC_EN_SHFT 0xa -#define GSI_GSI_CGC_CTRL_REGION_10_HW_CGC_EN_BMSK0x200 -#define GSI_GSI_CGC_CTRL_REGION_10_HW_CGC_EN_SHFT 0x9 -#define GSI_GSI_CGC_CTRL_REGION_9_HW_CGC_EN_BMSK 0x100 -#define GSI_GSI_CGC_CTRL_REGION_9_HW_CGC_EN_SHFT 0x8 -#define GSI_GSI_CGC_CTRL_REGION_8_HW_CGC_EN_BMSK 0x80 -#define GSI_GSI_CGC_CTRL_REGION_8_HW_CGC_EN_SHFT 0x7 -#define GSI_GSI_CGC_CTRL_REGION_7_HW_CGC_EN_BMSK 0x40 -#define GSI_GSI_CGC_CTRL_REGION_7_HW_CGC_EN_SHFT 0x6 -#define GSI_GSI_CGC_CTRL_REGION_6_HW_CGC_EN_BMSK 0x20 -#define GSI_GSI_CGC_CTRL_REGION_6_HW_CGC_EN_SHFT 0x5 -#define GSI_GSI_CGC_CTRL_REGION_5_HW_CGC_EN_BMSK 0x10 -#define GSI_GSI_CGC_CTRL_REGION_5_HW_CGC_EN_SHFT 0x4 -#define GSI_GSI_CGC_CTRL_REGION_4_HW_CGC_EN_BMSK 0x8 -#define GSI_GSI_CGC_CTRL_REGION_4_HW_CGC_EN_SHFT 0x3 -#define GSI_GSI_CGC_CTRL_REGION_3_HW_CGC_EN_BMSK 0x4 -#define GSI_GSI_CGC_CTRL_REGION_3_HW_CGC_EN_SHFT 0x2 -#define GSI_GSI_CGC_CTRL_REGION_2_HW_CGC_EN_BMSK 0x2 -#define GSI_GSI_CGC_CTRL_REGION_2_HW_CGC_EN_SHFT 0x1 -#define GSI_GSI_CGC_CTRL_REGION_1_HW_CGC_EN_BMSK 0x1 -#define GSI_GSI_CGC_CTRL_REGION_1_HW_CGC_EN_SHFT 0x0 - -#define GSI_GSI_MSI_CACHEATTR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000080) -#define GSI_GSI_MSI_CACHEATTR_RMSK 0x3f -#define GSI_GSI_MSI_CACHEATTR_AREQPRIORITY_BMSK 0x30 -#define GSI_GSI_MSI_CACHEATTR_AREQPRIORITY_SHFT 0x4 -#define GSI_GSI_MSI_CACHEATTR_ATRANSIENT_BMSK 0x8 -#define GSI_GSI_MSI_CACHEATTR_ATRANSIENT_SHFT 0x3 -#define GSI_GSI_MSI_CACHEATTR_ANOALLOCATE_BMSK 0x4 -#define GSI_GSI_MSI_CACHEATTR_ANOALLOCATE_SHFT 0x2 -#define GSI_GSI_MSI_CACHEATTR_AINNERSHARED_BMSK 0x2 -#define GSI_GSI_MSI_CACHEATTR_AINNERSHARED_SHFT 0x1 -#define GSI_GSI_MSI_CACHEATTR_ASHARED_BMSK 0x1 -#define GSI_GSI_MSI_CACHEATTR_ASHARED_SHFT 0x0 - -#define GSI_GSI_EVENT_CACHEATTR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000084) -#define GSI_GSI_EVENT_CACHEATTR_RMSK 0x3f -#define GSI_GSI_EVENT_CACHEATTR_AREQPRIORITY_BMSK 0x30 -#define GSI_GSI_EVENT_CACHEATTR_AREQPRIORITY_SHFT 0x4 -#define GSI_GSI_EVENT_CACHEATTR_ATRANSIENT_BMSK 0x8 -#define GSI_GSI_EVENT_CACHEATTR_ATRANSIENT_SHFT 0x3 -#define GSI_GSI_EVENT_CACHEATTR_ANOALLOCATE_BMSK 0x4 -#define GSI_GSI_EVENT_CACHEATTR_ANOALLOCATE_SHFT 0x2 -#define GSI_GSI_EVENT_CACHEATTR_AINNERSHARED_BMSK 0x2 -#define GSI_GSI_EVENT_CACHEATTR_AINNERSHARED_SHFT 0x1 -#define GSI_GSI_EVENT_CACHEATTR_ASHARED_BMSK 0x1 -#define GSI_GSI_EVENT_CACHEATTR_ASHARED_SHFT 0x0 - -#define GSI_GSI_DATA_CACHEATTR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000088) -#define GSI_GSI_DATA_CACHEATTR_RMSK 0x3f -#define GSI_GSI_DATA_CACHEATTR_AREQPRIORITY_BMSK 0x30 -#define GSI_GSI_DATA_CACHEATTR_AREQPRIORITY_SHFT 0x4 -#define GSI_GSI_DATA_CACHEATTR_ATRANSIENT_BMSK 0x8 -#define GSI_GSI_DATA_CACHEATTR_ATRANSIENT_SHFT 0x3 -#define GSI_GSI_DATA_CACHEATTR_ANOALLOCATE_BMSK 0x4 -#define GSI_GSI_DATA_CACHEATTR_ANOALLOCATE_SHFT 0x2 -#define GSI_GSI_DATA_CACHEATTR_AINNERSHARED_BMSK 0x2 -#define GSI_GSI_DATA_CACHEATTR_AINNERSHARED_SHFT 0x1 -#define GSI_GSI_DATA_CACHEATTR_ASHARED_BMSK 0x1 -#define GSI_GSI_DATA_CACHEATTR_ASHARED_SHFT 0x0 - -#define GSI_GSI_TRE_CACHEATTR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000090) -#define GSI_GSI_TRE_CACHEATTR_RMSK 0x3f -#define GSI_GSI_TRE_CACHEATTR_AREQPRIORITY_BMSK 0x30 -#define GSI_GSI_TRE_CACHEATTR_AREQPRIORITY_SHFT 0x4 -#define GSI_GSI_TRE_CACHEATTR_ATRANSIENT_BMSK 0x8 -#define GSI_GSI_TRE_CACHEATTR_ATRANSIENT_SHFT 0x3 -#define GSI_GSI_TRE_CACHEATTR_ANOALLOCATE_BMSK 0x4 -#define GSI_GSI_TRE_CACHEATTR_ANOALLOCATE_SHFT 0x2 -#define GSI_GSI_TRE_CACHEATTR_AINNERSHARED_BMSK 0x2 -#define GSI_GSI_TRE_CACHEATTR_AINNERSHARED_SHFT 0x1 -#define GSI_GSI_TRE_CACHEATTR_ASHARED_BMSK 0x1 -#define GSI_GSI_TRE_CACHEATTR_ASHARED_SHFT 0x0 - #define GSI_IC_DISABLE_CHNL_BCK_PRS_LSB_OFFS \ (GSI_GSI_REG_BASE_OFFS + 0x000000a0) #define GSI_IC_DISABLE_CHNL_BCK_PRS_LSB_RMSK 0x3ffc1047 @@ -475,123 +334,6 @@ #define GSI_IC_UCONTROLLER_GPR_BCK_PRS_MSB_TIMER_INT_BMSK 0x1 #define GSI_IC_UCONTROLLER_GPR_BCK_PRS_MSB_TIMER_INT_SHFT 0x0 -#define GSI_IC_INT_WEIGHT_REE_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000100) -#define GSI_IC_INT_WEIGHT_REE_RMSK 0xfff -#define GSI_IC_INT_WEIGHT_REE_CH_EMPTY_INT_WEIGHT_BMSK 0xf00 -#define GSI_IC_INT_WEIGHT_REE_CH_EMPTY_INT_WEIGHT_SHFT 0x8 -#define GSI_IC_INT_WEIGHT_REE_NEW_RE_INT_WEIGHT_BMSK 0xf0 -#define GSI_IC_INT_WEIGHT_REE_NEW_RE_INT_WEIGHT_SHFT 0x4 -#define GSI_IC_INT_WEIGHT_REE_STOP_CH_COMP_INT_WEIGHT_BMSK 0xf -#define GSI_IC_INT_WEIGHT_REE_STOP_CH_COMP_INT_WEIGHT_SHFT 0x0 - -#define GSI_IC_INT_WEIGHT_EVT_ENG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000104) -#define GSI_IC_INT_WEIGHT_EVT_ENG_RMSK 0xf -#define GSI_IC_INT_WEIGHT_EVT_ENG_EVNT_ENG_INT_WEIGHT_BMSK 0xf -#define GSI_IC_INT_WEIGHT_EVT_ENG_EVNT_ENG_INT_WEIGHT_SHFT 0x0 - -#define GSI_IC_INT_WEIGHT_INT_ENG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000108) -#define GSI_IC_INT_WEIGHT_INT_ENG_RMSK 0xf -#define GSI_IC_INT_WEIGHT_INT_ENG_INT_ENG_INT_WEIGHT_BMSK 0xf -#define GSI_IC_INT_WEIGHT_INT_ENG_INT_ENG_INT_WEIGHT_SHFT 0x0 - -#define GSI_IC_INT_WEIGHT_CSR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x0000010c) -#define GSI_IC_INT_WEIGHT_CSR_RMSK 0xffffff -#define GSI_IC_INT_WEIGHT_CSR_CH_START_CMD_INT_WEIGHT_BMSK 0xf00000 -#define GSI_IC_INT_WEIGHT_CSR_CH_START_CMD_INT_WEIGHT_SHFT 0x14 -#define GSI_IC_INT_WEIGHT_CSR_CH_STOP_CMD_INT_WEIGHT_BMSK 0xf0000 -#define GSI_IC_INT_WEIGHT_CSR_CH_STOP_CMD_INT_WEIGHT_SHFT 0x10 -#define GSI_IC_INT_WEIGHT_CSR_CH_RESET_CMD_INT_WEIGHT_BMSK 0xf000 -#define GSI_IC_INT_WEIGHT_CSR_CH_RESET_CMD_INT_WEIGHT_SHFT 0xc -#define GSI_IC_INT_WEIGHT_CSR_CH_ALLOC_CMD_INT_WEIGHT_BMSK 0xf00 -#define GSI_IC_INT_WEIGHT_CSR_CH_ALLOC_CMD_INT_WEIGHT_SHFT 0x8 -#define GSI_IC_INT_WEIGHT_CSR_EV_RESET_CMD_INT_WEIGHT_BMSK 0xf0 -#define GSI_IC_INT_WEIGHT_CSR_EV_RESET_CMD_INT_WEIGHT_SHFT 0x4 -#define GSI_IC_INT_WEIGHT_CSR_EV_ALLOC_CMD_INT_WEIGHT_BMSK 0xf -#define GSI_IC_INT_WEIGHT_CSR_EV_ALLOC_CMD_INT_WEIGHT_SHFT 0x0 - -#define GSI_IC_INT_WEIGHT_TLV_ENG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000110) -#define GSI_IC_INT_WEIGHT_TLV_ENG_RMSK 0xf -#define GSI_IC_INT_WEIGHT_TLV_ENG_TLV_INT_WEIGHT_BMSK 0xf -#define GSI_IC_INT_WEIGHT_TLV_ENG_TLV_INT_WEIGHT_SHFT 0x0 - -#define GSI_IC_INT_WEIGHT_TIMER_ENG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000114) -#define GSI_IC_INT_WEIGHT_TIMER_ENG_RMSK 0xf -#define GSI_IC_INT_WEIGHT_TIMER_ENG_TIMER_INT_WEIGHT_BMSK 0xf -#define GSI_IC_INT_WEIGHT_TIMER_ENG_TIMER_INT_WEIGHT_SHFT 0x0 - -#define GSI_IC_INT_WEIGHT_DB_ENG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000118) -#define GSI_IC_INT_WEIGHT_DB_ENG_RMSK 0xf -#define GSI_IC_INT_WEIGHT_DB_ENG_NEW_DB_INT_WEIGHT_BMSK 0xf -#define GSI_IC_INT_WEIGHT_DB_ENG_NEW_DB_INT_WEIGHT_SHFT 0x0 - -#define GSI_IC_INT_WEIGHT_RD_WR_ENG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x0000011c) -#define GSI_IC_INT_WEIGHT_RD_WR_ENG_RMSK 0xff -#define GSI_IC_INT_WEIGHT_RD_WR_ENG_WRITE_INT_WEIGHT_BMSK 0xf0 -#define GSI_IC_INT_WEIGHT_RD_WR_ENG_WRITE_INT_WEIGHT_SHFT 0x4 -#define GSI_IC_INT_WEIGHT_RD_WR_ENG_READ_INT_WEIGHT_BMSK 0xf -#define GSI_IC_INT_WEIGHT_RD_WR_ENG_READ_INT_WEIGHT_SHFT 0x0 - -#define GSI_IC_INT_WEIGHT_UCONTROLLER_ENG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000120) -#define GSI_IC_INT_WEIGHT_UCONTROLLER_ENG_RMSK 0xf -#define GSI_IC_INT_WEIGHT_UCONTROLLER_ENG_GP_INT_WEIGHT_BMSK 0xf -#define GSI_IC_INT_WEIGHT_UCONTROLLER_ENG_GP_INT_WEIGHT_SHFT 0x0 - -#define GSI_GSI_MANAGER_EE_QOS_n_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00000300 + 0x4 * (n)) -#define GSI_GSI_MANAGER_EE_QOS_n_RMSK 0x1f1f03 -#define GSI_GSI_MANAGER_EE_QOS_n_MAXn 3 -#define GSI_GSI_MANAGER_EE_QOS_n_MAX_EV_ALLOC_BMSK 0x1f0000 -#define GSI_GSI_MANAGER_EE_QOS_n_MAX_EV_ALLOC_SHFT 0x10 -#define GSI_GSI_MANAGER_EE_QOS_n_MAX_CH_ALLOC_BMSK 0x1f00 -#define GSI_GSI_MANAGER_EE_QOS_n_MAX_CH_ALLOC_SHFT 0x8 -#define GSI_GSI_MANAGER_EE_QOS_n_EE_PRIO_BMSK 0x3 -#define GSI_GSI_MANAGER_EE_QOS_n_EE_PRIO_SHFT 0x0 - -#define GSI_GSI_SHRAM_PTR_CH_CNTXT_BASE_ADDR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000200) -#define GSI_GSI_SHRAM_PTR_CH_CNTXT_BASE_ADDR_RMSK 0xffff -#define GSI_GSI_SHRAM_PTR_CH_CNTXT_BASE_ADDR_SHRAM_PTR_BMSK 0xffff -#define GSI_GSI_SHRAM_PTR_CH_CNTXT_BASE_ADDR_SHRAM_PTR_SHFT 0x0 - -#define GSI_GSI_SHRAM_PTR_EV_CNTXT_BASE_ADDR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000204) -#define GSI_GSI_SHRAM_PTR_EV_CNTXT_BASE_ADDR_RMSK 0xffff -#define GSI_GSI_SHRAM_PTR_EV_CNTXT_BASE_ADDR_SHRAM_PTR_BMSK 0xffff -#define GSI_GSI_SHRAM_PTR_EV_CNTXT_BASE_ADDR_SHRAM_PTR_SHFT 0x0 - -#define GSI_GSI_SHRAM_PTR_RE_STORAGE_BASE_ADDR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000208) -#define GSI_GSI_SHRAM_PTR_RE_STORAGE_BASE_ADDR_RMSK 0xffff -#define GSI_GSI_SHRAM_PTR_RE_STORAGE_BASE_ADDR_SHRAM_PTR_BMSK 0xffff -#define GSI_GSI_SHRAM_PTR_RE_STORAGE_BASE_ADDR_SHRAM_PTR_SHFT 0x0 - -#define GSI_GSI_SHRAM_PTR_RE_ESC_BUF_BASE_ADDR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x0000020c) -#define GSI_GSI_SHRAM_PTR_RE_ESC_BUF_BASE_ADDR_RMSK 0xffff -#define GSI_GSI_SHRAM_PTR_RE_ESC_BUF_BASE_ADDR_SHRAM_PTR_BMSK 0xffff -#define GSI_GSI_SHRAM_PTR_RE_ESC_BUF_BASE_ADDR_SHRAM_PTR_SHFT 0x0 - -#define GSI_GSI_SHRAM_PTR_EE_SCRACH_BASE_ADDR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000240) -#define GSI_GSI_SHRAM_PTR_EE_SCRACH_BASE_ADDR_RMSK 0xffff -#define GSI_GSI_SHRAM_PTR_EE_SCRACH_BASE_ADDR_SHRAM_PTR_BMSK 0xffff -#define GSI_GSI_SHRAM_PTR_EE_SCRACH_BASE_ADDR_SHRAM_PTR_SHFT 0x0 - -#define GSI_GSI_SHRAM_PTR_FUNC_STACK_BASE_ADDR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000244) -#define GSI_GSI_SHRAM_PTR_FUNC_STACK_BASE_ADDR_RMSK 0xffff -#define GSI_GSI_SHRAM_PTR_FUNC_STACK_BASE_ADDR_SHRAM_PTR_BMSK 0xffff -#define GSI_GSI_SHRAM_PTR_FUNC_STACK_BASE_ADDR_SHRAM_PTR_SHFT 0x0 - #define GSI_GSI_IRAM_PTR_CH_CMD_OFFS \ (GSI_GSI_REG_BASE_OFFS + 0x00000400) #define GSI_GSI_IRAM_PTR_CH_CMD_RMSK 0xfff @@ -688,11 +430,11 @@ #define GSI_GSI_IRAM_PTR_UC_GP_INT_IRAM_PTR_BMSK 0xfff #define GSI_GSI_IRAM_PTR_UC_GP_INT_IRAM_PTR_SHFT 0x0 -#define GSI_GSI_IRAM_PTR_INT_MOD_STOPPED_OFFS \ +#define GSI_GSI_IRAM_PTR_INT_MOD_STOPED_OFFS \ (GSI_GSI_REG_BASE_OFFS + 0x0000044c) -#define GSI_GSI_IRAM_PTR_INT_MOD_STOPPED_RMSK 0xfff -#define GSI_GSI_IRAM_PTR_INT_MOD_STOPPED_IRAM_PTR_BMSK 0xfff -#define GSI_GSI_IRAM_PTR_INT_MOD_STOPPED_IRAM_PTR_SHFT 0x0 +#define GSI_GSI_IRAM_PTR_INT_MOD_STOPED_RMSK 0xfff +#define GSI_GSI_IRAM_PTR_INT_MOD_STOPED_IRAM_PTR_BMSK 0xfff +#define GSI_GSI_IRAM_PTR_INT_MOD_STOPED_IRAM_PTR_SHFT 0x0 #define GSI_GSI_INST_RAM_n_WORD_SZ 0x4 #define GSI_GSI_INST_RAM_n_OFFS(n) \ @@ -713,336 +455,8 @@ #define GSI_GSI_INST_RAM_n_INST_BYTE_0_BMSK 0xff #define GSI_GSI_INST_RAM_n_INST_BYTE_0_SHFT 0x0 -#define GSI_GSI_SHRAM_n_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00002000 + 0x4 * (n)) -#define GSI_GSI_SHRAM_n_RMSK 0xffffffff -#define GSI_GSI_SHRAM_n_MAXn 1023 -#define GSI_GSI_SHRAM_n_SHRAM_BMSK 0xffffffff -#define GSI_GSI_SHRAM_n_SHRAM_SHFT 0x0 - -#define GSI_GSI_TEST_BUS_SEL_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001000) -#define GSI_GSI_TEST_BUS_SEL_RMSK 0xff -#define GSI_GSI_TEST_BUS_SEL_GSI_TESTBUS_SEL_BMSK 0xff -#define GSI_GSI_TEST_BUS_SEL_GSI_TESTBUS_SEL_SHFT 0x0 - -#define GSI_GSI_TEST_BUS_REG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001008) -#define GSI_GSI_TEST_BUS_REG_RMSK 0xffffffff -#define GSI_GSI_TEST_BUS_REG_GSI_TESTBUS_REG_BMSK 0xffffffff -#define GSI_GSI_TEST_BUS_REG_GSI_TESTBUS_REG_SHFT 0x0 - -#define GSI_GSI_DEBUG_BUSY_REG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001010) -#define GSI_GSI_DEBUG_BUSY_REG_RMSK 0xff -#define GSI_GSI_DEBUG_BUSY_REG_REE_PWR_CLPS_BUSY_BMSK 0x80 -#define GSI_GSI_DEBUG_BUSY_REG_REE_PWR_CLPS_BUSY_SHFT 0x7 -#define GSI_GSI_DEBUG_BUSY_REG_INT_ENG_BUSY_BMSK 0x40 -#define GSI_GSI_DEBUG_BUSY_REG_INT_ENG_BUSY_SHFT 0x6 -#define GSI_GSI_DEBUG_BUSY_REG_EV_ENG_BUSY_BMSK 0x20 -#define GSI_GSI_DEBUG_BUSY_REG_EV_ENG_BUSY_SHFT 0x5 -#define GSI_GSI_DEBUG_BUSY_REG_RD_WR_BUSY_BMSK 0x10 -#define GSI_GSI_DEBUG_BUSY_REG_RD_WR_BUSY_SHFT 0x4 -#define GSI_GSI_DEBUG_BUSY_REG_TIMER_BUSY_BMSK 0x8 -#define GSI_GSI_DEBUG_BUSY_REG_TIMER_BUSY_SHFT 0x3 -#define GSI_GSI_DEBUG_BUSY_REG_MCS_BUSY_BMSK 0x4 -#define GSI_GSI_DEBUG_BUSY_REG_MCS_BUSY_SHFT 0x2 -#define GSI_GSI_DEBUG_BUSY_REG_REE_BUSY_BMSK 0x2 -#define GSI_GSI_DEBUG_BUSY_REG_REE_BUSY_SHFT 0x1 -#define GSI_GSI_DEBUG_BUSY_REG_CSR_BUSY_BMSK 0x1 -#define GSI_GSI_DEBUG_BUSY_REG_CSR_BUSY_SHFT 0x0 - -#define GSI_GSI_DEBUG_COUNTER_CFGn_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00001200 + 0x4 * (n)) -#define GSI_GSI_DEBUG_COUNTER_CFGn_RMSK 0x3ffffff7 -#define GSI_GSI_DEBUG_COUNTER_CFGn_MAXn 7 -#define GSI_GSI_DEBUG_COUNTER_CFGn_TIMER_VALUE_BMSK 0x3ff80000 -#define GSI_GSI_DEBUG_COUNTER_CFGn_TIMER_VALUE_SHFT 0x13 -#define GSI_GSI_DEBUG_COUNTER_CFGn_VIRTUAL_CHNL_BMSK 0x7f000 -#define GSI_GSI_DEBUG_COUNTER_CFGn_VIRTUAL_CHNL_SHFT 0xc -#define GSI_GSI_DEBUG_COUNTER_CFGn_EE_BMSK 0xf00 -#define GSI_GSI_DEBUG_COUNTER_CFGn_EE_SHFT 0x8 -#define GSI_GSI_DEBUG_COUNTER_CFGn_EVNT_TYPE_BMSK 0xf0 -#define GSI_GSI_DEBUG_COUNTER_CFGn_EVNT_TYPE_SHFT 0x4 -#define GSI_GSI_DEBUG_COUNTER_CFGn_CLR_AT_READ_BMSK 0x4 -#define GSI_GSI_DEBUG_COUNTER_CFGn_CLR_AT_READ_SHFT 0x2 -#define GSI_GSI_DEBUG_COUNTER_CFGn_STOP_AT_WRAP_ARND_BMSK 0x2 -#define GSI_GSI_DEBUG_COUNTER_CFGn_STOP_AT_WRAP_ARND_SHFT 0x1 -#define GSI_GSI_DEBUG_COUNTER_CFGn_ENABLE_BMSK 0x1 -#define GSI_GSI_DEBUG_COUNTER_CFGn_ENABLE_SHFT 0x0 - -#define GSI_GSI_DEBUG_COUNTERn_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00001240 + 0x4 * (n)) -#define GSI_GSI_DEBUG_COUNTERn_RMSK 0xffff -#define GSI_GSI_DEBUG_COUNTERn_MAXn 7 -#define GSI_GSI_DEBUG_COUNTERn_COUNTER_VALUE_BMSK 0xffff -#define GSI_GSI_DEBUG_COUNTERn_COUNTER_VALUE_SHFT 0x0 - -#define GSI_GSI_DEBUG_PC_FROM_SW_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001040) -#define GSI_GSI_DEBUG_PC_FROM_SW_RMSK 0xfff -#define GSI_GSI_DEBUG_PC_FROM_SW_IRAM_PTR_BMSK 0xfff -#define GSI_GSI_DEBUG_PC_FROM_SW_IRAM_PTR_SHFT 0x0 - -#define GSI_GSI_DEBUG_SW_STALL_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001044) -#define GSI_GSI_DEBUG_SW_STALL_RMSK 0x1 -#define GSI_GSI_DEBUG_SW_STALL_MCS_STALL_BMSK 0x1 -#define GSI_GSI_DEBUG_SW_STALL_MCS_STALL_SHFT 0x0 - -#define GSI_GSI_DEBUG_PC_FOR_DEBUG_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001048) -#define GSI_GSI_DEBUG_PC_FOR_DEBUG_RMSK 0xfff -#define GSI_GSI_DEBUG_PC_FOR_DEBUG_IRAM_PTR_BMSK 0xfff -#define GSI_GSI_DEBUG_PC_FOR_DEBUG_IRAM_PTR_SHFT 0x0 - -#define GSI_GSI_DEBUG_QSB_LOG_SEL_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001050) -#define GSI_GSI_DEBUG_QSB_LOG_SEL_RMSK 0xffff01 -#define GSI_GSI_DEBUG_QSB_LOG_SEL_SEL_MID_BMSK 0xff0000 -#define GSI_GSI_DEBUG_QSB_LOG_SEL_SEL_MID_SHFT 0x10 -#define GSI_GSI_DEBUG_QSB_LOG_SEL_SEL_TID_BMSK 0xff00 -#define GSI_GSI_DEBUG_QSB_LOG_SEL_SEL_TID_SHFT 0x8 -#define GSI_GSI_DEBUG_QSB_LOG_SEL_SEL_WRITE_BMSK 0x1 -#define GSI_GSI_DEBUG_QSB_LOG_SEL_SEL_WRITE_SHFT 0x0 - -#define GSI_GSI_DEBUG_QSB_LOG_CLR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001058) -#define GSI_GSI_DEBUG_QSB_LOG_CLR_RMSK 0x1 -#define GSI_GSI_DEBUG_QSB_LOG_CLR_LOG_CLR_BMSK 0x1 -#define GSI_GSI_DEBUG_QSB_LOG_CLR_LOG_CLR_SHFT 0x0 - -#define GSI_GSI_DEBUG_QSB_LOG_ERR_TRNS_ID_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001060) -#define GSI_GSI_DEBUG_QSB_LOG_ERR_TRNS_ID_RMSK 0x1ffff01 -#define GSI_GSI_DEBUG_QSB_LOG_ERR_TRNS_ID_ERR_SAVED_BMSK 0x1000000 -#define GSI_GSI_DEBUG_QSB_LOG_ERR_TRNS_ID_ERR_SAVED_SHFT 0x18 -#define GSI_GSI_DEBUG_QSB_LOG_ERR_TRNS_ID_ERR_MID_BMSK 0xff0000 -#define GSI_GSI_DEBUG_QSB_LOG_ERR_TRNS_ID_ERR_MID_SHFT 0x10 -#define GSI_GSI_DEBUG_QSB_LOG_ERR_TRNS_ID_ERR_TID_BMSK 0xff00 -#define GSI_GSI_DEBUG_QSB_LOG_ERR_TRNS_ID_ERR_TID_SHFT 0x8 -#define GSI_GSI_DEBUG_QSB_LOG_ERR_TRNS_ID_ERR_WRITE_BMSK 0x1 -#define GSI_GSI_DEBUG_QSB_LOG_ERR_TRNS_ID_ERR_WRITE_SHFT 0x0 - -#define GSI_GSI_DEBUG_QSB_LOG_0_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001064) -#define GSI_GSI_DEBUG_QSB_LOG_0_RMSK 0xffffffff -#define GSI_GSI_DEBUG_QSB_LOG_0_ADDR_31_0_BMSK 0xffffffff -#define GSI_GSI_DEBUG_QSB_LOG_0_ADDR_31_0_SHFT 0x0 - -#define GSI_GSI_DEBUG_QSB_LOG_1_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00001068) -#define GSI_GSI_DEBUG_QSB_LOG_1_RMSK 0xfff7ffff -#define GSI_GSI_DEBUG_QSB_LOG_1_AREQPRIORITY_BMSK 0xf0000000 -#define GSI_GSI_DEBUG_QSB_LOG_1_AREQPRIORITY_SHFT 0x1c -#define GSI_GSI_DEBUG_QSB_LOG_1_ASIZE_BMSK 0xf000000 -#define GSI_GSI_DEBUG_QSB_LOG_1_ASIZE_SHFT 0x18 -#define GSI_GSI_DEBUG_QSB_LOG_1_ALEN_BMSK 0xf00000 -#define GSI_GSI_DEBUG_QSB_LOG_1_ALEN_SHFT 0x14 -#define GSI_GSI_DEBUG_QSB_LOG_1_AOOOWR_BMSK 0x40000 -#define GSI_GSI_DEBUG_QSB_LOG_1_AOOOWR_SHFT 0x12 -#define GSI_GSI_DEBUG_QSB_LOG_1_AOOORD_BMSK 0x20000 -#define GSI_GSI_DEBUG_QSB_LOG_1_AOOORD_SHFT 0x11 -#define GSI_GSI_DEBUG_QSB_LOG_1_ATRANSIENT_BMSK 0x10000 -#define GSI_GSI_DEBUG_QSB_LOG_1_ATRANSIENT_SHFT 0x10 -#define GSI_GSI_DEBUG_QSB_LOG_1_ACACHEABLE_BMSK 0x8000 -#define GSI_GSI_DEBUG_QSB_LOG_1_ACACHEABLE_SHFT 0xf -#define GSI_GSI_DEBUG_QSB_LOG_1_ASHARED_BMSK 0x4000 -#define GSI_GSI_DEBUG_QSB_LOG_1_ASHARED_SHFT 0xe -#define GSI_GSI_DEBUG_QSB_LOG_1_ANOALLOCATE_BMSK 0x2000 -#define GSI_GSI_DEBUG_QSB_LOG_1_ANOALLOCATE_SHFT 0xd -#define GSI_GSI_DEBUG_QSB_LOG_1_AINNERSHARED_BMSK 0x1000 -#define GSI_GSI_DEBUG_QSB_LOG_1_AINNERSHARED_SHFT 0xc -#define GSI_GSI_DEBUG_QSB_LOG_1_ADDR_43_32_BMSK 0xfff -#define GSI_GSI_DEBUG_QSB_LOG_1_ADDR_43_32_SHFT 0x0 - -#define GSI_GSI_DEBUG_QSB_LOG_2_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x0000106c) -#define GSI_GSI_DEBUG_QSB_LOG_2_RMSK 0xffff -#define GSI_GSI_DEBUG_QSB_LOG_2_AMEMTYPE_BMSK 0xf000 -#define GSI_GSI_DEBUG_QSB_LOG_2_AMEMTYPE_SHFT 0xc -#define GSI_GSI_DEBUG_QSB_LOG_2_AMMUSID_BMSK 0xfff -#define GSI_GSI_DEBUG_QSB_LOG_2_AMMUSID_SHFT 0x0 - -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00001070 + 0x4 * (n)) -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_RMSK 0xffffffff -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_MAXn 3 -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_MID_BMSK 0xf8000000 -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_MID_SHFT 0x1b -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_TID_BMSK 0x7c00000 -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_TID_SHFT 0x16 -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_WRITE_BMSK 0x200000 -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_WRITE_SHFT 0x15 -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_ADDR_20_0_BMSK 0x1fffff -#define GSI_GSI_DEBUG_QSB_LOG_LAST_MISC_IDn_ADDR_20_0_SHFT 0x0 - -#define GSI_GSI_DEBUG_SW_RF_n_WRITE_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00001080 + 0x4 * (n)) -#define GSI_GSI_DEBUG_SW_RF_n_WRITE_RMSK 0xffffffff -#define GSI_GSI_DEBUG_SW_RF_n_WRITE_MAXn 31 -#define GSI_GSI_DEBUG_SW_RF_n_WRITE_DATA_IN_BMSK 0xffffffff -#define GSI_GSI_DEBUG_SW_RF_n_WRITE_DATA_IN_SHFT 0x0 - -#define GSI_GSI_DEBUG_SW_RF_n_READ_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00001100 + 0x4 * (n)) -#define GSI_GSI_DEBUG_SW_RF_n_READ_RMSK 0xffffffff -#define GSI_GSI_DEBUG_SW_RF_n_READ_MAXn 31 -#define GSI_GSI_DEBUG_SW_RF_n_READ_RF_REG_BMSK 0xffffffff -#define GSI_GSI_DEBUG_SW_RF_n_READ_RF_REG_SHFT 0x0 - -#define GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_OFFS(k, n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00001400 + 0x80 * (n) + 0x4 * (k)) -#define GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_RMSK 0x3f -#define GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_MAXk 30 -#define GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_MAXn 3 -#define GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_VALID_BMSK 0x20 -#define GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_VALID_SHFT 0x5 -#define GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_PHY_CH_BMSK 0x1f -#define GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_PHY_CH_SHFT 0x0 - -#define GSI_GSI_DEBUG_EE_n_EV_k_VP_TABLE_OFFS(k, n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00001600 + 0x80 * (n) + 0x4 * (k)) -#define GSI_GSI_DEBUG_EE_n_EV_k_VP_TABLE_RMSK 0x3f -#define GSI_GSI_DEBUG_EE_n_EV_k_VP_TABLE_MAXk 15 -#define GSI_GSI_DEBUG_EE_n_EV_k_VP_TABLE_MAXn 3 -#define GSI_GSI_DEBUG_EE_n_EV_k_VP_TABLE_VALID_BMSK 0x20 -#define GSI_GSI_DEBUG_EE_n_EV_k_VP_TABLE_VALID_SHFT 0x5 -#define GSI_GSI_DEBUG_EE_n_EV_k_VP_TABLE_PHY_EV_CH_BMSK 0x1f -#define GSI_GSI_DEBUG_EE_n_EV_k_VP_TABLE_PHY_EV_CH_SHFT 0x0 - -#define GSI_GSI_UC_SRC_IRQ_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000500) -#define GSI_GSI_UC_SRC_IRQ_RMSK 0xf -#define GSI_GSI_UC_SRC_IRQ_IC_2_UC_MCS_INT_VLD_BMSK 0x8 -#define GSI_GSI_UC_SRC_IRQ_IC_2_UC_MCS_INT_VLD_SHFT 0x3 -#define GSI_GSI_UC_SRC_IRQ_ACC_2_UC_MCS_GO_ACK_BMSK 0x4 -#define GSI_GSI_UC_SRC_IRQ_ACC_2_UC_MCS_GO_ACK_SHFT 0x2 -#define GSI_GSI_UC_SRC_IRQ_UC_ACC_CMPLT_BMSK 0x2 -#define GSI_GSI_UC_SRC_IRQ_UC_ACC_CMPLT_SHFT 0x1 -#define GSI_GSI_UC_SRC_IRQ_UC_ACC_GO_BMSK 0x1 -#define GSI_GSI_UC_SRC_IRQ_UC_ACC_GO_SHFT 0x0 - -#define GSI_GSI_UC_SRC_IRQ_MSK_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000504) -#define GSI_GSI_UC_SRC_IRQ_MSK_RMSK 0xf -#define GSI_GSI_UC_SRC_IRQ_MSK_IC_2_UC_MCS_INT_VLD_BMSK 0x8 -#define GSI_GSI_UC_SRC_IRQ_MSK_IC_2_UC_MCS_INT_VLD_SHFT 0x3 -#define GSI_GSI_UC_SRC_IRQ_MSK_ACC_2_UC_MCS_GO_ACK_BMSK 0x4 -#define GSI_GSI_UC_SRC_IRQ_MSK_ACC_2_UC_MCS_GO_ACK_SHFT 0x2 -#define GSI_GSI_UC_SRC_IRQ_MSK_UC_ACC_CMPLT_BMSK 0x2 -#define GSI_GSI_UC_SRC_IRQ_MSK_UC_ACC_CMPLT_SHFT 0x1 -#define GSI_GSI_UC_SRC_IRQ_MSK_UC_ACC_GO_BMSK 0x1 -#define GSI_GSI_UC_SRC_IRQ_MSK_UC_ACC_GO_SHFT 0x0 - -#define GSI_GSI_UC_SRC_IRQ_CLR_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000508) -#define GSI_GSI_UC_SRC_IRQ_CLR_RMSK 0xf -#define GSI_GSI_UC_SRC_IRQ_CLR_IC_2_UC_MCS_INT_VLD_BMSK 0x8 -#define GSI_GSI_UC_SRC_IRQ_CLR_IC_2_UC_MCS_INT_VLD_SHFT 0x3 -#define GSI_GSI_UC_SRC_IRQ_CLR_ACC_2_UC_MCS_GO_ACK_BMSK 0x4 -#define GSI_GSI_UC_SRC_IRQ_CLR_ACC_2_UC_MCS_GO_ACK_SHFT 0x2 -#define GSI_GSI_UC_SRC_IRQ_CLR_UC_ACC_CMPLT_BMSK 0x2 -#define GSI_GSI_UC_SRC_IRQ_CLR_UC_ACC_CMPLT_SHFT 0x1 -#define GSI_GSI_UC_SRC_IRQ_CLR_UC_ACC_GO_BMSK 0x1 -#define GSI_GSI_UC_SRC_IRQ_CLR_UC_ACC_GO_SHFT 0x0 - -#define GSI_GSI_ACC_ARGS_n_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0000050c + 0x4 * (n)) -#define GSI_GSI_ACC_ARGS_n_RMSK 0xffffffff -#define GSI_GSI_ACC_ARGS_n_MAXn 5 -#define GSI_GSI_ACC_ARGS_n_GSI_ACC_ARGS_BMSK 0xffffffff -#define GSI_GSI_ACC_ARGS_n_GSI_ACC_ARGS_SHFT 0x0 - -#define GSI_GSI_ACC_ROUTINE_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000524) -#define GSI_GSI_ACC_ROUTINE_RMSK 0xffffffff -#define GSI_GSI_ACC_ROUTINE_GSI_ACC_ROUTINE_BMSK 0xffffffff -#define GSI_GSI_ACC_ROUTINE_GSI_ACC_ROUTINE_SHFT 0x0 - -#define GSI_GSI_ACC_GO_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000528) -#define GSI_GSI_ACC_GO_RMSK 0x7f -#define GSI_GSI_ACC_GO_TIMER_GO_BMSK 0x40 -#define GSI_GSI_ACC_GO_TIMER_GO_SHFT 0x6 -#define GSI_GSI_ACC_GO_RW_ENG_GO_BMSK 0x20 -#define GSI_GSI_ACC_GO_RW_ENG_GO_SHFT 0x5 -#define GSI_GSI_ACC_GO_INT_ENG_GO_BMSK 0x10 -#define GSI_GSI_ACC_GO_INT_ENG_GO_SHFT 0x4 -#define GSI_GSI_ACC_GO_TLV_OUT_GO_BMSK 0x8 -#define GSI_GSI_ACC_GO_TLV_OUT_GO_SHFT 0x3 -#define GSI_GSI_ACC_GO_CSR_GO_BMSK 0x4 -#define GSI_GSI_ACC_GO_CSR_GO_SHFT 0x2 -#define GSI_GSI_ACC_GO_RE_ENG_GO_BMSK 0x2 -#define GSI_GSI_ACC_GO_RE_ENG_GO_SHFT 0x1 -#define GSI_GSI_ACC_GO_EV_ENG_GO_BMSK 0x1 -#define GSI_GSI_ACC_GO_EV_ENG_GO_SHFT 0x0 - -#define GSI_GSI_ACC_2_UC_MCS_STTS_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x0000052c) -#define GSI_GSI_ACC_2_UC_MCS_STTS_RMSK 0xffffffff -#define GSI_GSI_ACC_2_UC_MCS_STTS_GSI_ACC_2_UC_MCS_STTS_BMSK 0xffffffff -#define GSI_GSI_ACC_2_UC_MCS_STTS_GSI_ACC_2_UC_MCS_STTS_SHFT 0x0 - -#define GSI_GSI_ACC_2_UC_MCS_RET_VAL_LSB_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000530) -#define GSI_GSI_ACC_2_UC_MCS_RET_VAL_LSB_RMSK 0xffffffff -#define GSI_GSI_ACC_2_UC_MCS_RET_VAL_LSB_GSI_ACC_2_UC_MCS_RET_VAL_BMSK \ - 0xffffffff -#define GSI_GSI_ACC_2_UC_MCS_RET_VAL_LSB_GSI_ACC_2_UC_MCS_RET_VAL_SHFT \ - 0x0 - -#define GSI_GSI_ACC_2_UC_MCS_RET_VAL_MSB_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000534) -#define GSI_GSI_ACC_2_UC_MCS_RET_VAL_MSB_RMSK 0xffffffff -#define GSI_GSI_ACC_2_UC_MCS_RET_VAL_MSB_GSI_ACC_2_UC_MCS_RET_VAL_BMSK \ - 0xffffffff -#define GSI_GSI_ACC_2_UC_MCS_RET_VAL_MSB_GSI_ACC_2_UC_MCS_RET_VAL_SHFT \ - 0x0 - -#define GSI_GSI_IC_2_UC_MCS_VLD_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000538) -#define GSI_GSI_IC_2_UC_MCS_VLD_RMSK 0xffffffff -#define GSI_GSI_IC_2_UC_MCS_VLD_GSI_IC_2_UC_MCS_VLD_BMSK 0xffffffff -#define GSI_GSI_IC_2_UC_MCS_VLD_GSI_IC_2_UC_MCS_VLD_SHFT 0x0 - -#define GSI_GSI_IC_2_UC_MCS_PC_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x0000053c) -#define GSI_GSI_IC_2_UC_MCS_PC_RMSK 0xffffffff -#define GSI_GSI_IC_2_UC_MCS_PC_GSI_IC_2_UC_MCS_PC_BMSK 0xffffffff -#define GSI_GSI_IC_2_UC_MCS_PC_GSI_IC_2_UC_MCS_PC_SHFT 0x0 - -#define GSI_GSI_IC_2_UC_MCS_ARGS_n_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00000540 + 0x4 * (n)) -#define GSI_GSI_IC_2_UC_MCS_ARGS_n_RMSK 0xffffffff -#define GSI_GSI_IC_2_UC_MCS_ARGS_n_MAXn 5 -#define GSI_GSI_IC_2_UC_MCS_ARGS_n_GSI_IC_2_UC_MCS_ARGS_BMSK 0xffffffff -#define GSI_GSI_IC_2_UC_MCS_ARGS_n_GSI_IC_2_UC_MCS_ARGS_SHFT 0x0 - -#define GSI_GSI_UC_TLV_IN_VLD_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x00000558) -#define GSI_GSI_UC_TLV_IN_VLD_RMSK 0x1 -#define GSI_GSI_UC_TLV_IN_VLD_GSI_UC_TLV_IN_VLD_BMSK 0x1 -#define GSI_GSI_UC_TLV_IN_VLD_GSI_UC_TLV_IN_VLD_SHFT 0x0 - -#define GSI_GSI_UC_TLV_IN_ROUTINE_OFFS \ - (GSI_GSI_REG_BASE_OFFS + 0x0000055c) -#define GSI_GSI_UC_TLV_IN_ROUTINE_RMSK 0xffffffff -#define GSI_GSI_UC_TLV_IN_ROUTINE_GSI_UC_TLV_IN_ROUTINE_BMSK 0xffffffff -#define GSI_GSI_UC_TLV_IN_ROUTINE_GSI_UC_TLV_IN_ROUTINE_SHFT 0x0 - -#define GSI_GSI_UC_TLV_IN_ARGS_n_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x00000560 + 0x4 * (n)) -#define GSI_GSI_UC_TLV_IN_ARGS_n_RMSK 0xffffffff -#define GSI_GSI_UC_TLV_IN_ARGS_n_MAXn 5 -#define GSI_GSI_UC_TLV_IN_ARGS_n_GSI_UC_TLV_IN_ARGS_BMSK 0xffffffff -#define GSI_GSI_UC_TLV_IN_ARGS_n_GSI_UC_TLV_IN_ARGS_SHFT 0x0 - #define GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c000 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_CNTXT_0_RMSK 0xfff7dfff -#define GSI_EE_n_GSI_CH_k_CNTXT_0_MAXk 30 -#define GSI_EE_n_GSI_CH_k_CNTXT_0_MAXn 3 #define GSI_EE_n_GSI_CH_k_CNTXT_0_ELEMENT_SIZE_BMSK 0xff000000 #define GSI_EE_n_GSI_CH_k_CNTXT_0_ELEMENT_SIZE_SHFT 0x18 #define GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_BMSK 0xf00000 @@ -1062,57 +476,36 @@ #define GSI_EE_n_GSI_CH_k_CNTXT_1_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c004 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_CNTXT_1_RMSK 0xffff -#define GSI_EE_n_GSI_CH_k_CNTXT_1_MAXk 30 -#define GSI_EE_n_GSI_CH_k_CNTXT_1_MAXn 3 #define GSI_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_BMSK 0xffff #define GSI_EE_n_GSI_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_CNTXT_2_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c008 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_CNTXT_2_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_CNTXT_2_MAXk 30 -#define GSI_EE_n_GSI_CH_k_CNTXT_2_MAXn 3 #define GSI_EE_n_GSI_CH_k_CNTXT_2_R_BASE_ADDR_LSBS_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_CNTXT_2_R_BASE_ADDR_LSBS_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_CNTXT_3_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c00c + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_CNTXT_3_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_CNTXT_3_MAXk 30 -#define GSI_EE_n_GSI_CH_k_CNTXT_3_MAXn 3 #define GSI_EE_n_GSI_CH_k_CNTXT_3_R_BASE_ADDR_MSBS_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_CNTXT_3_R_BASE_ADDR_MSBS_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_CNTXT_4_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c010 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_CNTXT_4_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_CNTXT_4_MAXk 30 -#define GSI_EE_n_GSI_CH_k_CNTXT_4_MAXn 3 #define GSI_EE_n_GSI_CH_k_CNTXT_4_READ_PTR_LSB_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_CNTXT_4_READ_PTR_LSB_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_CNTXT_5_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c014 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_CNTXT_5_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_CNTXT_5_MAXk 30 -#define GSI_EE_n_GSI_CH_k_CNTXT_5_MAXn 3 #define GSI_EE_n_GSI_CH_k_CNTXT_5_READ_PTR_MSB_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_CNTXT_5_READ_PTR_MSB_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_CNTXT_6_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c018 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_CNTXT_6_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_CNTXT_6_MAXk 30 -#define GSI_EE_n_GSI_CH_k_CNTXT_6_MAXn 3 #define GSI_EE_n_GSI_CH_k_CNTXT_6_WRITE_PTR_LSB_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_CNTXT_6_WRITE_PTR_LSB_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_CNTXT_7_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c01c + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_CNTXT_7_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_CNTXT_7_MAXk 30 -#define GSI_EE_n_GSI_CH_k_CNTXT_7_MAXn 3 #define GSI_EE_n_GSI_CH_k_CNTXT_7_WRITE_PTR_MSB_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_CNTXT_7_WRITE_PTR_MSB_SHFT 0x0 @@ -1162,41 +555,26 @@ #define GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c060 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_SCRATCH_0_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_SCRATCH_0_MAXk 30 -#define GSI_EE_n_GSI_CH_k_SCRATCH_0_MAXn 3 #define GSI_EE_n_GSI_CH_k_SCRATCH_0_SCRATCH_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_SCRATCH_0_SCRATCH_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_SCRATCH_1_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c064 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_SCRATCH_1_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_SCRATCH_1_MAXk 30 -#define GSI_EE_n_GSI_CH_k_SCRATCH_1_MAXn 3 #define GSI_EE_n_GSI_CH_k_SCRATCH_1_SCRATCH_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_SCRATCH_1_SCRATCH_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_SCRATCH_2_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c068 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_SCRATCH_2_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_SCRATCH_2_MAXk 30 -#define GSI_EE_n_GSI_CH_k_SCRATCH_2_MAXn 3 #define GSI_EE_n_GSI_CH_k_SCRATCH_2_SCRATCH_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_SCRATCH_2_SCRATCH_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001c06c + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_GSI_CH_k_SCRATCH_3_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_SCRATCH_3_MAXk 30 -#define GSI_EE_n_GSI_CH_k_SCRATCH_3_MAXn 3 #define GSI_EE_n_GSI_CH_k_SCRATCH_3_SCRATCH_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_SCRATCH_3_SCRATCH_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_0_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d000 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_0_RMSK 0xfff1ffff -#define GSI_EE_n_EV_CH_k_CNTXT_0_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_0_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_0_ELEMENT_SIZE_BMSK 0xff000000 #define GSI_EE_n_EV_CH_k_CNTXT_0_ELEMENT_SIZE_SHFT 0x18 #define GSI_EE_n_EV_CH_k_CNTXT_0_CHSTATE_BMSK 0xf00000 @@ -1212,65 +590,41 @@ #define GSI_EE_n_EV_CH_k_CNTXT_1_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d004 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_1_RMSK 0xffff -#define GSI_EE_n_EV_CH_k_CNTXT_1_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_1_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_BMSK 0xffff #define GSI_EE_n_EV_CH_k_CNTXT_1_R_LENGTH_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_2_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d008 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_2_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_2_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_2_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_2_R_BASE_ADDR_LSBS_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_2_R_BASE_ADDR_LSBS_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_3_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d00c + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_3_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_3_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_3_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_3_R_BASE_ADDR_MSBS_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_3_R_BASE_ADDR_MSBS_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_4_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d010 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_4_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_4_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_4_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_4_READ_PTR_LSB_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_4_READ_PTR_LSB_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_5_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d014 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_5_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_5_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_5_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_5_READ_PTR_MSB_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_5_READ_PTR_MSB_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_6_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d018 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_6_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_6_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_6_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_6_WRITE_PTR_LSB_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_6_WRITE_PTR_LSB_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_7_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d01c + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_7_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_7_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_7_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_7_WRITE_PTR_MSB_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_7_WRITE_PTR_MSB_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_8_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d020 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_8_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_8_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_8_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_8_INT_MOD_CNT_BMSK 0xff000000 #define GSI_EE_n_EV_CH_k_CNTXT_8_INT_MOD_CNT_SHFT 0x18 #define GSI_EE_n_EV_CH_k_CNTXT_8_INT_MODC_BMSK 0xff0000 @@ -1280,103 +634,66 @@ #define GSI_EE_n_EV_CH_k_CNTXT_9_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d024 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_9_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_9_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_9_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_9_INTVEC_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_9_INTVEC_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_10_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d028 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_10_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_10_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_10_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_10_MSI_ADDR_LSB_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_10_MSI_ADDR_LSB_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_11_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d02c + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_11_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_11_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_11_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_11_MSI_ADDR_MSB_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_11_MSI_ADDR_MSB_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_12_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d030 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_12_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_12_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_12_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_12_RP_UPDATE_ADDR_LSB_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_12_RP_UPDATE_ADDR_LSB_SHFT 0x0 #define GSI_EE_n_EV_CH_k_CNTXT_13_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d034 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_CNTXT_13_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_CNTXT_13_MAXk 15 -#define GSI_EE_n_EV_CH_k_CNTXT_13_MAXn 3 #define GSI_EE_n_EV_CH_k_CNTXT_13_RP_UPDATE_ADDR_MSB_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_CNTXT_13_RP_UPDATE_ADDR_MSB_SHFT 0x0 #define GSI_EE_n_EV_CH_k_SCRATCH_0_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d048 + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_SCRATCH_0_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_SCRATCH_0_MAXk 15 -#define GSI_EE_n_EV_CH_k_SCRATCH_0_MAXn 3 #define GSI_EE_n_EV_CH_k_SCRATCH_0_SCRATCH_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_SCRATCH_0_SCRATCH_SHFT 0x0 #define GSI_EE_n_EV_CH_k_SCRATCH_1_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001d04c + 0x4000 * (n) + 0x80 * (k)) -#define GSI_EE_n_EV_CH_k_SCRATCH_1_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_SCRATCH_1_MAXk 15 -#define GSI_EE_n_EV_CH_k_SCRATCH_1_MAXn 3 #define GSI_EE_n_EV_CH_k_SCRATCH_1_SCRATCH_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_SCRATCH_1_SCRATCH_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_DOORBELL_0_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001e000 + 0x4000 * (n) + 0x8 * (k)) -#define GSI_EE_n_GSI_CH_k_DOORBELL_0_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_DOORBELL_0_MAXk 30 -#define GSI_EE_n_GSI_CH_k_DOORBELL_0_MAXn 3 #define GSI_EE_n_GSI_CH_k_DOORBELL_0_WRITE_PTR_LSB_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_DOORBELL_0_WRITE_PTR_LSB_SHFT 0x0 #define GSI_EE_n_GSI_CH_k_DOORBELL_1_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001e004 + 0x4000 * (n) + 0x8 * (k)) -#define GSI_EE_n_GSI_CH_k_DOORBELL_1_RMSK 0xffffffff -#define GSI_EE_n_GSI_CH_k_DOORBELL_1_MAXk 30 -#define GSI_EE_n_GSI_CH_k_DOORBELL_1_MAXn 3 #define GSI_EE_n_GSI_CH_k_DOORBELL_1_WRITE_PTR_MSB_BMSK 0xffffffff #define GSI_EE_n_GSI_CH_k_DOORBELL_1_WRITE_PTR_MSB_SHFT 0x0 #define GSI_EE_n_EV_CH_k_DOORBELL_0_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001e100 + 0x4000 * (n) + 0x8 * (k)) -#define GSI_EE_n_EV_CH_k_DOORBELL_0_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_DOORBELL_0_MAXk 15 -#define GSI_EE_n_EV_CH_k_DOORBELL_0_MAXn 3 #define GSI_EE_n_EV_CH_k_DOORBELL_0_WRITE_PTR_LSB_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_DOORBELL_0_WRITE_PTR_LSB_SHFT 0x0 #define GSI_EE_n_EV_CH_k_DOORBELL_1_OFFS(k, n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001e104 + 0x4000 * (n) + 0x8 * (k)) -#define GSI_EE_n_EV_CH_k_DOORBELL_1_RMSK 0xffffffff -#define GSI_EE_n_EV_CH_k_DOORBELL_1_MAXk 15 -#define GSI_EE_n_EV_CH_k_DOORBELL_1_MAXn 3 #define GSI_EE_n_EV_CH_k_DOORBELL_1_WRITE_PTR_MSB_BMSK 0xffffffff #define GSI_EE_n_EV_CH_k_DOORBELL_1_WRITE_PTR_MSB_SHFT 0x0 #define GSI_EE_n_GSI_STATUS_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f000 + 0x4000 * (n)) -#define GSI_EE_n_GSI_STATUS_RMSK 0x1 -#define GSI_EE_n_GSI_STATUS_MAXn 3 #define GSI_EE_n_GSI_STATUS_ENABLED_BMSK 0x1 #define GSI_EE_n_GSI_STATUS_ENABLED_SHFT 0x0 #define GSI_EE_n_GSI_CH_CMD_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f008 + 0x4000 * (n)) -#define GSI_EE_n_GSI_CH_CMD_RMSK 0xff0000ff -#define GSI_EE_n_GSI_CH_CMD_MAXn 3 #define GSI_EE_n_GSI_CH_CMD_OPCODE_BMSK 0xff000000 #define GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT 0x18 #define GSI_EE_n_GSI_CH_CMD_CHID_BMSK 0xff @@ -1384,8 +701,6 @@ #define GSI_EE_n_EV_CH_CMD_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f010 + 0x4000 * (n)) -#define GSI_EE_n_EV_CH_CMD_RMSK 0xff0000ff -#define GSI_EE_n_EV_CH_CMD_MAXn 3 #define GSI_EE_n_EV_CH_CMD_OPCODE_BMSK 0xff000000 #define GSI_EE_n_EV_CH_CMD_OPCODE_SHFT 0x18 #define GSI_EE_n_EV_CH_CMD_CHID_BMSK 0xff @@ -1393,8 +708,6 @@ #define GSI_EE_n_GSI_EE_GENERIC_CMD_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f018 + 0x4000 * (n)) -#define GSI_EE_n_GSI_EE_GENERIC_CMD_RMSK 0xffffffff -#define GSI_EE_n_GSI_EE_GENERIC_CMD_MAXn 3 #define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK 0x1f #define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT 0x0 #define GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK 0x3e0 @@ -1402,11 +715,8 @@ #define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK 0x3c00 #define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT 0xa -/* v1.0 */ #define GSI_V1_0_EE_n_GSI_HW_PARAM_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f040 + 0x4000 * (n)) -#define GSI_V1_0_EE_n_GSI_HW_PARAM_RMSK 0x7fffffff -#define GSI_V1_0_EE_n_GSI_HW_PARAM_MAXn 3 #define GSI_V1_0_EE_n_GSI_HW_PARAM_PERIPH_SEC_GRP_BMSK 0x7c000000 #define GSI_V1_0_EE_n_GSI_HW_PARAM_PERIPH_SEC_GRP_SHFT 0x1a #define GSI_V1_0_EE_n_GSI_HW_PARAM_USE_AXI_M_BMSK 0x2000000 @@ -1420,11 +730,8 @@ #define GSI_V1_0_EE_n_GSI_HW_PARAM_GSI_EV_CH_NUM_BMSK 0xff #define GSI_V1_0_EE_n_GSI_HW_PARAM_GSI_EV_CH_NUM_SHFT 0x0 -/* v1.2 */ #define GSI_V1_2_EE_n_GSI_HW_PARAM_0_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f038 + 0x4000 * (n)) -#define GSI_V1_2_EE_n_GSI_HW_PARAM_0_RMSK 0xffffffff -#define GSI_V1_2_EE_n_GSI_HW_PARAM_0_MAXn 2 #define GSI_V1_2_EE_n_GSI_HW_PARAM_0_USE_AXI_M_BMSK 0x80000000 #define GSI_V1_2_EE_n_GSI_HW_PARAM_0_USE_AXI_M_SHFT 0x1f #define GSI_V1_2_EE_n_GSI_HW_PARAM_0_PERIPH_SEC_GRP_BMSK 0x7c000000 @@ -1438,98 +745,6 @@ #define GSI_V1_2_EE_n_GSI_HW_PARAM_0_GSI_EV_CH_NUM_BMSK 0xff #define GSI_V1_2_EE_n_GSI_HW_PARAM_0_GSI_EV_CH_NUM_SHFT 0x0 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0001f040 + 0x4000 * (n)) -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_RMSK 0xffffffff -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_MAXn 2 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_BLK_INT_ACCESS_REGION_2_EN_BMSK \ - 0x80000000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_BLK_INT_ACCESS_REGION_2_EN_SHFT 0x1f -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_BLK_INT_ACCESS_REGION_1_EN_BMSK \ - 0x40000000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_BLK_INT_ACCESS_REGION_1_EN_SHFT 0x1e -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_SIMPLE_RD_WR_BMSK 0x20000000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_SIMPLE_RD_WR_SHFT 0x1d -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_ESCAPE_BUF_ONLY_BMSK 0x10000000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_ESCAPE_BUF_ONLY_SHFT 0x1c -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_USE_UC_IF_BMSK 0x8000000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_USE_UC_IF_SHFT 0x1b -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_USE_DB_ENG_BMSK 0x4000000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_USE_DB_ENG_SHFT 0x1a -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_USE_BP_MTRIX_BMSK 0x2000000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_USE_BP_MTRIX_SHFT 0x19 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_NUM_TIMERS_BMSK 0x1f00000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_NUM_TIMERS_SHFT 0x14 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_USE_XPU_BMSK 0x80000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_USE_XPU_SHFT 0x13 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_QRIB_EN_BMSK 0x40000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_QRIB_EN_SHFT 0x12 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_VMIDACR_EN_BMSK 0x20000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_VMIDACR_EN_SHFT 0x11 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_SEC_EN_BMSK 0x10000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_SEC_EN_SHFT 0x10 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_NONSEC_EN_BMSK 0xf000 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_NONSEC_EN_SHFT 0xc -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_NUM_QAD_BMSK 0xf00 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_NUM_QAD_SHFT 0x8 -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_M_DATA_BUS_W_BMSK 0xff -#define GSI_V1_2_EE_n_GSI_HW_PARAM_1_GSI_M_DATA_BUS_W_SHFT 0x0 - -/* v1.3 */ -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0001f038 + 0x4000 * (n)) -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_RMSK 0xffffffff -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_MAXn 2 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_USE_AXI_M_BMSK 0x80000000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_USE_AXI_M_SHFT 0x1f -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_PERIPH_SEC_GRP_BMSK 0x7c000000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_PERIPH_SEC_GRP_SHFT 0x1a -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_PERIPH_CONF_ADDR_BUS_W_BMSK 0x3e00000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_PERIPH_CONF_ADDR_BUS_W_SHFT 0x15 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_NUM_EES_BMSK 0x1f0000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_NUM_EES_SHFT 0x10 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_GSI_CH_NUM_BMSK 0xff00 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_GSI_CH_NUM_SHFT 0x8 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_GSI_EV_CH_NUM_BMSK 0xff -#define GSI_V1_3_EE_n_GSI_HW_PARAM_0_GSI_EV_CH_NUM_SHFT 0x0 - -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0001f03c + 0x4000 * (n)) -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_RMSK 0xffffffff -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_MAXn 2 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_BLK_INT_ACCESS_REGION_2_EN_BMSK \ - 0x80000000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_BLK_INT_ACCESS_REGION_2_EN_SHFT 0x1f -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_BLK_INT_ACCESS_REGION_1_EN_BMSK \ - 0x40000000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_BLK_INT_ACCESS_REGION_1_EN_SHFT 0x1e -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_SIMPLE_RD_WR_BMSK 0x20000000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_SIMPLE_RD_WR_SHFT 0x1d -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_ESCAPE_BUF_ONLY_BMSK 0x10000000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_ESCAPE_BUF_ONLY_SHFT 0x1c -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_USE_UC_IF_BMSK 0x8000000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_USE_UC_IF_SHFT 0x1b -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_USE_DB_ENG_BMSK 0x4000000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_USE_DB_ENG_SHFT 0x1a -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_USE_BP_MTRIX_BMSK 0x2000000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_USE_BP_MTRIX_SHFT 0x19 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_NUM_TIMERS_BMSK 0x1f00000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_NUM_TIMERS_SHFT 0x14 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_USE_XPU_BMSK 0x80000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_USE_XPU_SHFT 0x13 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_QRIB_EN_BMSK 0x40000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_QRIB_EN_SHFT 0x12 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_VMIDACR_EN_BMSK 0x20000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_VMIDACR_EN_SHFT 0x11 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_SEC_EN_BMSK 0x10000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_SEC_EN_SHFT 0x10 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_NONSEC_EN_BMSK 0xf000 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_NONSEC_EN_SHFT 0xc -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_NUM_QAD_BMSK 0xf00 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_NUM_QAD_SHFT 0x8 -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_M_DATA_BUS_W_BMSK 0xff -#define GSI_V1_3_EE_n_GSI_HW_PARAM_1_GSI_M_DATA_BUS_W_SHFT 0x0 - #define GSI_V1_3_EE_n_GSI_HW_PARAM_2_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f040 + 0x4000 * (n)) #define GSI_V1_3_EE_n_GSI_HW_PARAM_2_RMSK 0x7fff @@ -1547,7 +762,6 @@ #define GSI_V1_3_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_ONE_KB_FVAL 0x0 #define GSI_V1_3_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_TWO_KB_FVAL 0x1 -/* v2.0 */ #define GSI_V2_0_EE_n_GSI_HW_PARAM_2_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f040 + 0x4000 * (n)) #define GSI_V2_0_EE_n_GSI_HW_PARAM_2_RMSK 0x7fff @@ -1575,7 +789,6 @@ #define GSI_V2_0_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_TWO_N_HALF_KB_FVAL 0x2 #define GSI_V2_0_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_THREE_KB_FVAL 0x3 -/* v2.2 */ #define GSI_V2_2_EE_n_GSI_HW_PARAM_2_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f040 + 0x4000 * (n)) #define GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_BMSK 0x8000 @@ -1607,10 +820,41 @@ #define GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_TWO_N_HALF_KB_FVAL 0x2 #define GSI_V2_2_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_THREE_KB_FVAL 0x3 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_OFFS(n) \ + (GSI_GSI_REG_BASE_OFFS + 0x00012040 + 0x4000 * (n)) +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_BMSK 0x8000 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_USE_INTER_EE_SHFT 0xf +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_BMSK 0x4000 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_USE_RD_WR_ENG_SHFT 0xE +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_RMSK 0x7fff +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_MAXn 2 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_IOVEC_BMSK 0x38000000 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_IOVEC_SHFT 0x1b +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_SDMA_MAX_BURST_BMSK 0x7F80000 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_SDMA_MAX_BURST_SHFT 0x13 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_INT_BMSK 0x70000 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_SDMA_N_INT_SHFT 0x10 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_USE_SDMA_BMSK 0x8000 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_USE_SDMA_SHFT 0xf +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_CH_FULL_LOGIC_BMSK 0x4000 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_CH_FULL_LOGIC_SHFT 0xe +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_CH_PEND_TRANSLATE_BMSK 0x2000 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_CH_PEND_TRANSLATE_SHFT 0xd +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_BMSK 0x1f00 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_NUM_EV_PER_EE_SHFT 0x8 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_BMSK 0xf8 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_NUM_CH_PER_EE_SHFT 0x3 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_BMSK 0x7 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_SHFT 0x0 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_ONE_KB_FVAL 0x0 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_TWO_KB_FVAL 0x1 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_TWO_N_HALF_KB_FVAL 0x2 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_THREE_KB_FVAL 0x3 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_THREE_N_HALF_KB_FVAL 0x4 +#define GSI_V2_5_EE_n_GSI_HW_PARAM_2_GSI_IRAM_SIZE_FOUR_KB_FVAL 0x5 + #define GSI_EE_n_GSI_SW_VERSION_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f044 + 0x4000 * (n)) -#define GSI_EE_n_GSI_SW_VERSION_RMSK 0xffffffff -#define GSI_EE_n_GSI_SW_VERSION_MAXn 3 #define GSI_EE_n_GSI_SW_VERSION_MAJOR_BMSK 0xf0000000 #define GSI_EE_n_GSI_SW_VERSION_MAJOR_SHFT 0x1c #define GSI_EE_n_GSI_SW_VERSION_MINOR_BMSK 0xfff0000 @@ -1618,17 +862,8 @@ #define GSI_EE_n_GSI_SW_VERSION_STEP_BMSK 0xffff #define GSI_EE_n_GSI_SW_VERSION_STEP_SHFT 0x0 -#define GSI_EE_n_GSI_MCS_CODE_VER_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0001f048 + 0x4000 * (n)) -#define GSI_EE_n_GSI_MCS_CODE_VER_RMSK 0xffffffff -#define GSI_EE_n_GSI_MCS_CODE_VER_MAXn 3 -#define GSI_EE_n_GSI_MCS_CODE_VER_VER_BMSK 0xffffffff -#define GSI_EE_n_GSI_MCS_CODE_VER_VER_SHFT 0x0 - #define GSI_EE_n_CNTXT_TYPE_IRQ_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f080 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_TYPE_IRQ_RMSK 0x7f -#define GSI_EE_n_CNTXT_TYPE_IRQ_MAXn 3 #define GSI_EE_n_CNTXT_TYPE_IRQ_GENERAL_BMSK 0x40 #define GSI_EE_n_CNTXT_TYPE_IRQ_GENERAL_SHFT 0x6 #define GSI_EE_n_CNTXT_TYPE_IRQ_INTER_EE_EV_CTRL_BMSK 0x20 @@ -1646,8 +881,6 @@ #define GSI_EE_n_CNTXT_TYPE_IRQ_MSK_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f088 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_TYPE_IRQ_MSK_RMSK 0x7f -#define GSI_EE_n_CNTXT_TYPE_IRQ_MSK_MAXn 3 #define GSI_EE_n_CNTXT_TYPE_IRQ_MSK_GENERAL_BMSK 0x40 #define GSI_EE_n_CNTXT_TYPE_IRQ_MSK_GENERAL_SHFT 0x6 #define GSI_EE_n_CNTXT_TYPE_IRQ_MSK_INTER_EE_EV_CTRL_BMSK 0x20 @@ -1665,74 +898,57 @@ #define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f090 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MAXn 3 #define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_GSI_CH_BIT_MAP_BMSK 0xffffffff #define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_GSI_CH_BIT_MAP_SHFT 0x0 #define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f094 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MAXn 3 #define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_EV_CH_BIT_MAP_BMSK 0xffffffff #define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_EV_CH_BIT_MAP_SHFT 0x0 #define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f098 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_MAXn 3 -#define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_GSI_CH_BIT_MAP_MSK_BMSK \ - 0xffffffff +#define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_GSI_CH_BIT_MAP_MSK_BMSK 0x1ffff +#define GSI_V2_5_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_GSI_CH_BIT_MAP_MSK_BMSK 0x7fffff #define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_GSI_CH_BIT_MAP_MSK_SHFT 0x0 +#define GSI_V2_5_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_GSI_CH_BIT_MAP_MSK_SHFT 0x0 #define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f09c + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_MAXn 3 -#define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_EV_CH_BIT_MAP_MSK_BMSK \ - 0xffffffff +#define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_EV_CH_BIT_MAP_MSK_BMSK 0xfff +#define GSI_V2_5_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_EV_CH_BIT_MAP_MSK_BMSK 0xfffff #define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_EV_CH_BIT_MAP_MSK_SHFT 0x0 +#define GSI_V2_5_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_EV_CH_BIT_MAP_MSK_SHFT 0x0 #define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f0a0 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_MAXn 3 #define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_GSI_CH_BIT_MAP_BMSK 0xffffffff #define GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_CLR_GSI_CH_BIT_MAP_SHFT 0x0 #define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f0a4 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR_MAXn 3 #define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_BMSK 0xffffffff #define GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_SHFT 0x0 #define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f0b0 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MAXn 3 #define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_EV_CH_BIT_MAP_BMSK 0xffffffff #define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_EV_CH_BIT_MAP_SHFT 0x0 #define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f0b8 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_MAXn 3 -#define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_EV_CH_BIT_MAP_MSK_BMSK \ - 0xffffffff +#define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_EV_CH_BIT_MAP_MSK_BMSK 0xfff +#define GSI_V2_5_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_EV_CH_BIT_MAP_MSK_BMSK 0xfffff #define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_EV_CH_BIT_MAP_MSK_SHFT 0x0 +#define GSI_V2_5_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_EV_CH_BIT_MAP_MSK_SHFT 0x0 #define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f0c0 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_MAXn 3 #define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_EV_CH_BIT_MAP_BMSK 0xffffffff #define GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_EV_CH_BIT_MAP_SHFT 0x0 #define GSI_EE_n_CNTXT_GLOB_IRQ_STTS_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f100 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_GLOB_IRQ_STTS_RMSK 0xf -#define GSI_EE_n_CNTXT_GLOB_IRQ_STTS_MAXn 3 #define GSI_EE_n_CNTXT_GLOB_IRQ_STTS_GP_INT3_BMSK 0x8 #define GSI_EE_n_CNTXT_GLOB_IRQ_STTS_GP_INT3_SHFT 0x3 #define GSI_EE_n_CNTXT_GLOB_IRQ_STTS_GP_INT2_BMSK 0x4 @@ -1744,8 +960,6 @@ #define GSI_EE_n_CNTXT_GLOB_IRQ_EN_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f108 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_GLOB_IRQ_EN_RMSK 0xf -#define GSI_EE_n_CNTXT_GLOB_IRQ_EN_MAXn 3 #define GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT3_BMSK 0x8 #define GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT3_SHFT 0x3 #define GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT2_BMSK 0x4 @@ -1757,8 +971,6 @@ #define GSI_EE_n_CNTXT_GLOB_IRQ_CLR_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f110 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_GLOB_IRQ_CLR_RMSK 0xf -#define GSI_EE_n_CNTXT_GLOB_IRQ_CLR_MAXn 3 #define GSI_EE_n_CNTXT_GLOB_IRQ_CLR_GP_INT3_BMSK 0x8 #define GSI_EE_n_CNTXT_GLOB_IRQ_CLR_GP_INT3_SHFT 0x3 #define GSI_EE_n_CNTXT_GLOB_IRQ_CLR_GP_INT2_BMSK 0x4 @@ -1770,8 +982,6 @@ #define GSI_EE_n_CNTXT_GSI_IRQ_STTS_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f118 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_GSI_IRQ_STTS_RMSK 0xf -#define GSI_EE_n_CNTXT_GSI_IRQ_STTS_MAXn 3 #define GSI_EE_n_CNTXT_GSI_IRQ_STTS_GSI_MCS_STACK_OVRFLOW_BMSK 0x8 #define GSI_EE_n_CNTXT_GSI_IRQ_STTS_GSI_MCS_STACK_OVRFLOW_SHFT 0x3 #define GSI_EE_n_CNTXT_GSI_IRQ_STTS_GSI_CMD_FIFO_OVRFLOW_BMSK 0x4 @@ -1783,8 +993,6 @@ #define GSI_EE_n_CNTXT_GSI_IRQ_EN_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f120 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_GSI_IRQ_EN_RMSK 0xf -#define GSI_EE_n_CNTXT_GSI_IRQ_EN_MAXn 3 #define GSI_EE_n_CNTXT_GSI_IRQ_EN_GSI_MCS_STACK_OVRFLOW_BMSK 0x8 #define GSI_EE_n_CNTXT_GSI_IRQ_EN_GSI_MCS_STACK_OVRFLOW_SHFT 0x3 #define GSI_EE_n_CNTXT_GSI_IRQ_EN_GSI_CMD_FIFO_OVRFLOW_BMSK 0x4 @@ -1796,8 +1004,6 @@ #define GSI_EE_n_CNTXT_GSI_IRQ_CLR_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f128 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_GSI_IRQ_CLR_RMSK 0xf -#define GSI_EE_n_CNTXT_GSI_IRQ_CLR_MAXn 3 #define GSI_EE_n_CNTXT_GSI_IRQ_CLR_GSI_MCS_STACK_OVRFLOW_BMSK 0x8 #define GSI_EE_n_CNTXT_GSI_IRQ_CLR_GSI_MCS_STACK_OVRFLOW_SHFT 0x3 #define GSI_EE_n_CNTXT_GSI_IRQ_CLR_GSI_CMD_FIFO_OVRFLOW_BMSK 0x4 @@ -1809,128 +1015,49 @@ #define GSI_EE_n_CNTXT_INTSET_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f180 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_INTSET_RMSK 0x1 -#define GSI_EE_n_CNTXT_INTSET_MAXn 3 #define GSI_EE_n_CNTXT_INTSET_INTYPE_BMSK 0x1 #define GSI_EE_n_CNTXT_INTSET_INTYPE_SHFT 0x0 -#define GSI_EE_n_CNTXT_MSI_BASE_LSB_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0001f188 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_MSI_BASE_LSB_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_MSI_BASE_LSB_MAXn 3 -#define GSI_EE_n_CNTXT_MSI_BASE_LSB_MSI_ADDR_LSB_BMSK 0xffffffff -#define GSI_EE_n_CNTXT_MSI_BASE_LSB_MSI_ADDR_LSB_SHFT 0x0 - -#define GSI_EE_n_CNTXT_MSI_BASE_MSB_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0001f18c + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_MSI_BASE_MSB_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_MSI_BASE_MSB_MAXn 3 -#define GSI_EE_n_CNTXT_MSI_BASE_MSB_MSI_ADDR_MSB_BMSK 0xffffffff -#define GSI_EE_n_CNTXT_MSI_BASE_MSB_MSI_ADDR_MSB_SHFT 0x0 - -#define GSI_EE_n_CNTXT_INT_VEC_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0001f190 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_INT_VEC_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_INT_VEC_MAXn 3 -#define GSI_EE_n_CNTXT_INT_VEC_INT_VEC_BMSK 0xffffffff -#define GSI_EE_n_CNTXT_INT_VEC_INT_VEC_SHFT 0x0 - #define GSI_EE_n_ERROR_LOG_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f200 + 0x4000 * (n)) -#define GSI_EE_n_ERROR_LOG_RMSK 0xffffffff -#define GSI_EE_n_ERROR_LOG_MAXn 3 #define GSI_EE_n_ERROR_LOG_TODO_BMSK 0xffffffff #define GSI_EE_n_ERROR_LOG_TODO_SHFT 0x0 #define GSI_EE_n_ERROR_LOG_CLR_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f210 + 0x4000 * (n)) -#define GSI_EE_n_ERROR_LOG_CLR_RMSK 0xffffffff -#define GSI_EE_n_ERROR_LOG_CLR_MAXn 3 #define GSI_EE_n_ERROR_LOG_CLR_TODO_BMSK 0xffffffff #define GSI_EE_n_ERROR_LOG_CLR_TODO_SHFT 0x0 #define GSI_EE_n_CNTXT_SCRATCH_0_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0001f400 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SCRATCH_0_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SCRATCH_0_MAXn 3 #define GSI_EE_n_CNTXT_SCRATCH_0_SCRATCH_BMSK 0xffffffff #define GSI_EE_n_CNTXT_SCRATCH_0_SCRATCH_SHFT 0x0 -#define GSI_EE_n_CNTXT_SCRATCH_1_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0001f404 + 0x4000 * (n)) -#define GSI_EE_n_CNTXT_SCRATCH_1_RMSK 0xffffffff -#define GSI_EE_n_CNTXT_SCRATCH_1_MAXn 3 -#define GSI_EE_n_CNTXT_SCRATCH_1_SCRATCH_BMSK 0xffffffff -#define GSI_EE_n_CNTXT_SCRATCH_1_SCRATCH_SHFT 0x0 - -#define GSI_INTER_EE_n_ORIGINATOR_EE_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0000c000 + 0x1000 * (n)) -#define GSI_INTER_EE_n_ORIGINATOR_EE_RMSK 0xf -#define GSI_INTER_EE_n_ORIGINATOR_EE_MAXn 3 -#define GSI_INTER_EE_n_ORIGINATOR_EE_EE_NUMBER_BMSK 0xf -#define GSI_INTER_EE_n_ORIGINATOR_EE_EE_NUMBER_SHFT 0x0 - -#define GSI_INTER_EE_n_GSI_CH_CMD_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0000c008 + 0x1000 * (n)) -#define GSI_INTER_EE_n_GSI_CH_CMD_RMSK 0xff0000ff -#define GSI_INTER_EE_n_GSI_CH_CMD_MAXn 3 -#define GSI_INTER_EE_n_GSI_CH_CMD_OPCODE_BMSK 0xff000000 -#define GSI_INTER_EE_n_GSI_CH_CMD_OPCODE_SHFT 0x18 -#define GSI_INTER_EE_n_GSI_CH_CMD_CHID_BMSK 0xff -#define GSI_INTER_EE_n_GSI_CH_CMD_CHID_SHFT 0x0 - -#define GSI_INTER_EE_n_EV_CH_CMD_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0000c010 + 0x1000 * (n)) -#define GSI_INTER_EE_n_EV_CH_CMD_RMSK 0xff0000ff -#define GSI_INTER_EE_n_EV_CH_CMD_MAXn 3 -#define GSI_INTER_EE_n_EV_CH_CMD_OPCODE_BMSK 0xff000000 -#define GSI_INTER_EE_n_EV_CH_CMD_OPCODE_SHFT 0x18 -#define GSI_INTER_EE_n_EV_CH_CMD_CHID_BMSK 0xff -#define GSI_INTER_EE_n_EV_CH_CMD_CHID_SHFT 0x0 - #define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0000c018 + 0x1000 * (n)) -#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_RMSK 0xffffffff -#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_MAXn 3 #define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_GSI_CH_BIT_MAP_BMSK 0xffffffff #define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_GSI_CH_BIT_MAP_SHFT 0x0 #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0000c01c + 0x1000 * (n)) -#define GSI_INTER_EE_n_SRC_EV_CH_IRQ_RMSK 0xffffffff -#define GSI_INTER_EE_n_SRC_EV_CH_IRQ_MAXn 3 #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_EV_CH_BIT_MAP_BMSK 0xffffffff #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_EV_CH_BIT_MAP_SHFT 0x0 -#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_MSK_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0000c020 + 0x1000 * (n)) -#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_MSK_RMSK 0xffffffff -#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_MSK_MAXn 3 -#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_MSK_GSI_CH_BIT_MAP_MSK_BMSK \ - 0x00003fff -#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_MSK_GSI_CH_BIT_MAP_MSK_SHFT 0x0 - -#define GSI_INTER_EE_n_SRC_EV_CH_IRQ_MSK_OFFS(n) \ - (GSI_GSI_REG_BASE_OFFS + 0x0000c024 + 0x1000 * (n)) -#define GSI_INTER_EE_n_SRC_EV_CH_IRQ_MSK_RMSK 0xffffffff -#define GSI_INTER_EE_n_SRC_EV_CH_IRQ_MSK_MAXn 3 -#define GSI_INTER_EE_n_SRC_EV_CH_IRQ_MSK_EV_CH_BIT_MAP_MSK_BMSK \ - 0x000003ff -#define GSI_INTER_EE_n_SRC_EV_CH_IRQ_MSK_EV_CH_BIT_MAP_MSK_SHFT 0x0 - #define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_CLR_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0000c028 + 0x1000 * (n)) -#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_CLR_RMSK 0xffffffff -#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_CLR_MAXn 3 #define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_CLR_GSI_CH_BIT_MAP_BMSK 0xffffffff #define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_CLR_GSI_CH_BIT_MAP_SHFT 0x0 #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_OFFS(n) \ (GSI_GSI_REG_BASE_OFFS + 0x0000c02c + 0x1000 * (n)) -#define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_RMSK 0xffffffff -#define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_MAXn 3 #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_BMSK 0xffffffff #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_SHFT 0x0 +#define GSI_V2_5_GSI_MAP_EE_n_CH_k_VP_TABLE_OFFS(k, n) \ + (GSI_GSI_REG_BASE_OFFS + 0x00003800 + 0x80 * (n) + 0x4 * (k)) +#define GSI_V2_5_GSI_MAP_EE_n_CH_k_VP_TABLE_VALID_BMSK 0x20 +#define GSI_V2_5_GSI_MAP_EE_n_CH_k_VP_TABLE_VALID_SHFT 0x5 +#define GSI_V2_5_GSI_MAP_EE_n_CH_k_VP_TABLE_PHY_CH_BMSK 0x1f +#define GSI_V2_5_GSI_MAP_EE_n_CH_k_VP_TABLE_PHY_CH_SHFT 0x0 #endif /* __GSI_REG_H__ */ -- GitLab From bf77f68397dcc142ec287f0e86f273603ea5f276 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Tue, 26 Jun 2018 13:03:30 +0530 Subject: [PATCH 0848/1299] defconfig: arm/arm64: enable memory debug configs on qcs405 Enable DEBUG_PAGEALLOC, SLUB_DEBUG and PAGE_POISON related config options that are used for debugging the memory allocation issues. Change-Id: Ic4b556c5bd5661af943173f0da32413e3e5967f3 Signed-off-by: Charan Teja Reddy --- arch/arm/configs/vendor/qcs405_defconfig | 5 +++++ arch/arm64/configs/vendor/qcs405_defconfig | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index fac263b18316..a116a1da4435 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -449,12 +449,17 @@ CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_INFO=y CONFIG_PAGE_OWNER=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_PAGEALLOC=y +CONFIG_SLUB_DEBUG_PANIC_ON=y +CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y +CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y CONFIG_DEBUG_OBJECTS=y CONFIG_DEBUG_OBJECTS_FREE=y CONFIG_DEBUG_OBJECTS_TIMERS=y CONFIG_DEBUG_OBJECTS_WORK=y CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_SLUB_DEBUG_ON=y CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index 5cf358ccdab1..1d2ac09021db 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -450,12 +450,18 @@ CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_INFO=y CONFIG_PAGE_OWNER=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_PAGEALLOC=y +CONFIG_SLUB_DEBUG_PANIC_ON=y +CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y +CONFIG_PAGE_POISONING=y +CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y CONFIG_DEBUG_OBJECTS=y CONFIG_DEBUG_OBJECTS_FREE=y CONFIG_DEBUG_OBJECTS_TIMERS=y CONFIG_DEBUG_OBJECTS_WORK=y CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_SLUB_DEBUG_ON=y CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y -- GitLab From d5ad2c42e349f16dbddef4d0ce6fad443b872c60 Mon Sep 17 00:00:00 2001 From: Saranya Chidura Date: Mon, 25 Jun 2018 12:07:48 +0530 Subject: [PATCH 0849/1299] ARM: dts: msm: add DCC clocks for qcs405 Add clocks dt entry of DCC for QCS405. Change-Id: I2f45b8b77c0316b5a20c93ed7afce54904fb6dff Signed-off-by: Saranya Chidura --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index ee07feb6e9aa..68f0a57f7b02 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -343,6 +343,10 @@ compatible = "qcom,dcc-v2"; reg = <0x000b2000 0x1000>, <0x000bf800 0x800>; + + clocks = <&clock_gcc GCC_DCC_CLK>; + clock-names = "dcc_clk"; + reg-names = "dcc-base", "dcc-ram-base"; dcc-ram-offset = <0x400>; }; -- GitLab From 482bb1b850aca4c0203a77a91cf25653db76a2b1 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Wed, 6 Jun 2018 14:49:26 +0530 Subject: [PATCH 0850/1299] platform: qpnp-revid: Add REVID support for SM6150 Add PMIC subtype and revid details for SM6150 and PM6150L. Change-Id: Ic8f6e2fffa84a8be36e4553fbf103675d81cbbec Signed-off-by: Kiran Gunda --- drivers/platform/msm/qpnp-revid.c | 1 + include/linux/qpnp/qpnp-revid.h | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/platform/msm/qpnp-revid.c b/drivers/platform/msm/qpnp-revid.c index 90586e5b5427..34231a943af4 100644 --- a/drivers/platform/msm/qpnp-revid.c +++ b/drivers/platform/msm/qpnp-revid.c @@ -64,6 +64,7 @@ static const char *const pmic_names[] = { [PM8150_SUBTYPE] = "PM8150", [PM8150B_SUBTYPE] = "PM8150B", [PM8150L_SUBTYPE] = "PM8150L", + [PM6150_SUBTYPE] = "PM6150", }; struct revid_chip { diff --git a/include/linux/qpnp/qpnp-revid.h b/include/linux/qpnp/qpnp-revid.h index f998a8c81214..8ab6e3336a5b 100644 --- a/include/linux/qpnp/qpnp-revid.h +++ b/include/linux/qpnp/qpnp-revid.h @@ -186,6 +186,9 @@ #define PM8150L_SUBTYPE 0x1F #define PM8150B_SUBTYPE 0x20 +#define PM6150_SUBTYPE 0x28 +#define PM6150L_SUBTYPE 0x1F + /* PMI632 */ #define PMI632_SUBTYPE 0x25 @@ -255,6 +258,21 @@ #define PM8150L_V3P0_REV3 0x00 #define PM8150L_V3P0_REV4 0x03 +#define PM6150_V1P0_REV1 0x00 +#define PM6150_V1P0_REV2 0x00 +#define PM6150_V1P0_REV3 0x00 +#define PM6150_V1P0_REV4 0x01 + +#define PM6150_V1P1_REV1 0x00 +#define PM6150_V1P1_REV2 0x00 +#define PM6150_V1P1_REV3 0x01 +#define PM6150_V1P1_REV4 0x01 + +#define PM6150_V2P0_REV1 0x00 +#define PM6150_V2P0_REV2 0x00 +#define PM6150_V2P0_REV3 0x00 +#define PM6150_V2P0_REV4 0x02 + /* PMI8998 FAB_ID */ #define PMI8998_FAB_ID_SMIC 0x11 #define PMI8998_FAB_ID_GF 0x30 -- GitLab From e04252329ace2f8b2a7ba0499a314c83f7d1c099 Mon Sep 17 00:00:00 2001 From: Umang Agrawal Date: Tue, 26 Jun 2018 11:28:44 +0530 Subject: [PATCH 0851/1299] ARM: dts: msm: Fix slave id for pm6150 charger Change slave id of pm6150 charger from 2 to 0 Change-Id: If334dab1886934afa7e19e1877dab43eb1201b38 Signed-off-by: Ashay Jaiswal --- arch/arm64/boot/dts/qcom/pm6150.dtsi | 108 +++++++++++++-------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/pm6150.dtsi b/arch/arm64/boot/dts/qcom/pm6150.dtsi index 1b9020eebd78..ed53778679a6 100644 --- a/arch/arm64/boot/dts/qcom/pm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/pm6150.dtsi @@ -69,14 +69,14 @@ qcom,chgr@1000 { reg = <0x1000 0x100>; interrupts = - <0x2 0x10 0x0 IRQ_TYPE_EDGE_RISING>, - <0x2 0x10 0x1 IRQ_TYPE_EDGE_RISING>, - <0x2 0x10 0x2 IRQ_TYPE_EDGE_RISING>, - <0x2 0x10 0x3 IRQ_TYPE_EDGE_RISING>, - <0x2 0x10 0x4 IRQ_TYPE_EDGE_RISING>, - <0x2 0x10 0x5 IRQ_TYPE_EDGE_RISING>, - <0x2 0x10 0x6 IRQ_TYPE_EDGE_RISING>, - <0x2 0x10 0x7 IRQ_TYPE_EDGE_RISING>; + <0x0 0x10 0x0 IRQ_TYPE_EDGE_RISING>, + <0x0 0x10 0x1 IRQ_TYPE_EDGE_RISING>, + <0x0 0x10 0x2 IRQ_TYPE_EDGE_RISING>, + <0x0 0x10 0x3 IRQ_TYPE_EDGE_RISING>, + <0x0 0x10 0x4 IRQ_TYPE_EDGE_RISING>, + <0x0 0x10 0x5 IRQ_TYPE_EDGE_RISING>, + <0x0 0x10 0x6 IRQ_TYPE_EDGE_RISING>, + <0x0 0x10 0x7 IRQ_TYPE_EDGE_RISING>; interrupt-names = "chgr-error", "chg-state-change", @@ -91,14 +91,14 @@ qcom,dcdc@1100 { reg = <0x1100 0x100>; interrupts = - <0x2 0x11 0x0 IRQ_TYPE_EDGE_RISING>, - <0x2 0x11 0x1 IRQ_TYPE_EDGE_RISING>, - <0x2 0x11 0x2 IRQ_TYPE_EDGE_RISING>, - <0x2 0x11 0x3 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x11 0x4 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x11 0x5 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x11 0x6 IRQ_TYPE_EDGE_RISING>, - <0x2 0x11 0x7 IRQ_TYPE_EDGE_BOTH>; + <0x0 0x11 0x0 IRQ_TYPE_EDGE_RISING>, + <0x0 0x11 0x1 IRQ_TYPE_EDGE_RISING>, + <0x0 0x11 0x2 IRQ_TYPE_EDGE_RISING>, + <0x0 0x11 0x3 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x11 0x4 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x11 0x5 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x11 0x6 IRQ_TYPE_EDGE_RISING>, + <0x0 0x11 0x7 IRQ_TYPE_EDGE_BOTH>; interrupt-names = "otg-fail", "otg-oc-disable-sw", @@ -113,13 +113,13 @@ qcom,batif@1200 { reg = <0x1200 0x100>; interrupts = - <0x2 0x12 0x0 IRQ_TYPE_EDGE_RISING>, - <0x2 0x12 0x2 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x12 0x3 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x12 0x4 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x12 0x5 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x12 0x6 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x12 0x7 IRQ_TYPE_EDGE_BOTH>; + <0x0 0x12 0x0 IRQ_TYPE_EDGE_RISING>, + <0x0 0x12 0x2 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x12 0x3 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x12 0x4 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x12 0x5 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x12 0x6 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x12 0x7 IRQ_TYPE_EDGE_BOTH>; interrupt-names = "bat-temp", "bat-ov", @@ -133,14 +133,14 @@ qcom,usb@1300 { reg = <0x1300 0x100>; interrupts = - <0x2 0x13 0x0 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x13 0x1 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x13 0x2 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x13 0x3 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x13 0x5 IRQ_TYPE_EDGE_RISING>, - <0x2 0x13 0x6 IRQ_TYPE_EDGE_RISING>, - <0x2 0x13 0x7 IRQ_TYPE_EDGE_RISING>; + <0x0 0x13 0x0 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x13 0x1 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x13 0x2 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x13 0x3 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x13 0x4 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x13 0x5 IRQ_TYPE_EDGE_RISING>, + <0x0 0x13 0x6 IRQ_TYPE_EDGE_RISING>, + <0x0 0x13 0x7 IRQ_TYPE_EDGE_RISING>; interrupt-names = "usbin-collapse", "usbin-vashdn", @@ -155,13 +155,13 @@ qcom,dc@1400 { reg = <0x1400 0x100>; interrupts = - <0x2 0x14 0x1 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x14 0x2 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x14 0x3 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x14 0x4 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x14 0x5 IRQ_TYPE_EDGE_RISING>, - <0x2 0x14 0x6 IRQ_TYPE_EDGE_RISING>, - <0x2 0x14 0x7 IRQ_TYPE_EDGE_RISING>; + <0x0 0x14 0x1 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x14 0x2 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x14 0x3 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x14 0x4 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x14 0x5 IRQ_TYPE_EDGE_RISING>, + <0x0 0x14 0x6 IRQ_TYPE_EDGE_RISING>, + <0x0 0x14 0x7 IRQ_TYPE_EDGE_RISING>; interrupt-names = "dcin-vashdn", "dcin-uv", @@ -175,14 +175,14 @@ qcom,typec@1500 { reg = <0x1500 0x100>; interrupts = - <0x2 0x15 0x0 IRQ_TYPE_EDGE_RISING>, - <0x2 0x15 0x1 IRQ_TYPE_LEVEL_HIGH>, - <0x2 0x15 0x2 IRQ_TYPE_EDGE_RISING>, - <0x2 0x15 0x3 IRQ_TYPE_LEVEL_HIGH>, - <0x2 0x15 0x4 IRQ_TYPE_EDGE_RISING>, - <0x2 0x15 0x5 IRQ_TYPE_EDGE_RISING>, - <0x2 0x15 0x6 IRQ_TYPE_LEVEL_HIGH>, - <0x2 0x15 0x7 IRQ_TYPE_EDGE_RISING>; + <0x0 0x15 0x0 IRQ_TYPE_EDGE_RISING>, + <0x0 0x15 0x1 IRQ_TYPE_LEVEL_HIGH>, + <0x0 0x15 0x2 IRQ_TYPE_EDGE_RISING>, + <0x0 0x15 0x3 IRQ_TYPE_LEVEL_HIGH>, + <0x0 0x15 0x4 IRQ_TYPE_EDGE_RISING>, + <0x0 0x15 0x5 IRQ_TYPE_EDGE_RISING>, + <0x0 0x15 0x6 IRQ_TYPE_LEVEL_HIGH>, + <0x0 0x15 0x7 IRQ_TYPE_EDGE_RISING>; interrupt-names = "typec-or-rid-detect-change", "typec-vpd-detect", @@ -197,14 +197,14 @@ qcom,misc@1600 { reg = <0x1600 0x100>; interrupts = - <0x2 0x16 0x0 IRQ_TYPE_EDGE_RISING>, - <0x2 0x16 0x1 IRQ_TYPE_EDGE_RISING>, - <0x2 0x16 0x2 IRQ_TYPE_EDGE_RISING>, - <0x2 0x16 0x3 IRQ_TYPE_EDGE_RISING>, - <0x2 0x16 0x4 IRQ_TYPE_LEVEL_HIGH>, - <0x2 0x16 0x5 IRQ_TYPE_EDGE_RISING>, - <0x2 0x16 0x6 IRQ_TYPE_EDGE_RISING>, - <0x2 0x16 0x7 IRQ_TYPE_EDGE_RISING>; + <0x0 0x16 0x0 IRQ_TYPE_EDGE_RISING>, + <0x0 0x16 0x1 IRQ_TYPE_EDGE_RISING>, + <0x0 0x16 0x2 IRQ_TYPE_EDGE_RISING>, + <0x0 0x16 0x3 IRQ_TYPE_EDGE_RISING>, + <0x0 0x16 0x4 IRQ_TYPE_LEVEL_HIGH>, + <0x0 0x16 0x5 IRQ_TYPE_EDGE_RISING>, + <0x0 0x16 0x6 IRQ_TYPE_EDGE_RISING>, + <0x0 0x16 0x7 IRQ_TYPE_EDGE_RISING>; interrupt-names = "wdog-snarl", "wdog-bark", -- GitLab From 4e6c467b5bbd1f6836623393391d4773f792ddc4 Mon Sep 17 00:00:00 2001 From: Sayali Lokhande Date: Tue, 26 Jun 2018 16:00:53 +0530 Subject: [PATCH 0852/1299] ARM: config: Enable Command Queue support for qcs405 Enable CONFIG_MMC_CQ_HCI to support command queue on qcs405 platform. Change-Id: I586f799c31016672c17a82ecfa3eca9ec3273a94 Signed-off-by: Sayali Lokhande --- arch/arm/configs/vendor/qcs405_defconfig | 1 + arch/arm64/configs/vendor/qcs405_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index fac263b18316..0e9a70df5aa9 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -364,6 +364,7 @@ CONFIG_MMC_CLKGATE=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_CQ_HCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_TRIGGERS=y diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index 5cf358ccdab1..b6f22db727cd 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -365,6 +365,7 @@ CONFIG_MMC_CLKGATE=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_CQ_HCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_TRIGGERS=y -- GitLab From 0a3809bbd87ec766f02510bbf095d62cfd71afe5 Mon Sep 17 00:00:00 2001 From: Dedy Lansky Date: Tue, 26 Jun 2018 13:38:02 +0300 Subject: [PATCH 0853/1299] cfg80211: fix rcu in cfg80211_unregister_wdev Callers of cfg80211_unregister_wdev can free the wdev object immediately after this function returns. This may crash the kernel because this wdev object is still in use by other threads. Add synchronize_rcu() after list_del_rcu to make sure wdev object can be safely freed. Change-Id: Id73921888bed032312b133e94fbfe06537e06b92 Signed-off-by: Dedy Lansky Signed-off-by: Johannes Berg Git-commit: bf2b61a6838f19cbc33f6732715012c483fa3795 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git --- net/wireless/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/wireless/core.c b/net/wireless/core.c index 45cbade9ad68..3ff638ce14e9 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -1008,6 +1008,7 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE); list_del_rcu(&wdev->list); + synchronize_rcu(); rdev->devlist_generation++; switch (wdev->iftype) { -- GitLab From 9fdbf85e6afb6d7738be188fc3d9f21c4728b207 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Wed, 17 Jan 2018 19:59:50 +0530 Subject: [PATCH 0854/1299] msm: ADSPRPC: Enable Audio PDR support Register for ADSP Audio PDR notifications and handle Audio PDR by notifying all the Audio static PD clients. change-Id: I97f3d2ebb204a276c4266c0d300ff96935e3082e Acked-by: Himateja Reddy Signed-off-by: Tharun Kumar Merugu --- .../devicetree/bindings/qdsp/msm-fastrpc.txt | 1 + drivers/char/adsprpc.c | 176 ++++++++++++++++++ 2 files changed, 177 insertions(+) diff --git a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt index e302bab4e0b9..5b1a1331c06f 100644 --- a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt +++ b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt @@ -15,6 +15,7 @@ Optional properties: - qcom,adsp-remoteheap-vmid: FastRPC remote heap VMID list - qcom,secure-context-bank : Bool indicating secure FastRPC context bank. - qcom,fastrpc-legacy-remote-heap : Bool indicating hypervisor is not supported. +- qcom,fastrpc-adsp-audio-pdr: Flag to enable ADSP Audio PDR Optional subnodes: - qcom,msm_fastrpc_compute_cb : Child nodes representing the compute context diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index e83a65ea45f6..5449a9148bba 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -61,6 +63,9 @@ #define VMID_ADSP_Q6 6 #define DEBUGFS_SIZE 1024 +#define AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME "audio_pdr_adsprpc" +#define AUDIO_PDR_ADSP_SERVICE_NAME "avs/audio" + #define RPC_TIMEOUT (5 * HZ) #define BALIGN 128 #define NUM_CHANNELS 4 /* adsp, mdsp, slpi, cdsp*/ @@ -112,6 +117,9 @@ (int64_t *)(perf_ptr + offset)\ : (int64_t *)NULL) : (int64_t *)NULL) +static int fastrpc_audio_pdr_notifier_cb(struct notifier_block *nb, + unsigned long code, + void *data); static struct dentry *debugfs_root; static struct dentry *debugfs_global_file; @@ -227,12 +235,23 @@ struct fastrpc_session_ctx { int used; }; +struct fastrpc_static_pd { + char *spdname; + struct notifier_block pdrnb; + struct notifier_block get_service_nb; + void *pdrhandle; + int pdrcount; + int prevpdrcount; + int ispdup; +}; + struct fastrpc_channel_ctx { char *name; char *subsys; struct rpmsg_device *chan; struct device *dev; struct fastrpc_session_ctx session[NUM_SESSIONS]; + struct fastrpc_static_pd spd[NUM_SESSIONS]; struct completion work; struct completion workport; struct notifier_block nb; @@ -331,6 +350,7 @@ struct fastrpc_file { int cid; int ssrcount; int pd; + char *spdname; int file_close; struct fastrpc_apps *apps; struct hlist_head perf; @@ -348,6 +368,14 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = { { .name = "adsprpc-smd", .subsys = "adsp", + .spd = { + { + .spdname = + AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME, + .pdrnb.notifier_call = + fastrpc_audio_pdr_notifier_cb, + } + }, }, { .name = "mdsprpc-smd", @@ -1150,6 +1178,21 @@ static void fastrpc_notify_drivers(struct fastrpc_apps *me, int cid) spin_unlock(&me->hlock); } + +static void fastrpc_notify_pdr_drivers(struct fastrpc_apps *me, char *spdname) +{ + struct fastrpc_file *fl; + struct hlist_node *n; + + spin_lock(&me->hlock); + hlist_for_each_entry_safe(fl, n, &me->drivers, hn) { + if (fl->spdname && !strcmp(spdname, fl->spdname)) + fastrpc_notify_users(fl); + } + spin_unlock(&me->hlock); + +} + static void context_list_ctor(struct fastrpc_ctx_lst *me) { INIT_HLIST_HEAD(&me->interrupted); @@ -1738,7 +1781,28 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, return err; } +static int fastrpc_get_adsp_session(char *name, int *session) +{ + struct fastrpc_apps *me = &gfa; + int err = 0, i; + + for (i = 0; i < NUM_SESSIONS; i++) { + if (!me->channel[0].spd[i].spdname) + continue; + if (!strcmp(name, me->channel[0].spd[i].spdname)) + break; + } + VERIFY(err, i < NUM_SESSIONS); + if (err) + goto bail; + *session = i; +bail: + return err; +} + +static int fastrpc_mmap_remove_pdr(struct fastrpc_file *fl); static int fastrpc_channel_open(struct fastrpc_file *fl); +static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl); static int fastrpc_init_process(struct fastrpc_file *fl, struct fastrpc_ioctl_init_attrs *uproc) { @@ -1878,6 +1942,12 @@ static int fastrpc_init_process(struct fastrpc_file *fl, inbuf.pgid = current->tgid; inbuf.namelen = init->filelen; inbuf.pageslen = 0; + + if (!strcmp(proc_name, "audiopd")) { + fl->spdname = AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME; + VERIFY(err, !fastrpc_mmap_remove_pdr(fl)); + } + if (!me->staticpd_flags && !(me->legacy_remote_heap)) { inbuf.pageslen = 1; mutex_lock(&fl->map_mutex); @@ -2202,6 +2272,33 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) return err; } +static int fastrpc_mmap_remove_pdr(struct fastrpc_file *fl) +{ + struct fastrpc_apps *me = &gfa; + int session = 0, err = 0; + + VERIFY(err, !fastrpc_get_adsp_session( + AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME, &session)); + if (err) + goto bail; + if (me->channel[fl->cid].spd[session].pdrcount != + me->channel[fl->cid].spd[session].prevpdrcount) { + if (fastrpc_mmap_remove_ssr(fl)) + pr_err("ADSPRPC: SSR: Failed to unmap remote heap\n"); + me->channel[fl->cid].spd[session].prevpdrcount = + me->channel[fl->cid].spd[session].pdrcount; + } + if (!me->channel[fl->cid].spd[session].ispdup) { + VERIFY(err, 0); + if (err) { + err = -ENOTCONN; + goto bail; + } + } +bail: + return err; +} + static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, size_t len, struct fastrpc_mmap **ppmap); @@ -3039,6 +3136,64 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb, return NOTIFY_DONE; } +static int fastrpc_audio_pdr_notifier_cb(struct notifier_block *pdrnb, + unsigned long code, + void *data) +{ + struct fastrpc_apps *me = &gfa; + struct fastrpc_static_pd *spd; + struct notif_data *notifdata = data; + + spd = container_of(pdrnb, struct fastrpc_static_pd, pdrnb); + if (code == SERVREG_NOTIF_SERVICE_STATE_DOWN_V01) { + mutex_lock(&me->smd_mutex); + spd->pdrcount++; + spd->ispdup = 0; + pr_info("ADSPRPC: Audio PDR notifier %d %s\n", + MAJOR(me->dev_no), spd->spdname); + mutex_unlock(&me->smd_mutex); + if (!strcmp(spd->spdname, + AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME)) + me->staticpd_flags = 0; + fastrpc_notify_pdr_drivers(me, spd->spdname); + } else if (code == SUBSYS_RAMDUMP_NOTIFICATION) { + if (me->channel[0].remoteheap_ramdump_dev && + notifdata->enable_ramdump) { + me->channel[0].ramdumpenabled = 1; + } + } else if (code == SERVREG_NOTIF_SERVICE_STATE_UP_V01) { + spd->ispdup = 1; + } + + return NOTIFY_DONE; +} + +static int fastrpc_get_service_location_notify(struct notifier_block *nb, + unsigned long opcode, void *data) +{ + struct fastrpc_static_pd *spd; + struct pd_qmi_client_data *pdr = data; + int curr_state = 0; + + spd = container_of(nb, struct fastrpc_static_pd, get_service_nb); + if (opcode == LOCATOR_DOWN) { + pr_err("ADSPRPC: Audio PD restart notifier locator down\n"); + return NOTIFY_DONE; + } + + if (pdr->total_domains == 1) { + spd->pdrhandle = service_notif_register_notifier( + pdr->domain_list[0].name, + pdr->domain_list[0].instance_id, + &spd->pdrnb, &curr_state); + if (IS_ERR(spd->pdrhandle)) + pr_err("ADSPRPC: Unable to register notifier\n"); + } else + pr_err("ADSPRPC: Service returned invalid domains\n"); + + return NOTIFY_DONE; +} + static const struct file_operations fops = { .open = fastrpc_device_open, .release = fastrpc_device_release, @@ -3207,6 +3362,7 @@ static int fastrpc_probe(struct platform_device *pdev) struct platform_device *ion_pdev; struct cma *cma; uint32_t val; + int ret = 0; if (of_device_is_compatible(dev->of_node, @@ -3264,6 +3420,26 @@ static int fastrpc_probe(struct platform_device *pdev) } me->legacy_remote_heap = of_property_read_bool(dev->of_node, "qcom,fastrpc-legacy-remote-heap"); + if (of_property_read_bool(dev->of_node, + "qcom,fastrpc-adsp-audio-pdr")) { + int session; + + VERIFY(err, !fastrpc_get_adsp_session( + AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME, &session)); + if (err) + goto spdbail; + me->channel[0].spd[session].get_service_nb.notifier_call = + fastrpc_get_service_location_notify; + ret = get_service_location( + AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME, + AUDIO_PDR_ADSP_SERVICE_NAME, + &me->channel[0].spd[session].get_service_nb); + if (ret) + pr_err("ADSPRPC: Get service location failed: %d\n", + ret); + } +spdbail: + err = 0; VERIFY(err, !of_platform_populate(pdev->dev.of_node, fastrpc_match_table, NULL, &pdev->dev)); -- GitLab From ff5d6f720f58e2c96ebd9547f36a916fccf01a85 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Tue, 26 Jun 2018 17:02:12 +0530 Subject: [PATCH 0855/1299] iommu/arm-smmu: fix issue by devm_free_irq on cb interrupt line Fix the issue caused by the devm_free_irq on a unfilled CB interrupt array by filling the cfg->irptndx at proper place. devm_free_irq+0x58/0x60 arm_smmu_destroy_domain_context+0xc4/0x188 arm_smmu_attach_dev+0xb00/0xb2c __iommu_attach_device+0x4c/0x110 __iommu_attach_group+0x54/0x74 iommu_attach_group+0x30/0x50 arm_iommu_attach_device+0x88/0x2f Change-Id: I50cb4206ab56d78809777543162edf68974fcc37 Signed-off-by: Charan Teja Reddy --- drivers/iommu/arm-smmu.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index d2629d41078a..4146ca5f435c 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1803,12 +1803,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, goto out_unlock; cfg->cbndx = ret; - if (smmu->version < ARM_SMMU_V2) { - cfg->irptndx = atomic_inc_return(&smmu->irptndx); - cfg->irptndx %= smmu->num_context_irqs; - } else { - cfg->irptndx = cfg->cbndx; - } if (arm_smmu_is_slave_side_secure(smmu_domain)) { smmu_domain->pgtbl_cfg = (struct io_pgtable_cfg) { @@ -1878,6 +1872,13 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, goto out_clear_smmu; + if (smmu->version < ARM_SMMU_V2) { + cfg->irptndx = atomic_inc_return(&smmu->irptndx); + cfg->irptndx %= smmu->num_context_irqs; + } else { + cfg->irptndx = cfg->cbndx; + } + /* * Request context fault interrupt. Do this last to avoid the * handler seeing a half-initialised domain state. -- GitLab From 80ff83e74c557a1b6d9ddd62fcecb11bbddec774 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Mon, 25 Jun 2018 17:27:04 +0530 Subject: [PATCH 0856/1299] ARM: dts: msm: Enable ADSP audio PDR for sm8150 Add device specific flag, to notify all Audio PD clients on ADSP audio PDR. Change-Id: I49108b001ef6de602f85631e34699f50272587d0 Acked-by: Himateja Reddy Signed-off-by: Tharun Kumar Merugu --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index c5529cfd06d3..cdb621f37ff6 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -2286,6 +2286,7 @@ qcom,msm_fastrpc { compatible = "qcom,msm-fastrpc-compute"; + qcom,fastrpc-adsp-audio-pdr; qcom,rpc-latency-us = <611>; qcom,msm_fastrpc_compute_cb1 { -- GitLab From f4ba86706842ebf9e112c6842ac8ddfb3bd4b7a2 Mon Sep 17 00:00:00 2001 From: Jingbiao Lu Date: Wed, 27 Dec 2017 10:27:02 +0800 Subject: [PATCH 0857/1299] soc: qcom: pil: get crypto cell-id through device tree scm_pas_init takes a cell-id argument which is hard coded. Since mas-crypto cell-id is changed from msm-3.18 to msm-4.9, it causes scm_pas_init to fail. So get crypto cell-id through device tree instead of hard coded. Change-Id: Icd58099a54bf389daa1caa3ef6f970b6e7e219b9 Signed-off-by: Jingbiao Lu --- .../devicetree/bindings/pil/subsys-pil-tz.txt | 1 + drivers/soc/qcom/subsys-pil-tz.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/pil/subsys-pil-tz.txt b/Documentation/devicetree/bindings/pil/subsys-pil-tz.txt index 36808c888b18..3606df280e7b 100644 --- a/Documentation/devicetree/bindings/pil/subsys-pil-tz.txt +++ b/Documentation/devicetree/bindings/pil/subsys-pil-tz.txt @@ -71,6 +71,7 @@ Optional properties: - qcom,signal-aop: Boolean. If set, when subsystem is brought up, pil will send a notification to AOP through qmp mailbox driver. +- qcom,mas-crypto: phandle to the bus master of crypto core. Example: qcom,venus@fdce0000 { diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index 2f5bd24a93f2..605aae29948b 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -1031,7 +1031,8 @@ static int pil_tz_driver_probe(struct platform_device *pdev) { struct pil_tz_data *d; struct resource *res; - u32 proxy_timeout; + struct device_node *crypto_node; + u32 proxy_timeout, crypto_id; int len, rc; d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL); @@ -1087,7 +1088,16 @@ static int pil_tz_driver_probe(struct platform_device *pdev) rc); return rc; } - scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE_0); + + crypto_id = MSM_BUS_MASTER_CRYPTO_CORE_0; + crypto_node = of_parse_phandle(pdev->dev.of_node, + "qcom,mas-crypto", 0); + if (!IS_ERR_OR_NULL(crypto_node)) { + of_property_read_u32(crypto_node, "cell-id", + &crypto_id); + } + of_node_put(crypto_node); + scm_pas_init((int)crypto_id); } rc = pil_desc_init(&d->desc); -- GitLab From 0fb63d2b23b014ab49fb5383dfe3dabf562d5a05 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Wed, 20 Jun 2018 17:05:11 +0530 Subject: [PATCH 0858/1299] ARM: dts: msm: Add master crypto property in pil nodes for qcs405 Master crypto property is required to vote for correct bus master while booting subsystems. Previously all subsystem use to vote hardcoded value, which was causing issue as different chipset now vote for different master node, hence required to add the property. Change-Id: Ibb2d1543644af9bba4ac22e621293e803701bb21 Signed-off-by: Avaneesh Kumar Dwivedi --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index ee07feb6e9aa..f06943eeba75 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -439,6 +439,7 @@ qcom,proxy-clock-names = "xo"; qcom,pas-id = <1>; + qcom,mas-crypto = <&mas_crypto>; qcom,complete-ramdump; qcom,proxy-timeout-ms = <10000>; qcom,smem-id = <423>; @@ -477,6 +478,7 @@ qcom,proxy-clock-names = "xo"; qcom,pas-id = <18>; + qcom,mas-crypto = <&mas_crypto>; qcom,complete-ramdump; qcom,proxy-timeout-ms = <10000>; qcom,smem-id = <601>; @@ -515,6 +517,7 @@ qcom,proxy-clock-names = "xo"; qcom,pas-id = <6>; + qcom,mas-crypto = <&mas_crypto>; qcom,proxy-timeout-ms = <10000>; qcom,smem-id = <422>; qcom,sysmon-id = <0>; -- GitLab From e6d78293de269ae5c586f2f27416eed532e1c712 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Thu, 21 Jun 2018 20:57:27 +0530 Subject: [PATCH 0859/1299] defconfig: qcs405: Enable watchdog configs for QCS405 Enabling watchdog mechanism for qcs405. Change-Id: I0f4a7946d5e542c966b6c78cf107ad78ae893dc0 Signed-off-by: Avaneesh Kumar Dwivedi --- arch/arm/configs/vendor/qcs405_defconfig | 3 +++ arch/arm64/configs/vendor/qcs405_defconfig | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index fac263b18316..8a2d6f0a153b 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -404,6 +404,9 @@ CONFIG_QCOM_SMD_RPM=y CONFIG_MSM_SPM=y CONFIG_MSM_L2_SPM=y CONFIG_QCOM_SCM=y +CONFIG_QCOM_WATCHDOG_V2=y +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_QCOM_WDOG_IPI_ENABLE=y CONFIG_QCOM_SMP2P=y CONFIG_MSM_SERVICE_LOCATOR=y CONFIG_MSM_SERVICE_NOTIFIER=y diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index 5cf358ccdab1..9261326bcfd4 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -404,6 +404,9 @@ CONFIG_QCOM_SMD_RPM=y CONFIG_MSM_SPM=y CONFIG_MSM_L2_SPM=y CONFIG_QCOM_SCM=y +CONFIG_QCOM_WATCHDOG_V2=y +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_QCOM_WDOG_IPI_ENABLE=y CONFIG_QCOM_SMP2P=y CONFIG_MSM_SERVICE_LOCATOR=y CONFIG_MSM_SERVICE_NOTIFIER=y -- GitLab From 85509c74f083970e0ae6fc0ab2a724ac663a18e6 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Wed, 6 Jun 2018 21:56:56 +0530 Subject: [PATCH 0860/1299] ARM: dts: msm: Add GPU properties for sm6150 Add device-specific GPU properties for sm6150. Add GPU clocks, registers, interrupts, bus, freq plan, SMMU properties, and GPU power levels. Change-Id: I56108c6e5c5718d5b1619d9291069ea9f3c3317c Signed-off-by: Hareesh Gundu --- arch/arm64/boot/dts/qcom/sm6150-gpu.dtsi | 216 +++++++++++++++++++++++ arch/arm64/boot/dts/qcom/sm6150.dtsi | 1 + 2 files changed, 217 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sm6150-gpu.dtsi diff --git a/arch/arm64/boot/dts/qcom/sm6150-gpu.dtsi b/arch/arm64/boot/dts/qcom/sm6150-gpu.dtsi new file mode 100644 index 000000000000..b93dcdce1044 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm6150-gpu.dtsi @@ -0,0 +1,216 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + msm_gpu: qcom,kgsl-3d0@5000000 { + label = "kgsl-3d0"; + compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; + status = "ok"; + reg = <0x5000000 0x40000>; + reg-names = "kgsl_3d0_reg_memory"; + interrupts = <0 300 0>; + interrupt-names = "kgsl_3d0_irq"; + qcom,id = <0>; + + qcom,chipid = <0x06000800>; + + qcom,initial-pwrlevel = <5>; + + /* */ + qcom,idle-timeout = <80>; + qcom,no-nap; + + qcom,highest-bank-bit = <14>; + qcom,ubwc-mode = <2>; + qcom,min-access-length = <32>; + + /* size in bytes */ + qcom,snapshot-size = <1048576>; + + /* base addr, size */ + qcom,gpu-qdss-stm = <0x06900000 0x40000>; + #cooling-cells = <2>; + + clocks = <&clock_gpucc GPU_CC_GX_GFX3D_CLK>, + <&clock_gpucc GPU_CC_CXO_CLK>, + <&clock_gcc GCC_DDRSS_GPU_AXI_CLK>, + <&clock_gpucc GPU_CC_AHB_CLK>, + <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&clock_gpucc GPU_CC_CX_SNOC_DVM_CLK>, + <&clock_gpucc GPU_CC_CX_GMU_CLK>; + + clock-names = "core_clk", "rbbmtimer_clk", "mem_clk", + "iface_clk", "mem_iface_clk", + "alt_mem_iface_clk", "gmu_clk"; + + /* Bus Scale Settings */ + qcom,msm-bus,name = "grp3d"; + qcom,msm-bus,num-cases = <12>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <26 512 0 0>, + <26 512 0 400000>, /* 1 bus=100 (Low SVS) */ + <26 512 0 800000>, /* 2 bus=200 (Low SVS) */ + <26 512 0 1200000>, /* 3 bus=300 (Low SVS) */ + <26 512 0 1804000>, /* 4 bus=451.2 (Low SVS) */ + <26 512 0 2188000>, /* 5 bus=547.2 (Low SVS) */ + <26 512 0 2726000>, /* 6 bus=681.6 (SVS) */ + <26 512 0 3072000>, /* 7 bus=768 (SVS) */ + <26 512 0 4070000>, /* 8 bus=1017.6 (SVS L1) */ + <26 512 0 5414000>, /* 9 bus=1353.6 (NOM) */ + <26 512 0 6220000>, /* 10 bus=1555.2 (NOM) */ + <26 512 0 7219000>; /* 11 bus=1804.8 (TURBO) */ + + /* GDSC regulator names */ + regulator-names = "vddcx", "vdd"; + /* GDSC oxili regulators */ + vddcx-supply = <&gpu_cx_gdsc>; + vdd-supply = <&gpu_gx_gdsc>; + + /* CPU latency parameter */ + qcom,pm-qos-active-latency = <67>; + qcom,pm-qos-wakeup-latency = <67>; + + /* Enable context aware freq. scaling */ + qcom,enable-ca-jump; + /* Context aware jump busy penalty in us */ + qcom,ca-busy-penalty = <12000>; + /* Context aware jump target power level */ + qcom,ca-target-pwrlevel = <3>; + + /* GPU Mempools */ + qcom,gpu-mempools { + #address-cells = <1>; + #size-cells = <0>; + compatible = "qcom,gpu-mempools"; + + /* 4K Page Pool configuration */ + qcom,gpu-mempool@0 { + reg = <0>; + qcom,mempool-page-size = <4096>; + qcom,mempool-allocate; + }; + /* 8K Page Pool configuration */ + qcom,gpu-mempool@1 { + reg = <1>; + qcom,mempool-page-size = <8192>; + qcom,mempool-allocate; + }; + /* 64K Page Pool configuration */ + qcom,gpu-mempool@2 { + reg = <2>; + qcom,mempool-page-size = <65536>; + qcom,mempool-reserved = <256>; + }; + /* 1M Page Pool configuration */ + qcom,gpu-mempool@3 { + reg = <3>; + qcom,mempool-page-size = <1048576>; + qcom,mempool-reserved = <32>; + }; + }; + + qcom,gpu-pwrlevels { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "qcom,gpu-pwrlevels"; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <845000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <10>; + qcom,bus-max = <11>; + }; + + /* NOM L1 */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <706000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <9>; + qcom,bus-max = <11>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <645000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <8>; + qcom,bus-max = <10>; + }; + + /* SVS L1 */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <513000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <7>; + qcom,bus-max = <9>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <400000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <5>; + qcom,bus-max = <8>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <290000000>; + qcom,bus-freq = <4>; + qcom,bus-min = <4>; + qcom,bus-max = <5>; + }; + + /* XO */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <0>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; + }; + + kgsl_msm_iommu: qcom,kgsl-iommu@0x050a0000 { + compatible = "qcom,kgsl-smmu-v2"; + + reg = <0x050a0000 0x10000>; + qcom,protect = <0xa0000 0x10000>; + + clocks =<&clock_gcc GCC_GPU_CFG_AHB_CLK>, + <&clock_gcc GCC_DDRSS_GPU_AXI_CLK>, + <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&clock_gpucc GPU_CC_CX_SNOC_DVM_CLK>; + + clock-names = "iface_clk", "mem_clk", "mem_iface_clk", + "alt_mem_iface_clk"; + + qcom,retention; + + gfx3d_user: gfx3d_user { + compatible = "qcom,smmu-kgsl-cb"; + label = "gfx3d_user"; + iommus = <&kgsl_smmu 0x0 0x401>; + qcom,gpu-offset = <0xa8000>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index 5d2ebe110a6b..2d5f56b4ab7d 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -1696,6 +1696,7 @@ #include "sm6150-gdsc.dtsi" #include "sm6150-qupv3.dtsi" #include "sm6150-thermal.dtsi" +#include "sm6150-gpu.dtsi" &emac_gdsc { status = "ok"; -- GitLab From 017add3e696a806d551e4dbbd56ed240e38ef2ae Mon Sep 17 00:00:00 2001 From: Neeraj Upadhyay Date: Thu, 12 Apr 2018 16:52:44 +0530 Subject: [PATCH 0861/1299] perf: don't zombie certain events in perf_event_release_kernel Ignore events with no particular cpu associated, while moving the events to zombie state, during event release. Change-Id: I11624f3734633ee6c55454be0cd32f638ed61024 Signed-off-by: Neeraj Upadhyay [rananta@codeaurora.org: resolve trivial merge conflicts] Signed-off-by: Raghavendra Rao Ananta --- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index ebd3baf759c9..21a05dc60d8c 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4487,7 +4487,7 @@ int perf_event_release_kernel(struct perf_event *event) if (event->state == PERF_EVENT_STATE_ZOMBIE) return 0; - if (!cpu_online(event->cpu) && + if (event->cpu != -1 && !cpu_online(event->cpu) && event->state == PERF_EVENT_STATE_ACTIVE) { event->state = PERF_EVENT_STATE_ZOMBIE; -- GitLab From aa5cf9eee08d5f07240d81e5dbf56ba1763cf099 Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Tue, 29 May 2018 10:19:09 +0530 Subject: [PATCH 0862/1299] memshare: Conditional free the clients allotted memory The patch adds an additional check to not free the clients memory if the client has a designated property of allocate-on-request. Change-Id: Iecf5886034ccd052ab82fff18cc66f1868604284 Signed-off-by: Manoj Prabhu B --- drivers/soc/qcom/memshare/msm_memshare.c | 20 +++++++++++++------- drivers/soc/qcom/memshare/msm_memshare.h | 2 ++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c index c300bc4b0b0c..4b0e0882ef82 100644 --- a/drivers/soc/qcom/memshare/msm_memshare.c +++ b/drivers/soc/qcom/memshare/msm_memshare.c @@ -345,6 +345,7 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code, memblock[i].peripheral == DHMS_MEM_PROC_MPSS_V01 && !memblock[i].guarantee && + !memblock[i].client_request && memblock[i].allotted && !memblock[i].alloc_request) { pr_debug("memshare: hypervisor unmapping for client id: %d\n", @@ -538,9 +539,10 @@ static void handle_free_generic_req(struct qmi_handle *handle, __func__); flag = 1; } else if (!memblock[client_id].guarantee && - memblock[client_id].allotted) { - pr_debug("memshare: %s: size: %d", - __func__, memblock[client_id].size); + !memblock[client_id].client_request && + memblock[client_id].allotted) { + pr_debug("memshare: %s:client_id:%d - size: %d", + __func__, client_id, memblock[client_id].size); ret = hyp_assign_phys(memblock[client_id].phy_addr, memblock[client_id].size, source_vmlist, 1, dest_vmids, dest_perms, 1); @@ -549,8 +551,8 @@ static void handle_free_generic_req(struct qmi_handle *handle, * This is an error case as hyp mapping was successful * earlier but during unmap it lead to failure. */ - pr_err("memshare: %s, failed to unmap the region\n", - __func__); + pr_err("memshare: %s, failed to unmap the region for client id:%d\n", + __func__, client_id); } size = memblock[client_id].size; if (memblock[client_id].client_id == 1) { @@ -569,8 +571,8 @@ static void handle_free_generic_req(struct qmi_handle *handle, attrs); free_client(client_id); } else { - pr_err("memshare: %s, Request came for a guaranteed client cannot free up the memory\n", - __func__); + pr_err("memshare: %s, Request came for a guaranteed client (client_id: %d) cannot free up the memory\n", + __func__, client_id); } if (flag) { @@ -781,6 +783,10 @@ static int memshare_child_probe(struct platform_device *pdev) pdev->dev.of_node, "qcom,allocate-boot-time"); + memblock[num_clients].client_request = of_property_read_bool( + pdev->dev.of_node, + "qcom,allocate-on-request"); + rc = of_property_read_string(pdev->dev.of_node, "label", &name); if (rc) { diff --git a/drivers/soc/qcom/memshare/msm_memshare.h b/drivers/soc/qcom/memshare/msm_memshare.h index 6b546528404c..908f091c86eb 100644 --- a/drivers/soc/qcom/memshare/msm_memshare.h +++ b/drivers/soc/qcom/memshare/msm_memshare.h @@ -41,6 +41,8 @@ struct mem_blocks { uint32_t allotted; /* Memory allocation request received or not */ uint32_t alloc_request; + /* Allocation on request from a client*/ + uint32_t client_request; /* Size required for client */ uint32_t size; /* -- GitLab From 828a8d40a370ef0bbd0647c417506aaba8cf4c63 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Sat, 21 Apr 2018 01:42:45 -0700 Subject: [PATCH 0863/1299] msm: ipa3: fix hdr offset issue Hdr offset calculation is wrong when driver received clean-up ioctl from user-space. The fix is to find right hdr offset to commit ned headers. Change-Id: I70878a19b64c3defa6101bd68d435f0b74bcfb9b Signed-off-by: Skylar Chang Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c | 45 +++++++++++++++++++---- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index 0a165957073d..8ea80d8af6df 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -659,7 +659,6 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, return 0; } - int __ipa3_del_hdr(u32 hdr_hdl, bool by_user) { struct ipa3_hdr_entry *entry; @@ -999,7 +998,8 @@ int ipa3_reset_hdr(bool user_only) struct ipa_hdr_offset_entry *off_next; struct ipa3_hdr_proc_ctx_offset_entry *ctx_off_entry; struct ipa3_hdr_proc_ctx_offset_entry *ctx_off_next; - int i; + int i, end = 0; + bool user_rule = false; /* * issue a reset on the routing module since routing rules point to @@ -1037,6 +1037,9 @@ int ipa3_reset_hdr(bool user_only) return -EFAULT; } + if (entry->ipacm_installed) + user_rule = true; + if (!user_only || entry->ipacm_installed) { if (entry->is_hdr_proc_ctx) { dma_unmap_single(ipa3_ctx->pdev, @@ -1046,6 +1049,7 @@ int ipa3_reset_hdr(bool user_only) entry->proc_ctx = NULL; } list_del(&entry->link); + ipa3_ctx->hdr_tbl.hdr_cnt--; entry->ref_cnt = 0; entry->cookie = 0; @@ -1071,6 +1075,13 @@ int ipa3_reset_hdr(bool user_only) list_del(&off_entry->link); kmem_cache_free(ipa3_ctx->hdr_offset_cache, off_entry); + } else { + if (off_entry->offset + + ipa_hdr_bin_sz[off_entry->bin] > end) { + end = off_entry->offset + + ipa_hdr_bin_sz[off_entry->bin]; + IPADBG("replace end = %d\n", end); + } } } list_for_each_entry_safe(off_entry, off_next, @@ -1085,11 +1096,15 @@ int ipa3_reset_hdr(bool user_only) } } } - /* there is one header of size 8 */ - ipa3_ctx->hdr_tbl.end = 8; - ipa3_ctx->hdr_tbl.hdr_cnt = 1; + IPADBG("hdr_tbl.end = %d\n", end); + if (user_rule) { + ipa3_ctx->hdr_tbl.end = end; + IPADBG("hdr_tbl.end = %d\n", end); + } IPADBG("reset hdr proc ctx\n"); + user_rule = false; + end = 0; list_for_each_entry_safe( ctx_entry, ctx_next, @@ -1102,9 +1117,13 @@ int ipa3_reset_hdr(bool user_only) return -EFAULT; } + if (entry->ipacm_installed) + user_rule = true; + if (!user_only || ctx_entry->ipacm_installed) { list_del(&ctx_entry->link); + ipa3_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt--; ctx_entry->ref_cnt = 0; ctx_entry->cookie = 0; @@ -1125,6 +1144,14 @@ int ipa3_reset_hdr(bool user_only) kmem_cache_free( ipa3_ctx->hdr_proc_ctx_offset_cache, ctx_off_entry); + } else { + if (ctx_off_entry->offset + + ipa_hdr_bin_sz[ctx_off_entry->bin] + > end) { + end = ctx_off_entry->offset + + ipa_hdr_bin_sz[ctx_off_entry->bin]; + IPADBG("replace hdr_proc as %d\n", end); + } } } list_for_each_entry_safe(ctx_off_entry, ctx_off_next, @@ -1140,8 +1167,12 @@ int ipa3_reset_hdr(bool user_only) } } } - ipa3_ctx->hdr_proc_ctx_tbl.end = 0; - ipa3_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt = 0; + + IPADBG("hdr_proc_tbl.end = %d\n", end); + if (user_rule) { + ipa3_ctx->hdr_proc_ctx_tbl.end = end; + IPADBG("hdr_proc_tbl.end = %d\n", end); + } mutex_unlock(&ipa3_ctx->lock); return 0; -- GitLab From 4f30ff4bf5c6f2c4ff58347cea083249f15ef721 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Mon, 18 Jun 2018 19:28:57 -0700 Subject: [PATCH 0864/1299] ARM: dts: msm: Update alium battery profile for SM8150 platforms Update alium battery profile for GEN4 FG that is being used for SM8150 platforms as obtained from the characterization. Change-Id: Ifea314070caaa6d65c5314cf55f64fa14ad23460 Signed-off-by: Subbaraman Narayanamurthy --- .../fg-gen4-batterydata-alium-3600mah.dtsi | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi b/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi index 4c79fcd4c6b5..22a8d112a783 100644 --- a/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi +++ b/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-alium-3600mah.dtsi @@ -11,8 +11,8 @@ * GNU General Public License for more details. */ -qcom,alium_860_89032_0000_3600mah_averaged_masterslave_feb7th2018 { - /* #Alium_860_89032_0000_3600mAh_averaged_MasterSlave_Feb7th2018*/ +qcom,alium_860_89032_0000_3600mah_averaged_masterslave_jun15th2018 { + /* #Alium_860_89032_0000_3600mAh_averaged_MasterSlave_Jun15th2018*/ qcom,max-voltage-uv = <4350000>; qcom,fastchg-current-ma = <5400>; qcom,jeita-fcc-ranges = <0 100 2500000 @@ -28,38 +28,41 @@ qcom,alium_860_89032_0000_3600mah_averaged_masterslave_feb7th2018 { qcom,battery-beta = <4250>; qcom,therm-room-temp = <100000>; qcom,fg-cc-cv-threshold-mv = <4340>; - qcom,battery-type = "alium_860_89032_0000_3600mah_feb7th2018"; + qcom,battery-type = "alium_860_89032_0000_3600mah_jun15th2018"; qcom,therm-coefficients = <0x2318 0xd0c 0xdaf7 0xc556 0x848d>; qcom,therm-center-offset = <0x70>; - qcom,checksum = <0xB126>; - qcom,gui-version = "PM8150GUI - 0.0.0.26"; + qcom,therm-pull-up = <100>; + qcom,rslow-normal-coeffs = <0xa4 0x01 0x24 0x13>; + qcom,rslow-low-coeffs = <0xa7 0xd5 0x0e 0x13>; + qcom,checksum = <0xCDFB>; + qcom,gui-version = "PM8150GUI - 1.0.0.7"; qcom,fg-profile-data = [ 09 00 B5 EA - 40 CC 19 AA - EA C2 00 00 + 3F CC 33 AA + E7 C2 00 00 13 BC 83 8A - 03 80 D3 92 - AA 9D 47 80 - 18 00 07 02 - 58 13 47 FD + 03 80 D1 92 + AB 9D 47 80 + 18 00 A4 01 + 24 13 47 FD A9 F2 CE 07 - 00 00 A6 00 - 36 F5 07 FD - 64 0D 0B 23 - 34 2A BE 23 - B4 43 5C 4B + 32 00 A6 00 + EF F5 CB FD + 11 0D 4A 23 + 60 2A C1 23 + 6F 42 F8 43 40 00 3A 00 - 3F 00 47 00 - 3A 00 33 00 - 36 00 37 00 - 47 00 41 00 + 40 00 48 00 + 3B 00 34 00 + 38 00 38 00 + 48 00 42 00 40 00 40 00 3B 00 30 00 32 00 39 00 32 00 42 00 5C 64 47 00 3B 08 40 10 - 40 00 3A 00 + 40 00 3B 00 35 00 36 00 3C 00 35 00 44 20 53 40 -- GitLab From e12729bbaddde9e0d41f78b0f36c5a321875e043 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Wed, 20 Jun 2018 19:56:36 -0700 Subject: [PATCH 0865/1299] power: qpnp-fg-gen4: Fix Rslow compensation workaround 'commit b8fbbafb6785 ("power: qpnp-fg-gen4: Disable Rslow compensation for PM8150B v1")' added a workaround for PM8150B v1. However, it will not work as expected when the profile is loaded after doing the configuration during boot. Fix it by doing the configuration after loading the profile. Change-Id: Ie356453076f8c0d91eb5e54f86a41475b3d10e46 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/qpnp-fg-gen4.c | 31 ++++++++++++++---------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 39f635435ce6..7e8f5c4980cb 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -1134,7 +1134,7 @@ static int fg_gen4_bp_params_config(struct fg_dev *fg) struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int rc, i; u8 buf, therm_coeffs[BATT_THERM_NUM_COEFFS * 2]; - u8 rslow_coeffs[RSLOW_NUM_COEFFS]; + u8 rslow_coeffs[RSLOW_NUM_COEFFS], val, mask; if (fg->bp.vbatt_full_mv > 0) { rc = fg_set_constant_chg_voltage(fg, @@ -1190,6 +1190,23 @@ static int fg_gen4_bp_params_config(struct fg_dev *fg) fg_dbg(fg, FG_STATUS, "Rslow_low: %d\n", chip->rslow_low); } + /* + * Since this SRAM word falls inside profile region, configure it after + * the profile is loaded. This parameter doesn't come from battery + * profile DT property. + */ + if (fg->wa_flags & PM8150B_V1_RSLOW_COMP_WA) { + val = 0; + mask = BIT(1); + rc = fg_sram_masked_write(fg, RSLOW_CONFIG_WORD, + RSLOW_CONFIG_OFFSET, mask, val, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing RSLOW_CONFIG_WORD, rc=%d\n", + rc); + return rc; + } + } + if (fg->bp.therm_pull_up_kohms > 0) { switch (fg->bp.therm_pull_up_kohms) { case 30: @@ -2964,18 +2981,6 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip) } } - if (fg->wa_flags & PM8150B_V1_RSLOW_COMP_WA) { - val = 0; - mask = BIT(1); - rc = fg_sram_masked_write(fg, RSLOW_CONFIG_WORD, - RSLOW_CONFIG_OFFSET, mask, val, FG_IMA_DEFAULT); - if (rc < 0) { - pr_err("Error in writing RSLOW_CONFIG_WORD, rc=%d\n", - rc); - return rc; - } - } - rc = restore_cycle_count(chip->counter); if (rc < 0) { pr_err("Error in restoring cycle_count, rc=%d\n", rc); -- GitLab From d78fdfaf53086fd8f422b57028efa63a2e1390ef Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Mon, 18 Jun 2018 19:32:13 -0700 Subject: [PATCH 0866/1299] power: qpnp-fg-gen4: Update default cutoff voltage to 3.1 V As per the hardware recommendation, update the default cutoff voltage to 3.1 V. Change-Id: Ie4584a94628859400044221a5307af258c8635a4 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/qpnp-fg-gen4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 7e8f5c4980cb..3804537f8e20 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -3094,7 +3094,7 @@ static int fg_parse_ki_coefficients(struct fg_dev *fg) return 0; } -#define DEFAULT_CUTOFF_VOLT_MV 3000 +#define DEFAULT_CUTOFF_VOLT_MV 3100 #define DEFAULT_EMPTY_VOLT_MV 2812 #define DEFAULT_SYS_TERM_CURR_MA -125 #define DEFAULT_CUTOFF_CURR_MA 200 -- GitLab From e174bb4342e4691b95adb6c1c381cf2d2dcecf18 Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Tue, 26 Jun 2018 20:28:23 +0300 Subject: [PATCH 0867/1299] wil6210: BRP antenna limit API Added vendor command for setting BRP antenna limit. It allows user space to set the number of antennas that will be active in different modes for each connection. Change-Id: I8a0eb1fa4c74b169faeec2761818a5bac60a8196 Signed-off-by: Alexei Avshalom Lazar --- drivers/net/wireless/ath/wil6210/cfg80211.c | 142 ++++++++++++++++++-- 1 file changed, 131 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 0c98459f01d6..299d8228307d 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -54,6 +54,9 @@ MODULE_PARM_DESC(ignore_reg_hints, " Ignore OTA regulatory hints (Default: true) .max_power = 40, \ } +#define WIL_BRP_ANT_LIMIT_MIN (1) +#define WIL_BRP_ANT_LIMIT_MAX (27) + static struct ieee80211_channel wil_60ghz_channels[] = { CHAN60G(1, 0), CHAN60G(2, 0), @@ -74,7 +77,7 @@ static struct ieee80211_channel wil_60ghz_channels[] = { #define WIL_MAX_RF_SECTORS (128) #define WIL_CID_ALL (0xff) -enum qca_wlan_vendor_attr_rf_sector { +enum qca_wlan_vendor_attr_wil { QCA_ATTR_MAC_ADDR = 6, QCA_ATTR_PAD = 13, QCA_ATTR_TSF = 29, @@ -82,7 +85,9 @@ enum qca_wlan_vendor_attr_rf_sector { QCA_ATTR_DMG_RF_SECTOR_TYPE = 31, QCA_ATTR_DMG_RF_MODULE_MASK = 32, QCA_ATTR_DMG_RF_SECTOR_CFG = 33, - QCA_ATTR_DMG_RF_SECTOR_MAX, + QCA_ATTR_BRP_ANT_LIMIT_MODE = 38, + QCA_ATTR_BRP_ANT_NUM_LIMIT = 39, + QCA_ATTR_WIL_MAX, }; enum qca_wlan_vendor_attr_dmg_rf_sector_type { @@ -107,8 +112,22 @@ enum qca_wlan_vendor_attr_dmg_rf_sector_cfg { QCA_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST - 1 }; +enum qca_wlan_vendor_attr_brp_ant_limit_mode { + QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_DISABLE, + QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_EFFECTIVE, + QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_FORCE, + QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODES_NUM +}; + static const struct -nla_policy wil_rf_sector_policy[QCA_ATTR_DMG_RF_SECTOR_MAX + 1] = { +nla_policy wil_brp_ant_limit_policy[QCA_ATTR_WIL_MAX + 1] = { + [QCA_ATTR_MAC_ADDR] = { .len = ETH_ALEN }, + [QCA_ATTR_BRP_ANT_NUM_LIMIT] = { .type = NLA_U8 }, + [QCA_ATTR_BRP_ANT_LIMIT_MODE] = { .type = NLA_U8 }, +}; + +static const struct +nla_policy wil_rf_sector_policy[QCA_ATTR_WIL_MAX + 1] = { [QCA_ATTR_MAC_ADDR] = { .len = ETH_ALEN }, [QCA_ATTR_DMG_RF_SECTOR_INDEX] = { .type = NLA_U16 }, [QCA_ATTR_DMG_RF_SECTOR_TYPE] = { .type = NLA_U8 }, @@ -141,6 +160,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG = 140, QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR = 141, QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR = 142, + QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT = 153, }; static int wil_rf_sector_get_cfg(struct wiphy *wiphy, @@ -155,6 +175,8 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, static int wil_rf_sector_set_selected(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); +static int wil_brp_set_ant_limit(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); /* vendor specific commands */ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = { @@ -230,6 +252,13 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = { WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wil_rf_sector_set_selected }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wil_brp_set_ant_limit + }, }; /* vendor specific events */ @@ -2385,7 +2414,7 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, struct wil6210_priv *wil = wdev_to_wil(wdev); struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc; - struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; + struct nlattr *tb[QCA_ATTR_WIL_MAX + 1]; u16 sector_index; u8 sector_type; u32 rf_modules_vec; @@ -2404,7 +2433,7 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) return -EOPNOTSUPP; - rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len, + rc = nla_parse(tb, QCA_ATTR_WIL_MAX, data, data_len, wil_rf_sector_policy, NULL); if (rc) { wil_err(wil, "Invalid rf sector ATTR\n"); @@ -2506,7 +2535,7 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, struct wil6210_priv *wil = wdev_to_wil(wdev); struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc, tmp; - struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; + struct nlattr *tb[QCA_ATTR_WIL_MAX + 1]; struct nlattr *tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1]; u16 sector_index, rf_module_index; u8 sector_type; @@ -2524,7 +2553,7 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) return -EOPNOTSUPP; - rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len, + rc = nla_parse(tb, QCA_ATTR_WIL_MAX, data, data_len, wil_rf_sector_policy, NULL); if (rc) { wil_err(wil, "Invalid rf sector ATTR\n"); @@ -2616,7 +2645,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, struct wil6210_priv *wil = wdev_to_wil(wdev); struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc; - struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; + struct nlattr *tb[QCA_ATTR_WIL_MAX + 1]; u8 sector_type, mac_addr[ETH_ALEN]; int cid = 0; struct wmi_get_selected_rf_sector_index_cmd cmd; @@ -2631,7 +2660,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) return -EOPNOTSUPP; - rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len, + rc = nla_parse(tb, QCA_ATTR_WIL_MAX, data, data_len, wil_rf_sector_policy, NULL); if (rc) { wil_err(wil, "Invalid rf sector ATTR\n"); @@ -2731,7 +2760,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, struct wil6210_priv *wil = wdev_to_wil(wdev); struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc; - struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; + struct nlattr *tb[QCA_ATTR_WIL_MAX + 1]; u16 sector_index; u8 sector_type, mac_addr[ETH_ALEN], i; int cid = 0; @@ -2739,7 +2768,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) return -EOPNOTSUPP; - rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len, + rc = nla_parse(tb, QCA_ATTR_WIL_MAX, data, data_len, wil_rf_sector_policy, NULL); if (rc) { wil_err(wil, "Invalid rf sector ATTR\n"); @@ -2821,3 +2850,94 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, return rc; } + +static int +wil_brp_wmi_set_ant_limit(struct wil6210_priv *wil, u8 mid, u8 cid, + u8 limit_mode, u8 antenna_num_limit) +{ + int rc; + struct wmi_brp_set_ant_limit_cmd cmd = { + .cid = cid, + .limit_mode = limit_mode, + .ant_limit = antenna_num_limit, + }; + struct { + struct wmi_cmd_hdr wmi; + struct wmi_brp_set_ant_limit_event evt; + } __packed reply; + + reply.evt.status = WMI_FW_STATUS_FAILURE; + + rc = wmi_call(wil, WMI_BRP_SET_ANT_LIMIT_CMDID, mid, &cmd, sizeof(cmd), + WMI_BRP_SET_ANT_LIMIT_EVENTID, &reply, + sizeof(reply), 250); + if (rc) + return rc; + + if (reply.evt.status != WMI_FW_STATUS_SUCCESS) { + wil_err(wil, "brp set antenna limit failed with status %d\n", + reply.evt.status); + rc = -EINVAL; + } + + return rc; +} + +static int wil_brp_set_ant_limit(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct wil6210_priv *wil = wdev_to_wil(wdev); + struct wil6210_vif *vif = wdev_to_vif(wil, wdev); + struct nlattr *tb[QCA_ATTR_WIL_MAX + 1]; + u8 mac_addr[ETH_ALEN]; + u8 antenna_num_limit = 0; + u8 limit_mode; + int cid = 0; + int rc; + + if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) + return -ENOTSUPP; + + rc = nla_parse(tb, QCA_ATTR_WIL_MAX, data, data_len, + wil_brp_ant_limit_policy, NULL); + if (rc) { + wil_err(wil, "Invalid ant limit ATTR\n"); + return rc; + } + + if (!tb[QCA_ATTR_BRP_ANT_LIMIT_MODE] || !tb[QCA_ATTR_MAC_ADDR]) { + wil_err(wil, "Invalid antenna limit spec\n"); + return -EINVAL; + } + + limit_mode = nla_get_u8(tb[QCA_ATTR_BRP_ANT_LIMIT_MODE]); + if (limit_mode >= QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODES_NUM) { + wil_err(wil, "Invalid limit mode %d\n", limit_mode); + return -EINVAL; + } + + if (limit_mode != QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_DISABLE) { + if (!tb[QCA_ATTR_BRP_ANT_NUM_LIMIT]) { + wil_err(wil, "Invalid limit number\n"); + return -EINVAL; + } + + antenna_num_limit = nla_get_u8(tb[QCA_ATTR_BRP_ANT_NUM_LIMIT]); + if (antenna_num_limit > WIL_BRP_ANT_LIMIT_MAX || + antenna_num_limit < WIL_BRP_ANT_LIMIT_MIN) { + wil_err(wil, "Invalid number of antenna limit: %d\n", + antenna_num_limit); + return -EINVAL; + } + } + + ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR])); + cid = wil_find_cid(wil, vif->mid, mac_addr); + if (cid < 0) { + wil_err(wil, "invalid MAC address %pM\n", mac_addr); + return -ENOENT; + } + + return wil_brp_wmi_set_ant_limit(wil, vif->mid, cid, limit_mode, + antenna_num_limit); +} -- GitLab From b6c7fbcd10e9dc21b7cf4780c7b883bc0ef6b039 Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Wed, 20 Jun 2018 16:40:56 -0400 Subject: [PATCH 0868/1299] msm: npu: Enable npu cti/apb/atb/perf_cnt clocks Enable npu cti/apb/atb/perf_cnt clocks to support QDSS hw events. Change-Id: I2b2b84cd5780ea9f03f4666f8991ccd145e682c0 Signed-off-by: Jilai Wang --- drivers/media/platform/msm/npu/npu_common.h | 2 +- drivers/media/platform/msm/npu/npu_dev.c | 71 +++++++++------------ 2 files changed, 31 insertions(+), 42 deletions(-) diff --git a/drivers/media/platform/msm/npu/npu_common.h b/drivers/media/platform/msm/npu/npu_common.h index d38cc87b13d9..c8b4523427cb 100644 --- a/drivers/media/platform/msm/npu/npu_common.h +++ b/drivers/media/platform/msm/npu/npu_common.h @@ -67,7 +67,7 @@ #define ROW_BYTES 16 #define GROUP_BYTES 4 -#define NUM_TOTAL_CLKS 19 +#define NUM_TOTAL_CLKS 20 #define NPU_MAX_REGULATOR_NUM 2 #define NPU_MAX_DT_NAME_LEN 21 #define NPU_MAX_PWRLEVELS 7 diff --git a/drivers/media/platform/msm/npu/npu_dev.c b/drivers/media/platform/msm/npu/npu_dev.c index 2cc21518989c..e422ea49c9e2 100644 --- a/drivers/media/platform/msm/npu/npu_dev.c +++ b/drivers/media/platform/msm/npu/npu_dev.c @@ -64,7 +64,6 @@ static ssize_t npu_store_pwr_state(struct device *dev, static void npu_suspend_devbw(struct npu_device *npu_dev); static void npu_resume_devbw(struct npu_device *npu_dev); static bool npu_is_post_clock(const char *clk_name); -static bool npu_is_exclude_clock(const char *clk_name); static bool npu_is_exclude_rate_clock(const char *clk_name); static int npu_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state); @@ -99,13 +98,14 @@ static void __exit npu_exit(void); * ------------------------------------------------------------------------- */ static const char * const npu_clock_order[] = { + "qdss_clk", + "at_clk", + "trig_clk", "armwic_core_clk", - "cal_dp_clk_src", "cal_dp_clk", "cal_dp_cdc_clk", "conf_noc_ahb_clk", "comp_noc_axi_clk", - "npu_core_clk_src", "npu_core_clk", "npu_core_cti_clk", "npu_core_apb_clk", @@ -125,19 +125,14 @@ static const char * const npu_post_clocks[] = { "npu_cpc_timer_clk" }; -static const char * const npu_exclude_clocks[] = { - "npu_core_clk_src", - "cal_dp_clk_src", - "perf_cnt_clk", - "npu_core_cti_clk", - "npu_core_apb_clk", - "npu_core_atb_clk" -}; - static const char * const npu_exclude_rate_clocks[] = { + "qdss_clk", + "at_clk", + "trig_clk", "sleep_clk", "xo_clk", "conf_noc_ahb_clk", + "comp_noc_axi_clk", "npu_core_cti_clk", "npu_core_apb_clk", "npu_core_atb_clk", @@ -354,7 +349,6 @@ static int npu_set_power_level(struct npu_device *npu_dev) struct npu_pwrctrl *pwr = &npu_dev->pwrctrl; struct npu_pwrlevel *pwrlevel; int i, ret = 0; - long clk_rate = 0; uint32_t pwr_level_to_set; if (!pwr->pwr_vote_num) { @@ -388,13 +382,12 @@ static int npu_set_power_level(struct npu_device *npu_dev) pr_debug("requested rate of clock [%s] to [%ld]\n", npu_dev->core_clks[i].clk_name, pwrlevel->clk_freq[i]); - pr_debug("actual round clk rate [%ld]\n", clk_rate); - - ret = clk_set_rate(npu_dev->core_clks[i].clk, clk_rate); + ret = clk_set_rate(npu_dev->core_clks[i].clk, + pwrlevel->clk_freq[i]); if (ret) { pr_debug("clk_set_rate %s to %ld failed with %d\n", npu_dev->core_clks[i].clk_name, - clk_rate, ret); + pwrlevel->clk_freq[i], ret); break; } } @@ -491,20 +484,6 @@ static bool npu_is_post_clock(const char *clk_name) return ret; } -static bool npu_is_exclude_clock(const char *clk_name) -{ - int ret = false; - int i; - - for (i = 0; i < ARRAY_SIZE(npu_exclude_clocks); i++) { - if (!strcmp(clk_name, npu_exclude_clocks[i])) { - ret = true; - break; - } - } - return ret; -} - static bool npu_is_exclude_rate_clock(const char *clk_name) { int ret = false; @@ -536,10 +515,7 @@ static int npu_enable_core_clocks(struct npu_device *npu_dev, bool post_pil) continue; } - if (npu_is_exclude_clock(core_clks[i].clk_name)) - continue; - - pr_debug("enabling clock [%s]\n", core_clks[i].clk_name); + pr_debug("enabling clock %s\n", core_clks[i].clk_name); rc = clk_prepare_enable(core_clks[i].clk); if (rc) { @@ -551,16 +527,31 @@ static int npu_enable_core_clocks(struct npu_device *npu_dev, bool post_pil) if (npu_is_exclude_rate_clock(core_clks[i].clk_name)) continue; - pr_debug("setting rate of clock [%s] to [%ld]\n", + pr_debug("setting rate of clock %s to %ld\n", core_clks[i].clk_name, pwrlevel->clk_freq[i]); rc = clk_set_rate(core_clks[i].clk, pwrlevel->clk_freq[i]); + /* not fatal error, keep using previous clk rate */ if (rc) { - pr_debug("clk_set_rate %s to %ld failed\n", + pr_err("clk_set_rate %s to %ld failed\n", core_clks[i].clk_name, pwrlevel->clk_freq[i]); - break; + rc = 0; + } + } + + if (rc) { + for (i--; i >= 0; i--) { + if (post_pil) { + if (!npu_is_post_clock(core_clks[i].clk_name)) + continue; + } else { + if (npu_is_post_clock(core_clks[i].clk_name)) + continue; + } + pr_debug("disabling clock %s\n", core_clks[i].clk_name); + clk_disable_unprepare(core_clks[i].clk); } } @@ -573,14 +564,12 @@ static void npu_disable_core_clocks(struct npu_device *npu_dev) struct npu_clk *core_clks = npu_dev->core_clks; for (i = (npu_dev->core_clk_num)-1; i >= 0 ; i--) { - if (npu_is_exclude_clock(core_clks[i].clk_name)) - continue; if (npu_dev->host_ctx.fw_state == FW_DISABLED) { if (npu_is_post_clock(npu_dev->core_clks[i].clk_name)) continue; } - pr_debug("disabling clock [%s]\n", core_clks[i].clk_name); + pr_debug("disabling clock %s\n", core_clks[i].clk_name); clk_disable_unprepare(core_clks[i].clk); } } -- GitLab From ad0ef433a509c9de3bfdaf250e6baf033313c523 Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Wed, 20 Jun 2018 16:13:44 -0400 Subject: [PATCH 0869/1299] ARM: dts: msm: Add NPU QDSS related clocks for sm8150 Add NPU QDSS related clocks to enable ati/apb/atp/perf_cnt clocks. Change-Id: Ife37e2e046ba0952f090e1633e694e687b888313 Signed-off-by: Jilai Wang --- arch/arm64/boot/dts/qcom/sm8150-npu.dtsi | 44 ++++++++++++++---------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi b/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi index fd99bfeb4482..b17b9a60f5da 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-npu.dtsi @@ -24,7 +24,6 @@ cache-slice-names = "npu"; cache-slices = <&llcc 23>; clocks = <&clock_npucc NPU_CC_CAL_DP_CLK>, - <&clock_npucc NPU_CC_CAL_DP_CLK_SRC>, <&clock_npucc NPU_CC_XO_CLK>, <&clock_npucc NPU_CC_ARMWIC_CORE_CLK>, <&clock_npucc NPU_CC_BTO_CORE_CLK>, @@ -35,15 +34,16 @@ <&clock_npucc NPU_CC_NPU_CORE_APB_CLK>, <&clock_npucc NPU_CC_NPU_CORE_ATB_CLK>, <&clock_npucc NPU_CC_NPU_CORE_CLK>, - <&clock_npucc NPU_CC_NPU_CORE_CLK_SRC>, <&clock_npucc NPU_CC_NPU_CORE_CTI_CLK>, <&clock_npucc NPU_CC_NPU_CPC_CLK>, <&clock_npucc NPU_CC_NPU_CPC_TIMER_CLK>, <&clock_npucc NPU_CC_PERF_CNT_CLK>, <&clock_npucc NPU_CC_QTIMER_CORE_CLK>, - <&clock_npucc NPU_CC_SLEEP_CLK>; + <&clock_npucc NPU_CC_SLEEP_CLK>, + <&clock_gcc GCC_NPU_AT_CLK>, + <&clock_gcc GCC_NPU_TRIG_CLK>, + <&clock_aop QDSS_CLK>; clock-names = "cal_dp_clk", - "cal_dp_clk_src", "xo_clk", "armwic_core_clk", "bto_core_clk", @@ -54,13 +54,15 @@ "npu_core_apb_clk", "npu_core_atb_clk", "npu_core_clk", - "npu_core_clk_src", "npu_core_cti_clk", "npu_cpc_clk", "npu_cpc_timer_clk", "perf_cnt_clk", "qtimer_core_clk", - "sleep_clk"; + "sleep_clk", + "at_clk", + "trig_clk", + "qdss_clk"; vdd-supply = <&npu_core_gdsc>; vdd_cx-supply = <&VDD_CX_LEVEL>; qcom,proxy-reg-names ="vdd", "vdd_cx"; @@ -77,7 +79,6 @@ qcom,npu-pwrlevel@0 { reg = <0>; clk-freq = <9600000 - 9600000 19200000 19200000 19200000 @@ -91,15 +92,16 @@ 19200000 19200000 19200000 - 19200000 9600000 19200000 + 0 + 0 + 0 0>; }; qcom,npu-pwrlevel@1 { reg = <1>; clk-freq = <300000000 - 300000000 19200000 100000000 19200000 @@ -110,18 +112,19 @@ 19200000 60000000 100000000 - 100000000 37500000 100000000 19200000 300000000 19200000 + 0 + 0 + 0 0>; }; qcom,npu-pwrlevel@2 { reg = <2>; clk-freq = <350000000 - 350000000 19200000 150000000 19200000 @@ -132,18 +135,19 @@ 19200000 120000000 150000000 - 150000000 75000000 150000000 19200000 350000000 19200000 + 0 + 0 + 0 0>; }; qcom,npu-pwrlevel@3 { reg = <3>; clk-freq = <400000000 - 400000000 19200000 200000000 19200000 @@ -154,18 +158,19 @@ 19200000 120000000 200000000 - 200000000 75000000 200000000 19200000 400000000 19200000 + 0 + 0 + 0 0>; }; qcom,npu-pwrlevel@4 { reg = <4>; clk-freq = <600000000 - 600000000 19200000 300000000 19200000 @@ -176,18 +181,19 @@ 19200000 240000000 300000000 - 300000000 150000000 300000000 19200000 600000000 19200000 + 0 + 0 + 0 0>; }; qcom,npu-pwrlevel@5 { reg = <5>; clk-freq = <715000000 - 715000000 19200000 350000000 19200000 @@ -198,12 +204,14 @@ 19200000 240000000 350000000 - 350000000 150000000 350000000 19200000 715000000 19200000 + 0 + 0 + 0 0>; }; }; -- GitLab From ff16ce0e1e440a9da10381738715aab844c6ce80 Mon Sep 17 00:00:00 2001 From: Narendra Muppalla Date: Thu, 1 Mar 2018 11:32:23 +0530 Subject: [PATCH 0870/1299] drm/msm/sde: Fix uninitialized variables and pointers Return values in some cases can be wrongs as its not initialized properly. Perform proper NULL check for pointers as well. Change-Id: Ieac1a8f50dabd2918edaba1bd93599a62b8c9bf0 Signed-off-by: Jayant Shekhar Signed-off-by: Narendra Muppalla --- drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c | 5 +++++ drivers/gpu/drm/msm/dp/dp_drm.c | 5 +++++ drivers/gpu/drm/msm/sde/sde_kms.c | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c index 7290205a85cd..874c229910cf 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c @@ -925,6 +925,11 @@ static unsigned long vco_10nm_recalc_rate(struct clk_hw *hw, if (!vco->priv) pr_err("vco priv is null\n"); + if (!pll) { + pr_err("pll is null\n"); + return 0; + } + /* * Calculate the vco rate from HW registers only for handoff cases. * For other cases where a vco_10nm_set_rate() has already been diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index a985969dc3af..f5473c10d7d3 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -219,6 +219,11 @@ static void dp_bridge_disable(struct drm_bridge *drm_bridge) dp = bridge->display; + if (!dp) { + pr_err("dp is null\n"); + return; + } + if (dp) sde_connector_helper_bridge_disable(bridge->connector); diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index c43977cec65b..dc2c555eba79 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -2343,7 +2343,7 @@ static int sde_kms_cont_splash_config(struct msm_kms *kms) * configuration. */ if (conn_iter && - conn_iter->encoder_ids[0] == encoder->base.id) { + (conn_iter->encoder_ids[0] == encoder->base.id)) { connector = conn_iter; break; } -- GitLab From 74ae899898e4e9d47d40d691763af22c9cb8e749 Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Tue, 26 Jun 2018 13:28:09 -0700 Subject: [PATCH 0871/1299] msm: vidc: Amend input buffer count in batch mode Batching needs minimum batch size count of input buffers else we may not see expected power savings in playback usecase. Change-Id: I4355daadd0e416f4bd48103b59b44efccd2abe31 Signed-off-by: Maheshwar Ajja --- drivers/media/platform/msm/vidc/msm_vidc_common.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index ac2eb4a63ff6..40d97e9e83d7 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -3093,6 +3093,11 @@ static int msm_comm_init_buffer_count(struct msm_vidc_inst *inst) extra_buff_count = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT); bufreq->buffer_count_min = inst->fmts[port].input_min_count; + /* batching needs minimum batch size count of input buffers */ + if (inst->core->resources.decode_batching && + is_decode_session(inst) && + bufreq->buffer_count_min < inst->batch.size) + bufreq->buffer_count_min = inst->batch.size; bufreq->buffer_count_min_host = bufreq->buffer_count_actual = bufreq->buffer_count_min + extra_buff_count; -- GitLab From d21ea38f028a478e7d9dd5c900dfb782b8634221 Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Tue, 26 Jun 2018 13:33:42 -0700 Subject: [PATCH 0872/1299] msm: vidc: Increase input buffer size Current input buffer size is sufficient for 8bit frame size and not sufficient for 10bit frame size and hence increase size to accommodate 10bit frames to resolve video playback failures observed with few 10bit contents. Change-Id: Ieb3cb73ce1ed5f326fc7273f73410b23f32be87b Signed-off-by: Maheshwar Ajja --- drivers/media/platform/msm/vidc/msm_vdec.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c index e2e5dd7fe658..6f6c2fe32acc 100644 --- a/drivers/media/platform/msm/vidc/msm_vdec.c +++ b/drivers/media/platform/msm/vidc/msm_vdec.c @@ -394,19 +394,33 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = { static u32 get_frame_size_compressed_full_yuv(int plane, u32 max_mbs_per_frame, u32 size_per_mb) { + u32 frame_size; + if (max_mbs_per_frame > MAX_4K_MBPF) - return (max_mbs_per_frame * size_per_mb * 3 / 2) / 4; + frame_size = (max_mbs_per_frame * size_per_mb * 3 / 2) / 4; else - return (max_mbs_per_frame * size_per_mb * 3 / 2); + frame_size = (max_mbs_per_frame * size_per_mb * 3 / 2); + + /* multiply by 10/8 (1.25) to get size for 10 bit case */ + frame_size = frame_size + (frame_size >> 2); + + return frame_size; } static u32 get_frame_size_compressed(int plane, u32 max_mbs_per_frame, u32 size_per_mb) { + u32 frame_size; + if (max_mbs_per_frame > MAX_4K_MBPF) - return (max_mbs_per_frame * size_per_mb * 3 / 2) / 4; + frame_size = (max_mbs_per_frame * size_per_mb * 3 / 2) / 4; else - return (max_mbs_per_frame * size_per_mb * 3/2)/2; + frame_size = (max_mbs_per_frame * size_per_mb * 3/2)/2; + + /* multiply by 10/8 (1.25) to get size for 10 bit case */ + frame_size = frame_size + (frame_size >> 2); + + return frame_size; } static u32 get_frame_size(struct msm_vidc_inst *inst, -- GitLab From 17d136354a378786702aa450118ba12e59af621f Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Wed, 27 Jun 2018 00:03:32 +0300 Subject: [PATCH 0873/1299] wil6210: publish/receive WMI events/commands through nl For general debug purposes added functionality for sending WMI events and receiving WMI commands to/from user-space through vendor commands. Change-Id: I889d30bf1f060f75d7ae933735d1d959e53e513e Signed-off-by: Alexei Avshalom Lazar --- drivers/net/wireless/ath/wil6210/cfg80211.c | 235 ++++++++++++++++++++ drivers/net/wireless/ath/wil6210/ftm.h | 3 +- drivers/net/wireless/ath/wil6210/main.c | 2 + drivers/net/wireless/ath/wil6210/wil6210.h | 6 + drivers/net/wireless/ath/wil6210/wmi.c | 23 +- 5 files changed, 263 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 299d8228307d..fa794275a8fb 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -64,6 +64,49 @@ static struct ieee80211_channel wil_60ghz_channels[] = { /* channel 4 not supported yet */ }; +enum wil_nl_60g_cmd_type { + NL_60G_CMD_FW_WMI, + NL_60G_CMD_DEBUG, + NL_60G_CMD_STATISTICS, + NL_60G_CMD_REGISTER, +}; + +enum wil_nl_60g_evt_type { + NL_60G_EVT_DRIVER_ERROR, + NL_60G_EVT_FW_ERROR, + NL_60G_EVT_FW_WMI, + NL_60G_EVT_DRIVER_SHUTOWN, + NL_60G_EVT_DRIVER_DEBUG_EVENT, +}; + +enum wil_nl_60g_debug_cmd { + NL_60G_DBG_FORCE_WMI_SEND, +}; + +struct wil_nl_60g_send_receive_wmi { + u32 cmd_id; /* enum wmi_command_id or enum wmi_event_id */ + u8 reserved[2]; + u8 dev_id; /* mid */ + u16 buf_len; + u8 buf[0]; +} __packed; + +struct wil_nl_60g_event { + u32 evt_type; /* wil_nl_60g_evt_type */ + u32 buf_len; + u8 reserved[9]; + u8 buf[0]; +} __packed; + +struct wil_nl_60g_debug { /* NL_60G_CMD_DEBUG */ + u32 cmd_id; /* wil_nl_60g_debug_cmd */ +} __packed; + +struct wil_nl_60g_debug_force_wmi { + struct wil_nl_60g_debug hdr; + u32 enable; +} __packed; + /* Vendor id to be used in vendor specific command and events * to user space. * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID, @@ -79,6 +122,8 @@ static struct ieee80211_channel wil_60ghz_channels[] = { enum qca_wlan_vendor_attr_wil { QCA_ATTR_MAC_ADDR = 6, + QCA_ATTR_FEATURE_FLAGS = 7, + QCA_ATTR_TEST = 8, QCA_ATTR_PAD = 13, QCA_ATTR_TSF = 29, QCA_ATTR_DMG_RF_SECTOR_INDEX = 30, @@ -90,6 +135,9 @@ enum qca_wlan_vendor_attr_wil { QCA_ATTR_WIL_MAX, }; +#define WIL_ATTR_60G_CMD_TYPE QCA_ATTR_FEATURE_FLAGS +#define WIL_ATTR_60G_BUF QCA_ATTR_TEST + enum qca_wlan_vendor_attr_dmg_rf_sector_type { QCA_ATTR_DMG_RF_SECTOR_TYPE_RX, QCA_ATTR_DMG_RF_SECTOR_TYPE_TX, @@ -146,7 +194,14 @@ nla_policy wil_rf_sector_cfg_policy[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1] = { [QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16] = { .type = NLA_U32 }, }; +static const struct +nla_policy wil_nl_60g_policy[QCA_ATTR_WIL_MAX + 1] = { + [WIL_ATTR_60G_CMD_TYPE] = { .type = NLA_U32 }, + [WIL_ATTR_60G_BUF] = { .type = NLA_BINARY }, +}; + enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA = 128, QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION = 129, QCA_NL80211_VENDOR_SUBCMD_FTM_ABORT_SESSION = 130, @@ -178,6 +233,8 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, static int wil_brp_set_ant_limit(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); +static int wil_nl_60g_handle_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); /* vendor specific commands */ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = { { @@ -259,6 +316,13 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = { WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wil_brp_set_ant_limit }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_UNSPEC, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wil_nl_60g_handle_cmd + }, }; /* vendor specific events */ @@ -275,6 +339,10 @@ static const struct nl80211_vendor_cmd_info wil_nl80211_vendor_events[] = { .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT }, + [QCA_NL80211_VENDOR_EVENT_UNSPEC_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_UNSPEC + }, }; static struct ieee80211_supported_band wil_band_60ghz = { @@ -2941,3 +3009,170 @@ static int wil_brp_set_ant_limit(struct wiphy *wiphy, struct wireless_dev *wdev, return wil_brp_wmi_set_ant_limit(wil, vif->mid, cid, limit_mode, antenna_num_limit); } + +static int wil_nl_60g_handle_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct wil6210_priv *wil = wdev_to_wil(wdev); + struct nlattr *tb[QCA_ATTR_WIL_MAX + 1]; + struct wil_nl_60g_send_receive_wmi *cmd; + struct wil_nl_60g_debug_force_wmi debug_force_wmi; + int rc, len; + u32 wil_nl_60g_cmd_type, publish; + + rc = nla_parse(tb, QCA_ATTR_WIL_MAX, data, data_len, + wil_nl_60g_policy, NULL); + if (rc) { + wil_err(wil, "Invalid nl_60g_cmd ATTR\n"); + return rc; + } + + if (!tb[WIL_ATTR_60G_CMD_TYPE]) { + wil_err(wil, "Invalid nl_60g_cmd type\n"); + return -EINVAL; + } + + wil_nl_60g_cmd_type = nla_get_u32(tb[WIL_ATTR_60G_CMD_TYPE]); + + switch (wil_nl_60g_cmd_type) { + case NL_60G_CMD_REGISTER: + if (!tb[WIL_ATTR_60G_BUF]) { + wil_err(wil, "Invalid nl_60g_cmd spec\n"); + return -EINVAL; + } + + len = nla_len(tb[WIL_ATTR_60G_BUF]); + if (len != sizeof(publish)) { + wil_err(wil, "cmd buffer wrong len %d\n", len); + return -EINVAL; + } + memcpy(&publish, nla_data(tb[WIL_ATTR_60G_BUF]), len); + wil->publish_nl_evt = publish; + + wil_dbg_wmi(wil, "Publish wmi event %s\n", + publish ? "enabled" : "disabled"); + break; + case NL_60G_CMD_DEBUG: + if (!tb[WIL_ATTR_60G_BUF]) { + wil_err(wil, "Invalid nl_60g_cmd spec\n"); + return -EINVAL; + } + + len = nla_len(tb[WIL_ATTR_60G_BUF]); + if (len < sizeof(struct wil_nl_60g_debug)) { + wil_err(wil, "cmd buffer too short %d\n", len); + return -EINVAL; + } + + memcpy(&debug_force_wmi, nla_data(tb[WIL_ATTR_60G_BUF]), + sizeof(struct wil_nl_60g_debug)); + + switch (debug_force_wmi.hdr.cmd_id) { + case NL_60G_DBG_FORCE_WMI_SEND: + if (len != sizeof(debug_force_wmi)) { + wil_err(wil, "cmd buffer wrong len %d\n", len); + return -EINVAL; + } + + memcpy(&debug_force_wmi, nla_data(tb[WIL_ATTR_60G_BUF]), + sizeof(debug_force_wmi)); + wil->force_wmi_send = debug_force_wmi.enable; + + wil_dbg_wmi(wil, "force sending wmi commands %d\n", + wil->force_wmi_send); + break; + default: + rc = -EINVAL; + wil_err(wil, "invalid debug_cmd id %d", + debug_force_wmi.hdr.cmd_id); + } + break; + case NL_60G_CMD_FW_WMI: + if (!tb[WIL_ATTR_60G_BUF]) { + wil_err(wil, "Invalid nl_60g_cmd spec\n"); + return -EINVAL; + } + + len = nla_len(tb[WIL_ATTR_60G_BUF]); + if (len < offsetof(struct wil_nl_60g_send_receive_wmi, buf)) { + wil_err(wil, "wmi cmd buffer too small\n"); + return -EINVAL; + } + + cmd = kmalloc(len, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + memcpy(cmd, nla_data(tb[WIL_ATTR_60G_BUF]), (unsigned int)len); + + wil_dbg_wmi(wil, "sending user-space command (0x%04x) [%d]\n", + cmd->cmd_id, cmd->buf_len); + + if (wil->force_wmi_send) + rc = wmi_force_send(wil, cmd->cmd_id, cmd->dev_id, + cmd->buf, cmd->buf_len); + else + rc = wmi_send(wil, cmd->cmd_id, cmd->dev_id, + cmd->buf, cmd->buf_len); + + kfree(cmd); + break; + default: + rc = -EINVAL; + wil_err(wil, "invalid nl_60g_cmd type %d", wil_nl_60g_cmd_type); + } + + return rc; +} + +void wil_nl_60g_receive_wmi_evt(struct wil6210_priv *wil, u8 *cmd, int len) +{ + struct sk_buff *vendor_event = NULL; + struct wil_nl_60g_event *evt; + struct wil_nl_60g_send_receive_wmi *wmi_buf; + struct wmi_cmd_hdr *wmi_hdr = (struct wmi_cmd_hdr *)cmd; + int data_len; + + if (!wil->publish_nl_evt) + return; + + wil_dbg_wmi(wil, "report wmi event to user-space (0x%04x) [%d]\n", + le16_to_cpu(wmi_hdr->command_id), len); + + data_len = len - sizeof(struct wmi_cmd_hdr); + + evt = kzalloc(sizeof(*evt) + sizeof(*wmi_buf) + data_len, GFP_KERNEL); + if (!evt) + return; + + evt->evt_type = NL_60G_EVT_FW_WMI; + evt->buf_len = sizeof(*wmi_buf) + data_len; + + wmi_buf = (struct wil_nl_60g_send_receive_wmi *)evt->buf; + + wmi_buf->cmd_id = le16_to_cpu(wmi_hdr->command_id); + wmi_buf->dev_id = wmi_hdr->mid; + wmi_buf->buf_len = data_len; + memcpy(wmi_buf->buf, cmd + sizeof(struct wmi_cmd_hdr), data_len); + + vendor_event = cfg80211_vendor_event_alloc( + wil_to_wiphy(wil), + NULL, + data_len + 4 + NLMSG_HDRLEN + + sizeof(*evt) + sizeof(*wmi_buf), + QCA_NL80211_VENDOR_EVENT_UNSPEC_INDEX, + GFP_KERNEL); + if (!vendor_event) + goto out; + + if (nla_put(vendor_event, WIL_ATTR_60G_BUF, + sizeof(*evt) + sizeof(*wmi_buf) + data_len, evt)) { + wil_err(wil, "failed to fill WIL_ATTR_60G_BUF\n"); + goto out; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + +out: + kfree(evt); +} diff --git a/drivers/net/wireless/ath/wil6210/ftm.h b/drivers/net/wireless/ath/wil6210/ftm.h index 21923c27ec06..e9efad7405dd 100644 --- a/drivers/net/wireless/ath/wil6210/ftm.h +++ b/drivers/net/wireless/ath/wil6210/ftm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -417,6 +417,7 @@ enum qca_nl80211_vendor_events_index { QCA_NL80211_VENDOR_EVENT_FTM_MEAS_RESULT_INDEX, QCA_NL80211_VENDOR_EVENT_FTM_SESSION_DONE_INDEX, QCA_NL80211_VENDOR_EVENT_AOA_MEAS_RESULT_INDEX, + QCA_NL80211_VENDOR_EVENT_UNSPEC_INDEX, }; /* measurement parameters. Specified for each peer as part diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 2453b3c6f7f5..c0342e5a874d 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1528,6 +1528,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wmi_event_flush(wil); + wil->force_wmi_send = false; + flush_workqueue(wil->wq_service); flush_workqueue(wil->wmi_wq); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 6ecfeb1fbe30..fbd458cd2515 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -996,6 +996,9 @@ struct wil6210_priv { bool secured_boot; u8 boot_config; + bool publish_nl_evt; /* deliver WMI events to user space */ + bool force_wmi_send; /* allow WMI command while FW in sysassert */ + /* relevant only for eDMA */ bool amsdu_en; }; @@ -1163,6 +1166,8 @@ void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, struct wil6210_mbox_hdr *hdr); int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len); +int wmi_force_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, + u16 len); void wmi_recv_cmd(struct wil6210_priv *wil); int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len, u16 reply_id, void *reply, u16 reply_size, int to_msec); @@ -1343,6 +1348,7 @@ void wil_ftm_evt_per_dest_res(struct wil6210_vif *vif, void wil_aoa_evt_meas(struct wil6210_vif *vif, struct wmi_aoa_meas_event *evt, int len); +void wil_nl_60g_receive_wmi_evt(struct wil6210_priv *wil, u8 *cmd, int len); /* link loss */ int wmi_link_maintain_cfg_write(struct wil6210_priv *wil, const u8 *addr, diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 9d82c37ece6f..b7c78e55a0be 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -605,7 +605,7 @@ static const char *eventid2name(u16 eventid) } static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, - void *buf, u16 len) + void *buf, u16 len, bool force_send) { struct { struct wil6210_mbox_hdr hdr; @@ -637,7 +637,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, might_sleep(); - if (!test_bit(wil_status_fwready, wil->status)) { + if (!test_bit(wil_status_fwready, wil->status) && !force_send) { wil_err(wil, "WMI: cannot send command while FW not ready\n"); return -EAGAIN; } @@ -676,7 +676,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head); /* wait till FW finish with previous command */ for (retry = 5; retry > 0; retry--) { - if (!test_bit(wil_status_fwready, wil->status)) { + if (!test_bit(wil_status_fwready, wil->status) && !force_send) { wil_err(wil, "WMI: cannot send command while FW not ready\n"); rc = -EAGAIN; goto out; @@ -731,7 +731,19 @@ int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len) int rc; mutex_lock(&wil->wmi_mutex); - rc = __wmi_send(wil, cmdid, mid, buf, len); + rc = __wmi_send(wil, cmdid, mid, buf, len, false); + mutex_unlock(&wil->wmi_mutex); + + return rc; +} + +int wmi_force_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, + u16 len) +{ + int rc; + + mutex_lock(&wil->wmi_mutex); + rc = __wmi_send(wil, cmdid, mid, buf, len, true); mutex_unlock(&wil->wmi_mutex); return rc; @@ -1471,6 +1483,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) u16 id = le16_to_cpu(wmi->command_id); u8 mid = wmi->mid; u32 tstamp = le32_to_cpu(wmi->fw_timestamp); + wil_nl_60g_receive_wmi_evt(wil, cmd, len); if (test_bit(wil_status_resuming, wil->status)) { if (id == WMI_TRAFFIC_RESUME_EVENTID) clear_bit(wil_status_resuming, @@ -1546,7 +1559,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len, reinit_completion(&wil->wmi_call); spin_unlock(&wil->wmi_ev_lock); - rc = __wmi_send(wil, cmdid, mid, buf, len); + rc = __wmi_send(wil, cmdid, mid, buf, len, false); if (rc) goto out; -- GitLab From 733cb264f1ebd0c5c83b5d2ec6ce75f59180b28b Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Wed, 13 Dec 2017 19:51:36 +0200 Subject: [PATCH 0874/1299] cfg80211: Scan results to also report the per chain signal strength This commit enhances the scan results to report the per chain signal strength based on the latest BSS update. This provides similar information to what is already available through STA information. Signed-off-by: Sunil Dutt Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Git-commit: 983dafaab799511e092ffd006f3a064b37ccbccf Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git CRs-fixed: 2173940 Change-Id: I4300c1a6a3af4dc1244ee4717a772bfaa927b2db Signed-off-by: Srinivas Dasari --- include/net/cfg80211.h | 8 ++++++++ include/uapi/linux/nl80211.h | 4 ++++ net/wireless/nl80211.c | 5 +++++ net/wireless/scan.c | 5 +++++ 4 files changed, 22 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index df5da42eaa4d..4a6ff5aff3b4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1781,6 +1781,8 @@ enum cfg80211_signal_type { * by %parent_bssid. * @parent_bssid: the BSS according to which %parent_tsf is set. This is set to * the BSS that requested the scan in which the beacon/probe was received. + * @chains: bitmask for filled values in @chain_signal. + * @chain_signal: per-chain signal strength of last received BSS in dBm. */ struct cfg80211_inform_bss { struct ieee80211_channel *chan; @@ -1789,6 +1791,8 @@ struct cfg80211_inform_bss { u64 boottime_ns; u64 parent_tsf; u8 parent_bssid[ETH_ALEN] __aligned(2); + u8 chains; + s8 chain_signal[IEEE80211_MAX_CHAINS]; }; /** @@ -1832,6 +1836,8 @@ struct cfg80211_bss_ies { * that holds the beacon data. @beacon_ies is still valid, of course, and * points to the same data as hidden_beacon_bss->beacon_ies in that case. * @signal: signal strength value (type depends on the wiphy's signal_type) + * @chains: bitmask for filled values in @chain_signal. + * @chain_signal: per-chain signal strength of last received BSS in dBm. * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes */ struct cfg80211_bss { @@ -1850,6 +1856,8 @@ struct cfg80211_bss { u16 capability; u8 bssid[ETH_ALEN]; + u8 chains; + s8 chain_signal[IEEE80211_MAX_CHAINS]; u8 priv[0] __aligned(sizeof(void *)); }; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 25426e9c4f41..6ed63fb5ddc5 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3903,6 +3903,9 @@ enum nl80211_bss_scan_width { * @NL80211_BSS_PARENT_BSSID. (u64). * @NL80211_BSS_PARENT_BSSID: the BSS according to which @NL80211_BSS_PARENT_TSF * is set. + * @NL80211_BSS_CHAIN_SIGNAL: per-chain signal strength of last BSS update. + * Contains a nested array of signal strength attributes (u8, dBm), + * using the nesting index as the antenna number. * @__NL80211_BSS_AFTER_LAST: internal * @NL80211_BSS_MAX: highest BSS attribute */ @@ -3926,6 +3929,7 @@ enum nl80211_bss { NL80211_BSS_PAD, NL80211_BSS_PARENT_TSF, NL80211_BSS_PARENT_BSSID, + NL80211_BSS_CHAIN_SIGNAL, /* keep last */ __NL80211_BSS_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 310cfe13c909..30683891305f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7797,6 +7797,11 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, intbss->ts_boottime, NL80211_BSS_PAD)) goto nla_put_failure; + if (!nl80211_put_signal(msg, intbss->pub.chains, + intbss->pub.chain_signal, + NL80211_BSS_CHAIN_SIGNAL)) + goto nla_put_failure; + switch (rdev->wiphy.signal_type) { case CFG80211_SIGNAL_TYPE_MBM: if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal)) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 1289cc14e9f9..d8e74445d633 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -981,6 +981,9 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, found->ts = tmp->ts; found->ts_boottime = tmp->ts_boottime; found->parent_tsf = tmp->parent_tsf; + found->pub.chains = tmp->pub.chains; + memcpy(found->pub.chain_signal, tmp->pub.chain_signal, + IEEE80211_MAX_CHAINS); ether_addr_copy(found->parent_bssid, tmp->parent_bssid); } else { struct cfg80211_internal_bss *new; @@ -1233,6 +1236,8 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); tmp.ts_boottime = data->boottime_ns; tmp.parent_tsf = data->parent_tsf; + tmp.pub.chains = data->chains; + memcpy(tmp.pub.chain_signal, data->chain_signal, IEEE80211_MAX_CHAINS); ether_addr_copy(tmp.parent_bssid, data->parent_bssid); signal_valid = abs(data->chan->center_freq - channel->center_freq) <= -- GitLab From 6c63c9aaa7359b9d563c7dd77376e8de0e52362d Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Fri, 22 Jun 2018 00:10:45 -0700 Subject: [PATCH 0875/1299] power: smb5: add support to configure charger temp_max Currently, both PM8150B and SMB1355 charger temp_max settings come from their die REG_H_THRESHOLDs. Add additional support to read the property from device tree, which take precedence if exists. Change-Id: I78b4376adb62bf6c95b4b128817e03db22d827f1 Signed-off-by: Harry Yang --- .../bindings/power/supply/qcom/qpnp-smb5.txt | 12 ++++++++ drivers/power/supply/qcom/qpnp-smb5.c | 24 +++++++++++---- drivers/power/supply/qcom/smb5-lib.c | 30 ++++++++++++------- drivers/power/supply/qcom/smb5-lib.h | 1 + 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt index f50211139a31..ed38a7c15dd2 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt +++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt @@ -52,6 +52,18 @@ Charger specific properties: addition battery properties will be faked such that the device assumes normal operation. +- qcom,charger-temp-max + Usage: optional + Value type: + Definition: Specifies the charger temp REG_H_THRESHOLD for PM8150B in deciDegC. + If the value is not present, use the setting read from the device. + +- qcom,smb-temp-max + Usage: optional + Value type: + Definition: Specifies the charger temp REG_H_THRESHOLD for SMB1355 in deciDegC. + If the value is not present, use the setting read from the device. + - qcom,fcc-max-ua Usage: optional Value type: diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 49515c6a8725..f0e3df20adfe 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -376,6 +376,16 @@ static int smb5_parse_dt(struct smb5 *chip) } } + rc = of_property_read_u32(node, "qcom,charger-temp-max", + &chg->charger_temp_max); + if (rc < 0) + chg->charger_temp_max = -EINVAL; + + rc = of_property_read_u32(node, "qcom,smb-temp-max", + &chg->smb_temp_max); + if (rc < 0) + chg->smb_temp_max = -EINVAL; + rc = of_property_read_u32(node, "qcom,float-option", &chip->dt.float_option); if (!rc && (chip->dt.float_option < 0 || chip->dt.float_option > 4)) { @@ -1600,11 +1610,15 @@ static int smb5_init_hw(struct smb5 *chip) smblib_get_charge_param(chg, &chg->param.usb_icl, &chg->default_icl_ua); - rc = smblib_get_thermal_threshold(chg, DIE_REG_H_THRESHOLD_MSB_REG, - &chg->charger_temp_max); - if (rc < 0) { - dev_err(chg->dev, "Couldn't get charger_temp_max rc=%d\n", rc); - return rc; + if (chg->charger_temp_max == -EINVAL) { + rc = smblib_get_thermal_threshold(chg, + DIE_REG_H_THRESHOLD_MSB_REG, + &chg->charger_temp_max); + if (rc < 0) { + dev_err(chg->dev, "Couldn't get charger_temp_max rc=%d\n", + rc); + return rc; + } } /* Disable SMB Temperature ADC INT */ diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 2ff4cd1d2168..df8a828f705d 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -3855,13 +3855,18 @@ static void pl_update_work(struct work_struct *work) pl_update_work); int rc; - rc = smblib_get_thermal_threshold(chg, SMB_REG_H_THRESHOLD_MSB_REG, - &prop_val.intval); - if (rc < 0) { - dev_err(chg->dev, "Couldn't get charger_temp_max rc=%d\n", rc); - return; + if (chg->smb_temp_max == -EINVAL) { + rc = smblib_get_thermal_threshold(chg, + SMB_REG_H_THRESHOLD_MSB_REG, + &chg->smb_temp_max); + if (rc < 0) { + dev_err(chg->dev, "Couldn't get charger_temp_max rc=%d\n", + rc); + return; + } } + prop_val.intval = chg->smb_temp_max; rc = power_supply_set_property(chg->pl.psy, POWER_SUPPLY_PROP_CHARGER_TEMP_MAX, &prop_val); @@ -4174,15 +4179,18 @@ int smblib_init(struct smb_charger *chg) } } - rc = smblib_get_thermal_threshold(chg, + if (chg->smb_temp_max == -EINVAL) { + rc = smblib_get_thermal_threshold(chg, SMB_REG_H_THRESHOLD_MSB_REG, - &prop_val.intval); - if (rc < 0) { - dev_err(chg->dev, "Couldn't get charger_temp_max rc=%d\n", - rc); - return rc; + &chg->smb_temp_max); + if (rc < 0) { + dev_err(chg->dev, "Couldn't get charger_temp_max rc=%d\n", + rc); + return rc; + } } + prop_val.intval = chg->smb_temp_max; rc = power_supply_set_property(chg->pl.psy, POWER_SUPPLY_PROP_CHARGER_TEMP_MAX, &prop_val); diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index b977a5fe168b..f65dae81ed4c 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -362,6 +362,7 @@ struct smb_charger { enum sink_src_mode sink_src_mode; bool jeita_configured; int charger_temp_max; + int smb_temp_max; /* workaround flag */ u32 wa_flags; -- GitLab From 94ce4baf8d291cf4af33c5943eb1e5e01b880fed Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Fri, 22 Jun 2018 00:37:28 -0700 Subject: [PATCH 0876/1299] ARM: dts: msm: add charger/smb temp_max properties for PM8150B Add qcom,charger-temp-max for PM8150B temp_max, and qcom,smb-charger-max for SMB1355 temp_max. Both are settings for REG_H_THRESHOLDs used in thermal balancing algorithm. Change-Id: I848a105f5045a5fa947b30a358f2c2687c4ec964 Signed-off-by: Harry Yang --- arch/arm64/boot/dts/qcom/pm8150b.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi b/arch/arm64/boot/dts/qcom/pm8150b.dtsi index 6f5667ec64ff..869fb0a34f69 100644 --- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi @@ -169,6 +169,9 @@ qcom,pmic-revid = <&pm8150b_revid>; + qcom,charger-temp-max = <800>; + qcom,smb-temp-max = <800>; + qcom,chgr@1000 { reg = <0x1000 0x100>; interrupts = -- GitLab From 54eebd2038e95203953ea12697e61bddabf8abe0 Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Tue, 19 Jun 2018 14:19:29 -0700 Subject: [PATCH 0877/1299] sched: improve trace prints Add the target and backup cpu in find_best_target trace print. During placement print more information about the cpu before skipping it. This helps in understanding why the cpu was not considered for placement. Change-Id: Ifc4de6b1d7495d2d701a92f465f4c81e86f468ea Signed-off-by: Abhijeet Dharmapurikar --- include/trace/events/sched.h | 29 +++++++++++++++++++++++------ kernel/sched/fair.c | 11 +++++++---- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index 3d23e8d12ddb..3b636833e16f 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -1157,10 +1157,12 @@ TRACE_EVENT(sched_find_best_target, TP_PROTO(struct task_struct *tsk, bool prefer_idle, unsigned long min_util, int start_cpu, - int best_idle, int best_active, int target), + int best_idle, int best_active, int most_spare_cap, int target, + int backup_cpu), TP_ARGS(tsk, prefer_idle, min_util, start_cpu, - best_idle, best_active, target), + best_idle, best_active, most_spare_cap, target, + backup_cpu), TP_STRUCT__entry( __array( char, comm, TASK_COMM_LEN ) @@ -1170,7 +1172,9 @@ TRACE_EVENT(sched_find_best_target, __field( int, start_cpu ) __field( int, best_idle ) __field( int, best_active ) + __field( int, most_spare_cap ) __field( int, target ) + __field( int, backup_cpu) ), TP_fast_assign( @@ -1181,15 +1185,19 @@ TRACE_EVENT(sched_find_best_target, __entry->start_cpu = start_cpu; __entry->best_idle = best_idle; __entry->best_active = best_active; + __entry->most_spare_cap = most_spare_cap; __entry->target = target; + __entry->backup_cpu = backup_cpu; ), TP_printk("pid=%d comm=%s prefer_idle=%d start_cpu=%d " - "best_idle=%d best_active=%d target=%d", + "best_idle=%d best_active=%d most_spare_cap=%d target=%d backup=%d", __entry->pid, __entry->comm, __entry->prefer_idle, __entry->start_cpu, __entry->best_idle, __entry->best_active, - __entry->target) + __entry->most_spare_cap, + __entry->target, + __entry->backup_cpu) ); TRACE_EVENT(sched_cpu_util, @@ -1208,6 +1216,10 @@ TRACE_EVENT(sched_cpu_util, __field(unsigned int, capacity_orig ) __field(int, idle_state ) __field(u64, irqload ) + __field(int, online ) + __field(int, isolated ) + __field(int, reserved ) + __field(int, high_irq_load ) ), TP_fast_assign( @@ -1220,10 +1232,15 @@ TRACE_EVENT(sched_cpu_util, __entry->capacity_orig = capacity_orig_of(cpu); __entry->idle_state = idle_get_state_idx(cpu_rq(cpu)); __entry->irqload = sched_irqload(cpu); + __entry->online = cpu_online(cpu); + __entry->isolated = cpu_isolated(cpu); + __entry->reserved = is_reserved(cpu); + __entry->high_irq_load = sched_cpu_high_irqload(cpu); ), - TP_printk("cpu=%d nr_running=%d cpu_util=%ld cpu_util_cum=%ld capacity_curr=%u capacity=%u capacity_orig=%u idle_state=%d irqload=%llu", - __entry->cpu, __entry->nr_running, __entry->cpu_util, __entry->cpu_util_cum, __entry->capacity_curr, __entry->capacity, __entry->capacity_orig, __entry->idle_state, __entry->irqload) + TP_printk("cpu=%d nr_running=%d cpu_util=%ld cpu_util_cum=%ld capacity_curr=%u capacity=%u capacity_orig=%u idle_state=%d irqload=%llu online=%u, isolated=%u, reserved=%u, high_irq_load=%u", + __entry->cpu, __entry->nr_running, __entry->cpu_util, __entry->cpu_util_cum, __entry->capacity_curr, __entry->capacity, __entry->capacity_orig, __entry->idle_state, __entry->irqload, + __entry->online, __entry->isolated, __entry->reserved, __entry->high_irq_load) ); TRACE_EVENT(sched_energy_diff, diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ed04a9ceeb20..edd140bf0848 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7150,6 +7150,8 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, unsigned long capacity_orig = capacity_orig_of(i); unsigned long wake_util, new_util, new_util_cuml; + trace_sched_cpu_util(i); + if (!cpu_online(i) || cpu_isolated(i)) continue; @@ -7164,8 +7166,6 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, if (sched_cpu_high_irqload(i)) continue; - trace_sched_cpu_util(i); - /* * p's blocked utilization is still accounted for on prev_cpu * so prev_cpu will receive a negative bias due to the double @@ -7238,7 +7238,8 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, trace_sched_find_best_target(p, prefer_idle, min_util, cpu, best_idle_cpu, - best_active_cpu, i); + best_active_cpu, + -1, i, -1); return i; } @@ -7426,7 +7427,9 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, trace_sched_find_best_target(p, prefer_idle, min_util, cpu, best_idle_cpu, best_active_cpu, - target_cpu); + most_spare_cap_cpu, + target_cpu, + *backup_cpu); /* it is possible for target and backup * to select same CPU - if so, drop backup -- GitLab From aba51e0e3345a19273e026616aecf33bca014d32 Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Wed, 20 Jun 2018 22:11:59 -0700 Subject: [PATCH 0878/1299] sched: remove skip_sg This function was used to steer placements to allowed groups. With earlier improvements on jumping to the correct start_cpu this usefulness of this function is reduced. Remove it and move the remaining useful functionality to find_best_target(). In particular * skip_sg would skip groups with all cores isolated. This would rarely be the situation in practice and moreover the loop that scans through cpus in the group would skip isolated cpus. * skip_sg would skip groups once target is found. This can be easily moved in to the loop that traverses groups. * skip_sg checks for situations where a task is confined to a cluster and forces us to visit that cluster. This is not required anymore as we traverse all the groups. Change-Id: Ia85b18e44af72b90adacf4bb84b497147263c343 Signed-off-by: Abhijeet Dharmapurikar --- kernel/sched/fair.c | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index edd140bf0848..5061b32a652a 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7044,31 +7044,6 @@ static bool is_packing_eligible(struct task_struct *p, int target_cpu, return (estimated_capacity <= capacity_curr_of(target_cpu)); } -static inline bool skip_sg(struct task_struct *p, struct sched_group *sg, - struct cpumask *rtg_target, - unsigned long target_capacity) -{ - /* Are all CPUs isolated in this group? */ - if (!sg->group_weight) - return true; - - /* - * Don't skip a group if a task affinity allows it - * to run only on that group. - */ - if (cpumask_subset(&p->cpus_allowed, sched_group_span(sg))) - return false; - - /* - * if we have found a target cpu within a group, don't bother checking - * other groups - */ - if (target_capacity != ULONG_MAX) - return true; - - return false; -} - static int start_cpu(struct task_struct *p, bool boosted, struct cpumask *rtg_target) { @@ -7142,9 +7117,6 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, /* Scan CPUs in all SDs */ sg = sd->groups; do { - if (skip_sg(p, sg, fbt_env->rtg_target, target_capacity)) - continue; - for_each_cpu_and(i, &p->cpus_allowed, sched_group_span(sg)) { unsigned long capacity_curr = capacity_curr_of(i); unsigned long capacity_orig = capacity_orig_of(i); @@ -7383,6 +7355,13 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, !is_max_capacity_cpu(group_first_cpu(sg))) target_capacity = ULONG_MAX; + /* + * if we have found a target cpu within a group, don't bother + * checking other groups + */ + if (target_capacity != ULONG_MAX) + break; + } while (sg = sg->next, sg != sd->groups); if (best_idle_cpu != -1 && !is_packing_eligible(p, target_cpu, fbt_env, -- GitLab From 6594e7cc3bb08107421c9f7d0c46613843e3f773 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Sun, 7 Dec 2014 09:01:52 +0200 Subject: [PATCH 0879/1299] scsi: ufs: Initiate crypto before SCSI for UFS fast boot UFS driver integrates a new functionality to support inline crypto engine, which was added to the crypto component. In case ICE driver is initialized after UFS driver, we experience long boot time as a result of probe defer handling. Changing the modules order in the makefile will reduce the probability for probe defer cases and will allow maintaining shorter boot time. Change-Id: I941a577a427ad45e7519408425e00541e825efc6 Signed-off-by: Maya Erez --- drivers/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/Makefile b/drivers/Makefile index 9fe69a241330..2d4eae87489e 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -79,6 +79,7 @@ obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/ obj-$(CONFIG_NUBUS) += nubus/ obj-y += macintosh/ obj-$(CONFIG_IDE) += ide/ +obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SCSI) += scsi/ obj-y += nvme/ obj-$(CONFIG_ATA) += ata/ @@ -136,7 +137,6 @@ obj-$(CONFIG_NEW_LEDS) += leds/ obj-$(CONFIG_INFINIBAND) += infiniband/ obj-$(CONFIG_SGI_SN) += sn/ obj-y += firmware/ -obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ ifndef CONFIG_ARCH_USES_GETTIMEOFFSET obj-y += clocksource/ -- GitLab From fcc4bc080d0d46cf1f9fa57ecec5d221fcad3d2b Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Tue, 26 Jun 2018 11:15:57 +0530 Subject: [PATCH 0880/1299] msm: msm_bus: Change the init level for bus scaling driver Change the driver init level for bus scaling driver to fs_initcall as it has dependency on clock driver which is probed at subsys_initcall level. Change-Id: Iaa32c4c37c2762092c90f551d394d81d5baaca33 Signed-off-by: Odelu Kukatla --- drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c index 61bfba938d62..471a9f8dac25 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c @@ -1273,4 +1273,4 @@ int __init msm_bus_device_init_driver(void) } return platform_driver_register(&msm_bus_rules_driver); } -subsys_initcall(msm_bus_device_init_driver); +fs_initcall(msm_bus_device_init_driver); -- GitLab From 085d0e457034c60c9d26ff5d8d2966d30de093e6 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Wed, 27 Jun 2018 09:54:33 +0530 Subject: [PATCH 0881/1299] msm: kgsl: Remove unused functions from gmu_core_ops get_idle_level() and set_idle_level() not implemented for any of the gmu. Hence removing these functions. Change-Id: Ifc3fa216fb8f9fa298aba00dc6af4040f107f5fe Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/kgsl_gmu_core.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/msm/kgsl_gmu_core.h b/drivers/gpu/msm/kgsl_gmu_core.h index d9bfacb8ef9b..91510e42f1e0 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.h +++ b/drivers/gpu/msm/kgsl_gmu_core.h @@ -128,8 +128,6 @@ struct gmu_core_ops { int (*start)(struct kgsl_device *device); void (*stop)(struct kgsl_device *device); void (*snapshot)(struct kgsl_device *device); - int (*get_idle_level)(struct kgsl_device *device); - void (*set_idle_level)(struct kgsl_device *device, unsigned int val); bool (*regulator_isenabled)(struct kgsl_device *device); int (*suspend)(struct kgsl_device *device); }; -- GitLab From 9b6c9bc14c0df3d23c969d70ff58cdd081231e09 Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Tue, 26 Jun 2018 12:45:14 +0800 Subject: [PATCH 0882/1299] usb: pd: Add DP lane number notification Add DP lane number notification which can be used in the case that need to know DP lane number. Change-Id: Iec66cbf6a34ca6c4346fa93f7706f3aff9f6a775 Signed-off-by: Liangliang Lu --- drivers/extcon/extcon.c | 2 +- drivers/usb/pd/policy_engine.c | 33 +++++++++++++++++++++++++++------ include/linux/extcon.h | 2 +- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 3f67b618b47e..e098d7a7138a 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -486,7 +486,7 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id) } EXPORT_SYMBOL_GPL(extcon_sync); -int extcon_blocking_sync(struct extcon_dev *edev, unsigned int id, bool val) +int extcon_blocking_sync(struct extcon_dev *edev, unsigned int id, u8 val) { int index; diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 1045a88cfd37..f473f0fc9624 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -431,6 +431,7 @@ struct usbpd { struct list_head instance; + bool has_dp; u16 ss_lane_svid; /* ext msg support */ @@ -453,6 +454,7 @@ static LIST_HEAD(_usbpd); /* useful for debugging */ static const unsigned int usbpd_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_DISP_DP, EXTCON_NONE, }; @@ -575,6 +577,13 @@ static int usbpd_release_ss_lane(struct usbpd *pd, pd->ss_lane_svid = hdlr->svid; + /* DP 4 Lane mode */ + ret = extcon_blocking_sync(pd->extcon, EXTCON_DISP_DP, 4); + if (ret) { + usbpd_err(&pd->dev, "err(%d) for notify DP 4 Lane", ret); + goto err_exit; + } + err_exit: return ret; } @@ -1568,11 +1577,19 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg) u8 i, num_vdos = PD_MSG_HDR_COUNT(rx_msg->hdr) - 1; u8 cmd = SVDM_HDR_CMD(vdm_hdr); u8 cmd_type = SVDM_HDR_CMD_TYPE(vdm_hdr); - bool has_dp = false; struct usbpd_svid_handler *handler; - usbpd_dbg(&pd->dev, "VDM rx: svid:%x cmd:%x cmd_type:%x vdm_hdr:%x\n", - svid, cmd, cmd_type, vdm_hdr); + usbpd_dbg(&pd->dev, + "VDM rx: svid:%x cmd:%x cmd_type:%x vdm_hdr:%x has_dp: %s\n", + svid, cmd, cmd_type, vdm_hdr, + pd->has_dp ? "true" : "false"); + + if ((svid == 0xFF01) && (pd->has_dp == false)) { + pd->has_dp = true; + + /* Set to USB and DP cocurrency mode */ + extcon_blocking_sync(pd->extcon, EXTCON_DISP_DP, 2); + } /* if it's a supported SVID, pass the message to the handler */ handler = find_svid_handler(pd, svid); @@ -1718,9 +1735,6 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg) handler->discovered = true; } } - - if (svid == 0xFF01) - has_dp = true; } break; @@ -2063,6 +2077,13 @@ static void usbpd_sm(struct work_struct *w) kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); dual_role_instance_changed(pd->dual_role); + if (pd->has_dp) { + pd->has_dp = false; + + /* Set to USB only mode when cable disconnected */ + extcon_blocking_sync(pd->extcon, EXTCON_DISP_DP, 0); + } + goto sm_done; } diff --git a/include/linux/extcon.h b/include/linux/extcon.h index 6b359a518eff..4bdd9dd87333 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -280,7 +280,7 @@ extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, extern const char *extcon_get_edev_name(struct extcon_dev *edev); extern int extcon_blocking_sync(struct extcon_dev *edev, unsigned int id, - bool val); + u8 val); #else /* CONFIG_EXTCON */ static inline int extcon_dev_register(struct extcon_dev *edev) { -- GitLab From fb2fba68a52b56097c910cfb97cac5280af312cb Mon Sep 17 00:00:00 2001 From: Hardik Arya Date: Wed, 6 Jun 2018 18:57:36 +0530 Subject: [PATCH 0883/1299] defconfig: arm64: sdmmagpie: Enable MPROC drivers Enable SMEM, RPMSG and Glink drivers for communication with MPSS, LPASS and CDSP. Change-Id: I3ee56dde6a9c2859c7124b1ef2a1321202790ae5 Signed-off-by: Hardik Arya --- arch/arm64/configs/vendor/sdmsteppe-perf_defconfig | 3 ++- arch/arm64/configs/vendor/sdmsteppe_defconfig | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index 9307f13eb5e3..573792da6388 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -480,7 +480,7 @@ CONFIG_IOMMU_DEBUG_TRACKING=y CONFIG_IOMMU_TESTS=y CONFIG_RPMSG_CHAR=y CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_RPMSG_QCOM_GLINK_SPSS=y +CONFIG_RPMSG_QCOM_GLINK_SPI=y CONFIG_QCOM_CPUSS_DUMP=y CONFIG_QCOM_RUN_QUEUE_STATS=y CONFIG_QCOM_LLCC=y @@ -509,6 +509,7 @@ CONFIG_QCOM_BUS_CONFIG_RPMH=y CONFIG_QCOM_COMMAND_DB=y CONFIG_QCOM_EARLY_RANDOM=y CONFIG_QTI_RPMH_API=y +CONFIG_QSEE_IPC_IRQ=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y CONFIG_QTI_RPM_STATS_LOG=y diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index efb59b304f8c..01ee88608fce 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -496,7 +496,7 @@ CONFIG_IOMMU_DEBUG_TRACKING=y CONFIG_IOMMU_TESTS=y CONFIG_RPMSG_CHAR=y CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_RPMSG_QCOM_GLINK_SPSS=y +CONFIG_RPMSG_QCOM_GLINK_SPI=y CONFIG_QCOM_CPUSS_DUMP=y CONFIG_QCOM_RUN_QUEUE_STATS=y CONFIG_QCOM_LLCC=y @@ -529,6 +529,7 @@ CONFIG_QCOM_BUS_CONFIG_RPMH=y CONFIG_QCOM_COMMAND_DB=y CONFIG_QCOM_EARLY_RANDOM=y CONFIG_QTI_RPMH_API=y +CONFIG_QSEE_IPC_IRQ=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y CONFIG_QTI_RPM_STATS_LOG=y -- GitLab From 8069c49a85d286349592265e8ff787ae9068a3c8 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Tue, 26 Jun 2018 11:35:57 +0530 Subject: [PATCH 0884/1299] ARM: dts: msm: enable graphics smmu on qcs405 Enable graphics SMMU that is used for VA to PA translations on qcs405 target. Change-Id: I083cb5de542240ae7d763457f87496a242a7ece8 Signed-off-by: Charan Teja Reddy --- arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi index 0dbe87184902..7a7beda8f149 100644 --- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi @@ -13,7 +13,7 @@ &soc { gfx_iommu: qcom,iommu@1f00000 { - status = "disabled"; + status = "okay"; compatible = "qcom,qsmmu-v500"; reg = <0x1f00000 0x10000>, <0x1ee2000 0x20>; -- GitLab From e9c434c26482368748ed61bd991679067f6c2229 Mon Sep 17 00:00:00 2001 From: Sumatheendra Raghavendrachar Date: Thu, 21 Jun 2018 19:25:12 +0530 Subject: [PATCH 0885/1299] NFC: Add driver support for NTAG Driver implementation to interact with NTAG chipsets, NTAG is NFC tags that combine passive NFC interface with contact i2c interface. Change-Id: I4f871285ece6c864f57274c86059096953e5535e Signed-off-by: Sumatheendra Raghavendrachar --- .../devicetree/bindings/nfc/nq-ntag.txt | 25 + drivers/nfc/Kconfig | 8 + drivers/nfc/Makefile | 1 + drivers/nfc/nq-ntag.c | 472 ++++++++++++++++++ drivers/nfc/nq-ntag.h | 28 ++ include/uapi/linux/nfc/Kbuild | 1 + include/uapi/linux/nfc/ntaginfo.h | 21 + 7 files changed, 556 insertions(+) create mode 100644 Documentation/devicetree/bindings/nfc/nq-ntag.txt create mode 100644 drivers/nfc/nq-ntag.c create mode 100644 drivers/nfc/nq-ntag.h create mode 100644 include/uapi/linux/nfc/ntaginfo.h diff --git a/Documentation/devicetree/bindings/nfc/nq-ntag.txt b/Documentation/devicetree/bindings/nfc/nq-ntag.txt new file mode 100644 index 000000000000..0009fb98c7ae --- /dev/null +++ b/Documentation/devicetree/bindings/nfc/nq-ntag.txt @@ -0,0 +1,25 @@ +Qualcomm Technologies, Inc NTx NTAG device + +Near Field Communication wireless tag integrated circuit device(NTAG) is compliant +with NFC Forum Type 2 Tag specification. + +Required properties: + +- compatible: "qcom,nq-ntag" +- reg: i2c slave address. +- pinctrl-names, pinctrl-0, pinctrl-1: references to our pinctrl settings +- qcom,nq-ntagfd : specific gpio for field detect interrupt. + +Example: + + nq-ntag@55 { + compatible = "qcom,nq-ntag"; + reg = <0x55>; + qcom,nq-ntagfd = <&tlmm 22 0x00>; + interrupt-parent = <&tlmm>; + interrupts = <22 0>; + interrupt-names = "ntag_fd"; + pinctrl-names = "ntag_active","ntag_suspend"; + pinctrl-0 = <&ntag_int_active>; + pinctrl-1 = <&ntag_int_suspend>; + }; diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 26e114f6c2e4..ce35eca4fc92 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig @@ -67,3 +67,11 @@ config NFC_NQ This enables the NFC driver for NQx based devices. This is for i2c connected version. NCI protocol logic resides in the usermode and it has no other NFC dependencies. + +config NTAG_NQ + tristate "QTI NTAG Driver for NTAG communication" + depends on I2C + help + This enables NTAG driver for NTx based devices. + NTAG is NFC tags that combine passive NFC interface with contact i2c interface. + This is for i2c connected version. diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index ad8b12d222cd..d8d45190599e 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/ obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5/ obj-$(CONFIG_NFC_ST95HF) += st95hf/ obj-$(CONFIG_NFC_NQ) += nq-nci.o +obj-$(CONFIG_NTAG_NQ) += nq-ntag.o diff --git a/drivers/nfc/nq-ntag.c b/drivers/nfc/nq-ntag.c new file mode 100644 index 000000000000..4d1c0861f5e9 --- /dev/null +++ b/drivers/nfc/nq-ntag.c @@ -0,0 +1,472 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nq-ntag.h" + +struct nqntag_platform_data { + unsigned int ntagfd_gpio; +}; + +const static struct of_device_id msm_match_table[] = { + {.compatible = "qcom,nq-ntag"}, + {}, +}; + +MODULE_DEVICE_TABLE(of, msm_match_table); + +struct nqntag_dev { + wait_queue_head_t fd_wq; + struct mutex fd_mutex; + struct i2c_client *client; + dev_t devno; + struct class *nqntag_class; + struct device *nqntag_device; + struct cdev c_dev; + bool irq_enabled; + bool irq_wake_up; + spinlock_t irq_enabled_lock; + char offset; + unsigned int ntagfd_gpio; + enum of_gpio_flags fdflag; + /* read buffer*/ + size_t kbuflen; + u8 *kbuf; +}; + +/** + * nqntag_irq_state() + * + * Based on state enable/disable FD interrupt + * + * Return: void + */ +static void nqntag_irq_state(struct nqntag_dev *nqntag_dev, unsigned int state) +{ + unsigned long flags; + + spin_lock_irqsave(&nqntag_dev->irq_enabled_lock, flags); + if (state == FD_DISABLE) { + if (nqntag_dev->irq_enabled) { + disable_irq_nosync(nqntag_dev->client->irq); + nqntag_dev->irq_enabled = false; + } + } else { + if (!nqntag_dev->irq_enabled) { + nqntag_dev->irq_enabled = true; + enable_irq(nqntag_dev->client->irq); + } + } + spin_unlock_irqrestore(&nqntag_dev->irq_enabled_lock, flags); +} + +static irqreturn_t nqntag_dev_irq_handler(int irq, void *dev_id) +{ + struct nqntag_dev *nqntag_dev = dev_id; + + if (device_may_wakeup(&nqntag_dev->client->dev)) + pm_wakeup_event(&nqntag_dev->client->dev, WAKEUP_SRC_TIMEOUT); + + nqntag_irq_state(nqntag_dev, FD_DISABLE); + wake_up(&nqntag_dev->fd_wq); + return IRQ_HANDLED; +} + +static ssize_t ntag_read(struct file *file, char __user *buf, size_t count, + loff_t *offset) +{ + char *readdata; + int ret = 0; + size_t tmpcount = 1; + struct nqntag_dev *nqntag_dev; + char *bufaddr = NULL; + + if (!file || !file->private_data) + return -ENODATA; + nqntag_dev = file->private_data; + if (nqntag_dev->offset < NTAG_MIN_OFFSET || + nqntag_dev->offset >= NTAG_USER_MEM_SPACE_MAX_OFFSET) { + return -EAGAIN; + } + bufaddr = &nqntag_dev->offset; + ret = i2c_master_send(nqntag_dev->client, bufaddr, tmpcount); + if (ret < 0) { + dev_err(&nqntag_dev->client->dev, + "%s: failed to write %d\n", __func__, ret); + return -EIO; + } + /* count+1 to store NULL byte */ + readdata = kzalloc(count + 1, GFP_KERNEL); + if (readdata == NULL) + return -ENOMEM; + ret = i2c_master_recv(nqntag_dev->client, readdata, count); + if (ret >= 0) + ret = copy_to_user(buf, readdata, count) ? -EFAULT : ret; + kfree(readdata); + return ret; +} + +static ssize_t ntag_write(struct file *file, const char __user *buf, + size_t count, loff_t *offset) +{ + int ret = 0; + char *writedata; + struct nqntag_dev *nqntag_dev; + + if (!file || !file->private_data) + return -ENODATA; + nqntag_dev = file->private_data; + if (nqntag_dev->offset < NTAG_MIN_OFFSET || + nqntag_dev->offset >= NTAG_USER_MEM_SPACE_MAX_OFFSET) { + return -EAGAIN; + } + /* count+2 to store Offset and NULL byte */ + writedata = kzalloc(count + 2, GFP_KERNEL); + if (writedata == NULL) + return -ENOMEM; + writedata[0] = nqntag_dev->offset; + if (copy_from_user(&writedata[1], buf, count)) { + dev_err(&nqntag_dev->client->dev, "Failed to copy from user\n"); + kfree(writedata); + return -EFAULT; + } + ret = i2c_master_send(nqntag_dev->client, writedata, count + 1); + if (ret != (count + 1)) { + dev_err(&nqntag_dev->client->dev, + "%s: failed to write %d\n", __func__, ret); + kfree(writedata); + return -EIO; + } + kfree(writedata); + return count; +} + +static int ntag_open(struct inode *inode, struct file *filp) +{ + struct nqntag_dev *nqntag_dev = container_of(inode->i_cdev, + struct nqntag_dev, c_dev); + + filp->private_data = nqntag_dev; + dev_dbg(&nqntag_dev->client->dev, + "%s: %d,%d\n", __func__, imajor(inode), iminor(inode)); + return 0; +} + +/** + * ntag_ioctl_fd_state() + * @filp: pointer to the file descriptor + * @arg: mode that we want to move to + * + * Device power control. Depending on the arg value, device moves to + * different states + * (arg = 0): FD_DISABLE + * (arg = 1): FD_ENABLE + * + * Return: -ENOIOCTLCMD if arg is not supported + */ +static int ntag_ioctl_fd_state(struct file *filp, unsigned long arg) +{ + int r = 0, ret = 0; + struct nqntag_dev *nqntag_dev = filp->private_data; + int irq_gpio_val = 0; + + if (arg == 0) { + /* Disabling FD interrupt */ + nqntag_irq_state(nqntag_dev, FD_DISABLE); + return ret; + } else if (arg == 1) { + /* Enable FD interrupt and wait for RF field detection*/ + nqntag_irq_state(nqntag_dev, FD_ENABLE); + mutex_lock(&nqntag_dev->fd_mutex); + irq_gpio_val = gpio_get_value(nqntag_dev->ntagfd_gpio); + dev_dbg(&nqntag_dev->client->dev, + "%s: READ GPIO_VAL: %d/n", __func__, irq_gpio_val); + if (!irq_gpio_val ^ nqntag_dev->fdflag) { + if (filp->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + goto err; + } + while (1) { + r = 0; + nqntag_irq_state(nqntag_dev, FD_ENABLE); + irq_gpio_val = gpio_get_value( + nqntag_dev->ntagfd_gpio); + if (!irq_gpio_val ^ nqntag_dev->fdflag) + r = wait_event_interruptible( + nqntag_dev->fd_wq, + !nqntag_dev->irq_enabled); + if (r) { + nqntag_irq_state(nqntag_dev, + FD_DISABLE); + ret = -EAGAIN; + goto err; + } else { + break; + } + } + } + } else { + ret = -EINVAL; + } +err: + mutex_unlock(&nqntag_dev->fd_mutex); + return ret; +} + +static long ntag_ioctl(struct file *pfile, unsigned int cmd, + unsigned long arg) +{ + long r = 0; + struct nqntag_dev *nqntag_dev; + + if (!pfile || !pfile->private_data) + return -ENODATA; + nqntag_dev = pfile->private_data; + switch (cmd) { + case NTAG_FD_STATE: + r = ntag_ioctl_fd_state(pfile, arg); + break; + case NTAG_SET_OFFSET: + nqntag_dev->offset = (char)arg; + break; + default: + r = -ENOIOCTLCMD; + } + return r; +} + +static const struct file_operations ntag_dev_fops = { + .llseek = no_llseek, + .read = ntag_read, + .write = ntag_write, + .open = ntag_open, + .unlocked_ioctl = ntag_ioctl, +}; + +static int nqntag_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int r = 0, irqn = 0; + struct nqntag_platform_data *pdata; + struct nqntag_dev *nqntag_dev; + enum of_gpio_flags fdflag; + + dev_dbg(&client->dev, "%s: enter\n", __func__); + pdata = devm_kzalloc(&client->dev, + sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + r = -ENOMEM; + goto err_probe; + } + pdata->ntagfd_gpio = of_get_named_gpio( + client->dev.of_node, "qcom,nq-ntagfd", 0); + if ((!gpio_is_valid(pdata->ntagfd_gpio))) { + r = -EINVAL; + goto err_probe; + } + r = of_get_named_gpio_flags( + client->dev.of_node, "qcom,nq-ntagfd", 0, &fdflag); + if (r < 0) + goto err_probe; + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "%s: need I2C_FUNC_I2C\n", __func__); + r = -ENODEV; + goto err_probe; + } + nqntag_dev = devm_kzalloc(&client->dev, sizeof(*nqntag_dev), + GFP_KERNEL); + if (nqntag_dev == NULL) { + r = -ENOMEM; + goto err_probe; + } + nqntag_dev->client = client; + nqntag_dev->fdflag = fdflag; + nqntag_dev->kbuflen = MAX_BUFFER_SIZE; + nqntag_dev->kbuf = devm_kzalloc(&client->dev, MAX_BUFFER_SIZE, + GFP_KERNEL); + if (!nqntag_dev->kbuf) { + r = -ENOMEM; + goto err_probe; + } + r = devm_gpio_request(&client->dev, pdata->ntagfd_gpio, + "ntagfd_gpio"); + if (r) { + r = -ENOMEM; + goto err_probe; + } + r = gpio_direction_input(pdata->ntagfd_gpio); + if (r) { + dev_err(&client->dev, + "%s: unable to set direction for fd gpio [%d]\n", + __func__, pdata->ntagfd_gpio); + r = -EINVAL; + goto err_probe; + } + irqn = gpio_to_irq(pdata->ntagfd_gpio); + if (irqn < 0) { + r = -EINVAL; + goto err_probe; + } + client->irq = irqn; + nqntag_dev->ntagfd_gpio = pdata->ntagfd_gpio; + /* init mutex and wait queues */ + init_waitqueue_head(&nqntag_dev->fd_wq); + mutex_init(&nqntag_dev->fd_mutex); + spin_lock_init(&nqntag_dev->irq_enabled_lock); + r = alloc_chrdev_region(&nqntag_dev->devno, 0, DEV_COUNT, DEVICE_NAME); + if (r < 0) { + dev_err(&client->dev, + "%s: failed to alloc chrdev region\n", __func__); + goto err_probe; + } + nqntag_dev->nqntag_class = class_create(THIS_MODULE, CLASS_NAME); + if (IS_ERR(nqntag_dev->nqntag_class)) { + dev_err(&client->dev, + "%s: failed to register device class\n", __func__); + r = -EINVAL; + goto err_class_create; + } + cdev_init(&nqntag_dev->c_dev, &ntag_dev_fops); + r = cdev_add(&nqntag_dev->c_dev, nqntag_dev->devno, DEV_COUNT); + if (r < 0) { + dev_err(&client->dev, "%s: failed to add cdev\n", __func__); + goto err_cdev_add; + } + nqntag_dev->nqntag_device = device_create(nqntag_dev->nqntag_class, + NULL, nqntag_dev->devno, nqntag_dev, + DEVICE_NAME); + if (IS_ERR(nqntag_dev->nqntag_device)) { + dev_err(&client->dev, + "%s: failed to create the device\n", __func__); + r = -EINVAL; + goto err_device_create; + } + /* NTAG_INT IRQ */ + nqntag_dev->irq_enabled = true; + r = devm_request_irq(&client->dev, client->irq, nqntag_dev_irq_handler, + IRQ_TYPE_EDGE_FALLING, client->name, nqntag_dev); + if (r) { + dev_err(&client->dev, "%s: request_irq failed\n", __func__); + goto err_request_irq_failed; + } + nqntag_irq_state(nqntag_dev, FD_DISABLE); + device_init_wakeup(&client->dev, true); + i2c_set_clientdata(client, nqntag_dev); + nqntag_dev->irq_wake_up = false; + return 0; + +err_request_irq_failed: + device_destroy(nqntag_dev->nqntag_class, nqntag_dev->devno); +err_device_create: + cdev_del(&nqntag_dev->c_dev); +err_cdev_add: + class_destroy(nqntag_dev->nqntag_class); +err_class_create: + unregister_chrdev_region(nqntag_dev->devno, DEV_COUNT); +err_probe: + dev_err(&client->dev, "%s: probing NQ NTAG failed ret: %d\n", + __func__, r); + return r; +} + +static int nqntag_remove(struct i2c_client *client) +{ + struct nqntag_dev *nqntag_dev; + + nqntag_dev = i2c_get_clientdata(client); + device_destroy(nqntag_dev->nqntag_class, nqntag_dev->devno); + cdev_del(&nqntag_dev->c_dev); + class_destroy(nqntag_dev->nqntag_class); + unregister_chrdev_region(nqntag_dev->devno, DEV_COUNT); + return 0; +} + +#ifdef CONFIG_PM +/* + * power management + */ +static int nqntag_suspend(struct device *device) +{ + struct i2c_client *client = to_i2c_client(device); + struct nqntag_dev *nqntag_dev = i2c_get_clientdata(client); + + nqntag_irq_state(nqntag_dev, FD_ENABLE); + if (device_may_wakeup(&client->dev)) { + if (!enable_irq_wake(client->irq)) + nqntag_dev->irq_wake_up = true; + } + return 0; +} + +static int nqntag_resume(struct device *device) +{ + struct i2c_client *client = to_i2c_client(device); + struct nqntag_dev *nqntag_dev = i2c_get_clientdata(client); + + nqntag_irq_state(nqntag_dev, FD_DISABLE); + if (device_may_wakeup(&client->dev) && nqntag_dev->irq_wake_up) { + if (!disable_irq_wake(client->irq)) + nqntag_dev->irq_wake_up = false; + } + return 0; +} +#endif /* CONFIG_PM */ + +static const struct i2c_device_id nqntag_id[] = { + {"nqntag-i2c", 0}, + {}, +}; +static const struct dev_pm_ops ntag_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(nqntag_suspend, + nqntag_resume) +}; + +static struct i2c_driver nqntag = { + .id_table = nqntag_id, + .probe = nqntag_probe, + .remove = nqntag_remove, + .driver = { + .name = "nq-ntag", + .of_match_table = msm_match_table, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + .pm = &ntag_pm_ops, + }, +}; + +static int __init nqntag_dev_init(void) +{ + return i2c_add_driver(&nqntag); +} +module_init(nqntag_dev_init); + +static void __exit nqntag_dev_exit(void) +{ + i2c_del_driver(&nqntag); +} +module_exit(nqntag_dev_exit); + +MODULE_DESCRIPTION("NTAG nqntag"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/nfc/nq-ntag.h b/drivers/nfc/nq-ntag.h new file mode 100644 index 000000000000..e1e9814dffc7 --- /dev/null +++ b/drivers/nfc/nq-ntag.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __NQ_NTAG_H +#define __NQ_NTAG_H + +#include + +#define DEV_COUNT 1 +#define DEVICE_NAME "nq-ntag" +#define CLASS_NAME "nqntag" +#define FD_DISABLE 1 +#define FD_ENABLE 0 +#define MAX_BUFFER_SIZE (320) +#define WAKEUP_SRC_TIMEOUT (2000) +#define NTAG_MIN_OFFSET 0 +#define NTAG_USER_MEM_SPACE_MAX_OFFSET 56 + +#endif diff --git a/include/uapi/linux/nfc/Kbuild b/include/uapi/linux/nfc/Kbuild index 90710153e462..62a89b999e88 100644 --- a/include/uapi/linux/nfc/Kbuild +++ b/include/uapi/linux/nfc/Kbuild @@ -1,2 +1,3 @@ #UAPI export list header-y += nfcinfo.h +header-y += ntaginfo.h diff --git a/include/uapi/linux/nfc/ntaginfo.h b/include/uapi/linux/nfc/ntaginfo.h new file mode 100644 index 000000000000..1deee3e4d455 --- /dev/null +++ b/include/uapi/linux/nfc/ntaginfo.h @@ -0,0 +1,21 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _UAPI_NTAGINFO_H_ +#define _UAPI_NTAGINFO_H_ + +#include + +#define NTAG_FD_STATE _IOW(0xE9, 0x01, unsigned int) +#define NTAG_SET_OFFSET _IOW(0xE9, 0x02, unsigned int) + +#endif -- GitLab From b4d36be28c4a69b676a16c9150b08df82c074555 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Wed, 27 Jun 2018 12:03:29 +0530 Subject: [PATCH 0886/1299] defconfig: arm/arm64: add smmu config for secure usecases on qcs405 Add the smmu config option that is used for the secure usecases running on QCS405. Change-Id: I67d64a9342b62c51e919c7da61e132467b74ce70 Signed-off-by: Charan Teja Reddy --- arch/arm/configs/vendor/qcs405_defconfig | 1 + arch/arm64/configs/vendor/qcs405_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index fac263b18316..b018a93ed561 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -415,6 +415,7 @@ CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_CORE_HANG_DETECT=y CONFIG_QCOM_DCC_V2=y CONFIG_QCOM_BUS_SCALING=y +CONFIG_MSM_TZ_SMMU=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y # CONFIG_MSM_JTAGV8 is not set diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index 5cf358ccdab1..9a0d19424602 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -415,6 +415,7 @@ CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_CORE_HANG_DETECT=y CONFIG_QCOM_DCC_V2=y CONFIG_QCOM_BUS_SCALING=y +CONFIG_MSM_TZ_SMMU=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y CONFIG_MSM_PM=y -- GitLab From 10aea9d07dd9ddcda7f511e16c1c410be46e20c9 Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Wed, 27 Jun 2018 12:46:19 +0530 Subject: [PATCH 0887/1299] devfreq: update freq variable in compute_freq function Update freq variable from unsigned long to uint64_t of compute_freq function to be in compliance with 32 bit environment. Change-Id: Ia9183b0e593daf3780135a8e1ae8ddb36db16f86 Signed-off-by: Santosh Mardi --- drivers/devfreq/arm-memlat-mon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/devfreq/arm-memlat-mon.c b/drivers/devfreq/arm-memlat-mon.c index defd6ab97476..d8193289a32e 100644 --- a/drivers/devfreq/arm-memlat-mon.c +++ b/drivers/devfreq/arm-memlat-mon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -77,7 +77,7 @@ static unsigned long compute_freq(struct cpu_pmu_stats *cpustats, { ktime_t ts; unsigned int diff; - unsigned long freq = 0; + uint64_t freq = 0; ts = ktime_get(); diff = ktime_to_us(ktime_sub(ts, cpustats->prev_ts)); -- GitLab From 42c3d45ba388c1974b94d0309b997f956ea08d8c Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Tue, 26 Jun 2018 14:50:09 +0530 Subject: [PATCH 0888/1299] defconfig: enable compute governor on qcs405 target To enable compute governor on qcs405 target enable memlat monitor and governor. Change-Id: I19c6663e2e83311d8c1ace8adb73360d8c0dc030 Signed-off-by: Santosh Mardi --- arch/arm/configs/vendor/qcs405_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index fac263b18316..03a5db1fe55e 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -418,6 +418,8 @@ CONFIG_QCOM_BUS_SCALING=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y # CONFIG_MSM_JTAGV8 is not set +CONFIG_ARM_MEMLAT_MON=y +CONFIG_DEVFREQ_GOV_MEMLAT=y CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y -- GitLab From 46e003728f7e72948299b5c9c69f17aa0809dc89 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Fri, 29 Sep 2017 18:04:45 -0700 Subject: [PATCH 0889/1299] of: reserved_mem: Fix kmemleak crash on no-map region Unable to handle kernel paging request at virtual address [] scan_block+0x88/0x170 [] scan_gray_list+0x18c/0x1c0 [] kmemleak_scan+0x208/0x4b0 [] kmemleak_write+0x338/0x378 [] full_proxy_write+0x80/0xe4 [] vfs_write+0xb4/0x1d0 early_init_dt_alloc_reserved_memory_arch() calls memblock_alloc_base(), which will create a kmemleak entry. Ensure this entry is ignored if the no-map property is set. This will prevent kmemleak from scanning the object if there is no kernel mapping for it. Change-Id: I45f35600ae2aacf0f10f8bcbc956d019b666e4a7 Signed-off-by: Patrick Daly Signed-off-by: Sudarshan Rajagopalan --- drivers/of/of_reserved_mem.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 91767d394b7a..3729fd1544b4 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -24,6 +24,7 @@ #include #include #include +#include #define MAX_RESERVED_REGIONS 32 static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; @@ -54,8 +55,10 @@ int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, } *res_base = base; - if (nomap) + if (nomap) { + kmemleak_ignore_phys(base); return memblock_remove(base, size); + } return 0; } #else -- GitLab From 1cfb7a7f42f320358a43873e7ed6e17b85609702 Mon Sep 17 00:00:00 2001 From: Yogesh Lal Date: Wed, 27 Jun 2018 15:17:56 +0530 Subject: [PATCH 0890/1299] defconfig: Enable page_owner for sdmshrike on perf config This patch enables CONFIG_PAGE_OWNER on perf config. The feature is not enabled by default and needs to be enabled via boot param "page_owner=on". Set STACK_HASH_ORDER_SHIFT to 12 to reduce stack depot hash size. Default value of STACK_HASH_ORDER_SHIFT=20 makes stack depot to consume 8MB of static memory. With STACK_HASH_ORDER_SHIFT=12 stack depot consume only 104KB. The time taken to read from /sys/kernel/debug/page_owner increased by around 60 secs with this patch on a 6 GB target, but we can live with it as it's a only debug feature. Change-Id: I71b1ad661d6aac3185257dba4d30427da7b555ae Signed-off-by: Yogesh Lal --- arch/arm64/configs/vendor/sdmshrike-perf_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sdmshrike-perf_defconfig b/arch/arm64/configs/vendor/sdmshrike-perf_defconfig index 23b8c69dfa56..d616eaaee5f4 100644 --- a/arch/arm64/configs/vendor/sdmshrike-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmshrike-perf_defconfig @@ -430,6 +430,7 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO=y +CONFIG_PAGE_OWNER=y CONFIG_MAGIC_SYSRQ=y CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y @@ -451,3 +452,4 @@ CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_STACK_HASH_ORDER_SHIFT=12 -- GitLab From a2f7ae6e1024934b875eaae913e9da6f39e0cd96 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Wed, 20 Jun 2018 18:36:57 +0530 Subject: [PATCH 0891/1299] msm: ipa: wdi: Add a boolean flag to represent wdi tx over pcie WLAN TX CE Door Bell register may over pcie or DDR. If SMMU S1 is enabled and CE DB register is over PCIe bus, then assign the physical address directly instead of SMMU's Intermediate physical address. Because, IPA PCIe master port does not go through SMMU. Change-Id: I4a7ed4e1e63bd08b7fe37c676d411feaad48257a Signed-off-by: Mohammed Javid --- .../devicetree/bindings/platform/msm/ipa.txt | 2 + drivers/platform/msm/ipa/ipa_v3/ipa.c | 7 + drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 2 + drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c | 139 ++++++++++++------ 4 files changed, 104 insertions(+), 46 deletions(-) diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt index 6983ad330f03..22e235748496 100644 --- a/Documentation/devicetree/bindings/platform/msm/ipa.txt +++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt @@ -89,6 +89,8 @@ memory allocation over a PCIe bridge monitoring of holb via IPA uc is required. -qcom,ipa-fltrt-not-hashable: Boolean context flag to indicate filter/route rules hashing not supported. +- qcom,wlan-ce-db-over-pcie: Boolean context flag to represent WLAN CE DB + over pcie bus or not. IPA pipe sub nodes (A2 static pipes configurations): diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 3f1525121115..1d08b1352f6c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -5150,6 +5150,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, ipa3_ctx->apply_rg10_wa = resource_p->apply_rg10_wa; ipa3_ctx->gsi_ch20_wa = resource_p->gsi_ch20_wa; ipa3_ctx->use_ipa_pm = resource_p->use_ipa_pm; + ipa3_ctx->wdi_over_pcie = resource_p->wdi_over_pcie; ipa3_ctx->ipa3_active_clients_logging.log_rdy = false; ipa3_ctx->ipa_config_is_mhi = resource_p->ipa_mhi_dynamic_config; ipa3_ctx->mhi_evid_limits[0] = resource_p->mhi_evid_limits[0]; @@ -5978,6 +5979,12 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, return result; } + ipa_drv_res->wdi_over_pcie = + of_property_read_bool(pdev->dev.of_node, + "qcom,wlan-ce-db-over-pcie"); + IPADBG("Is wdi_over_pcie ? (%s)\n", + ipa3_ctx->wdi_over_pcie ? "Yes":"No"); + return 0; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index c71d9448186d..3749bc585a54 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1427,6 +1427,7 @@ struct ipa3_context { struct mutex ipa_cne_evt_lock; bool use_ipa_pm; bool vlan_mode_iface[IPA_VLAN_IF_MAX]; + bool wdi_over_pcie; }; struct ipa3_plat_drv_res { @@ -1459,6 +1460,7 @@ struct ipa3_plat_drv_res { struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg; bool use_ipa_pm; struct ipa_pm_init_params pm_init; + bool wdi_over_pcie; }; /** diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c index 24ef2928f304..e06d6a4760f6 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c @@ -762,16 +762,21 @@ int ipa3_connect_wdi_pipe(struct ipa_wdi_in_params *in, return -EINVAL; } - if (IPA_CLIENT_IS_CONS(in->sys.client)) { - if (in->u.dl.comp_ring_base_pa % IPA_WDI_RING_ALIGNMENT || - in->u.dl.ce_ring_base_pa % IPA_WDI_RING_ALIGNMENT) { - IPAERR("alignment failure on TX\n"); - return -EINVAL; - } - } else { - if (in->u.ul.rdy_ring_base_pa % IPA_WDI_RING_ALIGNMENT) { - IPAERR("alignment failure on RX\n"); - return -EINVAL; + if (!in->smmu_enabled) { + if (IPA_CLIENT_IS_CONS(in->sys.client)) { + if (in->u.dl.comp_ring_base_pa % + IPA_WDI_RING_ALIGNMENT || + in->u.dl.ce_ring_base_pa % + IPA_WDI_RING_ALIGNMENT) { + IPAERR("alignment failure on TX\n"); + return -EINVAL; + } + } else { + if (in->u.ul.rdy_ring_base_pa % + IPA_WDI_RING_ALIGNMENT) { + IPAERR("alignment failure on RX\n"); + return -EINVAL; + } } } @@ -801,43 +806,73 @@ int ipa3_connect_wdi_pipe(struct ipa_wdi_in_params *in, cmd.size = sizeof(*tx_2); else cmd.size = sizeof(*tx); - IPADBG("comp_ring_base_pa=0x%pa\n", - &in->u.dl.comp_ring_base_pa); - IPADBG("comp_ring_size=%d\n", in->u.dl.comp_ring_size); - IPADBG("ce_ring_base_pa=0x%pa\n", &in->u.dl.ce_ring_base_pa); - IPADBG("ce_ring_size=%d\n", in->u.dl.ce_ring_size); - IPADBG("ce_ring_doorbell_pa=0x%pa\n", - &in->u.dl.ce_door_bell_pa); - IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers); + if (in->smmu_enabled) { + IPADBG("comp_ring_size=%d\n", + in->u.dl_smmu.comp_ring_size); + IPADBG("ce_ring_size=%d\n", in->u.dl_smmu.ce_ring_size); + IPADBG("ce_ring_doorbell_pa=0x%pa\n", + &in->u.dl_smmu.ce_door_bell_pa); + IPADBG("num_tx_buffers=%d\n", + in->u.dl_smmu.num_tx_buffers); + } else { + IPADBG("comp_ring_base_pa=0x%pa\n", + &in->u.dl.comp_ring_base_pa); + IPADBG("comp_ring_size=%d\n", in->u.dl.comp_ring_size); + IPADBG("ce_ring_base_pa=0x%pa\n", + &in->u.dl.ce_ring_base_pa); + IPADBG("ce_ring_size=%d\n", in->u.dl.ce_ring_size); + IPADBG("ce_ring_doorbell_pa=0x%pa\n", + &in->u.dl.ce_door_bell_pa); + IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers); + } } else { if (ipa3_ctx->ipa_wdi2) cmd.size = sizeof(*rx_2); else cmd.size = sizeof(*rx); - IPADBG("rx_ring_base_pa=0x%pa\n", - &in->u.ul.rdy_ring_base_pa); - IPADBG("rx_ring_size=%d\n", - in->u.ul.rdy_ring_size); - IPADBG("rx_ring_rp_pa=0x%pa\n", - &in->u.ul.rdy_ring_rp_pa); - IPADBG("rx_comp_ring_base_pa=0x%pa\n", - &in->u.ul.rdy_comp_ring_base_pa); - IPADBG("rx_comp_ring_size=%d\n", - in->u.ul.rdy_comp_ring_size); - IPADBG("rx_comp_ring_wp_pa=0x%pa\n", - &in->u.ul.rdy_comp_ring_wp_pa); - ipa3_ctx->uc_ctx.rdy_ring_base_pa = - in->u.ul.rdy_ring_base_pa; - ipa3_ctx->uc_ctx.rdy_ring_rp_pa = - in->u.ul.rdy_ring_rp_pa; - ipa3_ctx->uc_ctx.rdy_ring_size = - in->u.ul.rdy_ring_size; - ipa3_ctx->uc_ctx.rdy_comp_ring_base_pa = - in->u.ul.rdy_comp_ring_base_pa; - ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa = - in->u.ul.rdy_comp_ring_wp_pa; - ipa3_ctx->uc_ctx.rdy_comp_ring_size = - in->u.ul.rdy_comp_ring_size; + if (in->smmu_enabled) { + IPADBG("rx_ring_size=%d\n", + in->u.ul_smmu.rdy_ring_size); + IPADBG("rx_ring_rp_pa=0x%pa\n", + &in->u.ul_smmu.rdy_ring_rp_pa); + IPADBG("rx_comp_ring_size=%d\n", + in->u.ul_smmu.rdy_comp_ring_size); + IPADBG("rx_comp_ring_wp_pa=0x%pa\n", + &in->u.ul_smmu.rdy_comp_ring_wp_pa); + ipa3_ctx->uc_ctx.rdy_ring_rp_pa = + in->u.ul_smmu.rdy_ring_rp_pa; + ipa3_ctx->uc_ctx.rdy_ring_size = + in->u.ul_smmu.rdy_ring_size; + ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa = + in->u.ul_smmu.rdy_comp_ring_wp_pa; + ipa3_ctx->uc_ctx.rdy_comp_ring_size = + in->u.ul_smmu.rdy_comp_ring_size; + } else { + IPADBG("rx_ring_base_pa=0x%pa\n", + &in->u.ul.rdy_ring_base_pa); + IPADBG("rx_ring_size=%d\n", + in->u.ul.rdy_ring_size); + IPADBG("rx_ring_rp_pa=0x%pa\n", + &in->u.ul.rdy_ring_rp_pa); + IPADBG("rx_comp_ring_base_pa=0x%pa\n", + &in->u.ul.rdy_comp_ring_base_pa); + IPADBG("rx_comp_ring_size=%d\n", + in->u.ul.rdy_comp_ring_size); + IPADBG("rx_comp_ring_wp_pa=0x%pa\n", + &in->u.ul.rdy_comp_ring_wp_pa); + ipa3_ctx->uc_ctx.rdy_ring_base_pa = + in->u.ul.rdy_ring_base_pa; + ipa3_ctx->uc_ctx.rdy_ring_rp_pa = + in->u.ul.rdy_ring_rp_pa; + ipa3_ctx->uc_ctx.rdy_ring_size = + in->u.ul.rdy_ring_size; + ipa3_ctx->uc_ctx.rdy_comp_ring_base_pa = + in->u.ul.rdy_comp_ring_base_pa; + ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa = + in->u.ul.rdy_comp_ring_wp_pa; + ipa3_ctx->uc_ctx.rdy_comp_ring_size = + in->u.ul.rdy_comp_ring_size; + } } cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size, @@ -951,10 +986,11 @@ int ipa3_connect_wdi_pipe(struct ipa_wdi_in_params *in, tx->comp_ring_size = len; len = in->smmu_enabled ? in->u.dl_smmu.ce_ring_size : in->u.dl.ce_ring_size; - IPADBG("TX CE ring smmu_en=%d ring_size=%d %d\n", + IPADBG("TX CE ring smmu_en=%d ring_size=%d %d 0x%lx\n", in->smmu_enabled, in->u.dl_smmu.ce_ring_size, - in->u.dl.ce_ring_size); + in->u.dl.ce_ring_size, + va); if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES, in->smmu_enabled, in->u.dl.ce_ring_base_pa, @@ -981,8 +1017,19 @@ int ipa3_connect_wdi_pipe(struct ipa_wdi_in_params *in, result = -ENOMEM; goto uc_timeout; } - tx->ce_ring_doorbell_pa = va; - tx->num_tx_buffers = in->u.dl.num_tx_buffers; + + IPADBG("CE doorbell pa: 0x%pa va:0x%lx\n", &pa, va); + IPADBG("Is wdi_over_pcie ? (%s)\n", + ipa3_ctx->wdi_over_pcie ? "Yes":"No"); + + if (ipa3_ctx->wdi_over_pcie) + tx->ce_ring_doorbell_pa = pa; + else + tx->ce_ring_doorbell_pa = va; + + tx->num_tx_buffers = in->smmu_enabled ? + in->u.dl_smmu.num_tx_buffers : + in->u.dl.num_tx_buffers; tx->ipa_pipe_number = ipa_ep_idx; } out->uc_door_bell_pa = ipa3_ctx->ipa_wrapper_base + -- GitLab From 5d18901ca60de15fd29f9bc7e6ab31d0af38a5e7 Mon Sep 17 00:00:00 2001 From: Yogesh Lal Date: Wed, 27 Jun 2018 16:07:56 +0530 Subject: [PATCH 0892/1299] defconfig: Enable page_owner for sdmsteppe on perf config This patch enables CONFIG_PAGE_OWNER on perf config. The feature is not enabled by default and needs to be enabled via boot param "page_owner=on". Set STACK_HASH_ORDER_SHIFT to 12 to reduce stack depot hash size. Default value of STACK_HASH_ORDER_SHIFT=20 makes stack depot to consume 8MB of static memory. With STACK_HASH_ORDER_SHIFT=12 stack depot consume only 104KB. The time taken to read from /sys/kernel/debug/page_owner increased by around 60 secs with this patch on a 6 GB target, but we can live with it as it's a only debug feature. Change-Id: Idf321138e69a246f357ded77e521ec453d16e7dc Signed-off-by: Yogesh Lal --- arch/arm64/configs/vendor/sdmsteppe-perf_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index 9307f13eb5e3..483079168e77 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -565,6 +565,7 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO=y +CONFIG_PAGE_OWNER=y CONFIG_MAGIC_SYSRQ=y CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y @@ -604,3 +605,4 @@ CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_STACK_HASH_ORDER_SHIFT=12 -- GitLab From b625338a83f64c5ae694976285c346e21ac6bc3e Mon Sep 17 00:00:00 2001 From: Fei Mao Date: Tue, 26 Jun 2018 18:53:39 +0800 Subject: [PATCH 0893/1299] input: touchscreen: multi-touch for ST touch To support multi-touch better for ST touch, change the touch event report method. Change-Id: I6e36a5178d6910e20486e31aed9029d026e90bdf Signed-off-by: Fei Mao --- drivers/input/touchscreen/st/fts.c | 96 ++++++++++-------------------- 1 file changed, 31 insertions(+), 65 deletions(-) diff --git a/drivers/input/touchscreen/st/fts.c b/drivers/input/touchscreen/st/fts.c index e30f6e4a5dfd..c45671db6c2a 100644 --- a/drivers/input/touchscreen/st/fts.c +++ b/drivers/input/touchscreen/st/fts.c @@ -2780,14 +2780,16 @@ static void fts_enter_pointer_event_handler(struct fts_ts_info *info, touchId = event[1] & 0x0F; touchcount = (event[1] & 0xF0) >> 4; touchsize = (event[5] & 0xC0) >> 6; - major = (event[5] & 0x1F); // bit0-bit4: major - minor = event[6]; // event6:minor + major = (event[5] & 0x1F); // bit0-bit4: major + minor = event[6]; // event6:minor __set_bit(touchId, &info->touch_id); x = (event[2] << 4) | (event[4] & 0xF0) >> 4; y = (event[3] << 4) | (event[4] & 0x0F); z = (event[5] & 0x3F); + if (z == 0) + z = 10; if (x == X_AXIS_MAX) x--; @@ -2796,54 +2798,31 @@ static void fts_enter_pointer_event_handler(struct fts_ts_info *info, y--; input_mt_slot(info->input_dev, touchId); -/*#ifdef STYLUS_MODE*/ - /** - * TODO: check with ST how FW report a - * stylus touch in the touch event, - * this is an example code - */ - /*if (info->stylus_enabled == 1 && touchsize == STYLUS_SIZE) {*/ - /*__set_bit(touchId, &info->stylus_id);*/ - /*input_mt_report_slot_state(info->input_dev, MT_TOOL_PEN, 1);*/ - /*logError(0, "%s %s : It is a stylus!\n",tag,__func__); */ - /*} else*/ - /*input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 1);*/ -/*#else*/ - /*input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 1);*/ -/*#endif*/ input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 1); - /*logError(0,*/ - /*"%s %s:TouchID = %d, Touchcount = %d, minor:%d, major:%d\n",*/ - /*tag, __func__, touchId, touchcount, minor, major);*/ - /*logError(0,*/ - /*"%s %s : TouchID = %d,Touchcount = %d\n",*/ - /*tag, __func__, touchId,touchcount);*/ - /*if (touchcount == 1) {*/ - input_report_key(info->input_dev, BTN_TOUCH, 1); - input_report_key(info->input_dev, BTN_TOOL_FINGER, 1); - /*}*/ - /* input_report_abs(info->input_dev, ABS_MT_TRACKING_ID, touchId);*/ + + logError(0, "%s %s : TouchID = %d,Touchcount = %d,minor:%d,major:%d\n", + tag, __func__, touchId, touchcount, minor, major); + + if (touchcount == 1) { + input_report_key(info->input_dev, BTN_TOUCH, 1); + input_report_key(info->input_dev, BTN_TOOL_FINGER, 1); + } input_report_abs(info->input_dev, ABS_MT_POSITION_X, x); input_report_abs(info->input_dev, ABS_MT_POSITION_Y, y); - /*input_report_abs(info->input_dev, ABS_MT_TOUCH_MAJOR, z);*/ - /*input_report_abs(info->input_dev, ABS_MT_TOUCH_MINOR, z);*/ - /*input_report_abs(info->input_dev, ABS_MT_PRESSURE, z);*/ input_report_abs(info->input_dev, ABS_MT_TOUCH_MAJOR, major); input_report_abs(info->input_dev, ABS_MT_TOUCH_MINOR, minor); + input_report_abs(info->input_dev, ABS_MT_PRESSURE, z); input_report_abs(info->input_dev, ABS_MT_DISTANCE, distance); - /*logError(0,*/ - /*"%s%s:Event 0x%02x - ID[%d], (x, y, z) = (%3d, %3d, %3d)\n",*/ - /*tag, __func__, *event, touchId, x, y, z);*/ - no_report: return; - /* return fts_next_event(event); */ + } /* EventId : 0x04 */ static void fts_leave_pointer_event_handler(struct fts_ts_info *info, - unsigned char *event) + unsigned char *event) { + unsigned char touchId, touchcount; u8 touchsize; @@ -2851,37 +2830,18 @@ static void fts_leave_pointer_event_handler(struct fts_ts_info *info, touchcount = (event[1] & 0xF0) >> 4; touchsize = (event[5] & 0xC0) >> 6; - __clear_bit(touchId, &info->touch_id); - input_mt_slot(info->input_dev, touchId); -/*#ifdef STYLUS_MODE*/ - /** - * TODO: check with ST how FW report a stylus touch - * in the touch event, this is an example code - */ - /*if (info->stylus_enabled == 1 && touchsize == STYLUS_SIZE) {*/ - /* __clear_bit(touchId, &info->stylus_id);*/ - /* input_mt_report_slot_state(info->input_dev, MT_TOOL_PEN, 0);*/ - /*logError(0, "%s %s : It is a stylus!\n",tag,__func__);*/ - /*} else*/ - /*input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 0);*/ -/*#else*/ - /*input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 0);*/ -/*#endif*/ + + __clear_bit(touchId, &info->touch_id); input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 0); - /* input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 0);*/ - /*logError(0, "%s %s : TouchID = %d, Touchcount = %d\n",*/ - /*tag,__func__,touchId,touchcount);*/ - /*if (touchcount == 0) {*/ - input_report_key(info->input_dev, BTN_TOUCH, 0); - input_report_key(info->input_dev, BTN_TOOL_FINGER, 0); - /*}*/ + + if (touchcount == 0) { + input_report_key(info->input_dev, BTN_TOUCH, 0); + input_report_key(info->input_dev, BTN_TOOL_FINGER, 0); + } input_report_abs(info->input_dev, ABS_MT_TRACKING_ID, -1); - /*logError(0, "%s %s : Event 0x%02x - release ID[%d]\n",*/ - /*tag, __func__, event[0], touchId);*/ - /*return fts_next_event(event);*/ } /* EventId : 0x05 */ @@ -3932,12 +3892,15 @@ static int fts_fb_state_chg_callback(struct notifier_block *nb, struct fb_event *evdata = data; unsigned int blank; + if (!evdata || (evdata->id != 0)) + return 0; + if (val != FB_EVENT_BLANK) return 0; logError(0, "%s %s: fts notifier begin!\n", tag, __func__); - if (evdata && evdata->data && val == FB_EVENT_BLANK && info) { + if (evdata->data && val == FB_EVENT_BLANK && info) { blank = *(int *) (evdata->data); @@ -3978,11 +3941,14 @@ static int fts_fb_state_chg_callback(struct notifier_block *nb, struct msm_drm_notifier *evdata = data; unsigned int blank; + if (!evdata || (evdata->id != 0)) + return 0; + if (val != MSM_DRM_EVENT_BLANK) return 0; logError(0, "%s %s: fts notifier begin!\n", tag, __func__); - if (evdata && evdata->data && val == MSM_DRM_EVENT_BLANK && info) { + if (evdata->data && val == MSM_DRM_EVENT_BLANK && info) { blank = *(int *) (evdata->data); switch (blank) { -- GitLab From 215cdfb6a25ca271c2066fa911a5418350871579 Mon Sep 17 00:00:00 2001 From: Ashay Jaiswal Date: Wed, 27 Jun 2018 09:48:56 +0530 Subject: [PATCH 0894/1299] ARM: dts: msm: update regulator min/max voltages for sdmmagpie Update regulator min/max threshold as per AOP configuration. Change-Id: If8414e13c2cfbc96788b22a023e272e39c944398 Signed-off-by: Ashay Jaiswal --- .../boot/dts/qcom/sdmmagpie-regulator.dtsi | 122 +++++++++--------- .../dts/qcom/sdmmagpie-stub-regulator.dtsi | 78 +++++------ arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 1 + 3 files changed, 102 insertions(+), 99 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi index 621a6edad16a..ce55cc63ee77 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-regulator.dtsi @@ -82,6 +82,8 @@ compatible = "qcom,rpmh-arc-regulator"; mboxes = <&apps_rsc 0>; qcom,resource-name = "cx.lvl"; + pm6150l-s2-level-parent-supply = <&VDD_MX_LEVEL>; + pm6150l-s2-level_ao-parent-supply = <&VDD_MX_LEVEL_AO>; VDD_CX_LEVEL: S2C_LEVEL: pm6150l_s2_level: regulator-pm6150l-s2 { @@ -154,9 +156,9 @@ L1A: pm6150_l1: regulator-pm6150-l1 { regulator-name = "pm6150_l1"; qcom,set = ; - regulator-min-microvolt = <1200000>; + regulator-min-microvolt = <1174000>; regulator-max-microvolt = <1252000>; - qcom,init-voltage = <1200000>; + qcom,init-voltage = <1174000>; }; }; @@ -172,9 +174,9 @@ L2A: pm6150_l2: regulator-pm6150-l2 { regulator-name = "pm6150_l2"; qcom,set = ; - regulator-min-microvolt = <1000000>; + regulator-min-microvolt = <944000>; regulator-max-microvolt = <1050000>; - qcom,init-voltage = <1000000>; + qcom,init-voltage = <944000>; qcom,init-mode = ; }; }; @@ -191,9 +193,9 @@ L3A: pm6150_l3: regulator-pm6150-l3 { regulator-name = "pm6150_l3"; qcom,set = ; - regulator-min-microvolt = <1000000>; + regulator-min-microvolt = <968000>; regulator-max-microvolt = <1060000>; - qcom,init-voltage = <1000000>; + qcom,init-voltage = <968000>; qcom,init-mode = ; }; }; @@ -210,9 +212,9 @@ L4A: pm6150_l4: regulator-pm6150-l4 { regulator-name = "pm6150_l4"; qcom,set = ; - regulator-min-microvolt = <875000>; - regulator-max-microvolt = <975000>; - qcom,init-voltage = <875000>; + regulator-min-microvolt = <824000>; + regulator-max-microvolt = <920000>; + qcom,init-voltage = <824000>; qcom,init-mode = ; }; }; @@ -229,9 +231,9 @@ L5A: pm6150_l5: regulator-pm6150-l5 { regulator-name = "pm6150_l5"; qcom,set = ; - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <2970000>; - qcom,init-voltage = <2500000>; + regulator-min-microvolt = <2600000>; + regulator-max-microvolt = <2800000>; + qcom,init-voltage = <2600000>; qcom,init-mode = ; }; }; @@ -248,9 +250,9 @@ L6A: pm6150_l6: regulator-pm6150-l6 { regulator-name = "pm6150_l6"; qcom,set = ; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - qcom,init-voltage = <1200000>; + regulator-min-microvolt = <1096000>; + regulator-max-microvolt = <1304000>; + qcom,init-voltage = <1096000>; qcom,init-mode = ; }; }; @@ -305,9 +307,9 @@ L9A: pm6150_l9: regulator-pm6150-l9 { regulator-name = "pm6150_l9"; qcom,set = ; - regulator-min-microvolt = <400000>; - regulator-max-microvolt = <728000>; - qcom,init-voltage = <400000>; + regulator-min-microvolt = <624000>; + regulator-max-microvolt = <760000>; + qcom,init-voltage = <624000>; qcom,init-mode = ; }; }; @@ -324,9 +326,9 @@ L10A: pm6150_l10: regulator-pm6150-l10 { regulator-name = "pm6150_l10"; qcom,set = ; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1829000>; - qcom,init-voltage = <1800000>; + regulator-min-microvolt = <1720000>; + regulator-max-microvolt = <1832000>; + qcom,init-voltage = <1720000>; qcom,init-mode = ; }; }; @@ -343,9 +345,9 @@ L11A: pm6150_l11: regulator-pm6150-l11 { regulator-name = "pm6150_l11"; qcom,set = ; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1890000>; - qcom,init-voltage = <1800000>; + regulator-min-microvolt = <1616000>; + regulator-max-microvolt = <1984000>; + qcom,init-voltage = <1616000>; qcom,init-mode = ; }; }; @@ -362,9 +364,9 @@ L12A: pm6150_l12: regulator-pm6150-l12 { regulator-name = "pm6150_l12"; qcom,set = ; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1950000>; - qcom,init-voltage = <1800000>; + regulator-min-microvolt = <1696000>; + regulator-max-microvolt = <1952000>; + qcom,init-voltage = <1696000>; qcom,init-mode = ; }; }; @@ -381,9 +383,9 @@ L13A: pm6150_l13: regulator-pm6150-l13 { regulator-name = "pm6150_l13"; qcom,set = ; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1900000>; - qcom,init-voltage = <1800000>; + regulator-min-microvolt = <1696000>; + regulator-max-microvolt = <1904000>; + qcom,init-voltage = <1696000>; qcom,init-mode = ; }; }; @@ -400,9 +402,9 @@ L14A: pm6150_l14: regulator-pm6150-l14 { regulator-name = "pm6150_l14"; qcom,set = ; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1850000>; - qcom,init-voltage = <1800000>; + regulator-min-microvolt = <1720000>; + regulator-max-microvolt = <1856000>; + qcom,init-voltage = <1720000>; qcom,init-mode = ; }; }; @@ -419,9 +421,9 @@ L15A: pm6150_l15: regulator-pm6150-l15 { regulator-name = "pm6150_l15"; qcom,set = ; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1900000>; - qcom,init-voltage = <1800000>; + regulator-min-microvolt = <1696000>; + regulator-max-microvolt = <1904000>; + qcom,init-voltage = <1696000>; qcom,init-mode = ; }; }; @@ -438,9 +440,9 @@ L16A: pm6150_l16: regulator-pm6150-l16 { regulator-name = "pm6150_l16"; qcom,set = ; - regulator-min-microvolt = <2430000>; - regulator-max-microvolt = <2970000>; - qcom,init-voltage = <2430000>; + regulator-min-microvolt = <2424000>; + regulator-max-microvolt = <2976000>; + qcom,init-voltage = <2424000>; qcom,init-mode = ; }; }; @@ -458,7 +460,7 @@ regulator-name = "pm6150_l17"; qcom,set = ; regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3230000>; + regulator-max-microvolt = <3232000>; qcom,init-voltage = <3000000>; qcom,init-mode = ; }; @@ -477,7 +479,7 @@ regulator-name = "pm6150_l18"; qcom,set = ; regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3300000>; + regulator-max-microvolt = <3008000>; qcom,init-voltage = <3000000>; qcom,init-mode = ; }; @@ -495,9 +497,9 @@ L19A: pm6150_l19: regulator-pm6150-l19 { regulator-name = "pm6150_l19"; qcom,set = ; - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <3008000>; - qcom,init-voltage = <2700000>; + regulator-min-microvolt = <2944000>; + regulator-max-microvolt = <3304000>; + qcom,init-voltage = <2944000>; qcom,init-mode = ; }; }; @@ -514,9 +516,9 @@ L1C: pm6150l_l1: regulator-pm6150l-l1 { regulator-name = "pm6150l_l1"; qcom,set = ; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1900000>; - qcom,init-voltage = <1800000>; + regulator-min-microvolt = <1616000>; + regulator-max-microvolt = <1984000>; + qcom,init-voltage = <1616000>; qcom,init-mode = ; }; }; @@ -533,9 +535,9 @@ L2C: pm6150l_l2: regulator-pm6150l-l2 { regulator-name = "pm6150l_l2"; qcom,set = ; - regulator-min-microvolt = <1300000>; - regulator-max-microvolt = <1304000>; - qcom,init-voltage = <1300000>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1352000>; + qcom,init-voltage = <1200000>; qcom,init-mode = ; }; }; @@ -552,9 +554,9 @@ L3C: pm6150l_l3: regulator-pm6150l-l3 { regulator-name = "pm6150l_l3"; qcom,set = ; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1260000>; - qcom,init-voltage = <1200000>; + regulator-min-microvolt = <1144000>; + regulator-max-microvolt = <1256000>; + qcom,init-voltage = <1144000>; qcom,init-mode = ; }; }; @@ -571,9 +573,9 @@ L4C: pm6150l_l4: regulator-pm6150l-l4 { regulator-name = "pm6150l_l4"; qcom,set = ; - regulator-min-microvolt = <1650000>; + regulator-min-microvolt = <1648000>; regulator-max-microvolt = <2950000>; - qcom,init-voltage = <1650000>; + qcom,init-voltage = <1648000>; qcom,init-mode = ; }; }; @@ -590,9 +592,9 @@ L5C: pm6150l_l5: regulator-pm6150l-l5 { regulator-name = "pm6150l_l5"; qcom,set = ; - regulator-min-microvolt = <1650000>; + regulator-min-microvolt = <1648000>; regulator-max-microvolt = <2950000>; - qcom,init-voltage = <1650000>; + qcom,init-voltage = <1648000>; qcom,init-mode = ; }; }; @@ -609,9 +611,9 @@ L6C: pm6150l_l6: regulator-pm6150l-l6 { regulator-name = "pm6150l_l6"; qcom,set = ; - regulator-min-microvolt = <1650000>; + regulator-min-microvolt = <1648000>; regulator-max-microvolt = <3100000>; - qcom,init-voltage = <1650000>; + qcom,init-voltage = <1648000>; qcom,init-mode = ; }; }; @@ -705,7 +707,7 @@ regulator-name = "pm6150l_l11"; qcom,set = ; regulator-min-microvolt = <2950000>; - regulator-max-microvolt = <3312000>; + regulator-max-microvolt = <3400000>; qcom,init-voltage = <2950000>; qcom,init-mode = ; }; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-stub-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-stub-regulator.dtsi index 0407b95513ba..368685e6d1be 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-stub-regulator.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-stub-regulator.dtsi @@ -94,7 +94,7 @@ compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l1"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1200000>; + regulator-min-microvolt = <1174000>; regulator-max-microvolt = <1252000>; }; @@ -102,7 +102,7 @@ compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l2"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1000000>; + regulator-min-microvolt = <944000>; regulator-max-microvolt = <1050000>; }; @@ -110,7 +110,7 @@ compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l3"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1000000>; + regulator-min-microvolt = <968000>; regulator-max-microvolt = <1060000>; }; @@ -118,24 +118,24 @@ compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l4"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <875000>; - regulator-max-microvolt = <975000>; + regulator-min-microvolt = <824000>; + regulator-max-microvolt = <920000>; }; L5A: pm6150_l5: regulator-pm6150-l5 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l5"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <2970000>; + regulator-min-microvolt = <2600000>; + regulator-max-microvolt = <2800000>; }; L6A: pm6150_l6: regulator-pm6150-l6 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l6"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; + regulator-min-microvolt = <1096000>; + regulator-max-microvolt = <1304000>; }; /* pm6150 L7 = LPI_MX supply */ @@ -164,64 +164,64 @@ compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l9"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <400000>; - regulator-max-microvolt = <728000>; + regulator-min-microvolt = <624000>; + regulator-max-microvolt = <760000>; }; L10A: pm6150_l10: regulator-pm6150-l10 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l10"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1829000>; + regulator-min-microvolt = <1720000>; + regulator-max-microvolt = <1832000>; }; L11A: pm6150_l11: regulator-pm6150-l11 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l11"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1890000>; + regulator-min-microvolt = <1616000>; + regulator-max-microvolt = <1984000>; }; L12A: pm6150_l12: regulator-pm6150-l12 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l12"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1950000>; + regulator-min-microvolt = <1696000>; + regulator-max-microvolt = <1952000>; }; L13A: pm6150_l13: regulator-pm6150-l13 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l13"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1900000>; + regulator-min-microvolt = <1696000>; + regulator-max-microvolt = <1904000>; }; L14A: pm6150_l14: regulator-pm6150-l14 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l14"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1850000>; + regulator-min-microvolt = <1720000>; + regulator-max-microvolt = <1856000>; }; L15A: pm6150_l15: regulator-pm6150-l15 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l15"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1900000>; + regulator-min-microvolt = <1696000>; + regulator-max-microvolt = <1904000>; }; L16A: pm6150_l16: regulator-pm6150-l16 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l16"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <2430000>; - regulator-max-microvolt = <2970000>; + regulator-min-microvolt = <2424000>; + regulator-max-microvolt = <2976000>; }; L17A: pm6150_l17: regulator-pm6150-l17 { @@ -229,7 +229,7 @@ regulator-name = "pm6150_l17"; qcom,hpm-min-load = <10000>; regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3230000>; + regulator-max-microvolt = <3232000>; }; L18A: pm6150_l18: regulator-pm6150-l18 { @@ -237,46 +237,46 @@ regulator-name = "pm6150_l18"; qcom,hpm-min-load = <10000>; regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3300000>; + regulator-max-microvolt = <3008000>; }; L19A: pm6150_l19: regulator-pm6150-l19 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150_l19"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <3008000>; + regulator-min-microvolt = <2944000>; + regulator-max-microvolt = <3304000>; }; L1C: pm6150l_l1: regulator-pm6150l-l1 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150l_l1"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1900000>; + regulator-min-microvolt = <1616000>; + regulator-max-microvolt = <1984000>; }; L2C: pm6150l_l2: regulator-pm6150l-l2 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150l_l2"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1300000>; - regulator-max-microvolt = <1304000>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1352000>; }; L3C: pm6150l_l3: regulator-pm6150l-l3 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150l_l3"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1260000>; + regulator-min-microvolt = <1144000>; + regulator-max-microvolt = <1256000>; }; L4C: pm6150l_l4: regulator-pm6150l-l4 { compatible = "qcom,stub-regulator"; regulator-name = "pm6150l_l4"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1650000>; + regulator-min-microvolt = <1648000>; regulator-max-microvolt = <2950000>; }; @@ -284,7 +284,7 @@ compatible = "qcom,stub-regulator"; regulator-name = "pm6150l_l5"; qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1650000>; + regulator-min-microvolt = <1648000>; regulator-max-microvolt = <2950000>; }; @@ -292,7 +292,7 @@ compatible = "qcom,stub-regulator"; regulator-name = "pm6150l_l6"; qcom,hpm-min-load = <5000>; - regulator-min-microvolt = <1650000>; + regulator-min-microvolt = <1648000>; regulator-max-microvolt = <3100000>; }; @@ -333,7 +333,7 @@ regulator-name = "pm6150l_l11"; qcom,hpm-min-load = <10000>; regulator-min-microvolt = <2950000>; - regulator-max-microvolt = <3312000>; + regulator-max-microvolt = <3400000>; }; BOB: pm6150l_bob: regulator-pm6150l-bob { diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index 724198abec06..bdfca124935a 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -1103,3 +1103,4 @@ #include "sdmmagpie-ion.dtsi" #include "msm-arm-smmu-sdmmagpie.dtsi" #include "sdmmagpie-pm.dtsi" +#include "sdmmagpie-regulator.dtsi" -- GitLab From cef786455df0da01b6d0f99a7e077e24e79c995d Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Mon, 25 Jun 2018 13:46:05 +0530 Subject: [PATCH 0895/1299] rpmh_master_stat: Correctly initialize rpmh_unit_base Correctly initialize rpmh_unit_base during driver unbind. Change-Id: I06355c89a475c53ea3f345be0f53b3a5999f5818 Signed-off-by: Maulik Shah --- drivers/soc/qcom/rpmh_master_stat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/rpmh_master_stat.c b/drivers/soc/qcom/rpmh_master_stat.c index 283e367cf439..22704b807700 100644 --- a/drivers/soc/qcom/rpmh_master_stat.c +++ b/drivers/soc/qcom/rpmh_master_stat.c @@ -265,6 +265,7 @@ static int msm_rpmh_master_stats_remove(struct platform_device *pdev) kobject_put(prvdata->kobj); platform_set_drvdata(pdev, NULL); iounmap(rpmh_unit_base); + rpmh_unit_base = NULL; return 0; } -- GitLab From 4bee7e610564b9c7586def75a403dbc5d8fb2951 Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Wed, 27 Jun 2018 17:14:01 +0530 Subject: [PATCH 0896/1299] clk: qcom: smd-rpm: Remove rf_clk3 instance for QCS405 RF_CLK3 is no longer required from HW side. So remove support for the same in RPM clock driver. Change-Id: Idca9a31ddea21d48e6fbd0d14d28cf3c5c6d0ff3 Signed-off-by: Shefali Jain --- drivers/clk/qcom/clk-smd-rpm.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 729af0ebfa20..2f1661d0f746 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -610,10 +610,8 @@ DEFINE_CLK_SMD_RPM(qcs405, bimc_gpu_clk, bimc_gpu_a_clk, /* SMD_XO_BUFFER */ DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs405, ln_bb_clk, ln_bb_clk_a, 8); DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs405, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs405, rf_clk3, rf_clk3_a, 6); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs405, ln_bb_clk_pin, ln_bb_clk_a_pin, 8); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs405, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs405, rf_clk3_pin, rf_clk3_a_pin, 6); /* Voter clocks */ static DEFINE_CLK_VOTER(pnoc_msmbus_clk, pnoc_clk, LONG_MAX); @@ -664,10 +662,6 @@ static struct clk_hw *qcs405_clks[] = { [RPM_SMD_RF_CLK1_A] = &qcs405_rf_clk1_a.hw, [RPM_SMD_RF_CLK1_PIN] = &qcs405_rf_clk1_pin.hw, [RPM_SMD_RF_CLK1_A_PIN] = &qcs405_rf_clk1_a_pin.hw, - [RPM_SMD_RF_CLK3] = &qcs405_rf_clk3.hw, - [RPM_SMD_RF_CLK3_A] = &qcs405_rf_clk3_a.hw, - [RPM_SMD_RF_CLK3_PIN] = &qcs405_rf_clk3_pin.hw, - [RPM_SMD_RF_CLK3_A_PIN] = &qcs405_rf_clk3_a_pin.hw, [RPM_SMD_LN_BB_CLK] = &qcs405_ln_bb_clk.hw, [RPM_SMD_LN_BB_CLK_A] = &qcs405_ln_bb_clk_a.hw, [RPM_SMD_LN_BB_CLK_PIN] = &qcs405_ln_bb_clk_pin.hw, @@ -711,7 +705,7 @@ static struct clk_hw *qcs405_clks[] = { static const struct rpm_smd_clk_desc rpm_clk_qcs405 = { .clks = qcs405_clks, - .num_rpm_clks = RPM_SMD_RF_CLK3_A_PIN, + .num_rpm_clks = RPM_SMD_LN_BB_CLK_A_PIN, .num_clks = ARRAY_SIZE(qcs405_clks), }; -- GitLab From cd8c8ead468eae40de5f7301fc1905d44ae7a30a Mon Sep 17 00:00:00 2001 From: Maria Yu Date: Thu, 21 Sep 2017 11:30:53 +0800 Subject: [PATCH 0897/1299] arm: highmem: Fix CPU_DYING callback for kmap Add CPUHP_AP_KMAP_DYING state support instead of use cpu notify for CPU_DYING which is deprecated. Change-Id: Idaaf628ef4c89f361391151db523f5ffefc5bcc1 Signed-off-by: Maria Yu Signed-off-by: Kaushal Kumar --- arch/arm/mm/highmem.c | 26 ++------------------------ include/linux/cpuhotplug.h | 1 + include/linux/highmem.h | 5 +++++ kernel/cpu.c | 6 ++++++ 4 files changed, 14 insertions(+), 24 deletions(-) diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index 5d73327f8491..0bb76731ba11 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c @@ -150,7 +150,7 @@ void *kmap_atomic_pfn(unsigned long pfn) } #ifdef CONFIG_ARCH_WANT_KMAP_ATOMIC_FLUSH -static void kmap_remove_unused_cpu(int cpu) +int kmap_remove_unused_cpu(unsigned int cpu) { int start_idx, idx, type; @@ -167,6 +167,7 @@ static void kmap_remove_unused_cpu(int cpu) set_top_pte(vaddr, __pte(0)); } pagefault_enable(); + return 0; } static void kmap_remove_unused(void *unused) @@ -179,27 +180,4 @@ void kmap_atomic_flush_unused(void) on_each_cpu(kmap_remove_unused, NULL, 1); } -static int hotplug_kmap_atomic_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - switch (action & (~CPU_TASKS_FROZEN)) { - case CPU_DYING: - kmap_remove_unused_cpu((int)hcpu); - break; - default: - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block hotplug_kmap_atomic_notifier = { - .notifier_call = hotplug_kmap_atomic_callback, -}; - -static int __init init_kmap_atomic(void) -{ - return register_hotcpu_notifier(&hotplug_kmap_atomic_notifier); -} -early_initcall(init_kmap_atomic); #endif diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 3ecdd63e9e0f..bfd59289864a 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -97,6 +97,7 @@ enum cpuhp_state { CPUHP_AP_OFFLINE, CPUHP_AP_SCHED_STARTING, CPUHP_AP_RCUTREE_DYING, + CPUHP_AP_KMAP_DYING, CPUHP_AP_IRQ_GIC_STARTING, CPUHP_AP_IRQ_HIP04_STARTING, CPUHP_AP_IRQ_ARMADA_XP_STARTING, diff --git a/include/linux/highmem.h b/include/linux/highmem.h index e2f26daff2c1..4db2f34c4fe5 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -42,6 +42,7 @@ void kmap_flush_unused(void); #ifdef CONFIG_ARCH_WANT_KMAP_ATOMIC_FLUSH void kmap_atomic_flush_unused(void); +int kmap_remove_unused_cpu(unsigned int cpu); #else static inline void kmap_atomic_flush_unused(void) { } #endif @@ -92,6 +93,10 @@ static inline void __kunmap_atomic(void *addr) #endif /* CONFIG_HIGHMEM */ +#if !defined(CONFIG_HIGHMEM) || !defined(CONFIG_ARCH_WANT_KMAP_ATOMIC_FLUSH) +static inline int kmap_remove_unused_cpu(unsigned int cpu) { return 0; } +#endif + #if defined(CONFIG_HIGHMEM) || defined(CONFIG_X86_32) DECLARE_PER_CPU(int, __kmap_atomic_idx); diff --git a/kernel/cpu.c b/kernel/cpu.c index abc9676a1389..c1fc4874a0e9 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #define CREATE_TRACE_POINTS @@ -1392,6 +1393,11 @@ static struct cpuhp_step cpuhp_ap_states[] = { .startup.single = NULL, .teardown.single = rcutree_dying_cpu, }, + [CPUHP_AP_KMAP_DYING] = { + .name = "KMAP:dying", + .startup.single = NULL, + .teardown.single = kmap_remove_unused_cpu, + }, [CPUHP_AP_SMPCFD_DYING] = { .name = "smpcfd:dying", .startup.single = NULL, -- GitLab From 551d52c326d91b8d2a29aedc5d34980a17e74036 Mon Sep 17 00:00:00 2001 From: Kaushal Kumar Date: Wed, 27 Jun 2018 17:18:08 +0530 Subject: [PATCH 0898/1299] defconfig: Enable CONFIG_HIGHMEM for QCS405 Enable CONFIG_HIGHMEM for high memory support on QCS405 32bit. Change-Id: I4d1410033e6680654de8a9092b8a9a95943ccf30 Signed-off-by: Kaushal Kumar --- arch/arm/configs/vendor/qcs405_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index a116a1da4435..fe5b6d6f0220 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -36,6 +36,7 @@ CONFIG_ARCH_QCS405=y CONFIG_SMP=y CONFIG_ARM_PSCI=y CONFIG_PREEMPT=y +CONFIG_HIGHMEM=y CONFIG_CLEANCACHE=y CONFIG_CMA=y CONFIG_CMA_DEBUGFS=y -- GitLab From c87a9678bf9e2bbe82500805ba6febc6ef3507b4 Mon Sep 17 00:00:00 2001 From: Vijaykumar Badiger Date: Wed, 20 Jun 2018 14:56:30 -0700 Subject: [PATCH 0899/1299] ARM: dts: msm: Add device tree for SA8150P-adp-star Introduce DTS files to support APQ version of SA8150 chipset. Change-Id: I62d69558833f227cc814fa0145b2847d97c1e0ca Signed-off-by: Vijaykumar Badiger --- .../devicetree/bindings/arm/msm/msm.txt | 1 + arch/arm64/boot/dts/qcom/Makefile | 3 +++ .../dts/qcom/sa8150p-adp-star-overlay.dts | 23 +++++++++++++++++++ arch/arm64/boot/dts/qcom/sa8150p-adp-star.dts | 22 ++++++++++++++++++ arch/arm64/boot/dts/qcom/sa8150p.dts | 22 ++++++++++++++++++ arch/arm64/boot/dts/qcom/sa8150p.dtsi | 20 ++++++++++++++++ 6 files changed, 91 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sa8150p-adp-star-overlay.dts create mode 100644 arch/arm64/boot/dts/qcom/sa8150p-adp-star.dts create mode 100644 arch/arm64/boot/dts/qcom/sa8150p.dts create mode 100644 arch/arm64/boot/dts/qcom/sa8150p.dtsi diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index 40d302efe0a9..00b5ef73fe31 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -164,6 +164,7 @@ compatible = "qcom,qcs405-rumi" compatible = "qcom,qcs405-iot" compatible = "qcom,qcs403-iot" compatible = "qcom,sa8150-adp-star" +compatible = "qcom,sa8150p-adp-star" compatible = "qcom,adp-star" compatible = "qcom,sdxprairie-rumi" compatible = "qcom,sdxprairie-mtp" diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6d1a678feb0e..3905ad363267 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -26,6 +26,7 @@ ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y) sm8150-qrd-overlay.dtbo \ sm8150-qrd-dvt-overlay.dtbo \ sa8150-adp-star-overlay.dtbo \ + sa8150p-adp-star-overlay.dtbo \ sm8150p-cdp-overlay.dtbo \ sm8150p-mtp-overlay.dtbo \ sm8150p-qrd-overlay.dtbo \ @@ -40,6 +41,7 @@ sm8150-rumi-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-qrd-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-qrd-dvt-overlay.dtbo-base := sm8150-v2.dtb sa8150-adp-star-overlay.dtbo-base := sa8150.dtb +sa8150p-adp-star-overlay.dtbo-base := sa8150p.dtb sm8150-sdx50m-cdp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-sdx50m-mtp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-sdx50m-mtp-2.5k-panel-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb @@ -52,6 +54,7 @@ dtb-$(CONFIG_ARCH_SM8150) += sm8150-rumi.dtb \ sm8150-cdp.dtb \ sm8150-qrd.dtb \ sa8150-adp-star.dtb \ + sa8150p-adp-star.dtb \ sm8150-v2-rumi.dtb \ sm8150-v2-mtp.dtb \ sm8150-v2-cdp.dtb \ diff --git a/arch/arm64/boot/dts/qcom/sa8150p-adp-star-overlay.dts b/arch/arm64/boot/dts/qcom/sa8150p-adp-star-overlay.dts new file mode 100644 index 000000000000..bcef0c4fade5 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8150p-adp-star-overlay.dts @@ -0,0 +1,23 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; +/plugin/; + +#include "sa8150-adp-star.dtsi" + +/ { + model = "ADP-STAR"; + compatible = "qcom,sa8150p-adp-star", "qcom,sa8150p", + "qcom,adp-star"; + qcom,board-id = <25 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8150p-adp-star.dts b/arch/arm64/boot/dts/qcom/sa8150p-adp-star.dts new file mode 100644 index 000000000000..c51111d077c5 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8150p-adp-star.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; +#include "sa8150p.dtsi" +#include "sa8150-adp-star.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA8150P ADP-STAR"; + compatible = "qcom,sa8150p-adp-star", "qcom,sa8150p", + "qcom,adp-star"; + qcom,board-id = <25 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8150p.dts b/arch/arm64/boot/dts/qcom/sa8150p.dts new file mode 100644 index 000000000000..ad2069a8e223 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8150p.dts @@ -0,0 +1,22 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "sa8150p.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA8150P SoC"; + compatible = "qcom,sa8150p"; + qcom,pmic-name = "PM8150"; + qcom,board-id = <0 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8150p.dtsi b/arch/arm64/boot/dts/qcom/sa8150p.dtsi new file mode 100644 index 000000000000..4b4b42dd567d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8150p.dtsi @@ -0,0 +1,20 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sa8150.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA8150P "; + qcom,msm-name = "SA8150P"; + compatible = "qcom,sa8150p"; + qcom,msm-id = <367 0x10000>; +}; -- GitLab From 659b74163ef1a7d2478c744da9970f3dac85234f Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Thu, 21 Jun 2018 12:00:46 -0700 Subject: [PATCH 0900/1299] msm: sde: Allocate memory for SIDs passed in scm_call Allocate memory through kzalloc and pass the physical address to scm_call instead of using the local stack variable to make the implementation consistent with the SDE driver. Change-Id: Iee67c72758c2eab8c58014301ee6526ac339361b Signed-off-by: Veera Sundaram Sankaran --- .../msm/sde/rotator/sde_rotator_core.c | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c index 1132ec582012..28bcb1813594 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c @@ -584,17 +584,21 @@ static int sde_rotator_import_buffer(struct sde_layer_buffer *buffer, static int sde_rotator_secure_session_ctrl(bool enable) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); - uint32_t sid_info; + uint32_t *sid_info = NULL; struct scm_desc desc = {0}; unsigned int resp = 0; int ret = 0; - if (test_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU, - mdata->sde_caps_map)) { - sid_info = mdata->sde_smmu[SDE_IOMMU_DOMAIN_ROT_SECURE].sid; + if (test_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU, mdata->sde_caps_map)) { + + sid_info = kzalloc(sizeof(uint32_t), GFP_KERNEL); + if (!sid_info) + return -ENOMEM; + + sid_info[0] = mdata->sde_smmu[SDE_IOMMU_DOMAIN_ROT_SECURE].sid; desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL); desc.args[0] = SDE_ROTATOR_DEVICE; - desc.args[1] = SCM_BUFFER_PHYS(&sid_info); + desc.args[1] = SCM_BUFFER_PHYS(sid_info); desc.args[2] = sizeof(uint32_t); if (!mdata->sec_cam_en && enable) { @@ -608,7 +612,7 @@ static int sde_rotator_secure_session_ctrl(bool enable) mdata->sec_cam_en = 1; sde_smmu_secure_ctrl(0); - dmac_flush_range(&sid_info, &sid_info + 1); + dmac_flush_range(sid_info, sid_info + 1); ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, MEM_PROTECT_SD_CTRL_SWITCH), &desc); resp = desc.ret[0]; @@ -618,14 +622,16 @@ static int sde_rotator_secure_session_ctrl(bool enable) /* failure, attach smmu */ mdata->sec_cam_en = 0; sde_smmu_secure_ctrl(1); - return -EINVAL; + ret = -EINVAL; + goto end; } SDEROT_DBG( "scm(1) sid0x%x dev0x%llx vmid0x%llx ret%d resp%x\n", - sid_info, desc.args[0], desc.args[3], + sid_info[0], desc.args[0], desc.args[3], ret, resp); - SDEROT_EVTLOG(1, sid_info, desc.args[0], desc.args[3], + SDEROT_EVTLOG(1, sid_info, sid_info[0], + desc.args[0], desc.args[3], ret, resp); } else if (mdata->sec_cam_en && !enable) { /* @@ -636,25 +642,30 @@ static int sde_rotator_secure_session_ctrl(bool enable) desc.args[3] = VMID_CP_PIXEL; mdata->sec_cam_en = 0; - dmac_flush_range(&sid_info, &sid_info + 1); + dmac_flush_range(sid_info, sid_info + 1); ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, MEM_PROTECT_SD_CTRL_SWITCH), &desc); resp = desc.ret[0]; SDEROT_DBG( "scm(0) sid0x%x dev0x%llx vmid0x%llx ret%d resp%d\n", - sid_info, desc.args[0], desc.args[3], + sid_info[0], desc.args[0], desc.args[3], ret, resp); /* force smmu to reattach */ sde_smmu_secure_ctrl(1); - SDEROT_EVTLOG(0, sid_info, desc.args[0], desc.args[3], + SDEROT_EVTLOG(0, sid_info, sid_info[0], + desc.args[0], desc.args[3], ret, resp); } } else { return 0; } + +end: + kfree(sid_info); + if (ret) return ret; -- GitLab From 6c02048fb152d60688dd992d55d24fe8eb2d24ff Mon Sep 17 00:00:00 2001 From: Akshay Chandrashekhar Kalghatgi Date: Thu, 7 Jun 2018 14:23:52 -0700 Subject: [PATCH 0901/1299] staging: android: ion: Resolve prefetch 32bit compatibility Make ion prefetch both 32bit and 64bit compatible removing the necessity for compat_ioctl. Change-Id: Idd5fdfb481790aba46969d4ed38414b31ed11d49 Signed-off-by: Akshay Chandrashekhar Kalghatgi --- drivers/staging/android/ion/ion_system_secure_heap.c | 8 +++++--- drivers/staging/android/uapi/msm_ion.h | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c index e9dfa263b926..51ef7e27a3c2 100644 --- a/drivers/staging/android/ion/ion_system_secure_heap.c +++ b/drivers/staging/android/ion/ion_system_secure_heap.c @@ -215,7 +215,7 @@ static int alloc_prefetch_info( bool shrink, struct list_head *items) { struct prefetch_info *info; - u64 __user *user_sizes; + u64 user_sizes; int err; unsigned int nr_sizes, vmid, i; @@ -236,7 +236,7 @@ static int alloc_prefetch_info( if (!info) return -ENOMEM; - err = get_user(info->size, &user_sizes[i]); + err = get_user(info->size, ((u64 __user *)user_sizes + i)); if (err) goto out_free; @@ -270,7 +270,9 @@ static int __ion_system_secure_heap_resize(struct ion_heap *heap, void *ptr, return -EINVAL; for (i = 0; i < data->nr_regions; i++) { - ret = alloc_prefetch_info(&data->regions[i], shrink, &items); + ret = alloc_prefetch_info( + (struct ion_prefetch_regions *)data->regions + i, + shrink, &items); if (ret) goto out_free; } diff --git a/drivers/staging/android/uapi/msm_ion.h b/drivers/staging/android/uapi/msm_ion.h index a725b84bcf45..5752fb91de97 100644 --- a/drivers/staging/android/uapi/msm_ion.h +++ b/drivers/staging/android/uapi/msm_ion.h @@ -92,15 +92,15 @@ enum ion_heap_ids { #define ION_IOC_MSM_MAGIC 'M' struct ion_prefetch_regions { + __u64 sizes; __u32 vmid; - __u64 __user *sizes; __u32 nr_sizes; }; struct ion_prefetch_data { - __u32 heap_id; __u64 len; - struct ion_prefetch_regions __user *regions; + __u64 regions; + __u32 heap_id; __u32 nr_regions; }; -- GitLab From 7ba87d508f93986f0e1fb79c471a21539a664730 Mon Sep 17 00:00:00 2001 From: Michael Adisumarta Date: Wed, 27 Jun 2018 10:52:54 -0700 Subject: [PATCH 0902/1299] msm: ipa4: Cleanup IPA registers dump Move the macros and change the return type of the functions. Add an if condition to include the n_registers for printing to dmesg. Create a separate IPC log for regdumps. Change-Id: Ic2c11eda268342277e79465a0cfb329b95bf868b Signed-off-by: Michael Adisumarta --- .../platform/msm/ipa/ipa_v3/ipahal/ipahal.c | 8 +++++ .../platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h | 31 +++++++++---------- .../msm/ipa/ipa_v3/ipahal/ipahal_reg.c | 18 +++++++---- .../msm/ipa/ipa_v3/ipahal/ipahal_reg.h | 2 +- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c index c4c6785f942f..7f02a6b1079e 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c @@ -1564,6 +1564,12 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base, goto bail_free_fltrt; } + /* create an IPC buffer for the registers dump */ + ipahal_ctx->regdumpbuf = ipc_log_context_create(IPAHAL_IPC_LOG_PAGES, + "ipa_regs", 0); + if (ipahal_ctx->regdumpbuf == NULL) + IPAHAL_ERR("failed to create IPA regdump log, continue...\n"); + ipahal_debugfs_init(); return 0; @@ -1571,6 +1577,8 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base, bail_free_fltrt: ipahal_fltrt_destroy(); bail_free_ctx: + if (ipahal_ctx->regdumpbuf) + ipc_log_context_destroy(ipahal_ctx->regdumpbuf); kfree(ipahal_ctx); ipahal_ctx = NULL; bail_err_exit: diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h index d46f13ca8499..816bc584199d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h @@ -46,36 +46,34 @@ IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) +#define IPAHAL_ERR_RL(fmt, args...) \ + do { \ + pr_err_ratelimited_ipa(IPAHAL_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + #define IPAHAL_DBG_REG(fmt, args...) \ do { \ pr_err(fmt, ## args); \ - IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ - " %s:%d " fmt, ## args); \ - IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_IPC_LOGGING(ipahal_ctx->regdumpbuf, \ " %s:%d " fmt, ## args); \ } while (0) #define IPAHAL_DBG_REG_IPC_ONLY(fmt, args...) \ do { \ - IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ - " %s:%d " fmt, ## args); \ - IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_IPC_LOGGING(ipahal_ctx->regdumpbuf, \ " %s:%d " fmt, ## args); \ } while (0) -#define IPAHAL_ERR_RL(fmt, args...) \ - do { \ - pr_err_ratelimited_ipa(IPAHAL_DRV_NAME " %s:%d " fmt, \ - __func__, __LINE__, ## args); \ - IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ - IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \ - IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ - IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \ - } while (0) - #define IPAHAL_MEM_ALLOC(__size, __is_atomic_ctx) \ (kzalloc((__size), ((__is_atomic_ctx) ? GFP_ATOMIC : GFP_KERNEL))) +#define IPAHAL_IPC_LOG_PAGES 50 + /* * struct ipahal_context - HAL global context data * @hw_type: IPA H/W type/version. @@ -92,6 +90,7 @@ struct ipahal_context { struct dentry *dent; struct device *ipa_pdev; struct ipa_mem_buffer empty_fltrt_tbl; + void *regdumpbuf; }; extern struct ipahal_context *ipahal_ctx; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c index 13ca985f22f8..ef1d140e3695 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c @@ -2280,7 +2280,7 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = { 0x00000830, 0x70, 8, 17, 1}, }; -int ipahal_print_all_regs(bool print_to_dmesg) +void ipahal_print_all_regs(bool print_to_dmesg) { int i, j; @@ -2290,7 +2290,7 @@ int ipahal_print_all_regs(bool print_to_dmesg) if ((ipahal_ctx->hw_type < IPA_HW_v4_0) || (ipahal_ctx->hw_type >= IPA_HW_MAX)) { IPAHAL_ERR("invalid IPA HW type (%d)\n", ipahal_ctx->hw_type); - return -EINVAL; + return; } for (i = 0; i < IPA_REG_MAX ; i++) { @@ -2310,11 +2310,17 @@ int ipahal_print_all_regs(bool print_to_dmesg) ipahal_read_reg_n(i, j)); } - for (; j < ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end; j++) - IPAHAL_DBG_REG("%s_%u=0x%x\n", ipahal_reg_name_str(i), - j, ipahal_read_reg_n(i, j)); + for (; j < ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end; j++) { + if (print_to_dmesg) + IPAHAL_DBG_REG("%s_%u=0x%x\n", + ipahal_reg_name_str(i), + j, ipahal_read_reg_n(i, j)); + else + IPAHAL_DBG_REG_IPC_ONLY("%s_%u=0x%x\n", + ipahal_reg_name_str(i), + j, ipahal_read_reg_n(i, j)); + } } - return 0; } /* diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h index 8d2da38fa5a4..a788d348d06d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h @@ -535,7 +535,7 @@ struct ipahal_ep_cfg_ctrl_scnd { }; -int ipahal_print_all_regs(bool print_to_dmesg); +void ipahal_print_all_regs(bool print_to_dmesg); /* * ipahal_reg_name_str() - returns string that represent the register -- GitLab From 85d3620de8a707eff773d9b3ef53da1ad3ec158b Mon Sep 17 00:00:00 2001 From: Fuad Hossain Date: Wed, 27 Jun 2018 14:08:04 -0400 Subject: [PATCH 0903/1299] drm/msm: free atomic state during lastclose Ensure that the refcount of the atomic state is decremented during lastclose. This will make sure that when the atomic state is freed, all objects being held by it are released. Change-Id: I547cf997b9eb80560c9646f688071fb6a41648b2 Signed-off-by: Fuad Hossain --- drivers/gpu/drm/msm/msm_drv.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 95d9955e89db..eff5e013be23 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -979,9 +979,7 @@ static int msm_disable_all_modes( drm_modeset_backoff(ctx); } - /* on successful atomic commit state ownership transfers to framework */ - if (ret != 0) - drm_atomic_state_put(state); + drm_atomic_state_put(state); return ret; } -- GitLab From 128bb1d788ab0cceb2fb3fe89d2c8995900a5a68 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Thu, 10 May 2018 15:44:56 -0700 Subject: [PATCH 0904/1299] msm:ipa3: fix the header table gap issue Move those deleted entries to the free list to avoid the gap in hdr tbl. Change-Id: I5f5b6ec845e6b7e52c7079c2a3200a8290616951 Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c | 106 ++++++++-------------- 1 file changed, 39 insertions(+), 67 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index 8ea80d8af6df..5fe3c6775ab9 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -998,8 +998,9 @@ int ipa3_reset_hdr(bool user_only) struct ipa_hdr_offset_entry *off_next; struct ipa3_hdr_proc_ctx_offset_entry *ctx_off_entry; struct ipa3_hdr_proc_ctx_offset_entry *ctx_off_next; - int i, end = 0; - bool user_rule = false; + struct ipa3_hdr_tbl *htbl = &ipa3_ctx->hdr_tbl; + struct ipa3_hdr_proc_ctx_tbl *htbl_proc = &ipa3_ctx->hdr_proc_ctx_tbl; + int i; /* * issue a reset on the routing module since routing rules point to @@ -1037,9 +1038,6 @@ int ipa3_reset_hdr(bool user_only) return -EFAULT; } - if (entry->ipacm_installed) - user_rule = true; - if (!user_only || entry->ipacm_installed) { if (entry->is_hdr_proc_ctx) { dma_unmap_single(ipa3_ctx->pdev, @@ -1047,9 +1045,15 @@ int ipa3_reset_hdr(bool user_only) entry->hdr_len, DMA_TO_DEVICE); entry->proc_ctx = NULL; + } else { + /* move the offset entry to free list */ + entry->offset_entry->ipacm_installed = 0; + list_move(&entry->offset_entry->link, + &htbl->head_free_offset_list[ + entry->offset_entry->bin]); } list_del(&entry->link); - ipa3_ctx->hdr_tbl.hdr_cnt--; + htbl->hdr_cnt--; entry->ref_cnt = 0; entry->cookie = 0; @@ -1058,53 +1062,37 @@ int ipa3_reset_hdr(bool user_only) kmem_cache_free(ipa3_ctx->hdr_cache, entry); } } - for (i = 0; i < IPA_HDR_BIN_MAX; i++) { - list_for_each_entry_safe(off_entry, off_next, + + /* only clean up offset_list and free_offset_list on global reset */ + if (!user_only) { + for (i = 0; i < IPA_HDR_BIN_MAX; i++) { + list_for_each_entry_safe(off_entry, off_next, &ipa3_ctx->hdr_tbl.head_offset_list[i], link) { - - /* - * do not remove the default exception header which is - * at offset 0 - */ - if (off_entry->offset == 0) - continue; - - if (!user_only || - off_entry->ipacm_installed) { + /** + * do not remove the default exception + * header which is at offset 0 + */ + if (off_entry->offset == 0) + continue; list_del(&off_entry->link); kmem_cache_free(ipa3_ctx->hdr_offset_cache, off_entry); - } else { - if (off_entry->offset + - ipa_hdr_bin_sz[off_entry->bin] > end) { - end = off_entry->offset + - ipa_hdr_bin_sz[off_entry->bin]; - IPADBG("replace end = %d\n", end); - } } - } - list_for_each_entry_safe(off_entry, off_next, + list_for_each_entry_safe(off_entry, off_next, &ipa3_ctx->hdr_tbl.head_free_offset_list[i], link) { - - if (!user_only || - off_entry->ipacm_installed) { list_del(&off_entry->link); kmem_cache_free(ipa3_ctx->hdr_offset_cache, off_entry); } } + /* there is one header of size 8 */ + ipa3_ctx->hdr_tbl.end = 8; + ipa3_ctx->hdr_tbl.hdr_cnt = 1; } - IPADBG("hdr_tbl.end = %d\n", end); - if (user_rule) { - ipa3_ctx->hdr_tbl.end = end; - IPADBG("hdr_tbl.end = %d\n", end); - } IPADBG("reset hdr proc ctx\n"); - user_rule = false; - end = 0; list_for_each_entry_safe( ctx_entry, ctx_next, @@ -1117,13 +1105,14 @@ int ipa3_reset_hdr(bool user_only) return -EFAULT; } - if (entry->ipacm_installed) - user_rule = true; - if (!user_only || ctx_entry->ipacm_installed) { + /* move the offset entry to appropriate free list */ + list_move(&ctx_entry->offset_entry->link, + &htbl_proc->head_free_offset_list[ + ctx_entry->offset_entry->bin]); list_del(&ctx_entry->link); - ipa3_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt--; + htbl_proc->proc_ctx_cnt--; ctx_entry->ref_cnt = 0; ctx_entry->cookie = 0; @@ -1133,45 +1122,28 @@ int ipa3_reset_hdr(bool user_only) ctx_entry); } } - for (i = 0; i < IPA_HDR_PROC_CTX_BIN_MAX; i++) { - list_for_each_entry_safe(ctx_off_entry, ctx_off_next, + /* only clean up offset_list and free_offset_list on global reset */ + if (!user_only) { + for (i = 0; i < IPA_HDR_PROC_CTX_BIN_MAX; i++) { + list_for_each_entry_safe(ctx_off_entry, ctx_off_next, &ipa3_ctx->hdr_proc_ctx_tbl.head_offset_list[i], link) { - - if (!user_only || - ctx_off_entry->ipacm_installed) { list_del(&ctx_off_entry->link); kmem_cache_free( ipa3_ctx->hdr_proc_ctx_offset_cache, ctx_off_entry); - } else { - if (ctx_off_entry->offset + - ipa_hdr_bin_sz[ctx_off_entry->bin] - > end) { - end = ctx_off_entry->offset + - ipa_hdr_bin_sz[ctx_off_entry->bin]; - IPADBG("replace hdr_proc as %d\n", end); - } } - } - list_for_each_entry_safe(ctx_off_entry, ctx_off_next, - &ipa3_ctx->hdr_proc_ctx_tbl.head_free_offset_list[i], - link) { - - if (!user_only || - ctx_off_entry->ipacm_installed) { + list_for_each_entry_safe(ctx_off_entry, ctx_off_next, + &ipa3_ctx->hdr_proc_ctx_tbl. + head_free_offset_list[i], link) { list_del(&ctx_off_entry->link); kmem_cache_free( ipa3_ctx->hdr_proc_ctx_offset_cache, ctx_off_entry); } } - } - - IPADBG("hdr_proc_tbl.end = %d\n", end); - if (user_rule) { - ipa3_ctx->hdr_proc_ctx_tbl.end = end; - IPADBG("hdr_proc_tbl.end = %d\n", end); + ipa3_ctx->hdr_proc_ctx_tbl.end = 0; + ipa3_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt = 0; } mutex_unlock(&ipa3_ctx->lock); -- GitLab From 1215b115f038dd96036b21c56b53c4aee596498c Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Wed, 27 Jun 2018 14:12:01 -0700 Subject: [PATCH 0905/1299] rot: enable const color for sde rotator ubwc 3.0 Enable const color feature for ubwc 3.0 in sde rotator driver Change-Id: I3acd663733a6ebec65dcfa13e8a54fc4ec62c19e Signed-off-by: Dhaval Patel --- drivers/media/platform/msm/sde/rotator/sde_rotator_base.h | 2 ++ drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h index c5702e5603e0..c6e125986705 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h @@ -128,6 +128,7 @@ enum sde_rot_type { * @SDE_CAPS_UBWC_2: universal bandwidth compression version 2 * @SDE_CAPS_PARTIALWR: partial write override * @SDE_CAPS_HW_TIMESTAMP: rotator has hw timestamp support + * @SDE_CAPS_UBWC_3: universal bandwidth compression version 3 */ enum sde_caps_settings { SDE_CAPS_R1_WB, @@ -138,6 +139,7 @@ enum sde_caps_settings { SDE_CAPS_UBWC_2, SDE_CAPS_PARTIALWR, SDE_CAPS_HW_TIMESTAMP, + SDE_CAPS_UBWC_3, SDE_CAPS_MAX, }; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index d9f3fdc012cd..82e7a198605b 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -1492,6 +1492,8 @@ static void sde_hw_rotator_setup_fetchengine(struct sde_hw_rotator_context *ctx, ((ctx->rot->ubwc_malsize & 0x3) << 8) | ((ctx->rot->highest_bank & 0x3) << 4) | ((ctx->rot->ubwc_swizzle & 0x1) << 0)); + else if (test_bit(SDE_CAPS_UBWC_3, mdata->sde_caps_map)) + SDE_REGDMA_WRITE(wrptr, ROT_SSPP_UBWC_STATIC_CTRL, BIT(30)); /* setup source buffer plane security status */ if (flags & (SDE_ROT_FLAG_SECURE_OVERLAY_SESSION | @@ -3075,7 +3077,7 @@ static int sde_rotator_hw_rev_init(struct sde_hw_rotator *rot) if (IS_SDE_MAJOR_MINOR_SAME(mdata->mdss_version, SDE_MDP_HW_REV_500)) { SDEROT_DBG("Supporting sys cache inline rotation\n"); set_bit(SDE_CAPS_SBUF_1, mdata->sde_caps_map); - set_bit(SDE_CAPS_UBWC_2, mdata->sde_caps_map); + set_bit(SDE_CAPS_UBWC_3, mdata->sde_caps_map); set_bit(SDE_CAPS_PARTIALWR, mdata->sde_caps_map); set_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map); rot->inpixfmts[SDE_ROTATOR_MODE_OFFLINE] = -- GitLab From 5ac92ffb8aa09f36d258b06beb6d192c29ee1dd8 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Thu, 21 Jun 2018 17:49:39 -0700 Subject: [PATCH 0906/1299] drm: msm: sde: fix decimation validation in plane atomic_check Fix the invalid decimation check which skips the validations below when decimation is enabled. This fails to validate few parameters and also miss updating few state variables leading to various issues. Part of the change add an event log to track when the driver qseed/PE settings are used. Change-Id: I829d54d6b77b1ff39827b08a28f7edbb98ed8e24 Signed-off-by: Veera Sundaram Sankaran --- drivers/gpu/drm/msm/sde/sde_plane.c | 38 ++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index 208439aaf760..627f41f2cb0b 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -1146,6 +1146,12 @@ static void _sde_plane_setup_scaler3(struct sde_plane *psde, && (src_w == dst_w)) || pstate->multirect_mode) return; + SDE_DEBUG_PLANE(psde, + "setting bilinear: src:%dx%d dst:%dx%d chroma:%dx%d fmt:%x\n", + src_w, src_h, dst_w, dst_h, + chroma_subsmpl_v, chroma_subsmpl_h, + fmt->base.pixel_format); + scale_cfg->dst_width = dst_w; scale_cfg->dst_height = dst_h; scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL; @@ -1502,7 +1508,16 @@ static void _sde_plane_setup_scaler(struct sde_plane *psde, else rc = -EINVAL; if (rc || pstate->scaler_check_state != - SDE_PLANE_SCLCHECK_SCALER_V2) { + SDE_PLANE_SCLCHECK_SCALER_V2) { + SDE_EVT32(DRMID(&psde->base), color_fill, + pstate->scaler_check_state, + psde->debugfs_default_scale, rc, + psde->pipe_cfg.src_rect.w, + psde->pipe_cfg.src_rect.h, + psde->pipe_cfg.dst_rect.w, + psde->pipe_cfg.dst_rect.h, + pstate->multirect_mode); + /* calculate default config for QSEED3 */ _sde_plane_setup_scaler3(psde, pstate, fmt, chroma_subsmpl_h, chroma_subsmpl_v); @@ -3577,17 +3592,16 @@ static int sde_plane_sspp_atomic_check(struct drm_plane *plane, ret = -EINVAL; /* decimation validation */ - } else if (deci_w || deci_h) { - if ((deci_w > psde->pipe_sblk->maxhdeciexp) || - (deci_h > psde->pipe_sblk->maxvdeciexp)) { - SDE_ERROR_PLANE(psde, - "too much decimation requested\n"); - ret = -EINVAL; - } else if (fmt->fetch_mode != SDE_FETCH_LINEAR) { - SDE_ERROR_PLANE(psde, - "decimation requires linear fetch\n"); - ret = -EINVAL; - } + } else if ((deci_w || deci_h) + && ((deci_w > psde->pipe_sblk->maxhdeciexp) + || (deci_h > psde->pipe_sblk->maxvdeciexp))) { + SDE_ERROR_PLANE(psde, "too much decimation requested\n"); + ret = -EINVAL; + + } else if ((deci_w || deci_h) + && (fmt->fetch_mode != SDE_FETCH_LINEAR)) { + SDE_ERROR_PLANE(psde, "decimation requires linear fetch\n"); + ret = -EINVAL; } else if (!(psde->features & SDE_SSPP_SCALER) && ((src.w != dst.w) || (src.h != dst.h))) { -- GitLab From 00f9c6963eb3b8544e416afc93fafa320caea6db Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Thu, 24 May 2018 19:31:59 -0700 Subject: [PATCH 0907/1299] cfg80211: Add backport flag for enabling DFS offload Upstream commit 13cf6dec93e02 ("cfg80211/nl80211: add DFS offload flag") adds wiphy EXT_FEATURE flag to indicate that HW or driver does all DFS actions by itself. Add backport flag for the same. Change-Id: Ic79c10c82c6ba4fb5960c9f5a71fc0e69eeeb270 CRs-fixed: 2265562 Signed-off-by: Peng Xu --- include/net/cfg80211.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4a6ff5aff3b4..0bab260ba1e4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -26,6 +26,8 @@ /* Indicate backport support for processing user cell base hint */ #define CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED 1 +/* Backport support for DFS offload */ +#define CFG80211_DFS_OFFLOAD_BACKPORT 1 /* Indicate backport support for external authentication*/ #define CFG80211_EXTERNAL_AUTH_SUPPORT 1 -- GitLab From 0751b64e9e76a97e284da13e97ea988673aec2b2 Mon Sep 17 00:00:00 2001 From: Dmitry Lebed Date: Thu, 1 Mar 2018 12:39:16 +0300 Subject: [PATCH 0908/1299] cfg80211/nl80211: add CAC_STARTED event CAC_STARTED event is needed for DFS offload feature and should be generated by driver/HW if DFS_OFFLOAD is enabled. Signed-off-by: Dmitry Lebed Signed-off-by: Johannes Berg Change-Id: Ib670d13989650a4b4865d40f3b4f37fb94ebd161 Git-commit: 2cb021f5de55b1d158fa18b0215a4613c3289a82 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git CRs-fixed: 2265562 Signed-off-by: Peng Xu --- include/uapi/linux/nl80211.h | 3 +++ net/wireless/mlme.c | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 6ed63fb5ddc5..f80bf0939444 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -5201,6 +5201,8 @@ enum nl80211_smps_mode { * non-operating channel is expired and no longer valid. New CAC must * be done on this channel before starting the operation. This is not * applicable for ETSI dfs domain where pre-CAC is valid for ever. + * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started, + * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled. */ enum nl80211_radar_event { NL80211_RADAR_DETECTED, @@ -5208,6 +5210,7 @@ enum nl80211_radar_event { NL80211_RADAR_CAC_ABORTED, NL80211_RADAR_NOP_FINISHED, NL80211_RADAR_PRE_CAC_EXPIRED, + NL80211_RADAR_CAC_STARTED, }; /** diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index e7c64a8dce54..01c2e10ecc7f 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -888,14 +888,17 @@ void cfg80211_cac_event(struct net_device *netdev, sizeof(struct cfg80211_chan_def)); queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk); cfg80211_sched_dfs_chan_update(rdev); - break; + /* fall through */ case NL80211_RADAR_CAC_ABORTED: + wdev->cac_started = false; + break; + case NL80211_RADAR_CAC_STARTED: + wdev->cac_started = true; break; default: WARN_ON(1); return; } - wdev->cac_started = false; nl80211_radar_notify(rdev, chandef, event, netdev, gfp); } -- GitLab From 575f1369075129e6d20a2d1803f3b030fa4ec16d Mon Sep 17 00:00:00 2001 From: Dmitry Lebed Date: Mon, 26 Mar 2018 16:36:31 +0300 Subject: [PATCH 0909/1299] cfg80211: fix CAC_STARTED event handling Exclude CAC_STARTED event from !wdev->cac_started check, since cac_started will be set later in the same function. Signed-off-by: Dmitry Lebed Signed-off-by: Johannes Berg Change-Id: I7eb8f3e42221ae22e34b4edb06edcec7683eba33 Git-commit: 850964519a65a96aa8231ff31e28f30c2633484d Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git CRs-fixed: 2265562 Signed-off-by: Peng Xu --- net/wireless/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 01c2e10ecc7f..e33da93eb31a 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -872,7 +872,7 @@ void cfg80211_cac_event(struct net_device *netdev, trace_cfg80211_cac_event(netdev, event); - if (WARN_ON(!wdev->cac_started)) + if (WARN_ON(!wdev->cac_started && event != NL80211_RADAR_CAC_STARTED)) return; if (WARN_ON(!wdev->chandef.chan)) -- GitLab From 2049bbe399de9cafd77dbf9e790d6d23a020838c Mon Sep 17 00:00:00 2001 From: Dmitry Lebed Date: Mon, 26 Mar 2018 16:36:32 +0300 Subject: [PATCH 0910/1299] cfg80211: enable use of non-cleared DFS channels for DFS offload Currently channel switch/start_ap to DFS channel cannot be done to non-CAC-cleared channel even if DFS offload if enabled. Make non-cleared DFS channels available if DFS offload is enabled. CAC will be started by HW after channel change, start_ap call, etc. Signed-off-by: Dmitry Lebed Signed-off-by: Johannes Berg Change-Id: I381b973e7622195b5b88fe9e9f864a4d078ae425 Git-commit: 2c390e44e46675da0e7bba5c3b921a091a60ec2c Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git CRs-fixed: 2265562 Signed-off-by: Peng Xu --- net/wireless/chan.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/wireless/chan.c b/net/wireless/chan.c index fad1b5baf8ff..ef5016bf9549 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -581,6 +581,10 @@ static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, { struct ieee80211_channel *c; u32 freq, start_freq, end_freq; + bool dfs_offload; + + dfs_offload = wiphy_ext_feature_isset(wiphy, + NL80211_EXT_FEATURE_DFS_OFFLOAD); start_freq = cfg80211_get_start_freq(center_freq, bandwidth); end_freq = cfg80211_get_end_freq(center_freq, bandwidth); @@ -598,8 +602,9 @@ static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, if (c->flags & IEEE80211_CHAN_DISABLED) return false; - if ((c->flags & IEEE80211_CHAN_RADAR) && - (c->dfs_state != NL80211_DFS_AVAILABLE)) + if ((c->flags & IEEE80211_CHAN_RADAR) && + (c->dfs_state != NL80211_DFS_AVAILABLE) && + !(c->dfs_state == NL80211_DFS_USABLE && dfs_offload)) return false; } -- GitLab From 9d3453adafbe1f05459ae61f4fab498e48183f24 Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Wed, 30 May 2018 13:51:20 -0700 Subject: [PATCH 0911/1299] Revert "cfg80211: Add new wiphy flag WIPHY_FLAG_DFS_OFFLOAD" This reverts commit b07c35c1bdf5bf3b242c6e447d8c879d5158ff95. Upstream kernel has defined the flag NL80211_EXT_FEATURE_DFS_OFFLOAD for the same purpose, therefore remove WIPHY_FLAG_DFS_OFFLOAD from cfg80211. Change-Id: I729e84094a335595ee4cd86f721246dfc307ae61 CRs-fixed: 2265562 Signed-off-by: Peng Xu --- include/net/cfg80211.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4a6ff5aff3b4..884712798909 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -3302,7 +3302,6 @@ struct cfg80211_ops { * beaconing mode (AP, IBSS, Mesh, ...). * @WIPHY_FLAG_HAS_STATIC_WEP: The device supports static WEP key installation * before connection. - * @WIPHY_FLAG_DFS_OFFLOAD: The driver handles all the DFS related operations. */ enum wiphy_flags { /* use hole at 0 */ @@ -3329,7 +3328,6 @@ enum wiphy_flags { WIPHY_FLAG_SUPPORTS_5_10_MHZ = BIT(22), WIPHY_FLAG_HAS_CHANNEL_SWITCH = BIT(23), WIPHY_FLAG_HAS_STATIC_WEP = BIT(24), - WIPHY_FLAG_DFS_OFFLOAD = BIT(25) }; /** -- GitLab From 2b6c387f1f326c3458cc6687da21bf193a0cb17e Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Wed, 27 Jun 2018 17:32:38 -0700 Subject: [PATCH 0912/1299] spmi: spmi-pmic-arb-debug: Change the probe init order Currently, both the regular and debug spmi pmic arbiter devices are probed in the same initcall order (arch_init). This is fine. However, most of the sepolicy rules set in the userspace are for the PMIC devices under spmi-0 bus. If the debug spmi pmic arbiter device probes first and takes "spmi-0" name, then the sepolicy rules set will be broken. Fix it by changing the probe init order of debug spmi pmic arbiter device to module init. Change-Id: I145e78a205bc80f274d8d926353a88255a7f4167 Signed-off-by: Subbaraman Narayanamurthy --- drivers/spmi/spmi-pmic-arb-debug.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/spmi/spmi-pmic-arb-debug.c b/drivers/spmi/spmi-pmic-arb-debug.c index 2c90bef1224f..28fba4c44343 100644 --- a/drivers/spmi/spmi-pmic-arb-debug.c +++ b/drivers/spmi/spmi-pmic-arb-debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -365,17 +365,7 @@ static struct platform_driver spmi_pmic_arb_debug_driver = { }, }; -int __init spmi_pmic_arb_debug_init(void) -{ - return platform_driver_register(&spmi_pmic_arb_debug_driver); -} -arch_initcall(spmi_pmic_arb_debug_init); - -static void __exit spmi_pmic_arb_debug_exit(void) -{ - platform_driver_unregister(&spmi_pmic_arb_debug_driver); -} -module_exit(spmi_pmic_arb_debug_exit); +module_platform_driver(spmi_pmic_arb_debug_driver); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:spmi_pmic_arb_debug"); -- GitLab From cc9f328fcd02981abb1eb50d0f31a1beaef26715 Mon Sep 17 00:00:00 2001 From: Saranya Chidura Date: Mon, 25 Jun 2018 18:36:04 +0530 Subject: [PATCH 0913/1299] soc: qcom: dcc_v2: add clocks support in probe DCC_CLK is to be voted from HLOS for the successful device registration. Add the clock enable in dcc driver. Change-Id: I869a957dcc7f8f4da67191e96db1c14fbde4941b Signed-off-by: Saranya Chidura --- drivers/soc/qcom/dcc_v2.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c index 7c54073afb0a..234830752435 100644 --- a/drivers/soc/qcom/dcc_v2.c +++ b/drivers/soc/qcom/dcc_v2.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #define TIMEOUT_US (100) @@ -1549,6 +1551,7 @@ static int dcc_probe(struct platform_device *pdev) struct dcc_drvdata *drvdata; struct resource *res; const char *data_sink; + struct clk *pclk; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) @@ -1557,6 +1560,16 @@ static int dcc_probe(struct platform_device *pdev) drvdata->dev = &pdev->dev; platform_set_drvdata(pdev, drvdata); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dcc_clk"); + if (res) { + pclk = devm_clk_get(dev, "dcc_clk"); + if (!IS_ERR(pclk)) { + ret = clk_set_rate(pclk, QDSS_CLK_LEVEL_DYNAMIC); + if (ret) + dev_err(dev, "clk set rate failed\n"); + } + } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dcc-base"); if (!res) return -EINVAL; -- GitLab From a1bc21a0da25f8c31b0aaeb586e738522a0acbd4 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Wed, 27 Jun 2018 19:03:30 -0700 Subject: [PATCH 0914/1299] ion: Fix missing mutex_unlock on error path Fix a scenario where an ion_buffer attempts to grab a mutex it already has. Change-Id: Ie274904ef7b077cdb0a65e72b626dd37320c7e75 Signed-off-by: Patrick Daly --- drivers/staging/android/ion/ion.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 29094d9632ef..e68cafa23713 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -364,8 +364,10 @@ static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, map_attrs); } - if (count <= 0) + if (count <= 0) { + mutex_unlock(&buffer->lock); return ERR_PTR(-ENOMEM); + } a->dma_mapped = true; mutex_unlock(&buffer->lock); -- GitLab From 723a6e0779227edfbdbef4a5a7f9777f148716a8 Mon Sep 17 00:00:00 2001 From: Hardik Kantilal Patel Date: Mon, 25 Jun 2018 09:56:59 +0530 Subject: [PATCH 0915/1299] defconfig: Add WLAN related config parameter Add WLAN related configuration parameter to compile WLAN Host driver and ICNSS platform driver. Change-Id: Ib00aa6e6adf500beb6ad20e275e166788fdd9fc0 Signed-off-by: Hardik Kantilal Patel --- arch/arm64/configs/vendor/qcs405_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index 1d2ac09021db..d9bc9878a533 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -240,6 +240,7 @@ CONFIG_PPP_SYNC_TTY=y CONFIG_USB_USBNET=y CONFIG_USB_NET_SMSC75XX=y CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVBUG=m CONFIG_INPUT_KEYRESET=y @@ -414,6 +415,9 @@ CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_CORE_HANG_DETECT=y CONFIG_QCOM_DCC_V2=y +CONFIG_ICNSS=y +CONFIG_ICNSS_DEBUG=y +CONFIG_ICNSS_QMI=y CONFIG_QCOM_BUS_SCALING=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y -- GitLab From 6f2446ed8609393602d07a9268359a3334b7af3c Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Thu, 28 Jun 2018 11:26:04 +0800 Subject: [PATCH 0916/1299] ARM: dts: msm: Enable sw-jeita for QRD8150 Enable sw-jeita function for QRD8150 device so that the battery could be charged with the JEITA setting specified in the corresponding battery profile. Change-Id: I8bb6716087210cf0e6b819cdc571240bbc17443c Signed-off-by: Fenglin Wu --- arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi index d82e480bc2d0..cad8e1d389ba 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi @@ -520,6 +520,8 @@ io-channel-names = "usb_in_voltage", "usb_in_current", "chg_temp"; + qcom,battery-data = <&qrd_batterydata>; + qcom,sw-jeita-enable; }; &smb1390 { -- GitLab From 7d34c83dc82679530a00747bffbdccae16f9505a Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Wed, 27 Jun 2018 15:15:31 +0530 Subject: [PATCH 0917/1299] msm: kgsl: Add a check before accessing SPTPRAC head switch SPTPRAC head switch is not present all A6xx GPUs. Attempt to turn on SPTPRAC head switch such as A640 GPU will result into failure. Fix this by adding a conditional check before we attempt to turn it on/off. Change-Id: I9e3af0f31e164efe61bb4dd13b7ec3e89e609039 Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno_a6xx.c | 6 +++--- drivers/gpu/msm/adreno_a6xx_gmu.c | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 170e7d3c4206..908511ee663d 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -1201,7 +1201,7 @@ static int a6xx_rb_start(struct adreno_device *adreno_dev, */ static int a6xx_sptprac_enable(struct adreno_device *adreno_dev) { - if (!adreno_has_sptprac_gdsc(adreno_dev)) + if (adreno_is_a608(adreno_dev)) return 0; return a6xx_gmu_sptprac_enable(adreno_dev); @@ -1213,7 +1213,7 @@ static int a6xx_sptprac_enable(struct adreno_device *adreno_dev) */ static void a6xx_sptprac_disable(struct adreno_device *adreno_dev) { - if (!adreno_has_sptprac_gdsc(adreno_dev)) + if (adreno_is_a608(adreno_dev)) return; a6xx_gmu_sptprac_disable(adreno_dev); @@ -1384,7 +1384,7 @@ static int a6xx_soft_reset(struct adreno_device *adreno_dev) /* Clear GBIF client halt and CX arbiter halt */ adreno_deassert_gbif_halt(adreno_dev); - a6xx_gmu_sptprac_enable(adreno_dev); + a6xx_sptprac_enable(adreno_dev); return 0; } diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index b4fcdbd60e9d..8b5b797d014d 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -671,8 +671,9 @@ int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - if (!gmu_core_gpmu_isenabled(device)) - return -EINVAL; + if (!gmu_core_gpmu_isenabled(device) || + !adreno_has_sptprac_gdsc(adreno_dev)) + return 0; gmu_core_regwrite(device, A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, SPTPRAC_POWERON_CTRL_MASK); @@ -698,7 +699,8 @@ void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - if (!gmu_core_gpmu_isenabled(device)) + if (!gmu_core_gpmu_isenabled(device) || + !adreno_has_sptprac_gdsc(adreno_dev)) return; /* Ensure that retention is on */ -- GitLab From 36d76e6689a1c59ccf1d4b094dff56f8d1496d5a Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Sun, 10 Jun 2018 20:03:14 +0530 Subject: [PATCH 0918/1299] ARM: dts: msm: Add device node support for TSENS in sdmmagpie Add TSENS node and user thermal zone configurations for TSENS sensors in sdmmagpie. Change-Id: I53daded15c517c8af27cf5906bcfc87fbe13b1b3 Signed-off-by: Jishnu Prakash --- .../boot/dts/qcom/sdmmagpie-thermal.dtsi | 352 ++++++++++++++++++ arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 25 ++ 2 files changed, 377 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sdmmagpie-thermal.dtsi diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-thermal.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-thermal.dtsi new file mode 100644 index 000000000000..f3720892fa8a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-thermal.dtsi @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +&thermal_zones { + aoss-0-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "user_space"; + thermal-sensors = <&tsens0 0>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc0-cpu0-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "user_space"; + thermal-sensors = <&tsens0 1>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc0-cpu1-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "user_space"; + thermal-sensors = <&tsens0 2>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc0-cpu2-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "user_space"; + thermal-sensors = <&tsens0 3>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc0-cpu3-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 4>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc0-cpu4-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 5>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc0-cpu5-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 6>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + cpuss-0-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 7>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + cpuss-1-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 8>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc1-cpu0-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 9>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc1-cpu1-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 10>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc1-cpu2-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 11>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + apc1-cpu3-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 12>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + gpuss-0-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 13>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + gpuss-1-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens0 14>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + aoss-1-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens1 0>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + cwlan-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens1 1>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + video-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens1 2>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + ddr-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens1 3>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + q6-hvx-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens1 4>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + camera-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens1 5>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + cmpss-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens1 6>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + mdm-core-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens1 7>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + npu-usr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens1 8>; + thermal-governor = "user_space"; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index cdd0b2e2738b..6b18cc2f2ebb 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -945,6 +945,30 @@ }; }; + thermal_zones: thermal-zones {}; + + tsens0: tsens@c222000 { + compatible = "qcom,tsens24xx"; + reg = <0xc222000 0x8>, + <0xc263000 0x1ff>; + reg-names = "tsens_srot_physical", + "tsens_tm_physical"; + interrupts = <0 506 0>, <0 508 0>; + interrupt-names = "tsens-upper-lower", "tsens-critical"; + #thermal-sensor-cells = <1>; + }; + + tsens1: tsens@c223000 { + compatible = "qcom,tsens24xx"; + reg = <0xc223000 0x8>, + <0xc265000 0x1ff>; + reg-names = "tsens_srot_physical", + "tsens_tm_physical"; + interrupts = <0 507 0>, <0 509 0>; + interrupt-names = "tsens-upper-lower", "tsens-critical"; + #thermal-sensor-cells = <1>; + }; + qcom,llcc@9200000 { compatible = "qcom,llcc-core", "syscon", "simple-mfd"; reg = <0x9200000 0x450000>; @@ -1010,6 +1034,7 @@ #include "sdmmagpie-pinctrl.dtsi" #include "sdmmagpie-gdsc.dtsi" #include "sdmmagpie-qupv3.dtsi" +#include "sdmmagpie-thermal.dtsi" &pcie_0_gdsc { status = "ok"; -- GitLab From e2327e3632c1b408ab0f8b0f82ae9674e5c0512f Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Thu, 28 Jun 2018 11:02:38 +0530 Subject: [PATCH 0919/1299] clk: qcom: clk-pll: Fix compilation warning from HF pll ops The request rate is being assigned twice which throws compilation warning, hence fix the same. Change-Id: I688bfafcb445120707e299f2afc65edfc5959d8a Signed-off-by: Shefali Jain --- drivers/clk/qcom/clk-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c index e6220a0b8d2e..f8d46ae34ae1 100644 --- a/drivers/clk/qcom/clk-pll.c +++ b/drivers/clk/qcom/clk-pll.c @@ -143,7 +143,7 @@ clk_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) * req->best_parent_rate; else - req->rate = req->rate = f->freq; + req->rate = f->freq; return 0; } -- GitLab From def2f0fe9e66e017421cb0d6d625dcf11a5e5f56 Mon Sep 17 00:00:00 2001 From: Mohamed Sunfeer Date: Mon, 11 Jun 2018 17:56:35 +0530 Subject: [PATCH 0920/1299] kernel/msm: hdcp: Add API to enforce/revoke forced encryption The new API will improve modularization, segregate enablement and enforcement of encryption for DisplayPort. CRs-Fixed: 2231930 Change-Id: If58c0663ce1894be8ac5e12d6d90cf590fc920b1 Signed-off-by: Mohamed Sunfeer --- drivers/misc/hdcp_qseecom.c | 60 ++++++++++++++++++++++++++++++++++++ include/linux/hdcp_qseecom.h | 6 ++++ 2 files changed, 66 insertions(+) diff --git a/drivers/misc/hdcp_qseecom.c b/drivers/misc/hdcp_qseecom.c index 87f1b338106c..01b00176a0d6 100644 --- a/drivers/misc/hdcp_qseecom.c +++ b/drivers/misc/hdcp_qseecom.c @@ -71,6 +71,9 @@ */ #define SLEEP_SET_HW_KEY_MS 300 +/* Wait 200ms after authentication */ +#define SLEEP_FORCE_ENCRYPTION_MS 200 + /* hdcp command status */ #define HDCP_SUCCESS 0 #define HDCP_FAIL 1 @@ -110,6 +113,7 @@ #define HDCP_KEY_ALREADY_PROVISIONED 35 #define HDCP_KEY_NOT_PROVISIONED 36 #define HDCP_CALL_TOO_SOON 37 +#define HDCP_FORCE_ENCRYPTION_FAILED 38 /* flags set by tz in response message */ #define HDCP_TXMTR_SUBSTATE_INIT 0 @@ -177,6 +181,7 @@ enum { hdcp_cmd_session_init = SERVICE_CREATE_CMD(16), hdcp_cmd_session_deinit = SERVICE_CREATE_CMD(17), hdcp_cmd_start_auth = SERVICE_CREATE_CMD(18), + hdcp_cmd_force_encryption = SERVICE_CREATE_CMD(22), }; enum hdcp_state { @@ -448,6 +453,17 @@ struct __attribute__ ((__packed__)) hdcp_start_auth_rsp { uint8_t message[MAX_TX_MESSAGE_SIZE]; }; +struct __attribute__ ((__packed__)) hdcp_force_encryption_req { + uint32_t commandid; + uint32_t ctxhandle; + uint32_t enable; +}; + +struct __attribute__ ((__packed__)) hdcp_force_encryption_rsp { + uint32_t status; + uint32_t commandid; +}; + struct hdcp2_handle { struct hdcp2_app_data app_data; uint32_t tz_ctxhandle; @@ -552,6 +568,8 @@ static const char *hdcp_cmd_status_to_str(uint32_t err) return HDCP_CMD_STATUS_TO_STR(HDCP_KEY_NOT_PROVISIONED); case HDCP_CALL_TOO_SOON: return HDCP_CMD_STATUS_TO_STR(HDCP_CALL_TOO_SOON); + case HDCP_FORCE_ENCRYPTION_FAILED: + return HDCP_CMD_STATUS_TO_STR(HDCP_FORCE_ENCRYPTION_FAILED); default: return ""; } @@ -1088,6 +1106,48 @@ static int hdcp2_app_enable_encryption(struct hdcp2_handle *handle) return rc; } +int hdcp2_force_encryption_utility(struct hdcp2_handle *handle, uint32_t enable) +{ + int rc = 0; + + hdcp2_app_init_var(force_encryption); + if (handle->hdcp_state == HDCP_STATE_AUTHENTICATED) + msleep(SLEEP_FORCE_ENCRYPTION_MS); + + req_buf->ctxhandle = handle->tz_ctxhandle; + req_buf->enable = enable; + + rc = hdcp2_app_process_cmd(force_encryption); + if (rc || (rsp_buf->commandid != hdcp_cmd_force_encryption)) + goto error; + + return 0; +error: + return rc; +} + +int hdcp2_force_encryption(void *ctx, uint32_t enable) +{ + int rc = 0; + struct hdcp2_handle *handle = NULL; + + if (!ctx) { + pr_err("invalid input\n"); + return -EINVAL; + } + + handle = ctx; + rc = hdcp2_force_encryption_utility(handle, enable); + if (rc) + goto error; + + pr_debug("success\n"); + return 0; +error: + pr_err("failed, rc=%d\n", rc); + return rc; +} + static int hdcp2_app_query_stream(struct hdcp2_handle *handle) { int rc = 0; diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h index c8117801ab13..406a6ed7c818 100644 --- a/include/linux/hdcp_qseecom.h +++ b/include/linux/hdcp_qseecom.h @@ -68,6 +68,7 @@ void hdcp2_deinit(void *ctx); bool hdcp2_feature_supported(void *ctx); int hdcp2_app_comm(void *ctx, enum hdcp2_app_cmd cmd, struct hdcp2_app_data *app_data); +int hdcp2_force_encryption(void *ctx, uint32_t enable); #else static inline void *hdcp1_init(void) { @@ -113,6 +114,11 @@ static inline int hdcp2_app_comm(void *ctx, enum hdcp2_app_cmd cmd, { return 0; } + +static inline int hdcp2_force_encryption(void *ctx, uint32_t enable) +{ + return 0; +} #endif #endif /* __HDCP_QSEECOM_H */ -- GitLab From d73458ac0e92c70ffe7a8e4f2b41940464b998af Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Thu, 28 Jun 2018 12:36:28 +0530 Subject: [PATCH 0921/1299] ARM: dts: msm: Specify stream match mask for GPU SMMU on QCS405 Add stream match mask for GPU SMMU on QCS405. This is needed for GPU SMMU to work properly. Change-Id: Ib122db0eef314d2da39bf77179ea0f5288b38201 Signed-off-by: Deepak Kumar --- arch/arm64/boot/dts/qcom/qcs405-gpu.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-gpu.dtsi b/arch/arm64/boot/dts/qcom/qcs405-gpu.dtsi index 102533616403..2b58972a222c 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-gpu.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-gpu.dtsi @@ -180,7 +180,7 @@ qcom,retention; gfx3d_user: gfx3d_user { compatible = "qcom,smmu-kgsl-cb"; - iommus = <&gfx_iommu 0>; + iommus = <&gfx_iommu 0 1>; qcom,gpu-offset = <0xa000>; }; }; -- GitLab From aa61a89318c1974ec9d8b6ae233efc1a5e140c2b Mon Sep 17 00:00:00 2001 From: Konstantin Dorfman Date: Thu, 28 Jun 2018 09:55:04 +0300 Subject: [PATCH 0922/1299] soc: qcom: spcom: fix NULL pointer dereference This change fix kernel panic due to NULL pointer dereference from spcom_probe while unregister the device. Observed during kernel testing (bind/unbind of platform driver). Change-Id: I5ead40d9da25e9ca2a59af9ba8c236d575103eae Signed-off-by: Konstantin Dorfman --- drivers/soc/qcom/spcom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index b48e214d63dd..1010f47ddb6e 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -2086,7 +2086,7 @@ static int spcom_probe(struct platform_device *pdev) ret = spcom_register_chardev(); if (ret) { pr_err("create character device failed.\n"); - goto fail_reg_chardev; + goto fail_while_chardev_reg; } ret = spcom_parse_dt(np); @@ -2104,6 +2104,7 @@ static int spcom_probe(struct platform_device *pdev) fail_reg_chardev: pr_err("failed to init driver\n"); spcom_unregister_chrdev(); +fail_while_chardev_reg: kfree(dev); spcom_dev = NULL; -- GitLab From 9573547ea02a64462acb64fea95e1b6b1dd24e14 Mon Sep 17 00:00:00 2001 From: chenx Date: Mon, 11 Jun 2018 17:20:06 +0800 Subject: [PATCH 0923/1299] input: touchscreen: Add himax touchscreen support This new driver is for Himax's touch IC hx83112A. And it is for qrd640 and other latest projects. Change-Id: I8d18b020c280ff67fcb1911e48d0f8da6297eba2 Signed-off-by: chenx Git-commit: 58062446fbe1db2fd8af883d32a46be6b5b3076e Git-Repo: https://source.codeaurora.org/external/thundersoft/ihvjointlab/sensor-driver/log/?h=Himax_ctp_hx83112 Signed-off-by: Fei Mao --- Documentation/input/touchscreen/himax.txt | 28 + drivers/input/touchscreen/Kconfig | 12 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/hxchipset/Kconfig | 86 + drivers/input/touchscreen/hxchipset/Makefile | 13 + .../touchscreen/hxchipset/himax_common.c | 2332 +++++++++++++ .../touchscreen/hxchipset/himax_common.h | 497 +++ .../input/touchscreen/hxchipset/himax_debug.c | 3014 +++++++++++++++++ .../input/touchscreen/hxchipset/himax_debug.h | 60 + .../touchscreen/hxchipset/himax_ic_HX83112.c | 298 ++ .../touchscreen/hxchipset/himax_ic_HX83112.h | 22 + .../touchscreen/hxchipset/himax_ic_core.h | 716 ++++ .../hxchipset/himax_ic_incell_core.c | 2727 +++++++++++++++ .../touchscreen/hxchipset/himax_platform.c | 802 +++++ .../touchscreen/hxchipset/himax_platform.h | 136 + 15 files changed, 10744 insertions(+) create mode 100644 Documentation/input/touchscreen/himax.txt create mode 100644 drivers/input/touchscreen/hxchipset/Kconfig create mode 100644 drivers/input/touchscreen/hxchipset/Makefile create mode 100644 drivers/input/touchscreen/hxchipset/himax_common.c create mode 100644 drivers/input/touchscreen/hxchipset/himax_common.h create mode 100644 drivers/input/touchscreen/hxchipset/himax_debug.c create mode 100644 drivers/input/touchscreen/hxchipset/himax_debug.h create mode 100644 drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c create mode 100644 drivers/input/touchscreen/hxchipset/himax_ic_HX83112.h create mode 100644 drivers/input/touchscreen/hxchipset/himax_ic_core.h create mode 100644 drivers/input/touchscreen/hxchipset/himax_ic_incell_core.c create mode 100644 drivers/input/touchscreen/hxchipset/himax_platform.c create mode 100644 drivers/input/touchscreen/hxchipset/himax_platform.h diff --git a/Documentation/input/touchscreen/himax.txt b/Documentation/input/touchscreen/himax.txt new file mode 100644 index 000000000000..37ddc6749b24 --- /dev/null +++ b/Documentation/input/touchscreen/himax.txt @@ -0,0 +1,28 @@ +Himax touch controller + +The Himax touch controller is connected to host processor +via i2c. The controller generates interrupts when the +user touches the panel. The host controller is expected +to read the touch coordinates over i2c and pass the coordinates +to the rest of the system. + +Required properties: + + - compatible : Should be "himax,hxcommon" + - reg : i2c slave address of the device. + - interrupt-parent : parent of interrupt. + - himax,irq-gpio : irq gpio. + - himax,reset-gpio : reset gpio. + - vdd-supply : Power supply needed to power up the device. + - avdd-supply : Power source required to power up i2c bus. + - himax,panel-coords : panel coordinates for the chip in pixels. + It is a four tuple consisting of min x, + min y, max x and max y values. + - himax,display-coords : display coordinates in pixels. It is a four + tuple consisting of min x, min y, max x and + max y values + +Optional properties: + - himax,3v3-gpio : gpio acting as 3.3 v supply. + - himax,report_type : Multi-touch protocol type. Default 0. + 0 for protocol A, 1 for protocol B. diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 64f25cf45382..721dd2da4967 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1256,4 +1256,16 @@ config TOUCHSCREEN_ST source "drivers/input/touchscreen/st/Kconfig" +config TOUCHSCREEN_HIMAX_CHIPSET + bool "Himax touchpanel CHIPSET" + depends on I2C + help + Say Y here if you have a Himax CHIPSET touchscreen. + HIMAX controllers are multi touch controllers which can + report 10 touches at a time. + + If unsure, say N. + +source "drivers/input/touchscreen/hxchipset/Kconfig" + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 2809279cbcbf..b4bd108ff616 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -105,3 +105,4 @@ obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o obj-$(CONFIG_TOUCHSCREEN_ST) += st/ +obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET)» += hxchipset/ \ No newline at end of file diff --git a/drivers/input/touchscreen/hxchipset/Kconfig b/drivers/input/touchscreen/hxchipset/Kconfig new file mode 100644 index 000000000000..ead31d1aa4f5 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/Kconfig @@ -0,0 +1,86 @@ +# +# Himax Touchscreen driver configuration +# + +config TOUCHSCREEN_HIMAX_I2C + tristate "HIMAX chipset i2c touchscreen" + depends on TOUCHSCREEN_HIMAX_CHIPSET + help + This enables support for HIMAX CHIPSET over I2C based touchscreens. + + +# ***************** On-cell Start ***************** +config TOUCHSCREEN_HIMAX_ONCELL + tristate "HIMAX chipset on-cell function" + depends on TOUCHSCREEN_HIMAX_I2C + help + This enables support for HIMAX CHIPSET of on-cell function. + +config TOUCHSCREEN_HIMAX_IC_HX852xH + tristate "HIMAX chipset HX852xH function" + depends on TOUCHSCREEN_HIMAX_ONCELL + help + This enables support for HIMAX CHIPSET of HX852xH. + +config TOUCHSCREEN_HIMAX_IC_HX852xG + tristate "HIMAX chipset HX852xG function" + depends on TOUCHSCREEN_HIMAX_ONCELL + help + This enables support for HIMAX CHIPSET of HX852xG. +# ***************** On-cell End ******************* + +# ***************** In-cell Start ***************** +config TOUCHSCREEN_HIMAX_INCELL + tristate "HIMAX chipset in-cell function" + depends on TOUCHSCREEN_HIMAX_I2C + help + This enables support for HIMAX CHIPSET of in-cell function. + +config TOUCHSCREEN_HIMAX_IC_HX83191 + tristate "HIMAX chipset HX83191 function" + depends on TOUCHSCREEN_HIMAX_INCELL + help + This enables support for HIMAX CHIPSET of HX83191. + +config TOUCHSCREEN_HIMAX_IC_HX83112 + tristate "HIMAX chipset HX83112 function" + depends on TOUCHSCREEN_HIMAX_INCELL + help + This enables support for HIMAX CHIPSET of HX83112. + +config TOUCHSCREEN_HIMAX_IC_HX83111 + tristate "HIMAX chipset HX83111 function" + depends on TOUCHSCREEN_HIMAX_INCELL + help + This enables support for HIMAX CHIPSET of HX83111. + +config TOUCHSCREEN_HIMAX_IC_HX83103 + tristate "HIMAX chipset HX83103 function" + depends on TOUCHSCREEN_HIMAX_INCELL + help + This enables support for HIMAX CHIPSET of HX83103. + +config TOUCHSCREEN_HIMAX_IC_HX83102 + tristate "HIMAX chipset HX83102 function" + depends on TOUCHSCREEN_HIMAX_INCELL + help + This enables support for HIMAX CHIPSET of HX83102. +# ***************** In-cell End ******************* + +config TOUCHSCREEN_HIMAX_DEBUG + tristate "HIMAX debug function" + depends on TOUCHSCREEN_HIMAX_I2C + help + This enables support for HIMAX debug function. + +config TOUCHSCREEN_HIMAX_INSPECT + tristate "HIMAX inspect function" + depends on TOUCHSCREEN_HIMAX_I2C + help + This enables support for HIMAX debug function. + +config HMX_DB + tristate "HIMAX driver test over Dragon Board" + depends on TOUCHSCREEN_HIMAX_I2C + help + This enables support for HIMAX driver test over Dragon Board. diff --git a/drivers/input/touchscreen/hxchipset/Makefile b/drivers/input/touchscreen/hxchipset/Makefile new file mode 100644 index 000000000000..c44932bf7352 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/Makefile @@ -0,0 +1,13 @@ +# Makefile for the Himax touchscreen drivers. +obj-$(CONFIG_TOUCHSCREEN_HIMAX_ONCELL) += himax_ic_oncell_core.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_IC_HX852xH) += himax_ic_HX852xH.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_IC_HX852xG) += himax_ic_HX852xG.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_INCELL) += himax_ic_incell_core.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_IC_HX83191) += himax_ic_HX83191.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_IC_HX83112) += himax_ic_HX83112.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_IC_HX83111) += himax_ic_HX83111.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_IC_HX83103) += himax_ic_HX83103.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_IC_HX83102) += himax_ic_HX83102.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_I2C) += himax_common.o himax_platform.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) += himax_debug.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_INSPECT) += himax_inspection.o \ No newline at end of file diff --git a/drivers/input/touchscreen/hxchipset/himax_common.c b/drivers/input/touchscreen/hxchipset/himax_common.c new file mode 100644 index 000000000000..43ea1829c4af --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_common.c @@ -0,0 +1,2332 @@ +/* + * Himax Android Driver Sample Code for common functions + * + * Copyright (C) 2018 Himax Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "himax_common.h" +#include "himax_ic_core.h" +#include "himax_platform.h" + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_DEBUG +#include "himax_debug.h" +#endif + +#define SUPPORT_FINGER_DATA_CHECKSUM 0x0F +#define TS_WAKE_LOCK_TIMEOUT (2 * HZ) +#define FRAME_COUNT 5 +#define COMMON_BUF_SZ 80 + +#if defined(HX_AUTO_UPDATE_FW) +char *i_CTPM_firmware_name = "Himax_firmware.bin"; +const struct firmware *i_CTPM_FW; +#endif + +struct himax_ts_data *private_ts; +struct himax_ic_data *ic_data; +struct himax_report_data *hx_touch_data; +struct himax_core_fp g_core_fp; +struct himax_debug *debug_data; + +struct proc_dir_entry *himax_touch_proc_dir; +#define HIMAX_PROC_TOUCH_FOLDER "android_touch" + +/* ts_work about start */ +struct himax_target_report_data *g_target_report_data; +/* ts_work about end */ + +static int HX_TOUCH_INFO_POINT_CNT; + +unsigned long FW_VER_MAJ_FLASH_ADDR; +unsigned long FW_VER_MIN_FLASH_ADDR; +unsigned long CFG_VER_MAJ_FLASH_ADDR; +unsigned long CFG_VER_MIN_FLASH_ADDR; +unsigned long CID_VER_MAJ_FLASH_ADDR; +unsigned long CID_VER_MIN_FLASH_ADDR; + +unsigned long FW_VER_MAJ_FLASH_LENG; +unsigned long FW_VER_MIN_FLASH_LENG; +unsigned long CFG_VER_MAJ_FLASH_LENG; +unsigned long CFG_VER_MIN_FLASH_LENG; +unsigned long CID_VER_MAJ_FLASH_LENG; +unsigned long CID_VER_MIN_FLASH_LENG; + +unsigned long FW_CFG_VER_FLASH_ADDR; + +#ifdef HX_AUTO_UPDATE_FW + int g_i_FW_VER = 0; + int g_i_CFG_VER = 0; + int g_i_CID_MAJ = 0; /* GUEST ID */ + int g_i_CID_MIN = 0; /* VER for GUEST */ +#endif + +unsigned char IC_CHECKSUM; + +#ifdef HX_ESD_RECOVERY + u8 HX_ESD_RESET_ACTIVATE = 0; + int hx_EB_event_flag = 0; + int hx_EC_event_flag = 0; + int hx_ED_event_flag = 0; + int g_zero_event_count = 0; +#endif +u8 HX_HW_RESET_ACTIVATE; + +static uint8_t AA_press; +static uint8_t EN_NoiseFilter; +static uint8_t Last_EN_NoiseFilter; + +static int p_point_num = 0xFFFF; +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) +static uint8_t vk_press; +static int tpd_key; +static int tpd_key_old; +#endif +static int probe_fail_flag; +#ifdef HX_USB_DETECT_GLOBAL + bool USB_detect_flag; +#endif + + +#if defined(CONFIG_DRM) +int drm_notifier_callback(struct notifier_block *self, unsigned long event, void *data); +#elif defined(CONFIG_FB) +int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void himax_ts_early_suspend(struct early_suspend *h); +static void himax_ts_late_resume(struct early_suspend *h); +#endif + +#if defined(HX_PALM_REPORT) + int himax_palm_detect(uint8_t *buf); +#endif + +#ifdef HX_GESTURE_TRACK + static int gest_pt_cnt; + static int gest_pt_x[GEST_PT_MAX_NUM]; + static int gest_pt_y[GEST_PT_MAX_NUM]; + static int gest_start_x, gest_start_y, gest_end_x, gest_end_y; + static int gest_width, gest_height, gest_mid_x, gest_mid_y; + static int gn_gesture_coor[16]; +#endif + +int himax_report_data_init(void); + +int g_ts_dbg; + +/* File node for SMWP and HSEN - Start*/ +uint8_t HX_PROC_SEND_FLAG; +#ifdef HX_SMART_WAKEUP + #define HIMAX_PROC_SMWP_FILE "SMWP" + struct proc_dir_entry *himax_proc_SMWP_file = NULL; + #define HIMAX_PROC_GESTURE_FILE "GESTURE" + struct proc_dir_entry *himax_proc_GESTURE_file = NULL; + uint8_t HX_SMWP_EN = 0; + bool FAKE_POWER_KEY_SEND; +#endif + +#ifdef HX_HIGH_SENSE + #define HIMAX_PROC_HSEN_FILE "HSEN" + struct proc_dir_entry *himax_proc_HSEN_file = NULL; +#endif + +#ifdef HX_HIGH_SENSE +static ssize_t himax_HSEN_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + size_t count = 0; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + + count = snprintf(temp_buf, len, "%d\n", ts->HSEN_enable); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } else + HX_PROC_SEND_FLAG = 0; + + return count; +} + +static ssize_t himax_HSEN_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf[COMMON_BUF_SZ] = {0}; + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + if (buf[0] == '0') + ts->HSEN_enable = 0; + else if (buf[0] == '1') + ts->HSEN_enable = 1; + else + return -EINVAL; + + g_core_fp.fp_set_HSEN_enable(ts->HSEN_enable, ts->suspended); + I("%s: HSEN_enable = %d.\n", __func__, ts->HSEN_enable); + return len; +} + +static const struct file_operations himax_proc_HSEN_ops = { + .owner = THIS_MODULE, + .read = himax_HSEN_read, + .write = himax_HSEN_write, +}; +#endif + +#ifdef HX_SMART_WAKEUP +static ssize_t himax_SMWP_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + size_t count = 0; + struct himax_ts_data *ts = private_ts; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + count = snprintf(temp_buf, len, "%d\n", ts->SMWP_enable); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } else + HX_PROC_SEND_FLAG = 0; + + return count; +} + +static ssize_t himax_SMWP_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf[COMMON_BUF_SZ] = {0}; + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + if (buf[0] == '0') + ts->SMWP_enable = 0; + else if (buf[0] == '1') + ts->SMWP_enable = 1; + else + return -EINVAL; + + g_core_fp.fp_set_SMWP_enable(ts->SMWP_enable, ts->suspended); + HX_SMWP_EN = ts->SMWP_enable; + I("%s: SMART_WAKEUP_enable = %d.\n", __func__, HX_SMWP_EN); + return len; +} + +static const struct file_operations himax_proc_SMWP_ops = { + .owner = THIS_MODULE, + .read = himax_SMWP_read, + .write = himax_SMWP_write, +}; + +static ssize_t himax_GESTURE_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + int i = 0; + size_t ret = 0; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + + for (i = 0; i < 16; i++) + ret += snprintf(temp_buf + ret, len - ret, + "ges_en[%d]=%d\n", i, ts->gesture_cust_en[i]); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } else { + HX_PROC_SEND_FLAG = 0; + ret = 0; + } + + return ret; +} + +static ssize_t himax_GESTURE_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + int i = 0; + char buf[COMMON_BUF_SZ] = {0}; + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + I("himax_GESTURE_store= %s\n", buf); + + for (i = 0; i < 16; i++) { + if (buf[i] == '0') + ts->gesture_cust_en[i] = 0; + else if (buf[i] == '1') + ts->gesture_cust_en[i] = 1; + else + ts->gesture_cust_en[i] = 0; + + I("gesture en[%d]=%d\n", i, ts->gesture_cust_en[i]); + } + + return len; +} + +static const struct file_operations himax_proc_Gesture_ops = { + .owner = THIS_MODULE, + .read = himax_GESTURE_read, + .write = himax_GESTURE_write, +}; +#endif + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_INSPECT +extern void (*fp_himax_self_test_init)(void); +#endif + +int himax_common_proc_init(void) +{ + himax_touch_proc_dir = proc_mkdir(HIMAX_PROC_TOUCH_FOLDER, NULL); + + if (himax_touch_proc_dir == NULL) { + E(" %s: himax_touch_proc_dir file create failed!\n", __func__); + return -ENOMEM; + } +#ifdef CONFIG_TOUCHSCREEN_HIMAX_INSPECT + if (fp_himax_self_test_init != NULL) + fp_himax_self_test_init(); +#endif + +#ifdef HX_HIGH_SENSE + himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, 0666, + himax_touch_proc_dir, &himax_proc_HSEN_ops); + + if (himax_proc_HSEN_file == NULL) { + E(" %s: proc HSEN file create failed!\n", __func__); + goto fail_1; + } + +#endif +#ifdef HX_SMART_WAKEUP + himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, 0666, + himax_touch_proc_dir, &himax_proc_SMWP_ops); + + if (himax_proc_SMWP_file == NULL) { + E(" %s: proc SMWP file create failed!\n", __func__); + goto fail_2; + } + + himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, 0666, + himax_touch_proc_dir, &himax_proc_Gesture_ops); + + if (himax_proc_GESTURE_file == NULL) { + E(" %s: proc GESTURE file create failed!\n", __func__); + goto fail_3; + } +#endif + return 0; + +#ifdef HX_SMART_WAKEUP + remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir); +fail_3: + remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir); +fail_2: +#endif +#ifdef HX_HIGH_SENSE + remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir); +fail_1: +#endif + return -ENOMEM; +} + +void himax_common_proc_deinit(void) +{ +#ifdef HX_SMART_WAKEUP + remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir); +#endif +#ifdef HX_HIGH_SENSE + remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir); +#endif +} + +/* File node for SMWP and HSEN - End*/ + +int himax_input_register(struct himax_ts_data *ts) +{ + int ret = 0; + + ret = himax_dev_set(ts); + if (ret < 0) + goto input_device_fail; + + set_bit(EV_SYN, ts->input_dev->evbit); + set_bit(EV_ABS, ts->input_dev->evbit); + set_bit(EV_KEY, ts->input_dev->evbit); +#if defined(HX_PLATFOME_DEFINE_KEY) + himax_platform_key(); +#else + set_bit(KEY_BACK, ts->input_dev->keybit); + set_bit(KEY_HOME, ts->input_dev->keybit); + set_bit(KEY_MENU, ts->input_dev->keybit); + set_bit(KEY_SEARCH, ts->input_dev->keybit); +#endif +#if defined(HX_SMART_WAKEUP) || defined(HX_PALM_REPORT) + set_bit(KEY_POWER, ts->input_dev->keybit); +#endif +#if defined(HX_SMART_WAKEUP) + set_bit(KEY_CUST_01, ts->input_dev->keybit); + set_bit(KEY_CUST_02, ts->input_dev->keybit); + set_bit(KEY_CUST_03, ts->input_dev->keybit); + set_bit(KEY_CUST_04, ts->input_dev->keybit); + set_bit(KEY_CUST_05, ts->input_dev->keybit); + set_bit(KEY_CUST_06, ts->input_dev->keybit); + set_bit(KEY_CUST_07, ts->input_dev->keybit); + set_bit(KEY_CUST_08, ts->input_dev->keybit); + set_bit(KEY_CUST_09, ts->input_dev->keybit); + set_bit(KEY_CUST_10, ts->input_dev->keybit); + set_bit(KEY_CUST_11, ts->input_dev->keybit); + set_bit(KEY_CUST_12, ts->input_dev->keybit); + set_bit(KEY_CUST_13, ts->input_dev->keybit); + set_bit(KEY_CUST_14, ts->input_dev->keybit); + set_bit(KEY_CUST_15, ts->input_dev->keybit); +#endif + set_bit(BTN_TOUCH, ts->input_dev->keybit); + set_bit(KEY_APPSELECT, ts->input_dev->keybit); + set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); +#ifdef HX_PROTOCOL_A + /* ts->input_dev->mtsize = ts->nFinger_support; */ + input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, 3, 0, 0); +#else + set_bit(MT_TOOL_FINGER, ts->input_dev->keybit); +#if defined(HX_PROTOCOL_B_3PA) + input_mt_init_slots(ts->input_dev, ts->nFinger_support, INPUT_MT_DIRECT); +#else + input_mt_init_slots(ts->input_dev, ts->nFinger_support); +#endif +#endif + I("input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n", + ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0); +#ifndef HX_PROTOCOL_A + input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, ts->pdata->abs_width_min, ts->pdata->abs_width_max, ts->pdata->abs_pressure_fuzz, 0); +#endif + /* input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0, ((ts->pdata->abs_pressure_max << 16) | ts->pdata->abs_width_max), 0, 0); */ + /* input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0, (BIT(31) | (ts->pdata->abs_x_max << 16) | ts->pdata->abs_y_max), 0, 0); */ + + if (himax_input_register_device(ts->input_dev) == 0) + return NO_ERR; + + ret = INPUT_REGISTER_FAIL; + +input_device_fail: + I("%s, input device register fail!\n", __func__); + return ret; +} + +static void calcDataSize(uint8_t finger_num) +{ + struct himax_ts_data *ts_data = private_ts; + + ts_data->coord_data_size = 4 * finger_num; + ts_data->area_data_size = ((finger_num / 4) + (finger_num % 4 ? 1 : 0)) * 4; + ts_data->coordInfoSize = ts_data->coord_data_size + ts_data->area_data_size + 4; + ts_data->raw_data_frame_size = 128 - ts_data->coord_data_size - ts_data->area_data_size - 4 - 4 - 1; + + if (ts_data->raw_data_frame_size == 0) { + E("%s: could NOT calculate!\n", __func__); + return; + } + + ts_data->raw_data_nframes = ((uint32_t)ts_data->x_channel * ts_data->y_channel + + ts_data->x_channel + ts_data->y_channel) / ts_data->raw_data_frame_size + + (((uint32_t)ts_data->x_channel * ts_data->y_channel + + ts_data->x_channel + ts_data->y_channel) % ts_data->raw_data_frame_size) ? 1 : 0; + I("%s: coord_data_size: %d, area_data_size:%d, raw_data_frame_size:%d, raw_data_nframes:%d", __func__, ts_data->coord_data_size, ts_data->area_data_size, ts_data->raw_data_frame_size, ts_data->raw_data_nframes); +} + +static void calculate_point_number(void) +{ + HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4; + + if ((ic_data->HX_MAX_PT % 4) == 0) + HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4; + else + HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) + 1) * 4; +} + +#ifdef HX_AUTO_UPDATE_FW +static int i_update_FW(void) +{ + int upgrade_times = 0; + unsigned char *ImageBuffer = NULL; + int fullFileLength = 0; + uint8_t ret = 0, result = 0; + + himax_int_enable(0); + + I("file name = %s\n", i_CTPM_firmware_name); + ret = request_firmware(&i_CTPM_FW, i_CTPM_firmware_name, private_ts->dev); + if (ret < 0) { + E("%s,fail in line%d error code=%d\n", __func__, __LINE__, ret); + return OPEN_FILE_FAIL; + } + + if (i_CTPM_FW != NULL) { + fullFileLength = i_CTPM_FW->size; + ImageBuffer = (unsigned char *)i_CTPM_FW->data; + } else { + I("%s: i_CTPM_FW = NULL\n", __func__); + return OPEN_FILE_FAIL; + } + +update_retry: + + if (fullFileLength == FW_SIZE_32k) + ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k(ImageBuffer, fullFileLength, false); + else if (fullFileLength == FW_SIZE_60k) + ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k(ImageBuffer, fullFileLength, false); + else if (fullFileLength == FW_SIZE_64k) + ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k(ImageBuffer, fullFileLength, false); + else if (fullFileLength == FW_SIZE_124k) + ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k(ImageBuffer, fullFileLength, false); + else if (fullFileLength == FW_SIZE_128k) + ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k(ImageBuffer, fullFileLength, false); + + release_firmware(i_CTPM_FW); + + if (ret == 0) { + upgrade_times++; + E("%s: TP upgrade error, upgrade_times = %d\n", __func__, upgrade_times); + + if (upgrade_times < 3) + goto update_retry; + else + result = -1; /* upgrade fail */ + } else { + g_core_fp.fp_read_FW_ver(); + g_core_fp.fp_touch_information(); + result = 1;/* upgrade success */ + I("%s: TP upgrade OK\n", __func__); + } + +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(true, false); +#else + g_core_fp.fp_sense_on(0x00); +#endif + himax_int_enable(1); + return result; +} +#endif + +static int himax_loadSensorConfig(struct himax_i2c_platform_data *pdata) +{ + I("%s: initialization complete\n", __func__); + return NO_ERR; +} + +#ifdef HX_ESD_RECOVERY +static void himax_esd_hw_reset(void) +{ + if (g_ts_dbg != 0) + I("%s: Entering\n", __func__); + + I("START_Himax TP: ESD - Reset\n"); + + if (private_ts->in_self_test == 1) { + I("In self test , not TP: ESD - Reset\n"); + return; + } + + g_core_fp.fp_esd_ic_reset(); + I("END_Himax TP: ESD - Reset\n"); +} +#endif + +#ifdef HX_SMART_WAKEUP +#ifdef HX_GESTURE_TRACK +static void gest_pt_log_coordinate(int rx, int tx) +{ + /* driver report x y with range 0 - 255 , we scale it up to x/y pixel */ + gest_pt_x[gest_pt_cnt] = rx * (ic_data->HX_X_RES) / 255; + gest_pt_y[gest_pt_cnt] = tx * (ic_data->HX_Y_RES) / 255; +} +#endif +static int himax_wake_event_parse(struct himax_ts_data *ts, int ts_status) +{ + uint8_t *buf; +#ifdef HX_GESTURE_TRACK + int tmp_max_x = 0x00, tmp_min_x = 0xFFFF, tmp_max_y = 0x00, tmp_min_y = 0xFFFF; + int gest_len; +#endif + int i = 0, check_FC = 0, gesture_flag = 0; + + if (g_ts_dbg != 0) + I("%s: Entering!, ts_status=%d\n", __func__, ts_status); + + buf = kcalloc(hx_touch_data->event_size, sizeof(uint8_t), GFP_KERNEL); + if (!buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + memcpy(buf, hx_touch_data->hx_event_buf, hx_touch_data->event_size); + + for (i = 0; i < GEST_PTLG_ID_LEN; i++) { + if (check_FC == 0) { + if ((buf[0] != 0x00) && ((buf[0] <= 0x0F) || (buf[0] == 0x80))) { + check_FC = 1; + gesture_flag = buf[i]; + } else { + check_FC = 0; + I("ID START at %x , value = %x skip the event\n", i, buf[i]); + break; + } + } else { + if (buf[i] != gesture_flag) { + check_FC = 0; + I("ID NOT the same %x != %x So STOP parse event\n", buf[i], gesture_flag); + break; + } + } + + I("0x%2.2X ", buf[i]); + + if (i % 8 == 7) + I("\n"); + } + + I("Himax gesture_flag= %x\n", gesture_flag); + I("Himax check_FC is %d\n", check_FC); + + if (check_FC == 0) + return 0; + + if (buf[GEST_PTLG_ID_LEN] != GEST_PTLG_HDR_ID1 || + buf[GEST_PTLG_ID_LEN + 1] != GEST_PTLG_HDR_ID2) + return 0; + +#ifdef HX_GESTURE_TRACK + + if (buf[GEST_PTLG_ID_LEN] == GEST_PTLG_HDR_ID1 && + buf[GEST_PTLG_ID_LEN + 1] == GEST_PTLG_HDR_ID2) { + gest_len = buf[GEST_PTLG_ID_LEN + 2]; + I("gest_len = %d ", gest_len); + i = 0; + gest_pt_cnt = 0; + I("gest doornidate start\n %s", __func__); + + while (i < (gest_len + 1) / 2) { + gest_pt_log_coordinate(buf[GEST_PTLG_ID_LEN + 4 + i * 2], buf[GEST_PTLG_ID_LEN + 4 + i * 2 + 1]); + i++; + I("gest_pt_x[%d]=%d\n", gest_pt_cnt, gest_pt_x[gest_pt_cnt]); + I("gest_pt_y[%d]=%d\n", gest_pt_cnt, gest_pt_y[gest_pt_cnt]); + gest_pt_cnt += 1; + } + + if (gest_pt_cnt) { + for (i = 0; i < gest_pt_cnt; i++) { + if (tmp_max_x < gest_pt_x[i]) + tmp_max_x = gest_pt_x[i]; + + if (tmp_min_x > gest_pt_x[i]) + tmp_min_x = gest_pt_x[i]; + + if (tmp_max_y < gest_pt_y[i]) + tmp_max_y = gest_pt_y[i]; + + if (tmp_min_y > gest_pt_y[i]) + tmp_min_y = gest_pt_y[i]; + } + + I("gest_point x_min= %d, x_max= %d, y_min= %d, y_max= %d\n", tmp_min_x, tmp_max_x, tmp_min_y, tmp_max_y); + gest_start_x = gest_pt_x[0]; + gn_gesture_coor[0] = gest_start_x; + gest_start_y = gest_pt_y[0]; + gn_gesture_coor[1] = gest_start_y; + gest_end_x = gest_pt_x[gest_pt_cnt - 1]; + gn_gesture_coor[2] = gest_end_x; + gest_end_y = gest_pt_y[gest_pt_cnt - 1]; + gn_gesture_coor[3] = gest_end_y; + gest_width = tmp_max_x - tmp_min_x; + gn_gesture_coor[4] = gest_width; + gest_height = tmp_max_y - tmp_min_y; + gn_gesture_coor[5] = gest_height; + gest_mid_x = (tmp_max_x + tmp_min_x) / 2; + gn_gesture_coor[6] = gest_mid_x; + gest_mid_y = (tmp_max_y + tmp_min_y) / 2; + gn_gesture_coor[7] = gest_mid_y; + gn_gesture_coor[8] = gest_mid_x; /* gest_up_x */ + gn_gesture_coor[9] = gest_mid_y - gest_height / 2; /* gest_up_y */ + gn_gesture_coor[10] = gest_mid_x; /* gest_down_x */ + gn_gesture_coor[11] = gest_mid_y + gest_height / 2; /* gest_down_y */ + gn_gesture_coor[12] = gest_mid_x - gest_width / 2; /* gest_left_x */ + gn_gesture_coor[13] = gest_mid_y; /* gest_left_y */ + gn_gesture_coor[14] = gest_mid_x + gest_width / 2; /* gest_right_x */ + gn_gesture_coor[15] = gest_mid_y; /* gest_right_y */ + } + } + +#endif + + if (gesture_flag != 0x80) { + if (!ts->gesture_cust_en[gesture_flag]) { + I("%s NOT report customer key\n ", __func__); + g_target_report_data->SMWP_event_chk = 0; + return 0;/* NOT report customer key */ + } + } else { + if (!ts->gesture_cust_en[0]) { + I("%s NOT report report double click\n", __func__); + g_target_report_data->SMWP_event_chk = 0; + return 0;/* NOT report power key */ + } + } + + if (gesture_flag == 0x80) { + g_target_report_data->SMWP_event_chk = EV_GESTURE_PWR; + return EV_GESTURE_PWR; + } + + g_target_report_data->SMWP_event_chk = gesture_flag; + return gesture_flag; +} + +static void himax_wake_event_report(void) +{ + int ret_event = g_target_report_data->SMWP_event_chk; + int KEY_EVENT = 0; + + if (g_ts_dbg != 0) + I("%s: Entering!\n", __func__); + + switch (ret_event) { + case EV_GESTURE_PWR: + KEY_EVENT = KEY_POWER; + break; + + case EV_GESTURE_01: + KEY_EVENT = KEY_CUST_01; + break; + + case EV_GESTURE_02: + KEY_EVENT = KEY_CUST_02; + break; + + case EV_GESTURE_03: + KEY_EVENT = KEY_CUST_03; + break; + + case EV_GESTURE_04: + KEY_EVENT = KEY_CUST_04; + break; + + case EV_GESTURE_05: + KEY_EVENT = KEY_CUST_05; + break; + + case EV_GESTURE_06: + KEY_EVENT = KEY_CUST_06; + break; + + case EV_GESTURE_07: + KEY_EVENT = KEY_CUST_07; + break; + + case EV_GESTURE_08: + KEY_EVENT = KEY_CUST_08; + break; + + case EV_GESTURE_09: + KEY_EVENT = KEY_CUST_09; + break; + + case EV_GESTURE_10: + KEY_EVENT = KEY_CUST_10; + break; + + case EV_GESTURE_11: + KEY_EVENT = KEY_CUST_11; + break; + + case EV_GESTURE_12: + KEY_EVENT = KEY_CUST_12; + break; + + case EV_GESTURE_13: + KEY_EVENT = KEY_CUST_13; + break; + + case EV_GESTURE_14: + KEY_EVENT = KEY_CUST_14; + break; + + case EV_GESTURE_15: + KEY_EVENT = KEY_CUST_15; + break; + } + + if (ret_event) { + I(" %s SMART WAKEUP KEY event %x press\n", __func__, KEY_EVENT); + input_report_key(private_ts->input_dev, KEY_EVENT, 1); + input_sync(private_ts->input_dev); + I(" %s SMART WAKEUP KEY event %x release\n", __func__, KEY_EVENT); + input_report_key(private_ts->input_dev, KEY_EVENT, 0); + input_sync(private_ts->input_dev); + FAKE_POWER_KEY_SEND = true; +#ifdef HX_GESTURE_TRACK + I("gest_start_x= %d, gest_start_y= %d, gest_end_x= %d, gest_end_y= %d\n", gest_start_x, gest_start_y, + gest_end_x, gest_end_y); + I("gest_width= %d, gest_height= %d, gest_mid_x= %d, gest_mid_y= %d\n", gest_width, gest_height, + gest_mid_x, gest_mid_y); + I("gest_up_x= %d, gest_up_y= %d, gest_down_x= %d, gest_down_y= %d\n", gn_gesture_coor[8], gn_gesture_coor[9], + gn_gesture_coor[10], gn_gesture_coor[11]); + I("gest_left_x= %d, gest_left_y= %d, gest_right_x= %d, gest_right_y= %d\n", gn_gesture_coor[12], gn_gesture_coor[13], + gn_gesture_coor[14], gn_gesture_coor[15]); +#endif + g_target_report_data->SMWP_event_chk = 0; + } +} + +#endif + +int himax_report_data_init(void) +{ + if (hx_touch_data->hx_coord_buf != NULL) + kfree(hx_touch_data->hx_coord_buf); + + if (hx_touch_data->hx_rawdata_buf != NULL) + kfree(hx_touch_data->hx_rawdata_buf); + +#if defined(HX_SMART_WAKEUP) + hx_touch_data->event_size = g_core_fp.fp_get_touch_data_size(); + + if (hx_touch_data->hx_event_buf != NULL) + kfree(hx_touch_data->hx_event_buf); + +#endif + hx_touch_data->touch_all_size = g_core_fp.fp_get_touch_data_size(); + hx_touch_data->raw_cnt_max = ic_data->HX_MAX_PT / 4; + hx_touch_data->raw_cnt_rmd = ic_data->HX_MAX_PT % 4; + /* more than 4 fingers */ + if (hx_touch_data->raw_cnt_rmd != 0x00) { + hx_touch_data->rawdata_size = g_core_fp.fp_cal_data_len(hx_touch_data->raw_cnt_rmd, ic_data->HX_MAX_PT, hx_touch_data->raw_cnt_max); + hx_touch_data->touch_info_size = (ic_data->HX_MAX_PT + hx_touch_data->raw_cnt_max + 2) * 4; + } else { /* less than 4 fingers */ + hx_touch_data->rawdata_size = g_core_fp.fp_cal_data_len(hx_touch_data->raw_cnt_rmd, ic_data->HX_MAX_PT, hx_touch_data->raw_cnt_max); + hx_touch_data->touch_info_size = (ic_data->HX_MAX_PT + hx_touch_data->raw_cnt_max + 1) * 4; + } + + if ((ic_data->HX_TX_NUM * ic_data->HX_RX_NUM + ic_data->HX_TX_NUM + ic_data->HX_RX_NUM) % hx_touch_data->rawdata_size == 0) + hx_touch_data->rawdata_frame_size = (ic_data->HX_TX_NUM * ic_data->HX_RX_NUM + ic_data->HX_TX_NUM + ic_data->HX_RX_NUM) / hx_touch_data->rawdata_size; + else + hx_touch_data->rawdata_frame_size = (ic_data->HX_TX_NUM * ic_data->HX_RX_NUM + ic_data->HX_TX_NUM + ic_data->HX_RX_NUM) / hx_touch_data->rawdata_size + 1; + + + I("%s: rawdata_frame_size = %d ", __func__, hx_touch_data->rawdata_frame_size); + I("%s: ic_data->HX_MAX_PT:%d, hx_raw_cnt_max:%d, hx_raw_cnt_rmd:%d, g_hx_rawdata_size:%d, hx_touch_data->touch_info_size:%d\n", __func__, ic_data->HX_MAX_PT, hx_touch_data->raw_cnt_max, hx_touch_data->raw_cnt_rmd, hx_touch_data->rawdata_size, hx_touch_data->touch_info_size); + hx_touch_data->hx_coord_buf = kzalloc(sizeof(uint8_t) * (hx_touch_data->touch_info_size), GFP_KERNEL); + + if (hx_touch_data->hx_coord_buf == NULL) + goto mem_alloc_fail; + + g_target_report_data = kzalloc(sizeof(struct himax_target_report_data), GFP_KERNEL); + if (g_target_report_data == NULL) + goto mem_alloc_fail; + g_target_report_data->x = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + if (g_target_report_data->x == NULL) + goto mem_alloc_fail; + g_target_report_data->y = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + if (g_target_report_data->y == NULL) + goto mem_alloc_fail; + g_target_report_data->w = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + if (g_target_report_data->w == NULL) + goto mem_alloc_fail; + g_target_report_data->finger_id = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + if (g_target_report_data->finger_id == NULL) + goto mem_alloc_fail; +#ifdef HX_SMART_WAKEUP + g_target_report_data->SMWP_event_chk = 0; +#endif + + hx_touch_data->hx_rawdata_buf = kzalloc(sizeof(uint8_t) * (hx_touch_data->touch_all_size - hx_touch_data->touch_info_size), GFP_KERNEL); + + if (hx_touch_data->hx_rawdata_buf == NULL) + goto mem_alloc_fail; + +#if defined(HX_SMART_WAKEUP) + hx_touch_data->hx_event_buf = kzalloc(sizeof(uint8_t) * (hx_touch_data->event_size), GFP_KERNEL); + + if (hx_touch_data->hx_event_buf == NULL) + goto mem_alloc_fail; + +#endif + return NO_ERR; +mem_alloc_fail: + kfree(hx_touch_data->hx_coord_buf); + kfree(g_target_report_data->x); + kfree(g_target_report_data->y); + kfree(g_target_report_data->w); + kfree(g_target_report_data->finger_id); + kfree(hx_touch_data->hx_rawdata_buf); + +#if defined(HX_SMART_WAKEUP) + kfree(hx_touch_data->hx_event_buf); +#endif + I("%s: Memory allocate fail!\n", __func__); + return MEM_ALLOC_FAIL; +} + +/* start ts_work */ +#if defined(HX_USB_DETECT_GLOBAL) +void himax_cable_detect_func(bool force_renew) +{ + struct himax_ts_data *ts; + u32 connect_status = 0; + + connect_status = USB_detect_flag;/* upmu_is_chr_det(); */ + ts = private_ts; + + /* I("Touch: cable status=%d, cable_config=%p, usb_connected=%d\n", connect_status, ts->cable_config, ts->usb_connected); */ + if (ts->cable_config) { + if (((!!connect_status) != ts->usb_connected) || force_renew) { + if (!!connect_status) { + ts->cable_config[1] = 0x01; + ts->usb_connected = 0x01; + } else { + ts->cable_config[1] = 0x00; + ts->usb_connected = 0x00; + } + + g_core_fp.fp_usb_detect_set(ts->cable_config); + I("%s: Cable status change: 0x%2.2X\n", __func__, ts->usb_connected); + } + + /* else */ + /* I("%s: Cable status is the same as previous one, ignore.\n", __func__); */ + } +} +#endif + +static int himax_ts_work_status(struct himax_ts_data *ts) +{ + /* 1: normal, 2:SMWP */ + int result = HX_REPORT_COORD; + + hx_touch_data->diag_cmd = ts->diag_cmd; + if (hx_touch_data->diag_cmd) + result = HX_REPORT_COORD_RAWDATA; + +#ifdef HX_SMART_WAKEUP + if (atomic_read(&ts->suspend_mode) && (!FAKE_POWER_KEY_SEND) && (ts->SMWP_enable) && (!hx_touch_data->diag_cmd)) + result = HX_REPORT_SMWP_EVENT; +#endif + /* I("Now Status is %d\n", result); */ + return result; +} + +static int himax_touch_get(struct himax_ts_data *ts, uint8_t *buf, int ts_path, int ts_status) +{ + + if (g_ts_dbg != 0) + I("%s: Entering, ts_status=%d!\n", __func__, ts_status); + + switch (ts_path) { + /* normal */ + case HX_REPORT_COORD: + if ((HX_HW_RESET_ACTIVATE) +#ifdef HX_ESD_RECOVERY + || (HX_ESD_RESET_ACTIVATE) +#endif + ) { + if (!g_core_fp.fp_read_event_stack(buf, 128)) { + E("%s: can't read data from chip!\n", __func__); + ts_status = HX_TS_GET_DATA_FAIL; + goto END_FUNCTION; + } + } else { + if (!g_core_fp.fp_read_event_stack(buf, hx_touch_data->touch_info_size)) { + E("%s: can't read data from chip!\n", __func__); + ts_status = HX_TS_GET_DATA_FAIL; + goto END_FUNCTION; + } + } + break; +#if defined(HX_SMART_WAKEUP) + + /* SMWP */ + case HX_REPORT_SMWP_EVENT: + g_core_fp.fp_burst_enable(0); + + if (!g_core_fp.fp_read_event_stack(buf, hx_touch_data->event_size)) { + E("%s: can't read data from chip!\n", __func__); + ts_status = HX_TS_GET_DATA_FAIL; + goto END_FUNCTION; + } + break; +#endif + case HX_REPORT_COORD_RAWDATA: + if (!g_core_fp.fp_read_event_stack(buf, 128)) { + E("%s: can't read data from chip!\n", __func__); + ts_status = HX_TS_GET_DATA_FAIL; + goto END_FUNCTION; + } + break; + default: + break; + } + +END_FUNCTION: + return ts_status; +} + +/* start error_control*/ +static int himax_checksum_cal(struct himax_ts_data *ts, uint8_t *buf, int ts_path, int ts_status) +{ + uint16_t check_sum_cal = 0; + int32_t i = 0; + int length = 0; + int ret_val = ts_status; + + if (g_ts_dbg != 0) + I("%s: Entering, ts_status=%d!\n", __func__, ts_status); + + /* Normal */ + switch (ts_path) { + case HX_REPORT_COORD: + length = hx_touch_data->touch_info_size; + break; +#if defined(HX_SMART_WAKEUP) +/* SMWP */ + case HX_REPORT_SMWP_EVENT: + length = (GEST_PTLG_ID_LEN + GEST_PTLG_HDR_LEN); + break; +#endif + case HX_REPORT_COORD_RAWDATA: + length = hx_touch_data->touch_info_size; + break; + default: + I("%s, Neither Normal Nor SMWP error!\n", __func__); + ret_val = HX_PATH_FAIL; + goto END_FUNCTION; + + } + + for (i = 0; i < length; i++) + check_sum_cal += buf[i]; + if (check_sum_cal % 0x100 != 0) { + I("[HIMAX TP MSG] checksum fail : check_sum_cal: 0x%02X\n", check_sum_cal); + ret_val = HX_CHKSUM_FAIL; + } + +END_FUNCTION: + if (g_ts_dbg != 0) + I("%s: END, ret_val=%d!\n", __func__, ret_val); + return ret_val; +} + +#ifdef HX_ESD_RECOVERY +static int himax_ts_event_check(struct himax_ts_data *ts, uint8_t *buf, int ts_path, int ts_status) +{ + + int hx_EB_event = 0; + int hx_EC_event = 0; + int hx_ED_event = 0; + int hx_esd_event = 0; + int hx_zero_event = 0; + int shaking_ret = 0; + + int32_t loop_i = 0; + int length = 0; + int ret_val = ts_status; + + if (g_ts_dbg != 0) + I("%s: Entering, ts_status=%d!\n", __func__, ts_status); + + /* Normal */ + switch (ts_path) { + case HX_REPORT_COORD: + length = hx_touch_data->touch_info_size; + break; +#if defined(HX_SMART_WAKEUP) + /* SMWP */ + case HX_REPORT_SMWP_EVENT: + length = (GEST_PTLG_ID_LEN + GEST_PTLG_HDR_LEN); + break; +#endif + case HX_REPORT_COORD_RAWDATA: + length = hx_touch_data->touch_info_size; + break; + default: + I("%s, Neither Normal Nor SMWP error!\n", __func__); + ret_val = HX_PATH_FAIL; + goto END_FUNCTION; + } + + if (g_ts_dbg != 0) + I("Now Path=%d, Now status=%d, length=%d\n", ts_path, ts_status, length); + + for (loop_i = 0; loop_i < length; loop_i++) { + if (ts_path == HX_REPORT_COORD || ts_path == HX_REPORT_COORD_RAWDATA) { + /* case 1 ESD recovery flow */ + if (buf[loop_i] == 0xEB) + hx_EB_event++; + + else if (buf[loop_i] == 0xEC) + hx_EC_event++; + + else if (buf[loop_i] == 0xED) + hx_ED_event++; + + /* case 2 ESD recovery flow-Disable */ + else if (buf[loop_i] == 0x00) + hx_zero_event++; + else { + hx_EB_event = 0; + hx_EC_event = 0; + hx_ED_event = 0; + hx_zero_event = 0; + g_zero_event_count = 0; + } + } + } + + if (hx_EB_event == length) { + hx_esd_event = length; + hx_EB_event_flag++; + I("[HIMAX TP MSG]: ESD event checked - ALL 0xEB.\n"); + } else if (hx_EC_event == length) { + hx_esd_event = length; + hx_EC_event_flag++; + I("[HIMAX TP MSG]: ESD event checked - ALL 0xEC.\n"); + } else if (hx_ED_event == length) { + hx_esd_event = length; + hx_ED_event_flag++; + I("[HIMAX TP MSG]: ESD event checked - ALL 0xED.\n"); + } else { + hx_esd_event = 0; + } + + if ((hx_esd_event == length || hx_zero_event == length) + && (HX_HW_RESET_ACTIVATE == 0) + && (HX_ESD_RESET_ACTIVATE == 0) + && (hx_touch_data->diag_cmd == 0) + && (ts->in_self_test == 0)) { + + shaking_ret = g_core_fp.fp_ic_esd_recovery(hx_esd_event, hx_zero_event, length); + + if (shaking_ret == HX_ESD_EVENT) { + himax_esd_hw_reset(); + ret_val = HX_ESD_EVENT; + } else if (shaking_ret == HX_ZERO_EVENT_COUNT) + ret_val = HX_ZERO_EVENT_COUNT; + else { + I("I2C running. Nothing to be done!\n"); + ret_val = HX_IC_RUNNING; + } + } else if (HX_ESD_RESET_ACTIVATE) { + /* drop 1st interrupts after chip reset */ + HX_ESD_RESET_ACTIVATE = 0; + I("[HX_ESD_RESET_ACTIVATE]:%s: Back from reset, ready to serve.\n", __func__); + ret_val = HX_ESD_REC_OK; + } + +END_FUNCTION: + if (g_ts_dbg != 0) + I("%s: END, ret_val=%d!\n", __func__, ret_val); + + return ret_val; +} +#endif + +static int himax_err_ctrl(struct himax_ts_data *ts, uint8_t *buf, int ts_path, int ts_status) +{ + +#ifdef HX_RST_PIN_FUNC + if (HX_HW_RESET_ACTIVATE) { + /* drop 1st interrupts after chip reset */ + HX_HW_RESET_ACTIVATE = 0; + I("[HX_HW_RESET_ACTIVATE]:%s: Back from reset, ready to serve.\n", __func__); + ts_status = HX_RST_OK; + goto END_FUNCTION; + } +#endif + + ts_status = himax_checksum_cal(ts, buf, ts_path, ts_status); + if (ts_status == HX_CHKSUM_FAIL) + goto CHK_FAIL; + goto END_FUNCTION; + +CHK_FAIL: +#ifdef HX_ESD_RECOVERY + ts_status = himax_ts_event_check(ts, buf, ts_path, ts_status); +#endif + + +END_FUNCTION: + if (g_ts_dbg != 0) + I("%s: END, ts_status=%d!\n", __func__, ts_status); + return ts_status; +} +/* end error_control*/ + +/* start distribute_data*/ +static int himax_distribute_touch_data(uint8_t *buf, int ts_path, int ts_status) +{ + uint8_t hx_state_info_pos = hx_touch_data->touch_info_size - 3; + + if (g_ts_dbg != 0) + I("%s: Entering, ts_status=%d!\n", __func__, ts_status); + + if (ts_path == HX_REPORT_COORD) { + memcpy(hx_touch_data->hx_coord_buf, &buf[0], hx_touch_data->touch_info_size); + + if (buf[hx_state_info_pos] != 0xFF && buf[hx_state_info_pos + 1] != 0xFF) + memcpy(hx_touch_data->hx_state_info, &buf[hx_state_info_pos], 2); + else + memset(hx_touch_data->hx_state_info, 0x00, sizeof(hx_touch_data->hx_state_info)); + + if ((HX_HW_RESET_ACTIVATE) +#ifdef HX_ESD_RECOVERY + || (HX_ESD_RESET_ACTIVATE) +#endif + ) { + memcpy(hx_touch_data->hx_rawdata_buf, &buf[hx_touch_data->touch_info_size], hx_touch_data->touch_all_size - hx_touch_data->touch_info_size); + } + } else if (ts_path == HX_REPORT_COORD_RAWDATA) { + memcpy(hx_touch_data->hx_coord_buf, &buf[0], hx_touch_data->touch_info_size); + + if (buf[hx_state_info_pos] != 0xFF && buf[hx_state_info_pos + 1] != 0xFF) + memcpy(hx_touch_data->hx_state_info, &buf[hx_state_info_pos], 2); + else + memset(hx_touch_data->hx_state_info, 0x00, sizeof(hx_touch_data->hx_state_info)); + + memcpy(hx_touch_data->hx_rawdata_buf, &buf[hx_touch_data->touch_info_size], hx_touch_data->touch_all_size - hx_touch_data->touch_info_size); + } +#if defined(HX_SMART_WAKEUP) + else if (ts_path == HX_REPORT_SMWP_EVENT) + memcpy(hx_touch_data->hx_event_buf, buf, hx_touch_data->event_size); +#endif + else { + E("%s, Fail Path!\n", __func__); + ts_status = HX_PATH_FAIL; + } + + if (g_ts_dbg != 0) + I("%s: End, ts_status=%d!\n", __func__, ts_status); + return ts_status; +} +/* end assign_data*/ + +/* start parse_report_data*/ +int himax_parse_report_points(struct himax_ts_data *ts, int ts_path, int ts_status) +{ + int x = 0; + int y = 0; + int w = 0; + int base = 0; + int32_t loop_i = 0; + + if (g_ts_dbg != 0) + I("%s: start!\n", __func__); + + + ts->old_finger = ts->pre_finger_mask; + ts->pre_finger_mask = 0; + hx_touch_data->finger_num = hx_touch_data->hx_coord_buf[ts->coordInfoSize - 4] & 0x0F; + hx_touch_data->finger_on = 1; + AA_press = 1; + + g_target_report_data->finger_num = hx_touch_data->finger_num; + g_target_report_data->finger_on = hx_touch_data->finger_on; + + if (g_ts_dbg != 0) + I("%s:finger_num = 0x%2X, finger_on = %d\n", __func__, g_target_report_data->finger_num, g_target_report_data->finger_on); + + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { + base = loop_i * 4; + x = hx_touch_data->hx_coord_buf[base] << 8 | hx_touch_data->hx_coord_buf[base + 1]; + y = (hx_touch_data->hx_coord_buf[base + 2] << 8 | hx_touch_data->hx_coord_buf[base + 3]); + w = hx_touch_data->hx_coord_buf[(ts->nFinger_support * 4) + loop_i]; + + if (g_ts_dbg != 0) + D("%s: now parsing[%d]:x=%d, y=%d, w=%d\n", __func__, loop_i, x, y, w); + + if (x >= 0 && x <= ts->pdata->abs_x_max && y >= 0 && y <= ts->pdata->abs_y_max) { + hx_touch_data->finger_num--; + + g_target_report_data->x[loop_i] = x; + g_target_report_data->y[loop_i] = y; + g_target_report_data->w[loop_i] = w; + g_target_report_data->finger_id[loop_i] = 1; + + /* I("%s: g_target_report_data->x[loop_i]=%d, g_target_report_data->y[loop_i]=%d, g_target_report_data->w[loop_i]=%d", */ + /* __func__, g_target_report_data->x[loop_i], g_target_report_data->y[loop_i], g_target_report_data->w[loop_i]); */ + + + if (!ts->first_pressed) { + ts->first_pressed = 1; + I("S1@%d, %d\n", x, y); + } + + ts->pre_finger_data[loop_i][0] = x; + ts->pre_finger_data[loop_i][1] = y; + + ts->pre_finger_mask = ts->pre_finger_mask + (1 << loop_i); + } else {/* report coordinates */ + g_target_report_data->x[loop_i] = x; + g_target_report_data->y[loop_i] = y; + g_target_report_data->w[loop_i] = w; + g_target_report_data->finger_id[loop_i] = 0; + + if (loop_i == 0 && ts->first_pressed == 1) { + ts->first_pressed = 2; + I("E1@%d, %d\n", ts->pre_finger_data[0][0], ts->pre_finger_data[0][1]); + } + } + } + + if (g_ts_dbg != 0) { + for (loop_i = 0; loop_i < 10; loop_i++) + D("DBG X=%d Y=%d ID=%d\n", g_target_report_data->x[loop_i], g_target_report_data->y[loop_i], g_target_report_data->finger_id[loop_i]); + + D("DBG finger number %d\n", g_target_report_data->finger_num); + } + + if (g_ts_dbg != 0) + I("%s: end!\n", __func__); + return ts_status; +} + +static int himax_parse_report_data(struct himax_ts_data *ts, int ts_path, int ts_status) +{ + + if (g_ts_dbg != 0) + I("%s: start now_status=%d!\n", __func__, ts_status); + + + EN_NoiseFilter = (hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 3); + /* I("EN_NoiseFilter=%d\n", EN_NoiseFilter); */ + EN_NoiseFilter = EN_NoiseFilter & 0x01; + /* I("EN_NoiseFilter2=%d\n", EN_NoiseFilter); */ +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) + tpd_key = (hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 4); + + /* All (VK+AA)leave */ + if (tpd_key == 0x0F) + tpd_key = 0x00; +#endif + p_point_num = ts->hx_point_num; + + switch (ts_path) { + case HX_REPORT_COORD: + ts_status = himax_parse_report_points(ts, ts_path, ts_status); + break; + case HX_REPORT_COORD_RAWDATA: + /* touch monitor rawdata */ + if (debug_data != NULL) { + if (debug_data->fp_set_diag_cmd(ic_data, hx_touch_data)) + I("%s: coordinate dump fail and bypass with checksum err\n", __func__); + } else + E("%s,There is no init set_diag_cmd\n", __func__); + + ts_status = himax_parse_report_points(ts, ts_path, ts_status); + break; +#ifdef HX_SMART_WAKEUP + case HX_REPORT_SMWP_EVENT: + himax_wake_event_parse(ts, ts_status); + break; +#endif + default: + E("%s:Fail Path!\n", __func__); + ts_status = HX_PATH_FAIL; + break; + } + if (g_ts_dbg != 0) + I("%s: end now_status=%d!\n", __func__, ts_status); + return ts_status; +} + +/* end parse_report_data */ + +static void himax_report_all_leave_event(struct himax_ts_data *ts) +{ + int loop_i = 0; + + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { +#ifndef HX_PROTOCOL_A + input_mt_slot(ts->input_dev, loop_i); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); +#endif + } + input_report_key(ts->input_dev, BTN_TOUCH, 0); + input_sync(ts->input_dev); +} + +/* start report_data */ +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) +static void himax_key_report_operation(int tp_key_index, struct himax_ts_data *ts) +{ + uint16_t x_position = 0, y_position = 0; + + if (g_ts_dbg != 0) + I("%s: Entering\n", __func__); + + if (tp_key_index != 0x00) { + I("virtual key index =%x\n", tp_key_index); + + if (tp_key_index == 0x01) { + vk_press = 1; + I("back key pressed\n"); + + if (ts->pdata->virtual_key) { + if (ts->button[0].index) { + x_position = (ts->button[0].x_range_min + ts->button[0].x_range_max) / 2; + y_position = (ts->button[0].y_range_min + ts->button[0].y_range_max) / 2; + } + +#ifdef HX_PROTOCOL_A + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); + input_mt_sync(ts->input_dev); +#else + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); +#endif + } else { + input_report_key(ts->input_dev, KEY_BACK, 1); + } + } else if (tp_key_index == 0x02) { + vk_press = 1; + I("home key pressed\n"); + + if (ts->pdata->virtual_key) { + if (ts->button[1].index) { + x_position = (ts->button[1].x_range_min + ts->button[1].x_range_max) / 2; + y_position = (ts->button[1].y_range_min + ts->button[1].y_range_max) / 2; + } + +#ifdef HX_PROTOCOL_A + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); + input_mt_sync(ts->input_dev); +#else + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); +#endif + } else + input_report_key(ts->input_dev, KEY_HOME, 1); + + } else if (tp_key_index == 0x04) { + vk_press = 1; + I("APP_switch key pressed\n"); + + if (ts->pdata->virtual_key) { + if (ts->button[2].index) { + x_position = (ts->button[2].x_range_min + ts->button[2].x_range_max) / 2; + y_position = (ts->button[2].y_range_min + ts->button[2].y_range_max) / 2; + } + +#ifdef HX_PROTOCOL_A + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); + input_mt_sync(ts->input_dev); +#else + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); +#endif + } else + input_report_key(ts->input_dev, KEY_APPSELECT, 1); + } + + input_sync(ts->input_dev); + } else { /* tp_key_index =0x00 */ + I("virtual key released\n"); + vk_press = 0; +#ifndef HX_PROTOCOL_A + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); +#else + input_mt_sync(ts->input_dev); +#endif + input_report_key(ts->input_dev, KEY_BACK, 0); + input_report_key(ts->input_dev, KEY_HOME, 0); + input_report_key(ts->input_dev, KEY_APPSELECT, 0); +#ifndef HX_PROTOCOL_A + input_sync(ts->input_dev); +#endif + } +} + +void himax_finger_report_key(struct himax_ts_data *ts) +{ + if (hx_point_num != 0) { + /* Touch KEY */ + if ((tpd_key_old != 0x00) && (tpd_key == 0x00)) { + /* temp_x[0] = 0xFFFF; */ + /* temp_y[0] = 0xFFFF; */ + /* temp_x[1] = 0xFFFF; */ + /* temp_y[1] = 0xFFFF; */ + hx_touch_data->finger_on = 0; +#ifdef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, hx_touch_data->finger_on); +#endif + himax_key_report_operation(tpd_key, ts); + } + +#ifndef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, hx_touch_data->finger_on); +#endif + input_sync(ts->input_dev); + } +} + +void himax_finger_leave_key(struct himax_ts_data *ts) +{ + if (tpd_key != 0x00) { + hx_touch_data->finger_on = 1; +#ifdef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, hx_touch_data->finger_on); +#endif + himax_key_report_operation(tpd_key, ts); + } else if ((tpd_key_old != 0x00) && (tpd_key == 0x00)) { + hx_touch_data->finger_on = 0; +#ifdef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, hx_touch_data->finger_on); +#endif + himax_key_report_operation(tpd_key, ts); + } + +#ifndef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, hx_touch_data->finger_on); +#endif + input_sync(ts->input_dev); +} + +static void himax_report_key(struct himax_ts_data *ts) +{ + if (hx_point_num != 0) + himax_finger_report_key(ts); /* Touch KEY */ + else + himax_finger_leave_key(ts); /* Key */ + + tpd_key_old = tpd_key; + Last_EN_NoiseFilter = EN_NoiseFilter; +} +#endif + +/* start report_point*/ +static void himax_finger_report(struct himax_ts_data *ts) +{ + int i = 0; + bool valid = false; + + if (g_ts_dbg != 0) { + I("%s:start\n", __func__); + I("hx_touch_data->finger_num=%d\n", hx_touch_data->finger_num); + } + for (i = 0; i < ts->nFinger_support; i++) { + if (g_target_report_data->x[i] >= 0 && g_target_report_data->x[i] <= ts->pdata->abs_x_max + && g_target_report_data->y[i] >= 0 && g_target_report_data->y[i] <= ts->pdata->abs_y_max) + valid = true; + else + valid = false; + if (g_ts_dbg != 0) + I("valid=%d\n", valid); + if (valid) { + if (g_ts_dbg != 0) + I("g_target_report_data->x[i]=%d, g_target_report_data->y[i]=%d, g_target_report_data->w[i]=%d\n", + g_target_report_data->x[i], g_target_report_data->y[i], g_target_report_data->w[i]); +#ifndef HX_PROTOCOL_A + input_mt_slot(ts->input_dev, i); +#endif + input_report_key(ts->input_dev, BTN_TOUCH, g_target_report_data->finger_on); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, g_target_report_data->w[i]); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i); +#ifndef HX_PROTOCOL_A + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, g_target_report_data->w[i]); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, g_target_report_data->w[i]); +#endif + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, g_target_report_data->x[i]); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, g_target_report_data->y[i]); +#ifndef HX_PROTOCOL_A + ts->last_slot = i; + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); +#else + input_mt_sync(ts->input_dev); +#endif + + } else { + input_mt_slot(ts->input_dev, i); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); + } + } + + input_report_key(ts->input_dev, BTN_TOUCH, g_target_report_data->finger_on); + input_sync(ts->input_dev); + + if (g_ts_dbg != 0) + I("%s:end\n", __func__); +} + +static void himax_finger_leave(struct himax_ts_data *ts) +{ + int32_t loop_i = 0; + + if (g_ts_dbg != 0) + I("%s: start!\n", __func__); +#if defined(HX_PALM_REPORT) + if (himax_palm_detect(hx_touch_data->hx_coord_buf) == NO_ERR) { + I(" %s HX_PALM_REPORT KEY power event press\n", __func__); + input_report_key(ts->input_dev, KEY_POWER, 1); + input_sync(ts->input_dev); + msleep(100); + + I(" %s HX_PALM_REPORT KEY power event release\n", __func__); + input_report_key(ts->input_dev, KEY_POWER, 0); + input_sync(ts->input_dev); + return; + } +#endif + + hx_touch_data->finger_on = 0; + AA_press = 0; + +#ifdef HX_PROTOCOL_A + input_mt_sync(ts->input_dev); +#endif + + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { + if (((ts->pre_finger_mask >> loop_i) & 1) == 1) { + input_mt_slot(ts->input_dev, loop_i); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); + } + } + + if (ts->pre_finger_mask > 0) + ts->pre_finger_mask = 0; + + if (ts->first_pressed == 1) { + ts->first_pressed = 2; + I("E1@%d, %d\n", ts->pre_finger_data[0][0], ts->pre_finger_data[0][1]); + } + + /* if (ts->debug_log_level & BIT(1)) */ + /* himax_log_touch_event(x, y, w, loop_i, EN_NoiseFilter, HX_FINGER_LEAVE); */ + + input_report_key(ts->input_dev, BTN_TOUCH, hx_touch_data->finger_on); + input_sync(ts->input_dev); + + + if (g_ts_dbg != 0) + I("%s: end!\n", __func__); +} + +static void himax_report_points(struct himax_ts_data *ts) +{ + if (g_ts_dbg != 0) + I("%s: start!\n", __func__); + + if (ts->hx_point_num != 0) + himax_finger_report(ts); + else + himax_finger_leave(ts); + + + Last_EN_NoiseFilter = EN_NoiseFilter; + + if (g_ts_dbg != 0) + I("%s: end!\n", __func__); +} +/* end report_points */ + +int himax_report_data(struct himax_ts_data *ts, int ts_path, int ts_status) +{ + if (g_ts_dbg != 0) + I("%s: Entering, ts_status=%d!\n", __func__, ts_status); + + if (ts_path == HX_REPORT_COORD || ts_path == HX_REPORT_COORD_RAWDATA) { + if (hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT] == 0xff) + ts->hx_point_num = 0; + else + ts->hx_point_num = hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT] & 0x0f; + + /* Touch Point information */ + himax_report_points(ts); + +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) + /* report key(question mark) */ + if (tpd_key && tpd_key_old) + himax_report_key(ts); +#endif + } + +#ifdef HX_SMART_WAKEUP + else if (ts_path == HX_REPORT_SMWP_EVENT) { + __pm_wakeup_event(&ts->ts_SMWP_wake_src, TS_WAKE_LOCK_TIMEOUT); + himax_wake_event_report(); + } +#endif + + else { + E("%s:Fail Path!\n", __func__); + ts_status = HX_PATH_FAIL; + } + + if (g_ts_dbg != 0) + I("%s: END, ts_status=%d!\n", __func__, ts_status); + return ts_status; +} +/* end report_data */ + +static int himax_ts_operation(struct himax_ts_data *ts, int ts_path, int ts_status) +{ + uint8_t hw_reset_check[2]; + uint8_t buf[128]; + + memset(buf, 0x00, sizeof(buf)); + memset(hw_reset_check, 0x00, sizeof(hw_reset_check)); + + ts_status = himax_touch_get(ts, buf, ts_path, ts_status); + if (ts_status == HX_TS_GET_DATA_FAIL) + goto END_FUNCTION; + + ts_status = himax_err_ctrl(ts, buf, ts_path, ts_status); + if (ts_status == HX_REPORT_DATA || ts_status == HX_TS_NORMAL_END) { + ts_status = himax_distribute_touch_data(buf, ts_path, ts_status); + ts_status = himax_parse_report_data(ts, ts_path, ts_status); + } else + goto END_FUNCTION; + + ts_status = himax_report_data(ts, ts_path, ts_status); + + +END_FUNCTION: + return ts_status; +} + +void himax_ts_work(struct himax_ts_data *ts) +{ + + int ts_status = HX_TS_NORMAL_END; + int ts_path = 0; + + if (debug_data != NULL) + debug_data->fp_ts_dbg_func(ts, HX_FINGER_ON); + +#if defined(HX_USB_DETECT_GLOBAL) + himax_cable_detect_func(false); +#endif + + ts_path = himax_ts_work_status(ts); + switch (ts_path) { + case HX_REPORT_COORD: + ts_status = himax_ts_operation(ts, ts_path, ts_status); + break; + case HX_REPORT_SMWP_EVENT: + ts_status = himax_ts_operation(ts, ts_path, ts_status); + break; + case HX_REPORT_COORD_RAWDATA: + ts_status = himax_ts_operation(ts, ts_path, ts_status); + break; + default: + E("%s:Path Fault! value=%d\n", __func__, ts_path); + goto END_FUNCTION; + } + + if (ts_status == HX_TS_GET_DATA_FAIL) + goto GET_TOUCH_FAIL; + else + goto END_FUNCTION; + +GET_TOUCH_FAIL: + I("%s: Now reset the Touch chip.\n", __func__); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, true); +#endif +END_FUNCTION: + if (debug_data != NULL) + debug_data->fp_ts_dbg_func(ts, HX_FINGER_LEAVE); + + +} +/* end ts_work */ +enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer) +{ + struct himax_ts_data *ts; + + ts = container_of(timer, struct himax_ts_data, timer); + queue_work(ts->himax_wq, &ts->work); + hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL); + return HRTIMER_NORESTART; +} + +#if defined(HX_USB_DETECT_CALLBACK) +static void himax_cable_tp_status_handler_func(int connect_status) +{ + struct himax_ts_data *ts; + + I("Touch: cable change to %d\n", connect_status); + ts = private_ts; + + if (ts->cable_config) { + if (!atomic_read(&ts->suspend_mode)) { + if ((!!connect_status) != ts->usb_connected) { + if (!!connect_status) { + ts->cable_config[1] = 0x01; + ts->usb_connected = 0x01; + } + + else { + ts->cable_config[1] = 0x00; + ts->usb_connected = 0x00; + } + + if (himax_bus_master_write(ts->cable_config, sizeof(ts->cable_config), HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail: cable_config!\n", __func__); + return; + } + I("%s: Cable status change: 0x%2.2X\n", __func__, ts->cable_config[1]); + } else + I("%s: Cable status is the same as previous one, ignore.\n", __func__); + + } else { + if (connect_status) + ts->usb_connected = 0x01; + else + ts->usb_connected = 0x00; + + I("%s: Cable status remembered: 0x%2.2X\n", __func__, ts->usb_connected); + } + } +} + +static const struct t_cable_status_notifier himax_cable_status_handler = { + .name = "usb_tp_connected", + .func = himax_cable_tp_status_handler_func, +}; + +#endif + +#ifdef HX_AUTO_UPDATE_FW +static void himax_update_register(struct work_struct *work) +{ + I(" %s in", __func__); + + if (i_update_FW() <= 0) + I("FW =NOT UPDATE=\n"); + else + I("Have new FW =UPDATE=\n"); + +} +#endif + +#ifdef CONFIG_DRM +static void himax_fb_register(struct work_struct *work) +{ + int ret = 0; + struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work_att.work); + + I(" %s in\n", __func__); + ts->fb_notif.notifier_call = fb_notifier_callback; + ret = msm_drm_register_client(&ts->fb_notif); + if (ret) + E(" Unable to register fb_notifier: %d\n", ret); +} + +#elif defined CONFIG_FB +static void himax_fb_register(struct work_struct *work) +{ + int ret = 0; + struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work_att.work); + + I(" %s in\n", __func__); + ts->fb_notif.notifier_call = fb_notifier_callback; + ret = fb_register_client(&ts->fb_notif); + + if (ret) + E(" Unable to register fb_notifier: %d\n", ret); +} +#endif + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) +static void himax_ito_test_work(struct work_struct *work) +{ + I(" %s in\n", __func__); + himax_ito_test(); +} +#endif + +int himax_chip_common_init(void) +{ +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) + bool auto_update_flag = false; +#endif + int ret = 0, err = 0; + struct himax_ts_data *ts = private_ts; + struct himax_i2c_platform_data *pdata; + + I("PDATA START\n"); + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (pdata == NULL) { /* Allocate Platform data space */ + err = -ENOMEM; + goto err_dt_platform_data_fail; + } + + I("ic_data START\n"); + ic_data = kzalloc(sizeof(*ic_data), GFP_KERNEL); + if (ic_data == NULL) { /* Allocate IC data space */ + err = -ENOMEM; + goto err_dt_ic_data_fail; + } + + /* allocate report data */ + hx_touch_data = kzalloc(sizeof(struct himax_report_data), GFP_KERNEL); + if (hx_touch_data == NULL) { + err = -ENOMEM; + goto err_alloc_touch_data_failed; + } + + if (himax_parse_dt(ts, pdata) < 0) { + I(" pdata is NULL for DT\n"); + goto err_alloc_dt_pdata_failed; + } + +#ifdef HX_RST_PIN_FUNC + ts->rst_gpio = pdata->gpio_reset; +#endif + himax_gpio_power_config(pdata); +#ifndef CONFIG_OF + + if (pdata->power) { + ret = pdata->power(1); + + if (ret < 0) { + E("%s: power on failed\n", __func__); + goto err_power_failed; + } + } + +#endif + + if (g_core_fp.fp_chip_detect != NULL && g_core_fp.fp_chip_init != NULL) { + if (g_core_fp.fp_chip_detect() != false) { + g_core_fp.fp_chip_init(); + } else { + E("%s: chip detect failed!\n", __func__); + goto error_ic_detect_failed; + } + } else { + E("%s: function point is NULL!\n", __func__); + goto error_ic_detect_failed; + } + + if (pdata->virtual_key) + ts->button = pdata->virtual_key; + +#ifdef HX_AUTO_UPDATE_FW + auto_update_flag = (!g_core_fp.fp_calculateChecksum(false)); + auto_update_flag |= g_core_fp.fp_flash_lastdata_check(); + if (auto_update_flag) + goto FW_force_upgrade; +#endif + g_core_fp.fp_read_FW_ver(); + +#ifdef HX_AUTO_UPDATE_FW +FW_force_upgrade: + auto_update_flag |= ((ic_data->vendor_fw_ver < g_i_FW_VER) || (ic_data->vendor_config_ver < g_i_CFG_VER)); + /* Not sure to do */ + /* auto_update_flag |= ((ic_data->vendor_cid_maj_ver != g_i_CID_MAJ) || (ic_data->vendor_cid_min_ver < g_i_CID_MIN)); */ + if (auto_update_flag) { + ts->himax_update_wq = create_singlethread_workqueue("HMX_update_request"); + if (!ts->himax_update_wq) { + E(" allocate syn_update_wq failed\n"); + err = -ENOMEM; + goto err_update_wq_failed; + } + INIT_DELAYED_WORK(&ts->work_update, himax_update_register); + queue_delayed_work(ts->himax_update_wq, &ts->work_update, msecs_to_jiffies(2000)); + } +#endif +#ifdef HX_ZERO_FLASH + auto_update_flag = true; + ts->himax_0f_update_wq = create_singlethread_workqueue("HMX_0f_update_request"); + INIT_DELAYED_WORK(&ts->work_0f_update, g_core_fp.fp_0f_operation); + queue_delayed_work(ts->himax_0f_update_wq, &ts->work_0f_update, msecs_to_jiffies(2000)); +#endif + + /* Himax Power On and Load Config */ + if (himax_loadSensorConfig(pdata)) { + E("%s: Load Sesnsor configuration failed, unload driver.\n", __func__); + goto err_detect_failed; + } + + g_core_fp.fp_power_on_init(); + calculate_point_number(); + +#ifdef CONFIG_OF + ts->power = pdata->power; +#endif + ts->pdata = pdata; + ts->x_channel = ic_data->HX_RX_NUM; + ts->y_channel = ic_data->HX_TX_NUM; + ts->nFinger_support = ic_data->HX_MAX_PT; + /* calculate the i2c data size */ + calcDataSize(ts->nFinger_support); + I("%s: calcDataSize complete\n", __func__); +#ifdef CONFIG_OF + ts->pdata->abs_pressure_min = 0; + ts->pdata->abs_pressure_max = 200; + ts->pdata->abs_width_min = 0; + ts->pdata->abs_width_max = 200; + pdata->cable_config[0] = 0xF0; + pdata->cable_config[1] = 0x00; +#endif + ts->suspended = false; +#if defined(HX_USB_DETECT_CALLBACK) || defined(HX_USB_DETECT_GLOBAL) + ts->usb_connected = 0x00; + ts->cable_config = pdata->cable_config; +#endif +#ifdef HX_PROTOCOL_A + ts->protocol_type = PROTOCOL_TYPE_A; +#else + ts->protocol_type = PROTOCOL_TYPE_B; +#endif + I("%s: Use Protocol Type %c\n", __func__, + ts->protocol_type == PROTOCOL_TYPE_A ? 'A' : 'B'); + + ret = himax_input_register(ts); + if (ret) { + E("%s: Unable to register %s input device\n", + __func__, ts->input_dev->name); + goto err_input_register_device_failed; + } + +#if defined(CONFIG_DRM) || defined(CONFIG_FB) + + ts->himax_att_wq = create_singlethread_workqueue("HMX_ATT_request"); + + if (!ts->himax_att_wq) { + E(" allocate syn_att_wq failed\n"); + err = -ENOMEM; + goto err_get_intr_bit_failed; + } + + INIT_DELAYED_WORK(&ts->work_att, himax_fb_register); + queue_delayed_work(ts->himax_att_wq, &ts->work_att, msecs_to_jiffies(15000)); +#endif + +#ifdef HX_SMART_WAKEUP + ts->SMWP_enable = 0; + wakeup_source_init(&ts->ts_SMWP_wake_src, WAKE_LOCK_SUSPEND, HIMAX_common_NAME); +#endif +#ifdef HX_HIGH_SENSE + ts->HSEN_enable = 0; +#endif +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) + ts->ito_test_wq = create_singlethread_workqueue("himax_ito_test_wq"); + + if (!ts->ito_test_wq) { + E("%s: ito test workqueue failed\n", __func__); + err = -ENOMEM; + goto err_ito_test_wq_failed; + } + + INIT_WORK(&ts->ito_test_work, himax_ito_test_work); +#endif + + /* touch data init */ + err = himax_report_data_init(); + if (err) + goto err_report_data_init_failed; + + if (himax_common_proc_init()) { + E(" %s: himax_common proc_init failed!\n", __func__); + goto err_creat_proc_file_failed; + } + +#if defined(HX_USB_DETECT_CALLBACK) + + if (ts->cable_config) + cable_detect_register_notifier(&himax_cable_status_handler); + +#endif + err = himax_ts_register_interrupt(); + + if (err) + goto err_register_interrupt_failed; + + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_DEBUG + if (himax_debug_init()) + E(" %s: debug initial failed!\n", __func__); +#endif + +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) + + if (auto_update_flag) + himax_int_enable(0); + +#endif + return 0; +err_register_interrupt_failed: +remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL); +err_creat_proc_file_failed: +err_report_data_init_failed: +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) + destroy_workqueue(ts->ito_test_wq); +err_ito_test_wq_failed: +#endif +#ifdef HX_SMART_WAKEUP + wakeup_source_trash(&ts->ts_SMWP_wake_src); +#endif +#if defined(CONFIG_FB) || defined(CONFIG_DRM) +err_get_intr_bit_failed: + cancel_delayed_work_sync(&ts->work_att); + destroy_workqueue(ts->himax_att_wq); +#endif +err_input_register_device_failed: + input_free_device(ts->input_dev); +err_detect_failed: +#ifdef HX_AUTO_UPDATE_FW + if (auto_update_flag) { + cancel_delayed_work_sync(&ts->work_update); + destroy_workqueue(ts->himax_update_wq); + } +err_update_wq_failed: +#endif + +error_ic_detect_failed: + if (gpio_is_valid(pdata->gpio_irq)) + gpio_free(pdata->gpio_irq); + +#ifdef HX_RST_PIN_FUNC + + if (gpio_is_valid(pdata->gpio_reset)) + gpio_free(pdata->gpio_reset); + +#endif + +#ifndef CONFIG_OF +err_power_failed: +#endif + +err_alloc_dt_pdata_failed: + kfree(hx_touch_data); +err_alloc_touch_data_failed: + kfree(ic_data); +err_dt_ic_data_fail: + kfree(pdata); +err_dt_platform_data_fail: + kfree(ts); + probe_fail_flag = 1; + return err; +} + +void himax_chip_common_deinit(void) +{ + struct himax_ts_data *ts = private_ts; + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_DEBUG + himax_debug_remove(); +#endif + + remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL); + himax_common_proc_deinit(); + + if (!ts->use_irq) { + hrtimer_cancel(&ts->timer); + destroy_workqueue(ts->himax_wq); + } + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) + destroy_workqueue(ts->ito_test_wq); +#endif +#ifdef HX_SMART_WAKEUP + wakeup_source_trash(&ts->ts_SMWP_wake_src); +#endif + +#ifdef CONFIG_DRM + if (msm_drm_unregister_client(&ts->fb_notif)) + E("Error occurred while unregistering fb_notifier.\n"); + cancel_delayed_work_sync(&ts->work_att); + destroy_workqueue(ts->himax_att_wq); +#elif defined(CONFIG_FB) + if (fb_unregister_client(&ts->fb_notif)) + E("Error occurred while unregistering fb_notifier.\n"); + cancel_delayed_work_sync(&ts->work_att); + destroy_workqueue(ts->himax_att_wq); +#endif + input_free_device(ts->input_dev); +#ifdef HX_ZERO_FLASH + cancel_delayed_work_sync(&ts->work_0f_update); + destroy_workqueue(ts->himax_0f_update_wq); +#endif +#ifdef HX_AUTO_UPDATE_FW + cancel_delayed_work_sync(&ts->work_update); + destroy_workqueue(ts->himax_update_wq); +#endif + if (gpio_is_valid(ts->pdata->gpio_irq)) + gpio_free(ts->pdata->gpio_irq); +#ifdef HX_RST_PIN_FUNC + if (gpio_is_valid(ts->pdata->gpio_reset)) + gpio_free(ts->pdata->gpio_reset); +#endif + + kfree(hx_touch_data); + kfree(ic_data); + kfree(ts->pdata); + kfree(ts); + probe_fail_flag = 0; +} + +int himax_chip_common_suspend(struct himax_ts_data *ts) +{ + int ret; + + if (ts->suspended) { + I("%s: Already suspended. Skipped.\n", __func__); + return 0; + } + + ts->suspended = true; + I("%s: enter\n", __func__); + + if (debug_data != NULL && debug_data->flash_dump_going == true) { + I("[himax] %s: Flash dump is going, reject suspend\n", __func__); + return 0; + } + +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || defined(HX_USB_DETECT_GLOBAL) +#ifndef HX_RESUME_SEND_CMD + g_core_fp.fp_resend_cmd_func(ts->suspended); +#endif +#endif +#ifdef HX_SMART_WAKEUP + + if (ts->SMWP_enable) { + atomic_set(&ts->suspend_mode, 1); + ts->pre_finger_mask = 0; + FAKE_POWER_KEY_SEND = false; + I("[himax] %s: SMART_WAKEUP enable, reject suspend\n", __func__); + return 0; + } + +#endif + himax_int_enable(0); + g_core_fp.fp_suspend_ic_action(); + + if (!ts->use_irq) { + ret = cancel_work_sync(&ts->work); + + if (ret) + himax_int_enable(1); + } + + /* ts->first_pressed = 0; */ + atomic_set(&ts->suspend_mode, 1); + ts->pre_finger_mask = 0; + + if (ts->pdata->powerOff3V3 && ts->pdata->power) + ts->pdata->power(0); + + I("%s: END\n", __func__); + return 0; +} + +int himax_chip_common_resume(struct himax_ts_data *ts) +{ + I("%s: enter\n", __func__); + + if (ts->suspended == false) { + I("%s: It had entered resume, skip this step\n", __func__); + return 0; + } + ts->suspended = false; + + atomic_set(&ts->suspend_mode, 0); + + if (ts->pdata->powerOff3V3 && ts->pdata->power) + ts->pdata->power(1); + +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || defined(HX_USB_DETECT_GLOBAL) + g_core_fp.fp_resend_cmd_func(ts->suspended); +#elif defined(HX_RESUME_HW_RESET) + g_core_fp.fp_ic_reset(false, false); +#endif + himax_report_all_leave_event(ts); + + g_core_fp.fp_resume_ic_action(); + himax_int_enable(1); + + I("%s: END\n", __func__); + return 0; +} diff --git a/drivers/input/touchscreen/hxchipset/himax_common.h b/drivers/input/touchscreen/hxchipset/himax_common.h new file mode 100644 index 000000000000..e190490d469c --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_common.h @@ -0,0 +1,497 @@ +/* + * Himax Android Driver Sample Code for common functions + * + * Copyright (C) 2018 Himax Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef HIMAX_COMMON_H +#define HIMAX_COMMON_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "himax_platform.h" + +#ifdef CONFIG_DRM + #include +#elif defined(CONFIG_FB) + #include + #include +#elif defined(CONFIG_HAS_EARLYSUSPEND) + #include +#endif + +#ifdef CONFIG_OF + #include +#endif + +#define HIMAX_DRIVER_VER "1.2.2.4_ABCD1234_01" + +#define FLASH_DUMP_FILE "/sdcard/HX_Flash_Dump.bin" + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) + #define HX_TP_PROC_2T2R + /*#define HX_TP_SELF_TEST_DRIVER*/ /* if enable, selftest works in driver */ +#endif +/*===========Himax Option function=============*/ +#define HX_RST_PIN_FUNC +#define HX_RESUME_SEND_CMD +#define HX_ESD_RECOVERY +/*#define HX_AUTO_UPDATE_FW*/ +/*#define HX_SMART_WAKEUP*/ +/*#define HX_GESTURE_TRACK*/ +/*#define HX_HIGH_SENSE*/ +/*#define HX_PALM_REPORT*/ +/*#define HX_USB_DETECT_GLOBAL*/ +/*#define HX_USB_DETECT_CALLBACK*/ +/*#define HX_PROTOCOL_A*/ /* for MTK special platform.If turning on,it will report to system by using specific format. */ +/*#define HX_RESUME_HW_RESET*/ +#define HX_PROTOCOL_B_3PA +/*#define HX_FIX_TOUCH_INFO*/ /* if open, you need to change the touch info in the fix_touch_info*/ +/*#define HX_ZERO_FLASH*/ +#define HX_ORG_SELFTEST +/*#define CONFIG_CHIP_DTCFG*/ + +/*#define HX_EN_SEL_BUTTON*/ /* Support Self Virtual key, default is close*/ +/*#define HX_EN_MUT_BUTTON*/ /* Support Mutual Virtual Key, default is close*/ + +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) +/*#define HX_PLATFOME_DEFINE_KEY*/ /* for specific platform to set key(button) */ +#endif + +#define HX_KEY_MAX_COUNT 4 +#define DEFAULT_RETRY_CNT 3 + +#define HX_85XX_A_SERIES_PWON "HX85xxA" +#define HX_85XX_B_SERIES_PWON "HX85xxB" +#define HX_85XX_C_SERIES_PWON "HX85xxC" +#define HX_85XX_D_SERIES_PWON "HX85xxD" +#define HX_85XX_E_SERIES_PWON "HX85xxE" +#define HX_85XX_ES_SERIES_PWON "HX85xxES" +#define HX_85XX_F_SERIES_PWON "HX85xxF" +#define HX_85XX_H_SERIES_PWON "HX85xxH" +#define HX_83100A_SERIES_PWON "HX83100A" +#define HX_83102A_SERIES_PWON "HX83102A" +#define HX_83102B_SERIES_PWON "HX83102B" +#define HX_83102D_SERIES_PWON "HX83102D" +#define HX_83103A_SERIES_PWON "HX83103A" +#define HX_83110A_SERIES_PWON "HX83110A" +#define HX_83110B_SERIES_PWON "HX83110B" +#define HX_83111B_SERIES_PWON "HX83111B" +#define HX_83112A_SERIES_PWON "HX83112A" +#define HX_83112B_SERIES_PWON "HX83112B" +#define HX_83112D_SERIES_PWON "HX83112D" +#define HX_83112E_SERIES_PWON "HX83112E" +#define HX_83191A_SERIES_PWON "HX83191A" + +#define HX_TP_BIN_CHECKSUM_SW 1 +#define HX_TP_BIN_CHECKSUM_HW 2 +#define HX_TP_BIN_CHECKSUM_CRC 3 + +#define SHIFTBITS 5 + +#define FW_SIZE_32k 32768 +#define FW_SIZE_60k 61440 +#define FW_SIZE_64k 65536 +#define FW_SIZE_124k 126976 +#define FW_SIZE_128k 131072 + +#define NO_ERR 0 +#define READY_TO_SERVE 1 +#define WORK_OUT 2 +#define I2C_FAIL -1 +#define MEM_ALLOC_FAIL -2 +#define CHECKSUM_FAIL -3 +#define GESTURE_DETECT_FAIL -4 +#define INPUT_REGISTER_FAIL -5 +#define FW_NOT_READY -6 +#define LENGTH_FAIL -7 +#define OPEN_FILE_FAIL -8 +#define ERR_WORK_OUT -10 +#define HW_CRC_FAIL 1 + +#define HX_FINGER_ON 1 +#define HX_FINGER_LEAVE 2 + + +enum HX_TS_PATH { + HX_REPORT_COORD = 1, + HX_REPORT_SMWP_EVENT, + HX_REPORT_COORD_RAWDATA, +}; + +enum HX_TS_STATUS { + HX_TS_GET_DATA_FAIL = -4, + HX_ESD_EVENT, + HX_CHKSUM_FAIL, + HX_PATH_FAIL, + HX_TS_NORMAL_END = 0, + HX_ESD_REC_OK, + HX_READY_SERVE, + HX_REPORT_DATA, + HX_ESD_WARNING, + HX_IC_RUNNING, + HX_ZERO_EVENT_COUNT, + HX_RST_OK, +}; + +enum cell_type { + CHIP_IS_ON_CELL, + CHIP_IS_IN_CELL +}; +#ifdef HX_FIX_TOUCH_INFO +enum fix_touch_info { + FIX_HX_RX_NUM = 0, + FIX_HX_TX_NUM = 0, + FIX_HX_BT_NUM = 0, + FIX_HX_X_RES = 0, + FIX_HX_Y_RES = 0, + FIX_HX_MAX_PT = 0, + FIX_HX_XY_REVERSE = false, + FIX_HX_INT_IS_EDGE = true, +#ifdef HX_TP_PROC_2T2R + FIX_HX_RX_NUM_2 = 0, + FIX_HX_TX_NUM_2 = 0, +#endif +}; +#endif + +#ifdef HX_ZERO_FLASH + #define HX_0F_DEBUG +#endif +struct himax_ic_data { + int vendor_fw_ver; + int vendor_config_ver; + int vendor_touch_cfg_ver; + int vendor_display_cfg_ver; + int vendor_cid_maj_ver; + int vendor_cid_min_ver; + int vendor_panel_ver; + int vendor_sensor_id; + int HX_RX_NUM; + int HX_TX_NUM; + int HX_BT_NUM; + int HX_X_RES; + int HX_Y_RES; + int HX_MAX_PT; + bool HX_XY_REVERSE; + bool HX_INT_IS_EDGE; +#ifdef HX_TP_PROC_2T2R + int HX_RX_NUM_2; + int HX_TX_NUM_2; +#endif +}; + +struct himax_virtual_key { + int index; + int keycode; + int x_range_min; + int x_range_max; + int y_range_min; + int y_range_max; +}; + +struct himax_target_report_data { + int *x; + int *y; + int *w; + int *finger_id; + int finger_on; + int finger_num; +#ifdef HX_PLATFORM_DEFINE_KEY + int key_size; + int *key_x; + int *key_y; + int *key_w; +#endif +#ifdef HX_SMART_WAKEUP + int SMWP_event_chk; +#endif +}; + +struct himax_report_data { + int touch_all_size; + int raw_cnt_max; + int raw_cnt_rmd; + int touch_info_size; + uint8_t finger_num; + uint8_t finger_on; + uint8_t *hx_coord_buf; + uint8_t hx_state_info[2]; +#if defined(HX_SMART_WAKEUP) + int event_size; + uint8_t *hx_event_buf; +#endif + + int rawdata_size; + uint8_t diag_cmd; + uint8_t *hx_rawdata_buf; + uint8_t rawdata_frame_size; +}; + +struct himax_ts_data { + bool suspended; + atomic_t suspend_mode; + uint8_t x_channel; + uint8_t y_channel; + uint8_t useScreenRes; + uint8_t diag_cmd; + char chip_name[30]; + uint8_t chip_cell_type; + + uint8_t protocol_type; + uint8_t first_pressed; + uint8_t coord_data_size; + uint8_t area_data_size; + uint8_t coordInfoSize; + uint8_t raw_data_frame_size; + uint8_t raw_data_nframes; + uint8_t nFinger_support; + uint8_t irq_enabled; + uint8_t diag_self[50]; + + uint16_t finger_pressed; + uint16_t last_slot; + uint16_t pre_finger_mask; + uint16_t old_finger; + int hx_point_num; + + uint32_t debug_log_level; + uint32_t widthFactor; + uint32_t heightFactor; + uint32_t tw_x_min; + uint32_t tw_x_max; + uint32_t tw_y_min; + uint32_t tw_y_max; + uint32_t pl_x_min; + uint32_t pl_x_max; + uint32_t pl_y_min; + uint32_t pl_y_max; + + int rst_gpio; + int use_irq; + int (*power)(int on); + int pre_finger_data[10][2]; + + struct device *dev; + struct workqueue_struct *himax_wq; + struct work_struct work; + struct input_dev *input_dev; + struct hrtimer timer; + struct i2c_client *client; + struct himax_i2c_platform_data *pdata; + struct himax_virtual_key *button; + struct mutex rw_lock; + +/******* SPI-start *******/ + struct mutex spi_lock; + struct spi_device *spi; + int hx_irq; +/******* SPI-end *******/ + + int in_self_test; + +#if defined(CONFIG_FB) + struct notifier_block fb_notif; + struct workqueue_struct *himax_att_wq; + struct delayed_work work_att; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif + + struct workqueue_struct *flash_wq; + struct work_struct flash_work; + +#ifdef HX_AUTO_UPDATE_FW + struct workqueue_struct *himax_update_wq; + struct delayed_work work_update; +#endif + +#ifdef HX_ZERO_FLASH + struct workqueue_struct *himax_0f_update_wq; + struct delayed_work work_0f_update; +#endif + + struct workqueue_struct *himax_diag_wq; + struct delayed_work himax_diag_delay_wrok; + +#ifdef HX_SMART_WAKEUP + uint8_t SMWP_enable; + uint8_t gesture_cust_en[16]; + struct wakeup_source ts_SMWP_wake_src; +#endif + +#ifdef HX_HIGH_SENSE + uint8_t HSEN_enable; +#endif + +#if defined(HX_USB_DETECT_CALLBACK) || defined(HX_USB_DETECT_GLOBAL) + uint8_t usb_connected; + uint8_t *cable_config; +#endif + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) + struct workqueue_struct *ito_test_wq; + struct work_struct ito_test_work; +#endif + +}; + +struct himax_debug { + bool flash_dump_going; + void (*fp_ts_dbg_func)(struct himax_ts_data *ts, int start); + int (*fp_set_diag_cmd)(struct himax_ic_data *ic_data, struct himax_report_data *hx_touch_data); +}; + +enum input_protocol_type { + PROTOCOL_TYPE_A = 0x00, + PROTOCOL_TYPE_B = 0x01, +}; + +#ifdef HX_HIGH_SENSE + void himax_set_HSEN_func(uint8_t HSEN_enable); +#endif + +#ifdef HX_SMART_WAKEUP +void himax_set_SMWP_func(uint8_t SMWP_enable); + +#define GEST_PTLG_ID_LEN (4) +#define GEST_PTLG_HDR_LEN (4) +#define GEST_PTLG_HDR_ID1 (0xCC) +#define GEST_PTLG_HDR_ID2 (0x44) +#define GEST_PT_MAX_NUM (128) + +enum gesture_event_type { + EV_GESTURE_01 = 0x01, + EV_GESTURE_02, + EV_GESTURE_03, + EV_GESTURE_04, + EV_GESTURE_05, + EV_GESTURE_06, + EV_GESTURE_07, + EV_GESTURE_08, + EV_GESTURE_09, + EV_GESTURE_10, + EV_GESTURE_11, + EV_GESTURE_12, + EV_GESTURE_13, + EV_GESTURE_14, + EV_GESTURE_15, + EV_GESTURE_PWR = 0x80, +}; + +#define KEY_CUST_01 251 +#define KEY_CUST_02 252 +#define KEY_CUST_03 253 +#define KEY_CUST_04 254 +#define KEY_CUST_05 255 +#define KEY_CUST_06 256 +#define KEY_CUST_07 257 +#define KEY_CUST_08 258 +#define KEY_CUST_09 259 +#define KEY_CUST_10 260 +#define KEY_CUST_11 261 +#define KEY_CUST_12 262 +#define KEY_CUST_13 263 +#define KEY_CUST_14 264 +#define KEY_CUST_15 265 +#endif + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) + extern uint8_t himax_ito_test(void); +#endif + +extern struct himax_ts_data *private_ts; +extern struct himax_ic_data *ic_data; +extern struct himax_report_data *hx_touch_data; +extern struct himax_core_fp g_core_fp; +extern struct himax_debug *debug_data; +extern uint8_t HX_PROC_SEND_FLAG; + +#ifdef HX_AUTO_UPDATE_FW +extern int g_i_FW_VER; +extern int g_i_CFG_VER; +extern int g_i_CID_MAJ; /* GUEST ID */ +extern int g_i_CID_MIN; /* VER for GUEST */ +extern unsigned char i_CTPM_FW[]; +#endif + +extern unsigned long FW_VER_MAJ_FLASH_ADDR; +extern unsigned long FW_VER_MIN_FLASH_ADDR; +extern unsigned long CFG_VER_MAJ_FLASH_ADDR; +extern unsigned long CFG_VER_MIN_FLASH_ADDR; +extern unsigned long CID_VER_MAJ_FLASH_ADDR; +extern unsigned long CID_VER_MIN_FLASH_ADDR; + +extern unsigned long FW_VER_MAJ_FLASH_LENG; +extern unsigned long FW_VER_MIN_FLASH_LENG; +extern unsigned long CFG_VER_MAJ_FLASH_LENG; +extern unsigned long CFG_VER_MIN_FLASH_LENG; +extern unsigned long CID_VER_MAJ_FLASH_LENG; +extern unsigned long CID_VER_MIN_FLASH_LENG; +extern unsigned char IC_CHECKSUM; + +extern unsigned long FW_CFG_VER_FLASH_ADDR; + +#ifdef HX_RST_PIN_FUNC + extern u8 HX_HW_RESET_ACTIVATE; + + extern void himax_rst_gpio_set(int pinnum, uint8_t value); +#endif + +/* void himax_HW_reset(uint8_t loadconfig,uint8_t int_off); */ + +extern int himax_chip_common_suspend(struct himax_ts_data *ts); +extern int himax_chip_common_resume(struct himax_ts_data *ts); +extern int himax_chip_common_init(void); +extern void himax_chip_common_deinit(void); +extern int himax_input_register(struct himax_ts_data *ts); +extern void himax_ts_work(struct himax_ts_data *ts); +extern enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer); +extern int himax_report_data_init(void); +extern struct proc_dir_entry *himax_touch_proc_dir; + +extern int himax_parse_dt(struct himax_ts_data *ts, struct himax_i2c_platform_data *pdata); +extern int himax_dev_set(struct himax_ts_data *ts); +extern int himax_input_register_device(struct input_dev *input_dev); + +#ifdef HX_USB_DETECT_GLOBAL +extern void himax_cable_detect_func(bool force_renew); +#endif + +/* ts_work about start */ +extern struct himax_target_report_data *g_target_report_data; +extern int himax_report_data(struct himax_ts_data *ts, int ts_path, int ts_status); +/* ts_work about end */ + +#endif + diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.c b/drivers/input/touchscreen/hxchipset/himax_debug.c new file mode 100644 index 000000000000..de60c9e148cf --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_debug.c @@ -0,0 +1,3014 @@ +/* + * Himax Android Driver Sample Code for debug nodes + * + * Copyright (C) 2018 Himax Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "himax_debug.h" +#include "himax_ic_core.h" + +static struct proc_dir_entry *himax_proc_debug_level_file; +static struct proc_dir_entry *himax_proc_vendor_file; +static struct proc_dir_entry *himax_proc_attn_file; +static struct proc_dir_entry *himax_proc_int_en_file; +static struct proc_dir_entry *himax_proc_layout_file; +static struct proc_dir_entry *himax_proc_CRC_test_file; + +#ifdef HX_RST_PIN_FUNC + extern void himax_ic_reset(uint8_t loadconfig, uint8_t int_off); +#endif + +#ifdef HX_TP_PROC_2T2R + bool Is_2T2R = false; + int HX_RX_NUM_2 = 0; + int HX_TX_NUM_2 = 0; +#endif +uint8_t g_diag_arr_num; + +int g_max_mutual; +int g_min_mutual = 0xFFFF; +int g_max_self; +int g_min_self = 0xFFFF; + +struct timespec timeStart, timeEnd, timeDelta; +int g_switch_mode; + +#ifdef HX_TP_PROC_2T2R +static uint8_t x_channel_2; +static uint8_t y_channel_2; +static uint32_t *diag_mutual_2; + +int32_t *getMutualBuffer_2(void); +#endif + +#define HIMAX_PROC_REGISTER_FILE "register" +struct proc_dir_entry *himax_proc_register_file; +uint8_t byte_length; +uint8_t register_command[4]; +uint8_t cfg_flag; + +#define HIMAX_PROC_DIAG_FILE "diag" +struct proc_dir_entry *himax_proc_diag_file; +#define HIMAX_PROC_DIAG_ARR_FILE "diag_arr" +struct proc_dir_entry *himax_proc_diag_arrange_file; +struct file *diag_sram_fn; +uint8_t write_counter; +uint8_t write_max_count = 30; + +#define IIR_DUMP_FILE "/sdcard/HX_IIR_Dump.txt" +#define DC_DUMP_FILE "/sdcard/HX_DC_Dump.txt" +#define BANK_DUMP_FILE "/sdcard/HX_BANK_Dump.txt" + +uint8_t x_channel; +uint8_t y_channel; +int32_t *diag_mutual; +int32_t *diag_mutual_new; +int32_t *diag_mutual_old; +uint8_t diag_max_cnt; +uint8_t hx_state_info[2] = {0}; +uint8_t diag_coor[128]; +int32_t diag_self[100] = {0}; +int32_t diag_self_new[100] = {0}; +int32_t diag_self_old[100] = {0}; +int32_t *getMutualBuffer(void); +int32_t *getMutualNewBuffer(void); +int32_t *getMutualOldBuffer(void); +int32_t *getSelfBuffer(void); +int32_t *getSelfNewBuffer(void); +int32_t *getSelfOldBuffer(void); + +#define HIMAX_PROC_DEBUG_FILE "debug" +struct proc_dir_entry *himax_proc_debug_file; +#define HIMAX_PROC_FW_DEBUG_FILE "FW_debug" +struct proc_dir_entry *himax_proc_fw_debug_file; +#define HIMAX_PROC_DD_DEBUG_FILE "DD_debug" +struct proc_dir_entry *himax_proc_dd_debug_file; +bool fw_update_complete; +int handshaking_result; +unsigned char debug_level_cmd; +uint8_t cmd_set[8]; +uint8_t mutual_set_flag; + +#define HIMAX_PROC_FLASH_DUMP_FILE "flash_dump" +struct proc_dir_entry *himax_proc_flash_dump_file; +static int Flash_Size = 131072; +static uint8_t *flash_buffer; +static uint8_t flash_command; +static uint8_t flash_read_step; +static uint8_t flash_progress; +static uint8_t flash_dump_complete; +static uint8_t flash_dump_fail; +static uint8_t sys_operation; +static bool flash_dump_going; +static uint8_t getFlashDumpComplete(void); +static uint8_t getFlashDumpFail(void); +static uint8_t getFlashDumpProgress(void); +static uint8_t getFlashReadStep(void); +static void setFlashCommand(uint8_t command); +static void setFlashReadStep(uint8_t step); + +uint32_t **raw_data_array; +uint8_t X_NUM, Y_NUM; +uint8_t sel_type = 0x0D; + +#define HIMAX_PROC_RESET_FILE "reset" +struct proc_dir_entry *himax_proc_reset_file; + +#define HIMAX_PROC_SENSE_ON_OFF_FILE "SenseOnOff" +struct proc_dir_entry *himax_proc_SENSE_ON_OFF_file; + +#ifdef HX_ESD_RECOVERY + #define HIMAX_PROC_ESD_CNT_FILE "ESD_cnt" + struct proc_dir_entry *himax_proc_ESD_cnt_file; +#endif + +#define COMMON_BUF_SZ 80 +#define PROC_DD_BUF_SZ 20 +#define DEBUG_BUF_SZ 12 + +/* raw type */ +#define RAW_IIR 1 +#define RAW_DC 2 +#define RAW_BANK 3 +#define RAW_IIR2 4 +#define RAW_IIR2_N 5 +#define RAW_FIR2 6 +#define RAW_BASELINE 7 +#define RAW_DUMP_COORD 8 + +/* status type */ +#define START_TEST 0 +#define RAW_DATA 1 +#define PERCENT_TEST 2 +#define DEV_TEST 3 +#define NOISE_TEST 4 + +#define END_TEST 9 + +/* + *========================================================================= + * + * Segment : Himax PROC Debug Function + * + *========================================================================= + */ +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) + +static int himax_read_i2c_status(void) +{ + return i2c_error_count; +} + +static ssize_t himax_ito_test_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + ssize_t ret = 0; + uint8_t result = 0; + uint8_t status = 0; + char *temp_buf; + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return ret; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + status = ito_get_step_status(); + + switch (status) { + case START_TEST: + ret += snprintf(temp_buf + ret, len - ret, "Step : START_TEST\n"); + break; + + case RAW_DATA: + ret += snprintf(temp_buf + ret, len - ret, "Step : RAW_DATA\n"); + break; + + case PERCENT_TEST: + ret += snprintf(temp_buf + ret, len - ret, "Step : PERCENT_TEST\n"); + break; + + case DEV_TEST: + ret += snprintf(temp_buf + ret, len - ret, "Step : DEV_TEST\n"); + break; + + case NOISE_TEST: + ret += snprintf(temp_buf + ret, len - ret, "Step : NOISE_TEST\n"); + break; + + case END_TEST: + ret += snprintf(temp_buf + ret, len - ret, "Step : END_TEST\n"); + break; + + default: + ret += snprintf(temp_buf + ret, len - ret, "Step : Null\n"); + } + + result = ito_get_result_status(); + + if (result == 0xF) + ret += snprintf(temp_buf + ret, len - ret, "ITO test is On-going!\n"); + else if (result == 0) + ret += snprintf(temp_buf + ret, len - ret, "ITO test is Pass!\n"); + else if (result == 2) + ret += snprintf(temp_buf + ret, len - ret, "Open config file fail!\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "ITO test is Fail!\n"); + + HX_PROC_SEND_FLAG = 1; + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + return ret; +} + +static ssize_t himax_ito_test_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + uint8_t result = 0; + char buf[COMMON_BUF_SZ] = {0}; + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + result = ito_get_result_status(); + I("%s: buf = %s, result = %d.\n", __func__, buf, result); + + if (buf[0] == '1' && result != 0xF) { + I("%s: buf[0] = %c.\n", __func__, buf[0]); + ito_set_step_status(0); + queue_work(ts->ito_test_wq, &ts->ito_test_work); + } + + return len; +} + +static const struct file_operations himax_proc_ito_test_ops = { + .owner = THIS_MODULE, + .read = himax_ito_test_read, + .write = himax_ito_test_write, +}; +#endif + +static ssize_t himax_CRC_test_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + ssize_t ret = 0; + uint8_t result = 0; + char *temp_buf; + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + g_core_fp.fp_sense_off(); + msleep(20); + result = g_core_fp.fp_calculateChecksum(false); + g_core_fp.fp_sense_on(0x01); + + if (result) + ret += snprintf(temp_buf + ret, len - ret, "CRC test is Pass!\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "CRC test is Fail!\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + +static const struct file_operations himax_proc_CRC_test_ops = { + .owner = THIS_MODULE, + .read = himax_CRC_test_read, +}; + +static ssize_t himax_vendor_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + ssize_t ret = 0; + char *temp_buf; + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + ret += snprintf(temp_buf + ret, len - ret, "FW_VER = 0x%2.2X\n", ic_data->vendor_fw_ver); + + if (private_ts->chip_cell_type == CHIP_IS_ON_CELL) + ret += snprintf(temp_buf + ret, len - ret, "CONFIG_VER = 0x%2.2X\n", ic_data->vendor_config_ver); + else { + ret += snprintf(temp_buf + ret, len - ret, "TOUCH_VER = 0x%2.2X\n", ic_data->vendor_touch_cfg_ver); + ret += snprintf(temp_buf + ret, len - ret, "DISPLAY_VER = 0x%2.2X\n", ic_data->vendor_display_cfg_ver); + } + + if (ic_data->vendor_cid_maj_ver < 0 && ic_data->vendor_cid_min_ver < 0) + ret += snprintf(temp_buf + ret, len - ret, "CID_VER = NULL\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "CID_VER = 0x%2.2X\n", (ic_data->vendor_cid_maj_ver << 8 | ic_data->vendor_cid_min_ver)); + + if (ic_data->vendor_panel_ver < 0) + ret += snprintf(temp_buf + ret, len - ret, "PANEL_VER = NULL\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "PANEL_VER = 0x%2.2X\n", ic_data->vendor_panel_ver); + + ret += snprintf(temp_buf + ret, len - ret, "\n"); + ret += snprintf(temp_buf + ret, len - ret, "Himax Touch Driver Version:\n"); + ret += snprintf(temp_buf + ret, len - ret, "%s\n", HIMAX_DRIVER_VER); + HX_PROC_SEND_FLAG = 1; + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + + return ret; +} + +static const struct file_operations himax_proc_vendor_ops = { + .owner = THIS_MODULE, + .read = himax_vendor_read, +}; + +static ssize_t himax_attn_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + ssize_t ret = 0; + struct himax_ts_data *ts_data; + char *temp_buf; + + ts_data = private_ts; + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + ret += snprintf(temp_buf + ret, len - ret, "attn = %x\n", himax_int_gpio_read(ts_data->pdata->gpio_irq)); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + + +static const struct file_operations himax_proc_attn_ops = { + .owner = THIS_MODULE, + .read = himax_attn_read, +}; + +static ssize_t himax_int_en_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + size_t ret = 0; + char *temp_buf; + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + ret += snprintf(temp_buf + ret, len - ret, "%d ", ts->irq_enabled); + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + +static ssize_t himax_int_en_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf_tmp[DEBUG_BUF_SZ] = {0}; + int value, ret = 0; + + if (len >= DEBUG_BUF_SZ) { + I("%s: no command exceeds 12 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf_tmp, buff, len)) + return -EFAULT; + + if (buf_tmp[0] == '0') + value = false; + else if (buf_tmp[0] == '1') + value = true; + else + return -EINVAL; + + if (value) { + ret = himax_int_en_set(); + + if (ret == 0) { + ts->irq_enabled = 1; + irq_enable_count = 1; + } + } else { + himax_int_enable(0); + free_irq(ts->client->irq, ts); + ts->irq_enabled = 0; + } + + return len; +} + +static const struct file_operations himax_proc_int_en_ops = { + .owner = THIS_MODULE, + .read = himax_int_en_read, + .write = himax_int_en_write, +}; + +static ssize_t himax_layout_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + size_t ret = 0; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed\n", __func__); + return 0; + } + ret += snprintf(temp_buf + ret, len - ret, "%d ", ts->pdata->abs_x_min); + ret += snprintf(temp_buf + ret, len - ret, "%d ", ts->pdata->abs_x_max); + ret += snprintf(temp_buf + ret, len - ret, "%d ", ts->pdata->abs_y_min); + ret += snprintf(temp_buf + ret, len - ret, "%d ", ts->pdata->abs_y_max); + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + +static ssize_t himax_layout_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf_tmp[5]; + int i = 0, j = 0, k = 0, ret; + unsigned long value; + int layout[4] = {0}; + char buf[COMMON_BUF_SZ] = {0}; + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + for (i = 0; i < 20; i++) { + if (buf[i] == ',' || buf[i] == '\n') { + memset(buf_tmp, 0x0, sizeof(buf_tmp)); + + if (i - j <= 5) + memcpy(buf_tmp, buf + j, i - j); + else { + I("buffer size is over 5 char\n"); + return len; + } + + j = i + 1; + + if (k < 4) { + ret = kstrtoul(buf_tmp, 10, &value); + layout[k++] = value; + } + } + } + + if (k == 4) { + ts->pdata->abs_x_min = layout[0]; + ts->pdata->abs_x_max = layout[1]; + ts->pdata->abs_y_min = layout[2]; + ts->pdata->abs_y_max = layout[3]; + I("%d, %d, %d, %d\n", + ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max); + input_unregister_device(ts->input_dev); + himax_input_register(ts); + } else + I("ERR@%d, %d, %d, %d\n", + ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max); + + return len; +} + +static const struct file_operations himax_proc_layout_ops = { + .owner = THIS_MODULE, + .read = himax_layout_read, + .write = himax_layout_write, +}; + +static ssize_t himax_debug_level_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts_data; + size_t ret = 0; + char *temp_buf; + + ts_data = private_ts; + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + ret += snprintf(temp_buf + ret, len - ret, "%d\n", ts_data->debug_log_level); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + +static ssize_t himax_debug_level_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + struct himax_ts_data *ts; + char buf_tmp[DEBUG_BUF_SZ]; + int i; + + ts = private_ts; + + if (len >= DEBUG_BUF_SZ) { + I("%s: no command exceeds 12 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf_tmp, buff, len)) + return -EFAULT; + + ts->debug_log_level = 0; + + for (i = 0; i < len - 1; i++) { + if (buf_tmp[i] >= '0' && buf_tmp[i] <= '9') + ts->debug_log_level |= (buf_tmp[i] - '0'); + else if (buf_tmp[i] >= 'A' && buf_tmp[i] <= 'F') + ts->debug_log_level |= (buf_tmp[i] - 'A' + 10); + else if (buf_tmp[i] >= 'a' && buf_tmp[i] <= 'f') + ts->debug_log_level |= (buf_tmp[i] - 'a' + 10); + + if (i != len - 2) + ts->debug_log_level <<= 4; + } + + if (ts->debug_log_level & BIT(3)) { + if (ts->pdata->screenWidth > 0 && ts->pdata->screenHeight > 0 && + (ts->pdata->abs_x_max - ts->pdata->abs_x_min) > 0 && + (ts->pdata->abs_y_max - ts->pdata->abs_y_min) > 0) { + ts->widthFactor = (ts->pdata->screenWidth << SHIFTBITS) / (ts->pdata->abs_x_max - ts->pdata->abs_x_min); + ts->heightFactor = (ts->pdata->screenHeight << SHIFTBITS) / (ts->pdata->abs_y_max - ts->pdata->abs_y_min); + + if (ts->widthFactor > 0 && ts->heightFactor > 0) + ts->useScreenRes = 1; + else { + ts->heightFactor = 0; + ts->widthFactor = 0; + ts->useScreenRes = 0; + } + } else + I("Enable finger debug with raw position mode!\n"); + } else { + ts->useScreenRes = 0; + ts->widthFactor = 0; + ts->heightFactor = 0; + } + + return len; +} + +static const struct file_operations himax_proc_debug_level_ops = { + .owner = THIS_MODULE, + .read = himax_debug_level_read, + .write = himax_debug_level_write, +}; + +static ssize_t himax_proc_register_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + int ret = 0; + uint16_t loop_i; + uint8_t data[128]; + char *temp_buf; + + memset(data, 0x00, sizeof(data)); + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + I("himax_register_show: %02X,%02X,%02X,%02X\n", register_command[3], register_command[2], register_command[1], register_command[0]); + g_core_fp.fp_register_read(register_command, 128, data, cfg_flag); + ret += snprintf(temp_buf + ret, len - ret, "command: %02X,%02X,%02X,%02X\n", register_command[3], register_command[2], register_command[1], register_command[0]); + + for (loop_i = 0; loop_i < 128; loop_i++) { + ret += snprintf(temp_buf + ret, len - ret, "0x%2.2X ", data[loop_i]); + if ((loop_i % 16) == 15) + ret += snprintf(temp_buf + ret, len - ret, "\n"); + } + + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + +static ssize_t himax_proc_register_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + char buf[COMMON_BUF_SZ] = {0}; + char buf_tmp[16]; + uint8_t length = 0; + unsigned long result = 0; + uint8_t loop_i = 0; + uint16_t base = 2; + char *data_str = NULL; + uint8_t w_data[20]; + uint8_t x_pos[20]; + uint8_t count = 0; + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + memset(buf_tmp, 0x0, sizeof(buf_tmp)); + memset(w_data, 0x0, sizeof(w_data)); + memset(x_pos, 0x0, sizeof(x_pos)); + memset(register_command, 0x0, sizeof(register_command)); + + I("himax %s\n", buf); + + if ((buf[0] == 'r' || buf[0] == 'w') && buf[1] == ':' && buf[2] == 'x') { + length = strlen(buf); + + /* I("%s: length = %d.\n", __func__,length); */ + for (loop_i = 0; loop_i < length; loop_i++) { /* find postion of 'x' */ + if (buf[loop_i] == 'x') { + x_pos[count] = loop_i; + count++; + } + } + + data_str = strrchr(buf, 'x'); + I("%s: %s.\n", __func__, data_str); + length = strlen(data_str + 1) - 1; + + if (buf[0] == 'r') { + if (buf[3] == 'F' && buf[4] == 'E' && length == 4) { + length = length - base; + cfg_flag = 1; + memcpy(buf_tmp, data_str + base + 1, length); + } else { + cfg_flag = 0; + memcpy(buf_tmp, data_str + 1, length); + } + + byte_length = length / 2; + + if (!kstrtoul(buf_tmp, 16, &result)) { + for (loop_i = 0 ; loop_i < byte_length ; loop_i++) + register_command[loop_i] = (uint8_t)(result >> loop_i * 8); + } + + if (strcmp(HX_85XX_H_SERIES_PWON, private_ts->chip_name) == 0 && cfg_flag == 0) + cfg_flag = 2; + } else if (buf[0] == 'w') { + if (buf[3] == 'F' && buf[4] == 'E') { + cfg_flag = 1; + memcpy(buf_tmp, buf + base + 3, length); + } else { + cfg_flag = 0; + memcpy(buf_tmp, buf + 3, length); + } + + if (count < 3) { + byte_length = length / 2; + + if (!kstrtoul(buf_tmp, 16, &result)) { /* command */ + for (loop_i = 0 ; loop_i < byte_length ; loop_i++) + register_command[loop_i] = (uint8_t)(result >> loop_i * 8); + } + + if (!kstrtoul(data_str + 1, 16, &result)) { /* data */ + for (loop_i = 0 ; loop_i < byte_length ; loop_i++) + w_data[loop_i] = (uint8_t)(result >> loop_i * 8); + } + + g_core_fp.fp_register_write(register_command, byte_length, w_data, cfg_flag); + } else { + for (loop_i = 0; loop_i < count; loop_i++) { /* parsing addr after 'x' */ + memset(buf_tmp, 0x0, sizeof(buf_tmp)); + if (cfg_flag != 0 && loop_i != 0) + byte_length = 2; + else + byte_length = x_pos[1] - x_pos[0] - 2; /* original */ + + memcpy(buf_tmp, buf + x_pos[loop_i] + 1, byte_length); + + /* I("%s: buf_tmp = %s\n", __func__,buf_tmp); */ + if (kstrtoul(buf_tmp, 16, &result) != 0) + continue; + + if (loop_i == 0) + register_command[loop_i] = (uint8_t)(result); + else + w_data[loop_i - 1] = (uint8_t)(result); + } + + byte_length = count - 1; + if (strcmp(HX_85XX_H_SERIES_PWON, private_ts->chip_name) == 0 && cfg_flag == 0) + cfg_flag = 2; + g_core_fp.fp_register_write(register_command, byte_length, &w_data[0], cfg_flag); + } + } else + return len; + } + + return len; +} + +static const struct file_operations himax_proc_register_ops = { + .owner = THIS_MODULE, + .read = himax_proc_register_read, + .write = himax_proc_register_write, +}; + +int32_t *getMutualBuffer(void) +{ + return diag_mutual; +} +int32_t *getMutualNewBuffer(void) +{ + return diag_mutual_new; +} +int32_t *getMutualOldBuffer(void) +{ + return diag_mutual_old; +} +int32_t *getSelfBuffer(void) +{ + return &diag_self[0]; +} +int32_t *getSelfNewBuffer(void) +{ + return &diag_self_new[0]; +} +int32_t *getSelfOldBuffer(void) +{ + return &diag_self_old[0]; +} +uint8_t getXChannel(void) +{ + return x_channel; +} +uint8_t getYChannel(void) +{ + return y_channel; +} +void setXChannel(uint8_t x) +{ + x_channel = x; +} +void setYChannel(uint8_t y) +{ + y_channel = y; +} +void setMutualBuffer(void) +{ + diag_mutual = kzalloc(x_channel * y_channel * sizeof(int32_t), GFP_KERNEL); + if (!diag_mutual) + E("%s: allocate memory failed!\n", __func__); +} +void setMutualNewBuffer(void) +{ + diag_mutual_new = kzalloc(x_channel * y_channel * sizeof(int32_t), GFP_KERNEL); + if (!diag_mutual_new) + E("%s: allocate memory failed!\n", __func__); +} +void setMutualOldBuffer(void) +{ + diag_mutual_old = kzalloc(x_channel * y_channel * sizeof(int32_t), GFP_KERNEL); + if (!diag_mutual_old) + E("%s: allocate memory failed!\n", __func__); +} + +#ifdef HX_TP_PROC_2T2R +int32_t *getMutualBuffer_2(void) +{ + return diag_mutual_2; +} + +uint8_t getXChannel_2(void) +{ + return x_channel_2; +} + +uint8_t getYChannel_2(void) +{ + return y_channel_2; +} + +void setXChannel_2(uint8_t x) +{ + x_channel_2 = x; +} + +void setYChannel_2(uint8_t y) +{ + y_channel_2 = y; +} + +void setMutualBuffer_2(void) +{ + diag_mutual_2 = kzalloc(x_channel_2 * y_channel_2 * sizeof(int32_t), GFP_KERNEL); +} +#endif + +int himax_set_diag_cmd(struct himax_ic_data *ic_data, struct himax_report_data *hx_touch_data) +{ + struct himax_ts_data *ts = private_ts; + int32_t *mutual_data; + int32_t *self_data; + int mul_num; + int self_num; + + /* int RawDataLen = 0; */ + hx_touch_data->diag_cmd = ts->diag_cmd; + + if (hx_touch_data->diag_cmd >= 1 && hx_touch_data->diag_cmd <= 7) { + /* Check event stack CRC */ + if (!g_core_fp.fp_diag_check_sum(hx_touch_data)) + goto bypass_checksum_failed_packet; + +#ifdef HX_TP_PROC_2T2R + + if (Is_2T2R && (hx_touch_data->diag_cmd >= 4 && hx_touch_data->diag_cmd <= 6)) { + mutual_data = getMutualBuffer_2(); + self_data = getSelfBuffer(); + /* initiallize the block number of mutual and self */ + mul_num = getXChannel_2() * getYChannel_2(); +#ifdef HX_EN_SEL_BUTTON + self_num = getXChannel_2() + getYChannel_2() + ic_data->HX_BT_NUM; +#else + self_num = getXChannel_2() + getYChannel_2(); +#endif + } else +#endif + { + mutual_data = getMutualBuffer(); + self_data = getSelfBuffer(); + /* initiallize the block number of mutual and self */ + mul_num = getXChannel() * getYChannel(); +#ifdef HX_EN_SEL_BUTTON + self_num = getXChannel() + getYChannel() + ic_data->HX_BT_NUM; +#else + self_num = getXChannel() + getYChannel(); +#endif + } + + g_core_fp.fp_diag_parse_raw_data(hx_touch_data, mul_num, self_num, hx_touch_data->diag_cmd, mutual_data, self_data); + } + + else + if (hx_touch_data->diag_cmd == 8) { + memset(diag_coor, 0x00, sizeof(diag_coor)); + memcpy(&(diag_coor[0]), &hx_touch_data->hx_coord_buf[0], hx_touch_data->touch_info_size); + } + + /* assign state info data */ + memcpy(&(hx_state_info[0]), &hx_touch_data->hx_state_info[0], 2); + return NO_ERR; +bypass_checksum_failed_packet: + return 1; +} + +/* #if defined(HX_DEBUG_LEVEL) */ + +void himax_log_touch_data(int start) +{ + int loop_i = 0; + int print_size = 0; + uint8_t *buf; + + if (start == 1) + return; + + if (hx_touch_data->diag_cmd == 0) { + print_size = hx_touch_data->touch_info_size; + buf = kcalloc(hx_touch_data->touch_info_size, sizeof(uint8_t), GFP_KERNEL); + if (!buf) { + E("%s: allocate memory failed!\n", __func__); + return; + } + memcpy(buf, hx_touch_data->hx_coord_buf, hx_touch_data->touch_info_size); + } else if (hx_touch_data->diag_cmd > 0) { + print_size = hx_touch_data->touch_all_size; + buf = kcalloc(hx_touch_data->touch_info_size, sizeof(uint8_t), GFP_KERNEL); + if (!buf) { + E("%s: allocate memory failed!\n", __func__); + return; + } + memcpy(buf, hx_touch_data->hx_coord_buf, hx_touch_data->touch_info_size); + memcpy(&buf[hx_touch_data->touch_info_size], hx_touch_data->hx_rawdata_buf, hx_touch_data->touch_all_size - hx_touch_data->touch_info_size); + } else + E("%s:cmd fault\n", __func__); + + for (loop_i = 0; loop_i < print_size; loop_i += 8) { + if ((loop_i + 7) >= print_size) { + I("%s: over flow\n", __func__); + break; + } + + I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", loop_i, buf[loop_i], loop_i + 1, buf[loop_i + 1]); + I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", loop_i + 2, buf[loop_i + 2], loop_i + 3, buf[loop_i + 3]); + I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", loop_i + 4, buf[loop_i + 4], loop_i + 5, buf[loop_i + 5]); + I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", loop_i + 6, buf[loop_i + 6], loop_i + 7, buf[loop_i + 7]); + I("\n"); + } + kfree(buf); +} + +void himax_log_touch_event(struct himax_ts_data *ts, int start) +{ + int loop_i = 0; + + if (g_target_report_data->finger_on > 0 && g_target_report_data->finger_num > 0) { + + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { + if (g_target_report_data->x[loop_i] >= 0 && g_target_report_data->x[loop_i] <= ts->pdata->abs_x_max && g_target_report_data->y[loop_i] >= 0 && g_target_report_data->y[loop_i] <= ts->pdata->abs_y_max) { + I("Finger %d=> X:%d, Y:%d W:%d, Z:%d, F:%d\n", loop_i + 1, + g_target_report_data->x[loop_i], + g_target_report_data->y[loop_i], + g_target_report_data->w[loop_i], + g_target_report_data->w[loop_i], + loop_i + 1); + } + } + } else if (g_target_report_data->finger_on == 0 && g_target_report_data->finger_num == 0) + I("All Finger leave\n"); + else + I("%s : wrong input!\n", __func__); + +} + +void himax_log_touch_int_devation(int touched) +{ + if (touched == HX_FINGER_ON) { + getnstimeofday(&timeStart); + /* + * I(" Irq start time = %ld.%06ld s\n", + * timeStart.tv_sec, timeStart.tv_nsec/1000); + */ + } else if (touched == HX_FINGER_LEAVE) { + getnstimeofday(&timeEnd); + timeDelta.tv_nsec = (timeEnd.tv_sec * 1000000000 + timeEnd.tv_nsec) - (timeStart.tv_sec * 1000000000 + timeStart.tv_nsec); + /* + * I("Irq finish time = %ld.%06ld s\n", + * timeEnd.tv_sec, timeEnd.tv_nsec/1000); + */ + I("Touch latency = %ld us\n", timeDelta.tv_nsec / 1000); + } else + I("%s : wrong input!\n", __func__); +} + +void himax_log_touch_event_detail(struct himax_ts_data *ts, int start) +{ + int loop_i = 0; + + if (start == HX_FINGER_LEAVE) { + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { + if (((ts->old_finger >> loop_i & 1) == 0) && ((ts->pre_finger_mask >> loop_i & 1) == 1)) { + if (g_target_report_data->x[loop_i] >= 0 && g_target_report_data->x[loop_i] <= ts->pdata->abs_x_max && g_target_report_data->y[loop_i] >= 0 && g_target_report_data->y[loop_i] <= ts->pdata->abs_y_max) + I("status: Raw:F:%02d Down, X:%d, Y:%d, W:%d\n", loop_i + 1, g_target_report_data->x[loop_i], g_target_report_data->y[loop_i], g_target_report_data->w[loop_i]); + + } else if ((((ts->old_finger >> loop_i & 1) == 1) && ((ts->pre_finger_mask >> loop_i & 1) == 0))) + I("status: Raw:F:%02d Up, X:%d, Y:%d\n", loop_i + 1, ts->pre_finger_data[loop_i][0], ts->pre_finger_data[loop_i][1]); + /* + * else + * I("dbg hx_point_num=%d,old_finger=0x%02X,pre_finger_mask=0x%02X\n",ts->hx_point_num,ts->old_finger,ts->pre_finger_mask); + */ + + } + } + +} + +void himax_ts_dbg_func(struct himax_ts_data *ts, int start) +{ + switch (ts->debug_log_level) { + case 1: + himax_log_touch_data(start); + break; + case 2: + himax_log_touch_event(ts, start); + break; + case 4: + himax_log_touch_int_devation(start); + break; + case 8: + himax_log_touch_event_detail(ts, start); + break; + } +} + +/* #endif */ +static ssize_t himax_diag_arrange_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + char buf[COMMON_BUF_SZ] = {0}; + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + g_diag_arr_num = buf[0] - '0'; + I("%s: g_diag_arr_num = %d\n", __func__, g_diag_arr_num); + return len; +} + +void himax_get_mutual_edge(void) +{ + int i = 0; + + for (i = 0; i < (x_channel * y_channel); i++) { + if (diag_mutual[i] > g_max_mutual) + g_max_mutual = diag_mutual[i]; + + if (diag_mutual[i] < g_min_mutual) + g_min_mutual = diag_mutual[i]; + } +} + +void himax_get_self_edge(void) +{ + int i = 0; + + for (i = 0; i < (x_channel + y_channel); i++) { + if (diag_self[i] > g_max_self) + g_max_self = diag_self[i]; + + if (diag_self[i] < g_min_self) + g_min_self = diag_self[i]; + } +} + +/* print first step which is row */ +static const struct file_operations himax_proc_diag_arrange_ops = { + .owner = THIS_MODULE, + .write = himax_diag_arrange_write, +}; + +static void print_state_info(struct seq_file *s) +{ + /* seq_printf(s, "State_info_2bytes:%3d, %3d\n",hx_state_info[0],hx_state_info[1]); */ + seq_printf(s, "ReCal = %d\t", hx_state_info[0] & 0x01); + seq_printf(s, "Palm = %d\t", hx_state_info[0] >> 1 & 0x01); + seq_printf(s, "AC mode = %d\t", hx_state_info[0] >> 2 & 0x01); + seq_printf(s, "Water = %d\n", hx_state_info[0] >> 3 & 0x01); + seq_printf(s, "Glove = %d\t", hx_state_info[0] >> 4 & 0x01); + seq_printf(s, "TX Hop = %d\t", hx_state_info[0] >> 5 & 0x01); + seq_printf(s, "Base Line = %d\t", hx_state_info[0] >> 6 & 0x01); + seq_printf(s, "OSR Hop = %d\t", hx_state_info[1] >> 3 & 0x01); + seq_printf(s, "KEY = %d\n", hx_state_info[1] >> 4 & 0x0F); +} + +static void himax_diag_arrange_print(struct seq_file *s, int i, int j, int transpose) +{ + if (transpose) + seq_printf(s, "%6d", diag_mutual[j + i * x_channel]); + else + seq_printf(s, "%6d", diag_mutual[i + j * x_channel]); +} + +/* ready to print second step which is column*/ +static void himax_diag_arrange_inloop(struct seq_file *s, int in_init, int out_init, bool transpose, int j) +{ + int i; + int in_max = 0; + + if (transpose) + in_max = y_channel; + else + in_max = x_channel; + + if (in_init > 0) { /* bit0 = 1 */ + for (i = in_init - 1; i >= 0; i--) + himax_diag_arrange_print(s, i, j, transpose); + + if (transpose) { + if (out_init > 0) + seq_printf(s, " %5d\n", diag_self[j]); + else + seq_printf(s, " %5d\n", diag_self[x_channel - j - 1]); + } + } else { /* bit0 = 0 */ + for (i = 0; i < in_max; i++) + himax_diag_arrange_print(s, i, j, transpose); + + if (transpose) { + if (out_init > 0) + seq_printf(s, " %5d\n", diag_self[x_channel - j - 1]); + else + seq_printf(s, " %5d\n", diag_self[j]); + } + } +} + +/* print first step which is row */ +static void himax_diag_arrange_outloop(struct seq_file *s, int transpose, int out_init, int in_init) +{ + int j; + int out_max = 0; + int self_cnt = 0; + + if (transpose) + out_max = x_channel; + else + out_max = y_channel; + + if (out_init > 0) { /* bit1 = 1 */ + self_cnt = 1; + + for (j = out_init - 1; j >= 0; j--) { + seq_printf(s, "%3c%02d%c", '[', j + 1, ']'); + himax_diag_arrange_inloop(s, in_init, out_init, transpose, j); + + if (!transpose) { + seq_printf(s, " %5d\n", diag_self[y_channel + x_channel - self_cnt]); + self_cnt++; + } + } + } else { /* bit1 = 0 */ + /* self_cnt = x_channel; */ + for (j = 0; j < out_max; j++) { + seq_printf(s, "%3c%02d%c", '[', j + 1, ']'); + himax_diag_arrange_inloop(s, in_init, out_init, transpose, j); + + if (!transpose) + seq_printf(s, " %5d\n", diag_self[j + x_channel]); + } + } +} + +/* determin the output format of diag */ +static void himax_diag_arrange(struct seq_file *s) +{ + int bit2, bit1, bit0; + int i; + + /* rotate bit */ + bit2 = g_diag_arr_num >> 2; + /* reverse Y */ + bit1 = g_diag_arr_num >> 1 & 0x1; + /* reverse X */ + bit0 = g_diag_arr_num & 0x1; + + if (g_diag_arr_num < 4) { + for (i = 0 ; i <= x_channel; i++) + seq_printf(s, "%3c%02d%c", '[', i, ']'); + + seq_puts(s, "\n"); + himax_diag_arrange_outloop(s, bit2, bit1 * y_channel, bit0 * x_channel); + seq_printf(s, "%6c", ' '); + + if (bit0 == 1) { + for (i = x_channel - 1; i >= 0; i--) + seq_printf(s, "%6d", diag_self[i]); + } else { + for (i = 0; i < x_channel; i++) + seq_printf(s, "%6d", diag_self[i]); + } + } else { + for (i = 0 ; i <= y_channel; i++) + seq_printf(s, "%3c%02d%c", '[', i, ']'); + + seq_puts(s, "\n"); + himax_diag_arrange_outloop(s, bit2, bit1 * x_channel, bit0 * y_channel); + seq_printf(s, "%6c", ' '); + + if (bit1 == 1) { + for (i = x_channel + y_channel - 1; i >= x_channel; i--) + seq_printf(s, "%6d", diag_self[i]); + + } else { + for (i = x_channel; i < x_channel + y_channel; i++) + seq_printf(s, "%6d", diag_self[i]); + + } + } +} + +static void *himax_diag_seq_start(struct seq_file *s, loff_t *pos) +{ + if (*pos >= 1) + return NULL; + + return (void *)((unsigned long) *pos + 1); +} + +static void *himax_diag_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + return NULL; +} + +static void himax_diag_seq_stop(struct seq_file *s, void *v) +{ +} + +static int himax_diag_seq_read(struct seq_file *s, void *v) +{ + struct himax_ts_data *ts = private_ts; + size_t ret = 0; + uint32_t loop_i; + uint16_t mutual_num, self_num, width; + int dsram_type = 0; + + dsram_type = ts->diag_cmd / 10; + +#ifdef HX_TP_PROC_2T2R + if (Is_2T2R && (ts->diag_cmd >= 4 && ts->diag_cmd <= 6)) { + mutual_num = x_channel_2 * y_channel_2; + self_num = x_channel_2 + y_channel_2; /* don't add KEY_COUNT */ + width = x_channel_2; + seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel_2, y_channel_2); + } else +#endif + { + mutual_num = x_channel * y_channel; + self_num = x_channel + y_channel; /* don't add KEY_COUNT */ + width = x_channel; + seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel, y_channel); + } + + /* start to show out the raw data in adb shell */ + if ((ts->diag_cmd >= 1 && ts->diag_cmd <= 3) || (ts->diag_cmd == 7)) { + himax_diag_arrange(s); + seq_puts(s, "\n"); +#ifdef HX_EN_SEL_BUTTON + seq_puts(s, "\n"); + + for (loop_i = 0; loop_i < ic_data->HX_BT_NUM; loop_i++) + seq_printf(s, "%6d", diag_self[ic_data->HX_RX_NUM + ic_data->HX_TX_NUM + loop_i]); + +#endif + seq_puts(s, "ChannelEnd"); + seq_puts(s, "\n"); + } + +#ifdef HX_TP_PROC_2T2R + + else if (Is_2T2R && ts->diag_cmd >= 4 && ts->diag_cmd <= 6) { + for (loop_i = 0; loop_i < mutual_num; loop_i++) { + seq_printf(s, "%4d", diag_mutual_2[loop_i]); + + if ((loop_i % width) == (width - 1)) + seq_printf(s, " %4d\n", diag_self[width + loop_i / width]); + } + + seq_puts(s, "\n"); + + for (loop_i = 0; loop_i < width; loop_i++) { + seq_printf(s, "%4d", diag_self[loop_i]); + + if (((loop_i) % width) == (width - 1)) + seq_puts(s, "\n"); + } + +#ifdef HX_EN_SEL_BUTTON + seq_puts(s, "\n"); + + for (loop_i = 0; loop_i < ic_data->HX_BT_NUM; loop_i++) + seq_printf(s, "%4d", diag_self[ic_data->HX_RX_NUM_2 + ic_data->HX_TX_NUM_2 + loop_i]); + +#endif + seq_puts(s, "ChannelEnd"); + seq_puts(s, "\n"); + } + +#endif + + else if (ts->diag_cmd == 8) { + for (loop_i = 0; loop_i < 128 ; loop_i++) { + if ((loop_i % 16) == 0) + seq_puts(s, "LineStart:"); + + seq_printf(s, "%4x", diag_coor[loop_i]); + + if ((loop_i % 16) == 15) + seq_puts(s, "\n"); + } + } else if (dsram_type > 0 && dsram_type <= 8) { + himax_diag_arrange(s); + seq_puts(s, "\n ChannelEnd"); + seq_puts(s, "\n"); + } + + if ((ts->diag_cmd >= 1 && ts->diag_cmd <= 7) || dsram_type > 0) { + /* print Mutual/Slef Maximum and Minimum */ + himax_get_mutual_edge(); + himax_get_self_edge(); + seq_printf(s, "Mutual Max:%3d, Min:%3d\n", g_max_mutual, g_min_mutual); + seq_printf(s, "Self Max:%3d, Min:%3d\n", g_max_self, g_min_self); + /* recovery status after print */ + g_max_mutual = 0; + g_min_mutual = 0xFFFF; + g_max_self = 0; + g_min_self = 0xFFFF; + } + + /* pring state info */ + print_state_info(s); + return ret; +} + +static const struct seq_operations himax_diag_seq_ops = { + .start = himax_diag_seq_start, + .next = himax_diag_seq_next, + .stop = himax_diag_seq_stop, + .show = himax_diag_seq_read, +}; + +static int himax_diag_proc_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &himax_diag_seq_ops); +}; + +bool DSRAM_Flag; + +/* DSRAM thread */ +void himax_ts_diag_func(void) +{ + struct himax_ts_data *ts = private_ts; + int i = 0, j = 0; + unsigned int index = 0; + int total_size = (y_channel * x_channel + y_channel + x_channel) * 2; + uint8_t *info_data; + int32_t *mutual_data; + int32_t *mutual_data_new; + int32_t *mutual_data_old; + int32_t *self_data; + int32_t *self_data_new; + int32_t *self_data_old; + int32_t new_data; + /* 1:common dsram,2:100 frame Max,3:N-(N-1)frame */ + int dsram_type = 0; + char temp_buf[20]; + char write_buf[total_size * 3]; + + mutual_data = NULL; + mutual_data_new = NULL; + mutual_data_old = NULL; + self_data = NULL; + self_data_new = NULL; + self_data_old = NULL; + + info_data = kcalloc(total_size, sizeof(uint8_t), GFP_KERNEL); + if (info_data == NULL) { + E("%s: allocate memory failed!\n", __func__); + return; + } + memset(write_buf, '\0', sizeof(write_buf)); + memset(info_data, 0, total_size * sizeof(uint8_t)); + dsram_type = ts->diag_cmd / 10; + I("%s:Entering ts->diag_cmd=%d\n!", __func__, ts->diag_cmd); + + if (dsram_type == 8) { + dsram_type = 1; + I("%s Sorting Mode run sram type1 !\n", __func__); + } + + g_core_fp.fp_burst_enable(1); + + if (dsram_type == 1 || dsram_type == 2 || dsram_type == 4) { + mutual_data = getMutualBuffer(); + self_data = getSelfBuffer(); + + } else if (dsram_type == 3) { + mutual_data = getMutualBuffer(); + mutual_data_new = getMutualNewBuffer(); + mutual_data_old = getMutualOldBuffer(); + self_data = getSelfBuffer(); + self_data_new = getSelfNewBuffer(); + self_data_old = getSelfOldBuffer(); + } + + g_core_fp.fp_get_DSRAM_data(info_data, DSRAM_Flag); + index = 0; + + for (i = 0; i < y_channel; i++) { /* mutual data */ + for (j = 0; j < x_channel; j++) { + new_data = (((int8_t)info_data[index + 1] << 8) | info_data[index]); + + if (dsram_type == 1 || dsram_type == 4) + mutual_data[i * x_channel + j] = new_data; + else if (dsram_type == 2) { + /* Keep max data */ + if (mutual_data[i * x_channel + j] < new_data) + mutual_data[i * x_channel + j] = new_data; + } else if (dsram_type == 3) { + /* Cal data for [N]-[N-1] frame */ + mutual_data_new[i * x_channel + j] = new_data; + mutual_data[i * x_channel + j] = mutual_data_new[i * x_channel + j] - mutual_data_old[i * x_channel + j]; + } + + index += 2; + } + } + + for (i = 0; i < x_channel + y_channel; i++) { /* self data */ + new_data = (info_data[index + 1] << 8 | info_data[index]); + if (dsram_type == 1 || dsram_type == 4) + self_data[i] = new_data; + else if (dsram_type == 2) { + /* Keep max data */ + if (self_data[i] < new_data) + self_data[i] = new_data; + } else if (dsram_type == 3) { + /* Cal data for [N]-[N-1] frame */ + self_data_new[i] = new_data; + self_data[i] = self_data_new[i] - self_data_old[i]; + } + index += 2; + } + + kfree(info_data); + + if (dsram_type == 3) { + memcpy(mutual_data_old, mutual_data_new, x_channel * y_channel * sizeof(int32_t)); /* copy N data to N-1 array */ + memcpy(self_data_old, self_data_new, (x_channel + y_channel) * sizeof(int32_t)); /* copy N data to N-1 array */ + } + + diag_max_cnt++; + + if (dsram_type >= 1 && dsram_type <= 3) + queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1 / 10 * HZ); + else if (dsram_type == 4) { + for (i = 0; i < x_channel * y_channel; i++) { + memset(temp_buf, '\0', sizeof(temp_buf)); + + if (i == (x_channel * y_channel - 1)) { + snprintf(temp_buf, sizeof(temp_buf), "%4d\t", mutual_data[i]); + snprintf(temp_buf, sizeof(temp_buf), "%4d\n", self_data[x_channel + y_channel - 1]); + I("%s :i = %d 3\n", __func__, i); + } else if (i % x_channel == (x_channel - 1)) { + snprintf(temp_buf, sizeof(temp_buf), "%4d\t", mutual_data[i]); + snprintf(temp_buf, sizeof(temp_buf), "%4d\n", self_data[x_channel + (i / x_channel) + 1]); + } else + snprintf(temp_buf, sizeof(temp_buf), "%4d\t", mutual_data[i]); + + strlcat(&write_buf[i*strlen(temp_buf)], temp_buf, strlen(temp_buf)); + } + + for (i = 0; i < x_channel; i++) { + memset(temp_buf, '\0', sizeof(temp_buf)); + if (i == x_channel - 1) + snprintf(temp_buf, sizeof(temp_buf), "%4d\n", self_data[i]); + else + snprintf(temp_buf, sizeof(temp_buf), "%4d\t", self_data[i]); + strlcat(&write_buf[(i+x_channel * y_channel)*strlen(temp_buf)], temp_buf, strlen(temp_buf)); + } + + /* save raw data in file */ + if (!IS_ERR(diag_sram_fn)) { + I("%s create file and ready to write\n", __func__); + diag_sram_fn->f_op->write(diag_sram_fn, write_buf, sizeof(write_buf), &diag_sram_fn->f_pos); + write_counter++; + + if (write_counter < write_max_count) + queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1 / 10 * HZ); + else { + filp_close(diag_sram_fn, NULL); + write_counter = 0; + } + } + } +} + +static ssize_t himax_diag_write(struct file *filp, const char __user *buff, size_t len, loff_t *data) +{ + struct himax_ts_data *ts = private_ts; + char messages[COMMON_BUF_SZ] = {0}; + struct filename *vts_name; + uint8_t command[2] = {0x00, 0x00}; + uint8_t receive[1]; + /* 0: common , other: dsram */ + int storage_type = 0; + /* 1:IIR,2:DC,3:Bank,4:IIR2,5:IIR2_N,6:FIR2,7:Baseline,8:dump coord */ + int rawdata_type = 0; + + memset(receive, 0x00, sizeof(receive)); + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(messages, buff, len)) + return -EFAULT; + + I("%s:g_switch_mode = %d\n", __func__, g_switch_mode); + + if (messages[1] == 0x0A) + ts->diag_cmd = messages[0] - '0'; + else + ts->diag_cmd = (messages[0] - '0') * 10 + (messages[1] - '0'); + + storage_type = g_core_fp.fp_determin_diag_storage(ts->diag_cmd); + rawdata_type = g_core_fp.fp_determin_diag_rawdata(ts->diag_cmd); + + if (ts->diag_cmd > 0 && rawdata_type == 0) { + I("[Himax]ts->diag_cmd=0x%x ,storage_type=%d, rawdata_type=%d! Maybe no support!\n" + , ts->diag_cmd, storage_type, rawdata_type); + ts->diag_cmd = 0x00; + } else + I("[Himax]ts->diag_cmd=0x%x ,storage_type=%d, rawdata_type=%d\n", ts->diag_cmd, storage_type, rawdata_type); + + memset(diag_mutual, 0x00, x_channel * y_channel * sizeof(int32_t)); + memset(diag_self, 0x00, sizeof(diag_self)); + if (storage_type == 0 && rawdata_type >= RAW_IIR && rawdata_type < RAW_DUMP_COORD) { + I("%s,common\n", __func__); + + if (DSRAM_Flag) { + /* 1. Clear DSRAM flag */ + DSRAM_Flag = false; + /* 2. Stop DSRAM thread */ + cancel_delayed_work(&private_ts->himax_diag_delay_wrok); + /* 3. Enable ISR */ + himax_int_enable(1); + /* (4) FW leave sram and return to event stack */ + g_core_fp.fp_return_event_stack(); + } + + if (g_switch_mode == 2) { + g_core_fp.fp_idle_mode(0); + g_switch_mode = g_core_fp.fp_switch_mode(0); + } + + if (ts->diag_cmd == 0x04) { +#if defined(HX_TP_PROC_2T2R) + command[0] = ts->diag_cmd; +#else + ts->diag_cmd = 0x00; + command[0] = 0x00; +#endif + } else + command[0] = ts->diag_cmd; + + g_core_fp.fp_diag_register_set(command[0], storage_type); + } else if (storage_type > 0 && storage_type < 8 + && rawdata_type >= RAW_IIR && rawdata_type < RAW_DUMP_COORD) { + I("%s,dsram\n", __func__); + diag_max_cnt = 0; + + /* 0. set diag flag */ + if (DSRAM_Flag) { + /* (1) Clear DSRAM flag */ + DSRAM_Flag = false; + /* (2) Stop DSRAM thread */ + cancel_delayed_work(&private_ts->himax_diag_delay_wrok); + /* (3) Enable ISR */ + himax_int_enable(1); + /* (4) FW leave sram and return to event stack */ + g_core_fp.fp_return_event_stack(); + } + + /* close sorting if turn on */ + if (g_switch_mode == 2) { + g_core_fp.fp_idle_mode(0); + g_switch_mode = g_core_fp.fp_switch_mode(0); + } + + command[0] = rawdata_type;/* ts->diag_cmd; */ + g_core_fp.fp_diag_register_set(command[0], storage_type); + /* 1. Disable ISR */ + himax_int_enable(0); + + /* Open file for save raw data log */ + if (storage_type == 4) { + switch (rawdata_type) { + case RAW_IIR: + vts_name = getname_kernel(IIR_DUMP_FILE); + diag_sram_fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0); + break; + + case RAW_DC: + vts_name = getname_kernel(DC_DUMP_FILE); + diag_sram_fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0); + break; + + case RAW_BANK: + vts_name = getname_kernel(BANK_DUMP_FILE); + diag_sram_fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0); + break; + + default: + I("%s raw data type is not true. raw data type is %d\n", __func__, rawdata_type); + } + } + + /* 2. Start DSRAM thread */ + queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 2 * HZ / 100); + I("%s: Start get raw data in DSRAM\n", __func__); + + if (storage_type == 4) + msleep(6000); + + /* 3. Set DSRAM flag */ + DSRAM_Flag = true; + + } else if (storage_type == 8) { + I("Soritng mode!\n"); + + if (DSRAM_Flag) { + /* 1. Clear DSRAM flag */ + DSRAM_Flag = false; + /* 2. Stop DSRAM thread */ + cancel_delayed_work(&private_ts->himax_diag_delay_wrok); + /* 3. Enable ISR */ + himax_int_enable(1); + /* (4) FW leave sram and return to event stack */ + g_core_fp.fp_return_event_stack(); + } + + g_core_fp.fp_idle_mode(1); + g_switch_mode = g_core_fp.fp_switch_mode(1); + + if (g_switch_mode == 2) + g_core_fp.fp_diag_register_set(command[0], storage_type); + + queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 2 * HZ / 100); + DSRAM_Flag = true; + } else { + /* set diag flag */ + if (DSRAM_Flag) { + I("return and cancel sram thread!\n"); + /* (1) Clear DSRAM flag */ + DSRAM_Flag = false; + /* (2) Stop DSRAM thread */ + cancel_delayed_work(&private_ts->himax_diag_delay_wrok); + /* (3) Enable ISR */ + himax_int_enable(1); + /* (4) FW leave sram and return to event stack */ + g_core_fp.fp_return_event_stack(); + } + + if (g_switch_mode == 2) { + g_core_fp.fp_idle_mode(0); + g_switch_mode = g_core_fp.fp_switch_mode(0); + } + + if (ts->diag_cmd != 0x00) { + E("[Himax]ts->diag_cmd error!diag_command=0x%x so reset\n", ts->diag_cmd); + command[0] = 0x00; + + if (ts->diag_cmd != 0x08) + ts->diag_cmd = 0x00; + + g_core_fp.fp_diag_register_set(command[0], storage_type); + } else { + command[0] = 0x00; + ts->diag_cmd = 0x00; + g_core_fp.fp_diag_register_set(command[0], storage_type); + I("return to normal ts->diag_cmd=0x%x\n", ts->diag_cmd); + } + } + + return len; +} + +static const struct file_operations himax_proc_diag_ops = { + .owner = THIS_MODULE, + .open = himax_diag_proc_open, + .read = seq_read, + .write = himax_diag_write, +}; + +static ssize_t himax_reset_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + char buf_tmp[DEBUG_BUF_SZ]; + + if (len >= DEBUG_BUF_SZ) { + I("%s: no command exceeds 12 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf_tmp, buff, len)) + return -EFAULT; + +#ifdef HX_RST_PIN_FUNC + + if (buf_tmp[0] == '1') + g_core_fp.fp_ic_reset(false, false); + else if (buf_tmp[0] == '2') + g_core_fp.fp_ic_reset(false, true); + else if (buf_tmp[0] == '3') + g_core_fp.fp_ic_reset(true, false); + else if (buf_tmp[0] == '4') + g_core_fp.fp_ic_reset(true, true); + + /* else if (buf_tmp[0] == '5') */ + /* ESD_HW_REST(); */ +#endif + return len; +} + +static const struct file_operations himax_proc_reset_ops = { + .owner = THIS_MODULE, + .write = himax_reset_write, +}; + +static ssize_t himax_debug_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + size_t ret = 0; + char *temp_buf; + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + + if (debug_level_cmd == 't') { + if (fw_update_complete) + ret += snprintf(temp_buf + ret, len - ret, "FW Update Complete "); + else + ret += snprintf(temp_buf + ret, len - ret, "FW Update Fail "); + + } else if (debug_level_cmd == 'h') { + if (handshaking_result == 0) + ret += snprintf(temp_buf + ret, len - ret, "Handshaking Result = %d (MCU Running)\n", handshaking_result); + else if (handshaking_result == 1) + ret += snprintf(temp_buf + ret, len - ret, "Handshaking Result = %d (MCU Stop)\n", handshaking_result); + else if (handshaking_result == 2) + ret += snprintf(temp_buf + ret, len - ret, "Handshaking Result = %d (I2C Error)\n", handshaking_result); + else + ret += snprintf(temp_buf + ret, len - ret, "Handshaking Result = error\n"); + + } else if (debug_level_cmd == 'v') { + ret += snprintf(temp_buf + ret, len - ret, "FW_VER = 0x%2.2X\n", ic_data->vendor_fw_ver); + + if (private_ts->chip_cell_type == CHIP_IS_ON_CELL) + ret += snprintf(temp_buf + ret, len - ret, "CONFIG_VER = 0x%2.2X\n", ic_data->vendor_config_ver); + else { + ret += snprintf(temp_buf + ret, len - ret, "TOUCH_VER = 0x%2.2X\n", ic_data->vendor_touch_cfg_ver); + ret += snprintf(temp_buf + ret, len - ret, "DISPLAY_VER = 0x%2.2X\n", ic_data->vendor_display_cfg_ver); + } + if (ic_data->vendor_cid_maj_ver < 0 && ic_data->vendor_cid_min_ver < 0) + ret += snprintf(temp_buf + ret, len - ret, "CID_VER = NULL\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "CID_VER = 0x%2.2X\n", (ic_data->vendor_cid_maj_ver << 8 | ic_data->vendor_cid_min_ver)); + + if (ic_data->vendor_panel_ver < 0) + ret += snprintf(temp_buf + ret, len - ret, "PANEL_VER = NULL\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "PANEL_VER = 0x%2.2X\n", ic_data->vendor_panel_ver); + + ret += snprintf(temp_buf + ret, len - ret, "\n"); + ret += snprintf(temp_buf + ret, len - ret, "Himax Touch Driver Version:\n"); + ret += snprintf(temp_buf + ret, len - ret, "%s\n", HIMAX_DRIVER_VER); + + } else if (debug_level_cmd == 'd') { + ret += snprintf(temp_buf + ret, len - ret, "Himax Touch IC Information :\n"); + ret += snprintf(temp_buf + ret, len - ret, "%s\n", private_ts->chip_name); + + switch (IC_CHECKSUM) { + case HX_TP_BIN_CHECKSUM_SW: + ret += snprintf(temp_buf + ret, len - ret, "IC Checksum : SW\n"); + break; + + case HX_TP_BIN_CHECKSUM_HW: + ret += snprintf(temp_buf + ret, len - ret, "IC Checksum : HW\n"); + break; + + case HX_TP_BIN_CHECKSUM_CRC: + ret += snprintf(temp_buf + ret, len - ret, "IC Checksum : CRC\n"); + break; + + default: + ret += snprintf(temp_buf + ret, len - ret, "IC Checksum error.\n"); + } + + if (ic_data->HX_INT_IS_EDGE) + ret += snprintf(temp_buf + ret, len - ret, "Driver register Interrupt : EDGE TIRGGER\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "Driver register Interrupt : LEVEL TRIGGER\n"); + + if (private_ts->protocol_type == PROTOCOL_TYPE_A) + ret += snprintf(temp_buf + ret, len - ret, "Protocol : TYPE_A\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "Protocol : TYPE_B\n"); + + ret += snprintf(temp_buf + ret, len - ret, "RX Num : %d\n", ic_data->HX_RX_NUM); + ret += snprintf(temp_buf + ret, len - ret, "TX Num : %d\n", ic_data->HX_TX_NUM); + ret += snprintf(temp_buf + ret, len - ret, "BT Num : %d\n", ic_data->HX_BT_NUM); + ret += snprintf(temp_buf + ret, len - ret, "X Resolution : %d\n", ic_data->HX_X_RES); + ret += snprintf(temp_buf + ret, len - ret, "Y Resolution : %d\n", ic_data->HX_Y_RES); + ret += snprintf(temp_buf + ret, len - ret, "Max Point : %d\n", ic_data->HX_MAX_PT); + ret += snprintf(temp_buf + ret, len - ret, "XY reverse : %d\n", ic_data->HX_XY_REVERSE); +#ifdef HX_TP_PROC_2T2R + + if (Is_2T2R) { + ret += snprintf(temp_buf + ret, len - ret, "2T2R panel\n"); + ret += snprintf(temp_buf + ret, len - ret, "RX Num_2 : %d\n", HX_RX_NUM_2); + ret += snprintf(temp_buf + ret, len - ret, "TX Num_2 : %d\n", HX_TX_NUM_2); + } + +#endif + } else if (debug_level_cmd == 'i') { + + if (g_core_fp.fp_read_i2c_status()) + ret += snprintf(temp_buf + ret, len - ret, "I2C communication is bad.\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "I2C communication is good.\n"); + } else if (debug_level_cmd == 'n') { + + if (g_core_fp.fp_read_ic_trigger_type() == 1) /* Edgd = 1, Level = 0 */ + ret += snprintf(temp_buf + ret, len - ret, "IC Interrupt type is edge trigger.\n"); + else if (g_core_fp.fp_read_ic_trigger_type() == 0) + ret += snprintf(temp_buf + ret, len - ret, "IC Interrupt type is level trigger.\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "Unknown IC trigger type.\n"); + + if (ic_data->HX_INT_IS_EDGE) + ret += snprintf(temp_buf + ret, len - ret, "Driver register Interrupt : EDGE TIRGGER\n"); + else + ret += snprintf(temp_buf + ret, len - ret, "Driver register Interrupt : LEVEL TRIGGER\n"); + } + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + +extern int g_ts_dbg; +static ssize_t himax_debug_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + int result = 0; + char fileName[128]; + char buf[COMMON_BUF_SZ] = {0}; + int fw_type = 0; + const struct firmware *fw = NULL; + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + if (buf[0] == 'h') { /* handshaking */ + debug_level_cmd = buf[0]; + himax_int_enable(0); + /* 0:Running, 1:Stop, 2:I2C Fail */ + handshaking_result = g_core_fp.fp_hand_shaking(); + himax_int_enable(1); + return len; + } else if (buf[0] == 'v') { /* firmware version */ + himax_int_enable(0); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#endif + debug_level_cmd = buf[0]; + g_core_fp.fp_read_FW_ver(); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(true, false); +#endif + himax_int_enable(1); + /* himax_check_chip_version(); */ + return len; + } else if (buf[0] == 'd') { /* ic information */ + debug_level_cmd = buf[0]; + return len; + } else if (buf[0] == 't') { + if (buf[1] == 's' && buf[2] == 'd' + && buf[3] == 'b' && buf[4] == 'g') { + if (buf[5] == '1') { + I("Open Ts Debug!\n"); + g_ts_dbg = 1; + } else if (buf[5] == '0') { + I("Close Ts Debug!\n"); + g_ts_dbg = 0; + } else + E("Parameter fault for ts debug\n"); + goto ENDFUCTION; + } + himax_int_enable(0); + debug_level_cmd = buf[0]; + fw_update_complete = false; + memset(fileName, 0, 128); + /* parse the file name */ + snprintf(fileName, len - 2, "%s", &buf[2]); + I("%s: upgrade from file(%s) start!\n", __func__, fileName); + result = request_firmware(&fw, fileName, private_ts->dev); + + if (result < 0) { + I("fail to request_firmware fwpath: %s (ret:%d)\n", fileName, result); + return result; + } + + I("%s: FW image: %02X, %02X, %02X, %02X\n", __func__, fw->data[0], fw->data[1], fw->data[2], fw->data[3]); + fw_type = (fw->size) / 1024; + /* start to upgrade */ + himax_int_enable(0); + I("Now FW size is : %dk\n", fw_type); + + switch (fw_type) { + case 32: + if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k((unsigned char *)fw->data, fw->size, false) == 0) { + E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + fw_update_complete = false; + } else { + I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + fw_update_complete = true; + } + + break; + + case 60: + if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k((unsigned char *)fw->data, fw->size, false) == 0) { + E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + fw_update_complete = false; + } else { + I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + fw_update_complete = true; + } + + break; + + case 64: + if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k((unsigned char *)fw->data, fw->size, false) == 0) { + E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + fw_update_complete = false; + } else { + I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + fw_update_complete = true; + } + + break; + + case 124: + if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k((unsigned char *)fw->data, fw->size, false) == 0) { + E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + fw_update_complete = false; + } else { + I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + fw_update_complete = true; + } + + break; + + case 128: + if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k((unsigned char *)fw->data, fw->size, false) == 0) { + E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + fw_update_complete = false; + } else { + I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + fw_update_complete = true; + } + + break; + + default: + E("%s: Flash command fail: %d\n", __func__, __LINE__); + fw_update_complete = false; + break; + } + release_firmware(fw); + goto firmware_upgrade_done; + } else if (buf[0] == 'i' && buf[1] == '2' && buf[2] == 'c') { + /* i2c commutation */ + debug_level_cmd = 'i'; + return len; + } else if (buf[0] == 'i' && buf[1] == 'n' && buf[2] == 't') { + /* INT trigger */ + debug_level_cmd = 'n'; + return len; + } + +#ifdef HX_ZERO_FLASH + + else if (buf[0] == 'z') { + + if (buf[1] == '0') + g_core_fp.fp_0f_operation_check(0); + else + g_core_fp.fp_0f_operation_check(1); + return len; + + } else if (buf[0] == 'p') { + + I("NOW debug echo r!\n"); + /* himax_program_sram(); */ + private_ts->himax_0f_update_wq = create_singlethread_workqueue("HMX_update_0f_reqest_write"); + + if (!private_ts->himax_0f_update_wq) + E(" allocate syn_update_wq failed\n"); + + INIT_DELAYED_WORK(&private_ts->work_0f_update, g_core_fp.fp_0f_operation); + queue_delayed_work(private_ts->himax_0f_update_wq, &private_ts->work_0f_update, msecs_to_jiffies(100)); + return len; + } else if (buf[0] == 'x') { + g_core_fp.fp_sys_reset(); + return len; + } +#endif + + else { /* others,do nothing */ + debug_level_cmd = 0; + return len; + } + +firmware_upgrade_done: + g_core_fp.fp_read_FW_ver(); + g_core_fp.fp_touch_information(); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(true, false); +#else + g_core_fp.fp_sense_on(0x00); +#endif + himax_int_enable(1); +/* todo himax_chip->tp_firmware_upgrade_proceed = 0; */ +/* todo himax_chip->suspend_state = 0; */ +/* todo enable_irq(himax_chip->irq); */ +ENDFUCTION: + return len; +} + +static const struct file_operations himax_proc_debug_ops = { + .owner = THIS_MODULE, + .read = himax_debug_read, + .write = himax_debug_write, +}; + +static ssize_t himax_proc_FW_debug_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + ssize_t ret = 0; + uint8_t loop_i = 0; + uint8_t tmp_data[64]; + char *temp_buf; + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + cmd_set[0] = 0x01; + + if (g_core_fp.fp_read_FW_status(cmd_set, tmp_data) == NO_ERR) { + ret += snprintf(temp_buf + ret, len - ret, "0x%02X%02X%02X%02X :\t", cmd_set[5], cmd_set[4], cmd_set[3], cmd_set[2]); + + for (loop_i = 0; loop_i < cmd_set[1]; loop_i++) + ret += snprintf(temp_buf + ret, len - ret, "%5d\t", tmp_data[loop_i]); + + ret += snprintf(temp_buf + ret, len - ret, "\n"); + } + + cmd_set[0] = 0x02; + + if (g_core_fp.fp_read_FW_status(cmd_set, tmp_data) == NO_ERR) { + for (loop_i = 0; loop_i < cmd_set[1]; loop_i = loop_i + 2) { + if ((loop_i % 16) == 0) + ret += snprintf(temp_buf + ret, len - ret, "0x%02X%02X%02X%02X :\t", + cmd_set[5], cmd_set[4], cmd_set[3] + (((cmd_set[2] + loop_i) >> 8) & 0xFF), (cmd_set[2] + loop_i) & 0xFF); + + ret += snprintf(temp_buf + ret, len - ret, "%5d\t", tmp_data[loop_i] + (tmp_data[loop_i + 1] << 8)); + + if ((loop_i % 16) == 14) + ret += snprintf(temp_buf + ret, len - ret, "\n"); + } + } + + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + +static const struct file_operations himax_proc_fw_debug_ops = { + .owner = THIS_MODULE, + .read = himax_proc_FW_debug_read, +}; + +static ssize_t himax_proc_DD_debug_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + ssize_t ret = 0; + uint8_t tmp_data[64]; + uint8_t loop_i = 0; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + if (mutual_set_flag == 1) { + if (g_core_fp.fp_read_DD_status(cmd_set, tmp_data) == NO_ERR) { + for (loop_i = 0; loop_i < cmd_set[0]; loop_i++) { + if ((loop_i % 8) == 0) + ret += snprintf(temp_buf + ret, len - ret, "0x%02X : ", loop_i); + + ret += snprintf(temp_buf + ret, len - ret, "0x%02X ", tmp_data[loop_i]); + + if ((loop_i % 8) == 7) + ret += snprintf(temp_buf + ret, len - ret, "\n"); + } + } + } + + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + +static ssize_t himax_proc_DD_debug_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + uint8_t i = 0; + uint8_t cnt = 2; + unsigned long result = 0; + char buf_tmp[PROC_DD_BUF_SZ]; + char buf_tmp2[4]; + + if (len >= PROC_DD_BUF_SZ) { + I("%s: no command exceeds 20 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf_tmp, buff, len)) + return -EFAULT; + + memset(buf_tmp2, 0x0, sizeof(buf_tmp2)); + + if (buf_tmp[2] == 'x' && buf_tmp[6] == 'x' && buf_tmp[10] == 'x') { + mutual_set_flag = 1; + + for (i = 3; i < 12; i = i + 4) { + memcpy(buf_tmp2, buf_tmp + i, 2); + + if (!kstrtoul(buf_tmp2, 16, &result)) + cmd_set[cnt] = (uint8_t)result; + else + I("String to oul is fail in cnt = %d, buf_tmp2 = %s", cnt, buf_tmp2); + + cnt--; + } + + I("cmd_set[2] = %02X, cmd_set[1] = %02X, cmd_set[0] = %02X\n", cmd_set[2], cmd_set[1], cmd_set[0]); + } else + mutual_set_flag = 0; + + return len; +} + +static const struct file_operations himax_proc_dd_debug_ops = { + .owner = THIS_MODULE, + .read = himax_proc_DD_debug_read, + .write = himax_proc_DD_debug_write, +}; + +uint8_t getFlashCommand(void) +{ + return flash_command; +} + +static uint8_t getFlashDumpProgress(void) +{ + return flash_progress; +} + +static uint8_t getFlashDumpComplete(void) +{ + return flash_dump_complete; +} + +static uint8_t getFlashDumpFail(void) +{ + return flash_dump_fail; +} + +uint8_t getSysOperation(void) +{ + return sys_operation; +} + +static uint8_t getFlashReadStep(void) +{ + return flash_read_step; +} + +bool getFlashDumpGoing(void) +{ + return flash_dump_going; +} + +void setFlashBuffer(void) +{ + flash_buffer = kcalloc(Flash_Size, sizeof(uint8_t), GFP_KERNEL); + if (!flash_buffer) + E("%s: allocate memory failed!\n", __func__); +} + +void setSysOperation(uint8_t operation) +{ + sys_operation = operation; +} + +void setFlashDumpProgress(uint8_t progress) +{ + flash_progress = progress; + /* I("setFlashDumpProgress : progress = %d ,flash_progress = %d\n",progress,flash_progress); */ +} + +void setFlashDumpComplete(uint8_t status) +{ + flash_dump_complete = status; +} + +void setFlashDumpFail(uint8_t fail) +{ + flash_dump_fail = fail; +} + +static void setFlashCommand(uint8_t command) +{ + flash_command = command; +} + +static void setFlashReadStep(uint8_t step) +{ + flash_read_step = step; +} + +void setFlashDumpGoing(bool going) +{ + flash_dump_going = going; + debug_data->flash_dump_going = going; +} + +static ssize_t himax_proc_flash_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + ssize_t ret = 0; + int loop_i; + uint8_t local_flash_read_step = 0; + uint8_t local_flash_complete = 0; + uint8_t local_flash_progress = 0; + uint8_t local_flash_command = 0; + uint8_t local_flash_fail = 0; + char *temp_buf; + + local_flash_complete = getFlashDumpComplete(); + local_flash_progress = getFlashDumpProgress(); + local_flash_command = getFlashCommand(); + local_flash_fail = getFlashDumpFail(); + I("flash_progress = %d\n", local_flash_progress); + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + + if (local_flash_fail) { + ret += snprintf(temp_buf + ret, len - ret, "FlashStart:Fail\n"); + ret += snprintf(temp_buf + ret, len - ret, "FlashEnd"); + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + return ret; + } + + if (!local_flash_complete) { + ret += snprintf(temp_buf + ret, len - ret, "FlashStart:Ongoing:0x%2.2x\n", flash_progress); + ret += snprintf(temp_buf + ret, len - ret, "FlashEnd"); + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + return ret; + } + + if (local_flash_command == 1 && local_flash_complete) { + ret += snprintf(temp_buf + ret, len - ret, "FlashStart:Complete\n"); + ret += snprintf(temp_buf + ret, len - ret, "FlashEnd"); + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + return ret; + } + + if (local_flash_command == 3 && local_flash_complete) { + ret += snprintf(temp_buf + ret, len - ret, "FlashStart:\n"); + + for (loop_i = 0; loop_i < 128; loop_i++) { + ret += snprintf(temp_buf + ret, len - ret, "x%2.2x", flash_buffer[loop_i]); + + if ((loop_i % 16) == 15) + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + } + + ret += snprintf(temp_buf + ret, len - ret, "FlashEnd"); + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + return ret; + } + + /* flash command == 0 , report the data */ + local_flash_read_step = getFlashReadStep(); + ret += snprintf(temp_buf + ret, len - ret, "FlashStart:%2.2x\n", local_flash_read_step); + + for (loop_i = 0; loop_i < 1024; loop_i++) { + ret += snprintf(temp_buf + ret, len - ret, "x%2.2X", flash_buffer[local_flash_read_step * 1024 + loop_i]); + + if ((loop_i % 16) == 15) + ret += snprintf(temp_buf + ret, len - ret, "\n"); + } + + ret += snprintf(temp_buf + ret, len - ret, "FlashEnd"); + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + +static ssize_t himax_proc_flash_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + char buf_tmp[6]; + unsigned long result = 0; + char buf[COMMON_BUF_SZ] = {0}; + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + memset(buf_tmp, 0x0, sizeof(buf_tmp)); + I("%s: buf = %s\n", __func__, buf); + + if (getSysOperation() == 1) { + E("%s: PROC is busy , return!\n", __func__); + return len; + } + + if (buf[0] == '0') { + setFlashCommand(0); + + if (buf[1] == ':' && buf[2] == 'x') { + memcpy(buf_tmp, buf + 3, 2); + I("%s: read_Step = %s\n", __func__, buf_tmp); + + if (!kstrtoul(buf_tmp, 16, &result)) { + I("%s: read_Step = %lu\n", __func__, result); + setFlashReadStep(result); + } + } + } else if (buf[0] == '1') { + /* 1_32,1_60,1_64,1_24,1_28 for flash size 32k,60k,64k,124k,128k */ + setSysOperation(1); + setFlashCommand(1); + setFlashDumpProgress(0); + setFlashDumpComplete(0); + setFlashDumpFail(0); + + if ((buf[1] == '_') && (buf[2] == '3') && (buf[3] == '2')) { + Flash_Size = FW_SIZE_32k; + } else if ((buf[1] == '_') && (buf[2] == '6')) { + if (buf[3] == '0') + Flash_Size = FW_SIZE_60k; + else if (buf[3] == '4') + Flash_Size = FW_SIZE_64k; + } else if ((buf[1] == '_') && (buf[2] == '2')) { + if (buf[3] == '4') + Flash_Size = FW_SIZE_124k; + else if (buf[3] == '8') + Flash_Size = FW_SIZE_128k; + } + queue_work(private_ts->flash_wq, &private_ts->flash_work); + } else if (buf[0] == '2') { + /* 2_32,2_60,2_64,2_24,2_28 for flash size 32k,60k,64k,124k,128k */ + setSysOperation(1); + setFlashCommand(2); + setFlashDumpProgress(0); + setFlashDumpComplete(0); + setFlashDumpFail(0); + + if ((buf[1] == '_') && (buf[2] == '3') && (buf[3] == '2')) + Flash_Size = FW_SIZE_32k; + else if ((buf[1] == '_') && (buf[2] == '6')) { + if (buf[3] == '0') + Flash_Size = FW_SIZE_60k; + else if (buf[3] == '4') + Flash_Size = FW_SIZE_64k; + } else if ((buf[1] == '_') && (buf[2] == '2')) { + if (buf[3] == '4') + Flash_Size = FW_SIZE_124k; + else if (buf[3] == '8') + Flash_Size = FW_SIZE_128k; + } + queue_work(private_ts->flash_wq, &private_ts->flash_work); + } + + return len; +} + +static const struct file_operations himax_proc_flash_ops = { + .owner = THIS_MODULE, + .read = himax_proc_flash_read, + .write = himax_proc_flash_write, +}; + +void himax_ts_flash_func(void) +{ + uint8_t local_flash_command = 0; + + himax_int_enable(0); + setFlashDumpGoing(true); + /* sector = getFlashDumpSector(); */ + /* page = getFlashDumpPage(); */ + local_flash_command = getFlashCommand(); + msleep(100); + I("%s: local_flash_command = %d enter.\n", __func__, local_flash_command); + + if ((local_flash_command == 1 || local_flash_command == 2) || (local_flash_command == 0x0F)) + g_core_fp.fp_flash_dump_func(local_flash_command, Flash_Size, flash_buffer); + + I("Complete~~~~~~~~~~~~~~~~~~~~~~~\n"); + + if (local_flash_command == 2) { + struct file *fn; + struct filename *vts_name; + + vts_name = getname_kernel(FLASH_DUMP_FILE); + fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0); + + if (!IS_ERR(fn)) { + I("%s create file and ready to write\n", __func__); + fn->f_op->write(fn, flash_buffer, Flash_Size * sizeof(uint8_t), &fn->f_pos); + filp_close(fn, NULL); + } + } + + himax_int_enable(1); + setFlashDumpGoing(false); + setFlashDumpComplete(1); + setSysOperation(0); + return; + /* Flash_Dump_i2c_transfer_error: */ + /* himax_int_enable(1); */ + /* setFlashDumpGoing(false); */ + /* setFlashDumpComplete(0); */ + /* setFlashDumpFail(1); */ + /* setSysOperation(0); */ + /* return; */ +} + + + +static ssize_t himax_sense_on_off_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + char buf[COMMON_BUF_SZ] = {0}; + + if (len >= COMMON_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + if (buf[0] == '0') { + g_core_fp.fp_sense_off(); + I("Sense off\n"); + } else if (buf[0] == '1') { + if (buf[1] == 's') { + g_core_fp.fp_sense_on(0x00); + I("Sense on re-map on, run sram\n"); + } else { + g_core_fp.fp_sense_on(0x01); + I("Sense on re-map off, run flash\n"); + } + } else + I("Do nothing\n"); + + return len; +} + +static const struct file_operations himax_proc_sense_on_off_ops = { + .owner = THIS_MODULE, + .write = himax_sense_on_off_write, +}; + +#ifdef HX_ESD_RECOVERY +static ssize_t himax_esd_cnt_read(struct file *file, char __user *buf, size_t len, loff_t *pos) +{ + size_t ret = 0; + char *temp_buf; + + I("%s: enter, %d\n", __func__, __LINE__); + + if (HX_PROC_SEND_FLAG) { + HX_PROC_SEND_FLAG = 0; + return 0; + } + + temp_buf = kzalloc(len, GFP_KERNEL); + if (!temp_buf) { + E("%s: allocate memory failed!\n", __func__); + return 0; + } + ret += snprintf(temp_buf + ret, len - ret, "EB_cnt = %d, EC_cnt = %d, ED_cnt = %d\n", hx_EB_event_flag, hx_EC_event_flag, hx_ED_event_flag); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + + return ret; +} + +static ssize_t himax_esd_cnt_write(struct file *file, const char __user *buff, size_t len, loff_t *pos) +{ + int i = 0; + char buf[DEBUG_BUF_SZ] = {0}; + + if (len >= DEBUG_BUF_SZ) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + I("Clear ESD Flag\n"); + + if (buf[i] == '0') { + hx_EB_event_flag = 0; + hx_EC_event_flag = 0; + hx_ED_event_flag = 0; + } + + return len; +} + +static const struct file_operations himax_proc_esd_cnt_ops = { + .owner = THIS_MODULE, + .read = himax_esd_cnt_read, + .write = himax_esd_cnt_write, +}; +#endif + +static void himax_himax_data_init(void) +{ + debug_data->fp_ts_dbg_func = himax_ts_dbg_func; + debug_data->fp_set_diag_cmd = himax_set_diag_cmd; + debug_data->flash_dump_going = false; +} + +static void himax_ts_flash_work_func(struct work_struct *work) +{ + himax_ts_flash_func(); +} + +static void himax_ts_diag_work_func(struct work_struct *work) +{ + himax_ts_diag_func(); +} + +int himax_touch_proc_init(void) +{ + himax_proc_debug_level_file = proc_create(HIMAX_PROC_DEBUG_LEVEL_FILE, 0644, + himax_touch_proc_dir, &himax_proc_debug_level_ops); + if (himax_proc_debug_level_file == NULL) { + E(" %s: proc debug_level file create failed!\n", __func__); + goto fail_1; + } + + himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, 0444, + himax_touch_proc_dir, &himax_proc_vendor_ops); + if (himax_proc_vendor_file == NULL) { + E(" %s: proc vendor file create failed!\n", __func__); + goto fail_2; + } + + himax_proc_attn_file = proc_create(HIMAX_PROC_ATTN_FILE, 0444, + himax_touch_proc_dir, &himax_proc_attn_ops); + if (himax_proc_attn_file == NULL) { + E(" %s: proc attn file create failed!\n", __func__); + goto fail_3; + } + + himax_proc_int_en_file = proc_create(HIMAX_PROC_INT_EN_FILE, 0644, + himax_touch_proc_dir, &himax_proc_int_en_ops); + if (himax_proc_int_en_file == NULL) { + E(" %s: proc int en file create failed!\n", __func__); + goto fail_4; + } + + himax_proc_layout_file = proc_create(HIMAX_PROC_LAYOUT_FILE, 0644, + himax_touch_proc_dir, &himax_proc_layout_ops); + if (himax_proc_layout_file == NULL) { + E(" %s: proc layout file create failed!\n", __func__); + goto fail_5; + } + + himax_proc_reset_file = proc_create(HIMAX_PROC_RESET_FILE, 0200, + himax_touch_proc_dir, &himax_proc_reset_ops); + if (himax_proc_reset_file == NULL) { + E(" %s: proc reset file create failed!\n", __func__); + goto fail_6; + } + + himax_proc_diag_file = proc_create(HIMAX_PROC_DIAG_FILE, 0644, + himax_touch_proc_dir, &himax_proc_diag_ops); + if (himax_proc_diag_file == NULL) { + E(" %s: proc diag file create failed!\n", __func__); + goto fail_7; + } + + himax_proc_diag_arrange_file = proc_create(HIMAX_PROC_DIAG_ARR_FILE, 0644, + himax_touch_proc_dir, &himax_proc_diag_arrange_ops); + if (himax_proc_diag_arrange_file == NULL) { + E(" %s: proc diag file create failed!\n", __func__); + goto fail_7_1; + } + + himax_proc_register_file = proc_create(HIMAX_PROC_REGISTER_FILE, 0644, + himax_touch_proc_dir, &himax_proc_register_ops); + if (himax_proc_register_file == NULL) { + E(" %s: proc register file create failed!\n", __func__); + goto fail_8; + } + + himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE, 0644, + himax_touch_proc_dir, &himax_proc_debug_ops); + if (himax_proc_debug_file == NULL) { + E(" %s: proc debug file create failed!\n", __func__); + goto fail_9; + } + + himax_proc_fw_debug_file = proc_create(HIMAX_PROC_FW_DEBUG_FILE, 0644, + himax_touch_proc_dir, &himax_proc_fw_debug_ops); + if (himax_proc_fw_debug_file == NULL) { + E(" %s: proc fw debug file create failed!\n", __func__); + goto fail_9_1; + } + + himax_proc_dd_debug_file = proc_create(HIMAX_PROC_DD_DEBUG_FILE, 0644, + himax_touch_proc_dir, &himax_proc_dd_debug_ops); + if (himax_proc_dd_debug_file == NULL) { + E(" %s: proc DD debug file create failed!\n", __func__); + goto fail_9_2; + } + + himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE, 0644, + himax_touch_proc_dir, &himax_proc_flash_ops); + if (himax_proc_flash_dump_file == NULL) { + E(" %s: proc flash dump file create failed!\n", __func__); + goto fail_10; + } + + himax_proc_SENSE_ON_OFF_file = proc_create(HIMAX_PROC_SENSE_ON_OFF_FILE, 0666, + himax_touch_proc_dir, &himax_proc_sense_on_off_ops); + if (himax_proc_SENSE_ON_OFF_file == NULL) { + E(" %s: proc SENSE_ON_OFF file create failed!\n", __func__); + goto fail_16; + } + +#ifdef HX_ESD_RECOVERY + himax_proc_ESD_cnt_file = proc_create(HIMAX_PROC_ESD_CNT_FILE, 0666, + himax_touch_proc_dir, &himax_proc_esd_cnt_ops); + + if (himax_proc_ESD_cnt_file == NULL) { + E(" %s: proc ESD cnt file create failed!\n", __func__); + goto fail_17; + } + +#endif + himax_proc_CRC_test_file = proc_create(HIMAX_PROC_CRC_TEST_FILE, 0666, + himax_touch_proc_dir, &himax_proc_CRC_test_ops); + + if (himax_proc_CRC_test_file == NULL) { + E(" %s: proc CRC test file create failed!\n", __func__); + goto fail_18; + } + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) + himax_proc_ito_test_file = proc_create(HIMAX_PROC_ITO_TEST_FILE, 0777, + himax_touch_proc_dir, &himax_proc_ito_test_ops); + + if (himax_proc_ito_test_file == NULL) { + E(" %s: proc ITO test file create failed!\n", __func__); + goto fail_19; + } + +#endif + return 0; +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) + remove_proc_entry(HIMAX_PROC_ITO_TEST_FILE, himax_touch_proc_dir); +fail_19: +#endif +fail_18: +#ifdef HX_ESD_RECOVERY + remove_proc_entry(HIMAX_PROC_ESD_CNT_FILE, himax_touch_proc_dir); +fail_17: +#endif + remove_proc_entry(HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir); +fail_16: + remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir); +fail_10: + remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir); +fail_9: + remove_proc_entry(HIMAX_PROC_FW_DEBUG_FILE, himax_touch_proc_dir); +fail_9_1: + remove_proc_entry(HIMAX_PROC_DD_DEBUG_FILE, himax_touch_proc_dir); +fail_9_2: + remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir); +fail_8: + remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir); +fail_7: + remove_proc_entry(HIMAX_PROC_DIAG_ARR_FILE, himax_touch_proc_dir); +fail_7_1: + remove_proc_entry(HIMAX_PROC_RESET_FILE, himax_touch_proc_dir); +fail_6: + remove_proc_entry(HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir); +fail_5: + remove_proc_entry(HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir); +fail_4: + remove_proc_entry(HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir); +fail_3: + remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir); +fail_2: + remove_proc_entry(HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir); +fail_1: + return -ENOMEM; +} + +void himax_touch_proc_deinit(void) +{ +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) + remove_proc_entry(HIMAX_PROC_ITO_TEST_FILE, himax_touch_proc_dir); +#endif + remove_proc_entry(HIMAX_PROC_CRC_TEST_FILE, himax_touch_proc_dir); +#ifdef HX_ESD_RECOVERY + remove_proc_entry(HIMAX_PROC_ESD_CNT_FILE, himax_touch_proc_dir); +#endif + remove_proc_entry(HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_FW_DEBUG_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_DD_DEBUG_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_RESET_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir); +} + +int himax_debug_init(void) +{ + struct himax_ts_data *ts = private_ts; + int err = 0; + + I("%s:Enter\n", __func__); + + if (ts == NULL) { + E("%s: ts struct is NULL\n", __func__); + return -EPROBE_DEFER; + } + + debug_data = kzalloc(sizeof(*debug_data), GFP_KERNEL); + if (debug_data == NULL) { + E("%s: allocate memory failed!\n", __func__); + err = -ENOMEM; + goto err_alloc_debug_data_fail; + } + + himax_himax_data_init(); + + ts->flash_wq = create_singlethread_workqueue("himax_flash_wq"); + + if (!ts->flash_wq) { + E("%s: create flash workqueue failed\n", __func__); + err = -ENOMEM; + goto err_create_flash_dump_wq_failed; + } + + INIT_WORK(&ts->flash_work, himax_ts_flash_work_func); + setSysOperation(0); + setFlashBuffer(); + + ts->himax_diag_wq = create_singlethread_workqueue("himax_diag"); + + if (!ts->himax_diag_wq) { + E("%s: create diag workqueue failed\n", __func__); + err = -ENOMEM; + goto err_create_diag_wq_failed; + } + + INIT_DELAYED_WORK(&ts->himax_diag_delay_wrok, himax_ts_diag_work_func); + + setXChannel(ic_data->HX_RX_NUM); /* X channel */ + setYChannel(ic_data->HX_TX_NUM); /* Y channel */ + setMutualBuffer(); + setMutualNewBuffer(); + setMutualOldBuffer(); + + if (getMutualBuffer() == NULL) { + E("%s: mutual buffer allocate fail failed\n", __func__); + err = MEM_ALLOC_FAIL; + goto err_get_MutualBuffer_failed; + } +#ifdef HX_TP_PROC_2T2R + + if (Is_2T2R) { + setXChannel_2(ic_data->HX_RX_NUM_2); /* X channel */ + setYChannel_2(ic_data->HX_TX_NUM_2); /* Y channel */ + setMutualBuffer_2(); + + if (getMutualBuffer_2() == NULL) { + E("%s: mutual buffer 2 allocate fail failed\n", __func__); + err = MEM_ALLOC_FAIL; + goto err_get_MutualBuffer2_failed; + } + } +#endif + + himax_touch_proc_init(); + + return 0; + +err_get_MutualBuffer2_failed: +err_get_MutualBuffer_failed: + cancel_delayed_work_sync(&ts->himax_diag_delay_wrok); + destroy_workqueue(ts->himax_diag_wq); + +err_create_diag_wq_failed: + destroy_workqueue(ts->flash_wq); + +err_create_flash_dump_wq_failed: + kfree(debug_data); + +err_alloc_debug_data_fail: + + return err; +} + +int himax_debug_remove(void) +{ + struct himax_ts_data *ts = private_ts; + + himax_touch_proc_deinit(); + + cancel_delayed_work_sync(&ts->himax_diag_delay_wrok); + destroy_workqueue(ts->himax_diag_wq); + destroy_workqueue(ts->flash_wq); + + kfree(debug_data); + + return 0; +} + diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.h b/drivers/input/touchscreen/hxchipset/himax_debug.h new file mode 100644 index 000000000000..f1df7cbbb16f --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_debug.h @@ -0,0 +1,60 @@ +/* + * Himax Android Driver Sample Code for debug nodes + * + * Copyright (C) 2018 Himax Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef H_HIMAX_DEBUG +#define H_HIMAX_DEBUG + +#include "himax_platform.h" +#include "himax_common.h" + +#define HIMAX_PROC_DEBUG_LEVEL_FILE "debug_level" +#define HIMAX_PROC_VENDOR_FILE "vendor" +#define HIMAX_PROC_ATTN_FILE "attn" +#define HIMAX_PROC_INT_EN_FILE "int_en" +#define HIMAX_PROC_LAYOUT_FILE "layout" +#define HIMAX_PROC_CRC_TEST_FILE "CRC_test" + +#ifdef HX_ESD_RECOVERY +extern u8 HX_ESD_RESET_ACTIVATE; +extern int hx_EB_event_flag; +extern int hx_EC_event_flag; +extern int hx_ED_event_flag; +#endif + +#ifdef HX_TP_PROC_2T2R + extern bool Is_2T2R; +#endif + +extern bool DSRAM_Flag; + +int himax_touch_proc_init(void); +void himax_touch_proc_deinit(void); +extern int himax_int_en_set(void); + +extern int himax_debug_init(void); +extern int himax_debug_remove(void); + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) +#define HIMAX_PROC_ITO_TEST_FILE "ITO_test" +static struct proc_dir_entry *himax_proc_ito_test_file; + +extern void ito_set_step_status(uint8_t status); +extern uint8_t ito_get_step_status(void); +extern void ito_set_result_status(uint8_t status); +extern uint8_t ito_get_result_status(void); +#endif + +#endif diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c b/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c new file mode 100644 index 000000000000..307ea4842ade --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c @@ -0,0 +1,298 @@ +/* + * Himax Android Driver Sample Code for HX83112 chipset + * + * Copyright (C) 2018 Himax Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "himax_ic_HX83112.h" + + +extern unsigned char IC_TYPE; + + +static bool hx83112_sense_off(void) +{ + uint8_t cnt = 0; + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + + do { + /* + *=========================================== + * I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 + *=========================================== + */ + tmp_data[0] = pic_op->data_i2c_psw_lb[0]; + + if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /* + *=========================================== + * I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 + *=========================================== + */ + tmp_data[0] = pic_op->data_i2c_psw_ub[0]; + + if (himax_bus_write(pic_op->adr_i2c_psw_ub[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /* + *=========================================== + * I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x00 + *=========================================== + */ + tmp_data[0] = 0x00; + + if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /* + *========================================== + * I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 + *=========================================== + */ + tmp_data[0] = pic_op->data_i2c_psw_lb[0]; + + if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /* + *========================================== + * I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 + *========================================== + */ + tmp_data[0] = pic_op->data_i2c_psw_ub[0]; + + if (himax_bus_write(pic_op->adr_i2c_psw_ub[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /* + *===================== + * Check enter_save_mode + *===================== + */ + g_core_fp.fp_register_read(pic_op->addr_cs_central_state, FOUR_BYTE_ADDR_SZ, tmp_data, 0); + I("%s: Check enter_save_mode data[0]=%X\n", __func__, tmp_data[0]); + + if (tmp_data[0] == 0x0C) { + /* + *=================================== + * Reset TCON + *==================================== + */ + g_core_fp.fp_flash_write_burst(pic_op->addr_tcon_on_rst, pic_op->data_rst); + msleep(20); + tmp_data[3] = pic_op->data_rst[3]; + tmp_data[2] = pic_op->data_rst[2]; + tmp_data[1] = pic_op->data_rst[1]; + tmp_data[0] = pic_op->data_rst[0] | 0x01; + g_core_fp.fp_flash_write_burst(pic_op->addr_tcon_on_rst, tmp_data); + /* + *=================================== + * Reset ADC + *==================================== + */ + g_core_fp.fp_flash_write_burst(pic_op->addr_adc_on_rst, pic_op->data_rst); + msleep(20); + tmp_data[3] = pic_op->data_rst[3]; + tmp_data[2] = pic_op->data_rst[2]; + tmp_data[1] = pic_op->data_rst[1]; + tmp_data[0] = pic_op->data_rst[0] | 0x01; + g_core_fp.fp_flash_write_burst(pic_op->addr_adc_on_rst, tmp_data); + return true; + } + + msleep(20); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#endif + + } while (cnt++ < 15); + + return false; +} + +static void hx83112_func_re_init(void) +{ + g_core_fp.fp_sense_off = hx83112_sense_off; +} + +static void hx83112_reg_re_init(void) +{ +} + +static bool hx83112_chip_detect(void) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + bool ret_data = false; + int i = 0; + + himax_mcu_in_cmd_struct_init(); + himax_mcu_in_cmd_init(); + + hx83112_reg_re_init(); + hx83112_func_re_init(); + + g_core_fp.fp_sense_off(); + + for (i = 0; i < 5; i++) { + g_core_fp.fp_register_read(pfw_op->addr_icid_addr, FOUR_BYTE_DATA_SZ, tmp_data, false); + I("%s:Read driver IC ID = %X, %X, %X\n", __func__, tmp_data[3], tmp_data[2], tmp_data[1]); + + if ((tmp_data[3] == 0x83) && (tmp_data[2] == 0x11) && ((tmp_data[1] == 0x2a) || (tmp_data[1] == 0x2b))) { + if (tmp_data[1] == 0x2a) + strlcpy(private_ts->chip_name, HX_83112A_SERIES_PWON, 30); + else if (tmp_data[1] == 0x2b) + strlcpy(private_ts->chip_name, HX_83112B_SERIES_PWON, 30); + + I("%s:IC name = %s\n", __func__, private_ts->chip_name); + + I("Himax IC package %x%x%x in\n", tmp_data[3], tmp_data[2], tmp_data[1]); + ret_data = true; + break; + } + + ret_data = false; + E("%s:Read driver ID register Fail:\n", __func__); + + } + + return ret_data; +} + +static void hx83112_chip_init(void) +{ + + private_ts->chip_cell_type = CHIP_IS_IN_CELL; + I("%s:IC cell type = %d\n", __func__, private_ts->chip_cell_type); + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + /* Himax: Set FW and CFG Flash Address */ + FW_VER_MAJ_FLASH_ADDR = 49157; /* 0x00C005 */ + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 49158; /* 0x00C006 */ + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 49408; /* 0x00C100 */ + CFG_VER_MAJ_FLASH_LENG = 1; + CFG_VER_MIN_FLASH_ADDR = 49409; /* 0x00C101 */ + CFG_VER_MIN_FLASH_LENG = 1; + CID_VER_MAJ_FLASH_ADDR = 49154; /* 0x00C002 */ + CID_VER_MAJ_FLASH_LENG = 1; + CID_VER_MIN_FLASH_ADDR = 49155; /* 0x00C003 */ + CID_VER_MIN_FLASH_LENG = 1; + +#ifdef HX_AUTO_UPDATE_FW + g_i_FW_VER = (i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR] << 8) | i_CTPM_FW[FW_VER_MIN_FLASH_ADDR]; + g_i_CFG_VER = (i_CTPM_FW[CFG_VER_MAJ_FLASH_ADDR] << 8) | i_CTPM_FW[CFG_VER_MIN_FLASH_ADDR]; + g_i_CID_MAJ = i_CTPM_FW[CID_VER_MAJ_FLASH_ADDR]; + g_i_CID_MIN = i_CTPM_FW[CID_VER_MIN_FLASH_ADDR]; +#endif +} + +#ifdef CONFIG_CHIP_DTCFG +static int himax_hx83112_probe(struct platform_device *pdev) +{ + I("%s:Enter\n", __func__); + g_core_fp.fp_chip_detect = hx83112_chip_detect; + g_core_fp.fp_chip_init = hx83112_chip_init; + return 0; +} + +static int himax_hx83112_remove(struct platform_device *pdev) +{ + g_core_fp.fp_chip_detect = NULL; + g_core_fp.fp_chip_init = NULL; + return 0; +} + + +#ifdef CONFIG_OF +static const struct of_device_id himax_hx83112_mttable[] = { + { .compatible = "himax,hx83112"}, + { }, +}; +#else +#define himax_hx83112_mttabl NULL +#endif + +static struct platform_driver himax_hx83112_driver = { + .probe = himax_hx83112_probe, + .remove = himax_hx83112_remove, + .driver = { + .name = "HIMAX_HX83112", + .owner = THIS_MODULE, + .of_match_table = himax_hx83112_mttable, + }, +}; + +static int __init himax_hx83112_init(void) +{ + I("%s\n", __func__); + platform_driver_register(&himax_hx83112_driver); + return 0; +} + +static void __exit himax_hx83112_exit(void) +{ + platform_driver_unregister(&himax_hx83112_driver); +} + +#else +static int himax_hx83112_probe(void) +{ + I("%s:Enter\n", __func__); + + g_core_fp.fp_chip_detect = hx83112_chip_detect; + g_core_fp.fp_chip_init = hx83112_chip_init; + + return 0; +} + +static int himax_hx83112_remove(void) +{ + g_core_fp.fp_chip_detect = NULL; + g_core_fp.fp_chip_init = NULL; + return 0; +} + +static int __init himax_hx83112_init(void) +{ + int ret = 0; + + I("%s\n", __func__); + ret = himax_hx83112_probe(); + return 0; +} + +static void __exit himax_hx83112_exit(void) +{ + himax_hx83112_remove(); +} +#endif + +module_init(himax_hx83112_init); +module_exit(himax_hx83112_exit); + +MODULE_DESCRIPTION("HIMAX HX83112 touch driver"); +MODULE_LICENSE("GPL v2"); + + diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.h b/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.h new file mode 100644 index 000000000000..3576ec7c6cb9 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.h @@ -0,0 +1,22 @@ +/* + * Himax Android Driver Sample Code for HX83112 chipset + * + * Copyright (C) 2018 Himax Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include + +#include "himax_platform.h" +#include "himax_common.h" +#include "himax_ic_core.h" + diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_core.h b/drivers/input/touchscreen/hxchipset/himax_ic_core.h new file mode 100644 index 000000000000..1986cbbe42c1 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_ic_core.h @@ -0,0 +1,716 @@ +/* + * Himax Android Driver Sample Code for IC Core + * + * Copyright (C) 2018 Himax Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include + +#include "himax_platform.h" +#include "himax_common.h" + +#define EIGHT_BYTE_DATA_SZ 8 +#define FOUR_BYTE_DATA_SZ 4 +#define FOUR_BYTE_ADDR_SZ 4 +#define FLASH_RW_MAX_LEN 256 +#define FLASH_WRITE_BURST_SZ 8 +#define PROGRAM_SZ 48 +#define MAX_I2C_TRANS_SZ 128 +#define HIMAX_REG_RETRY_TIMES 5 +#define FW_BIN_16K_SZ 0x4000 +#define HIMAX_TOUCH_DATA_SIZE 128 +#define MASK_BIT_0 0x01 +#define MASK_BIT_1 0x02 +#define MASK_BIT_2 0x04 + +#define FW_SECTOR_PER_BLOCK 8 +#define FW_PAGE_PER_SECTOR 64 +#define FW_PAGE_SEZE 128 +#define HX256B 0x100 +#define HX4K 0x1000 +#define HX_32K_SZ 0x8000 +#define HX_48K_SZ 0xC000 +#define HX64K 0x10000 +#define HX124K 0x1f000 +#define HX4000K 0x1000000 + +#define HX_NORMAL_MODE 1 +#define HX_SORTING_MODE 2 +#define HX_CHANGE_MODE_FAIL (-1) +#define HX_RW_REG_FAIL (-1) + +#define CORE_INIT +#define CORE_IC +#define CORE_FW +#define CORE_FLASH +#define CORE_SRAM +#define CORE_DRIVER + +#define HX_0F_DEBUG + +#ifdef HX_ESD_RECOVERY + extern u8 HX_ESD_RESET_ACTIVATE; +#endif + +#ifdef CORE_INIT + void himax_mcu_in_cmd_struct_init(void); + /*void himax_mcu_in_cmd_struct_free(void);*/ + void himax_in_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len); + void himax_mcu_in_cmd_init(void); + + void himax_mcu_on_cmd_struct_init(void); + /*static void himax_mcu_on_cmd_struct_free(void);*/ + void himax_on_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len); + void himax_mcu_on_cmd_init(void); +#endif + +#if defined(CORE_IC) + #define ic_adr_ahb_addr_byte_0 0x00 + #define ic_adr_ahb_rdata_byte_0 0x08 + #define ic_adr_ahb_access_direction 0x0c + #define ic_adr_conti 0x13 + #define ic_adr_incr4 0x0D + #define ic_adr_i2c_psw_lb 0x31 + #define ic_adr_i2c_psw_ub 0x32 + #define ic_cmd_ahb_access_direction_read 0x00 + #define ic_cmd_conti 0x31 + #define ic_cmd_incr4 0x10 + #define ic_cmd_i2c_psw_lb 0x27 + #define ic_cmd_i2c_psw_ub 0x95 + #define ic_adr_tcon_on_rst 0x80020020 + #define ic_addr_adc_on_rst 0x80020094 + #define ic_adr_psl 0x900000A0 + #define ic_adr_cs_central_state 0x900000A8 + #define ic_cmd_rst 0x00000000 + + #define on_ic_adr_ahb_addr_byte_0 0x00 + #define on_ic_adr_ahb_rdata_byte_0 0x08 + #define on_ic_adr_ahb_access_direction 0x0c + #define on_ic_adr_conti 0x13 + #define on_ic_adr_incr4 0x0D + #define on_ic_cmd_ahb_access_direction_read 0x00 + #define on_ic_cmd_conti 0x31 + #define on_ic_cmd_incr4 0x10 + #define on_ic_adr_mcu_ctrl 0x82 + #define on_ic_cmd_mcu_on 0x25 + #define on_ic_cmd_mcu_off 0xDA + #define on_ic_adr_sleep_ctrl 0x99 + #define on_ic_cmd_sleep_in 0x80 + #define on_ic_adr_tcon_ctrl 0x80020000 + #define on_ic_cmd_tcon_on 0x00000000 + #define on_ic_adr_wdg_ctrl 0x9000800C + #define on_ic_cmd_wdg_psw 0x0000AC53 + #define on_ic_adr_wdg_cnt_ctrl 0x90008010 + #define on_ic_cmd_wdg_cnt_clr 0x000035CA +#endif + +#if defined(CORE_FW) + #define fw_addr_system_reset 0x90000018 + #define fw_addr_safe_mode_release_pw 0x90000098 + #define fw_addr_ctrl_fw 0x9000005c + #define fw_addr_flag_reset_event 0x900000e4 + #define fw_addr_hsen_enable 0x10007F14 + #define fw_addr_smwp_enable 0x10007F10 + #define fw_usb_detect_addr 0x10007F38 + #define fw_addr_program_reload_from 0x00000000 + #define fw_addr_program_reload_to 0x08000000 + #define fw_addr_program_reload_page_write 0x0000fb00 + #define fw_addr_raw_out_sel 0x800204b4 + #define fw_addr_reload_status 0x80050000 + #define fw_addr_reload_crc32_result 0x80050018 + #define fw_addr_reload_addr_from 0x80050020 + #define fw_addr_reload_addr_cmd_beat 0x80050028 + #define fw_data_system_reset 0x00000055 + #define fw_data_safe_mode_release_pw_active 0x00000053 + #define fw_data_safe_mode_release_pw_reset 0x00000000 + #define fw_data_clear 0x00000000 + #define fw_data_program_reload_start 0x0A3C3000 + #define fw_data_program_reload_compare 0x04663000 + #define fw_data_program_reload_break 0x15E75678 + #define fw_addr_selftest_addr_en 0x10007F18 + #define fw_addr_selftest_result_addr 0x10007f24 + #define fw_data_selftest_request 0x00006AA6 + #define fw_addr_criteria_addr 0x10007f1c + #define fw_data_criteria_aa_top 0xff + #define fw_data_criteria_aa_bot 0x00 + #define fw_data_criteria_key_top 0xff + #define fw_data_criteria_key_bot 0x00 + #define fw_data_criteria_avg_top 0xff + #define fw_data_criteria_avg_bot 0x00 + #define fw_addr_set_frame_addr 0x10007294 + #define fw_data_set_frame 0x0000000A + #define fw_data_selftest_ack_hb 0xa6 + #define fw_data_selftest_ack_lb 0x6a + #define fw_data_selftest_pass 0xaa + #define fw_data_normal_cmd 0x00 + #define fw_data_normal_status 0x99 + #define fw_data_sorting_cmd 0xaa + #define fw_data_sorting_status 0xcc + #define fw_data_idle_dis_pwd 0x17 + #define fw_data_idle_en_pwd 0x1f + #define fw_addr_sorting_mode_en 0x10007f04 + #define fw_addr_fw_mode_status 0x10007088 + #define fw_addr_icid_addr 0x900000d0 + #define fw_addr_trigger_addr 0x10007089 + #define fw_addr_fw_ver_addr 0x10007004 + #define fw_addr_fw_cfg_addr 0x10007084 + #define fw_addr_fw_vendor_addr 0x10007000 + #define fw_addr_fw_state_addr 0x900000f8 + #define fw_addr_fw_dbg_msg_addr 0x10007f44 + #define fw_addr_chk_fw_status 0x900000a8 + #define fw_addr_dd_handshak_addr 0x900000fc + #define fw_addr_dd_data_addr 0x10007f80 + #define fw_data_dd_request 0xaa + #define fw_data_dd_ack 0xbb + #define fw_data_rawdata_ready_hb 0xa3 + #define fw_data_rawdata_ready_lb 0x3a + #define fw_addr_ahb_addr 0x11 + #define fw_data_ahb_dis 0x00 + #define fw_data_ahb_en 0x01 + #define fw_addr_event_addr 0x30 + #define fw_func_handshaking_pwd 0xA55AA55A + #define fw_func_handshaking_end 0x77887788 + + #define on_fw_addr_smwp_enable 0xA2 + #define on_fw_usb_detect_addr 0xA4 + #define on_fw_addr_program_reload_from 0x00000000 + #define on_fw_addr_raw_out_sel 0x98 + #define on_fw_addr_flash_checksum 0x80000044 + #define on_fw_data_flash_checksum 0x00000491 + #define on_fw_addr_crc_value 0x80000050 + #define on_fw_data_safe_mode_release_pw_active 0x00000053 + #define on_fw_data_safe_mode_release_pw_reset 0x00000000 + #define on_fw_addr_criteria_addr 0x9A + #define on_fw_data_selftest_pass 0xaa + #define on_fw_addr_reK_crtl 0x8000000C + #define on_fw_data_reK_en 0x02 + #define on_fw_data_reK_dis 0xFD + #define on_fw_data_rst_init 0xF0 + #define on_fw_data_dc_set 0x02 + #define on_fw_data_bank_set 0x03 + #define on_fw_addr_selftest_addr_en 0x98 + #define on_fw_addr_selftest_result_addr 0x9B + #define on_fw_data_selftest_request 0x06 + #define on_fw_data_thx_avg_mul_dc_lsb 0x22 + #define on_fw_data_thx_avg_mul_dc_msb 0x0B + #define on_fw_data_thx_mul_dc_up_low_bud 0x64 + #define on_fw_data_thx_avg_slf_dc_lsb 0x14 + #define on_fw_data_thx_avg_slf_dc_msb 0x05 + #define on_fw_data_thx_slf_dc_up_low_bud 0x64 + #define on_fw_data_thx_slf_bank_up 0x40 + #define on_fw_data_thx_slf_bank_low 0x00 + #define on_fw_data_idle_dis_pwd 0x40 + #define on_fw_data_idle_en_pwd 0x00 + #define on_fw_addr_fw_mode_status 0x99 + #define on_fw_addr_icid_addr 0x900000d0 + #define on_fw_addr_trigger_addr 0x10007089 + #define on_fw_addr_fw_ver_start 0x90 + #define on_fw_data_rawdata_ready_hb 0xa3 + #define on_fw_data_rawdata_ready_lb 0x3a + #define on_fw_addr_ahb_addr 0x11 + #define on_fw_data_ahb_dis 0x00 + #define on_fw_data_ahb_en 0x01 + #define on_fw_addr_event_addr 0x30 +#endif + +#if defined(CORE_FLASH) + #define flash_addr_ctrl_base 0x80000000 + #define flash_addr_spi200_trans_fmt (flash_addr_ctrl_base + 0x10) + #define flash_addr_spi200_trans_ctrl (flash_addr_ctrl_base + 0x20) + #define flash_addr_spi200_cmd (flash_addr_ctrl_base + 0x24) + #define flash_addr_spi200_addr (flash_addr_ctrl_base + 0x28) + #define flash_addr_spi200_data (flash_addr_ctrl_base + 0x2c) + #define flash_addr_spi200_bt_num (flash_addr_ctrl_base + 0xe8) + #define flash_data_spi200_trans_fmt 0x00020780 + #define flash_data_spi200_trans_ctrl_1 0x42000003 + #define flash_data_spi200_trans_ctrl_2 0x47000000 + #define flash_data_spi200_trans_ctrl_3 0x67000000 + #define flash_data_spi200_trans_ctrl_4 0x610ff000 + #define flash_data_spi200_trans_ctrl_5 0x694002ff + #define flash_data_spi200_cmd_1 0x00000005 + #define flash_data_spi200_cmd_2 0x00000006 + #define flash_data_spi200_cmd_3 0x000000C7 + #define flash_data_spi200_cmd_4 0x00000052 + #define flash_data_spi200_cmd_5 0x00000020 + #define flash_data_spi200_cmd_6 0x00000002 + #define flash_data_spi200_cmd_7 0x0000003b + #define flash_data_spi200_addr 0x00000000 + + #define on_flash_addr_ctrl_base 0x80000000 + #define on_flash_addr_ctrl_auto 0x80000004 + #define on_flash_data_main_erase 0x0000A50D + #define on_flash_data_auto 0xA5 + #define on_flash_data_main_read 0x03 + #define on_flash_data_page_write 0x05 + #define on_flash_data_spp_read 0x10 + #define on_flash_data_sfr_read 0x14 + #define on_flash_addr_ahb_ctrl 0x80000020 + #define on_flash_data_ahb_squit 0x00000001 + #define on_flash_addr_unlock_0 0x00000000 + #define on_flash_addr_unlock_4 0x00000004 + #define on_flash_addr_unlock_8 0x00000008 + #define on_flash_addr_unlock_c 0x0000000C + #define on_flash_data_cmd0 0x28178EA0 + #define on_flash_data_cmd1 0x0A0E03FF + #define on_flash_data_cmd2 0x8C203D0C + #define on_flash_data_cmd3 0x00300263 + #define on_flash_data_lock 0x03400000 +#endif + +#if defined(CORE_SRAM) + #define sram_adr_mkey 0x100070E8 + #define sram_adr_rawdata_addr 0x10000000 + #define sram_adr_rawdata_end 0x00000000 + #define sram_cmd_conti 0x44332211 + #define sram_cmd_fin 0x00000000 + #define sram_passwrd_start 0x5AA5 + #define sram_passwrd_end 0xA55A + + #define on_sram_adr_rawdata_addr 0x080002E0 + #define on_sram_adr_rawdata_end 0x00000000 + #define on_sram_cmd_conti 0x44332211 + #define on_sram_cmd_fin 0x00000000 + #define on_sram_passwrd_start 0x5AA5 + #define on_sram_passwrd_end 0xA55A +#endif + +#if defined(CORE_DRIVER) + #define driver_addr_fw_define_flash_reload 0x10007f00 + #define driver_addr_fw_define_2nd_flash_reload 0x100072c0 + #define driver_data_fw_define_flash_reload_dis 0x0000a55a + #define driver_data_fw_define_flash_reload_en 0x00000000 + #define driver_addr_fw_define_int_is_edge 0x10007089 + #define driver_addr_fw_define_rxnum_txnum_maxpt 0x100070f4 + #define driver_data_fw_define_rxnum_txnum_maxpt_sorting 0x00000008 + #define driver_data_fw_define_rxnum_txnum_maxpt_normal 0x00000014 + #define driver_addr_fw_define_xy_res_enable 0x100070fa + #define driver_addr_fw_define_x_y_res 0x100070fc + + #define on_driver_addr_fw_define_int_is_edge 0x10007089 + #define on_driver_addr_fw_rx_tx_maxpt_num 0x0800001C + #define on_driver_addr_fw_xy_rev_int_edge 0x0800000C + #define on_driver_addr_fw_define_x_y_res 0x08000030 +#endif + +#if defined(HX_ZERO_FLASH) + #define zf_addr_dis_flash_reload 0x10007f00 + #define zf_data_dis_flash_reload 0x00009AA9 + #define zf_addr_system_reset 0x90000018 + #define zf_data_system_reset 0x00000055 + #define zf_data_sram_start_addr 0x08000000 + #define zf_data_sram_clean 0x10000000 + #define zf_data_cfg_info 0x10007000 + #define zf_data_fw_cfg 0x10007084 + #define zf_data_adc_cfg_1 0x10007800 + #define zf_data_adc_cfg_2 0x10007978 + #define zf_data_adc_cfg_3 0x10007AF0 +#endif + +struct ic_operation { + uint8_t addr_ahb_addr_byte_0[1]; + uint8_t addr_ahb_rdata_byte_0[1]; + uint8_t addr_ahb_access_direction[1]; + uint8_t addr_conti[1]; + uint8_t addr_incr4[1]; + uint8_t adr_i2c_psw_lb[1]; + uint8_t adr_i2c_psw_ub[1]; + uint8_t data_ahb_access_direction_read[1]; + uint8_t data_conti[1]; + uint8_t data_incr4[1]; + uint8_t data_i2c_psw_lb[1]; + uint8_t data_i2c_psw_ub[1]; + uint8_t addr_tcon_on_rst[4]; + uint8_t addr_adc_on_rst[4]; + uint8_t addr_psl[4]; + uint8_t addr_cs_central_state[4]; + uint8_t data_rst[4]; +}; + +struct fw_operation { + uint8_t addr_system_reset[4]; + uint8_t addr_safe_mode_release_pw[4]; + uint8_t addr_ctrl_fw_isr[4]; + uint8_t addr_flag_reset_event[4]; + uint8_t addr_hsen_enable[4]; + uint8_t addr_smwp_enable[4]; + uint8_t addr_program_reload_from[4]; + uint8_t addr_program_reload_to[4]; + uint8_t addr_program_reload_page_write[4]; + uint8_t addr_raw_out_sel[4]; + uint8_t addr_reload_status[4]; + uint8_t addr_reload_crc32_result[4]; + uint8_t addr_reload_addr_from[4]; + uint8_t addr_reload_addr_cmd_beat[4]; + uint8_t addr_selftest_addr_en[4]; + uint8_t addr_criteria_addr[4]; + uint8_t addr_set_frame_addr[4]; + uint8_t addr_selftest_result_addr[4]; + uint8_t addr_sorting_mode_en[4]; + uint8_t addr_fw_mode_status[4]; + uint8_t addr_icid_addr[4]; + uint8_t addr_trigger_addr[4]; + uint8_t addr_fw_ver_addr[4]; + uint8_t addr_fw_cfg_addr[4]; + uint8_t addr_fw_vendor_addr[4]; + uint8_t addr_fw_state_addr[4]; + uint8_t addr_fw_dbg_msg_addr[4]; + uint8_t addr_chk_fw_status[4]; + uint8_t addr_dd_handshak_addr[4]; + uint8_t addr_dd_data_addr[4]; + uint8_t data_system_reset[4]; + uint8_t data_safe_mode_release_pw_active[4]; + uint8_t data_safe_mode_release_pw_reset[4]; + uint8_t data_clear[4]; + uint8_t data_program_reload_start[4]; + uint8_t data_program_reload_compare[4]; + uint8_t data_program_reload_break[4]; + uint8_t data_selftest_request[4]; + uint8_t data_criteria_aa_top[1]; + uint8_t data_criteria_aa_bot[1]; + uint8_t data_criteria_key_top[1]; + uint8_t data_criteria_key_bot[1]; + uint8_t data_criteria_avg_top[1]; + uint8_t data_criteria_avg_bot[1]; + uint8_t data_set_frame[4]; + uint8_t data_selftest_ack_hb[1]; + uint8_t data_selftest_ack_lb[1]; + uint8_t data_selftest_pass[1]; + uint8_t data_normal_cmd[1]; + uint8_t data_normal_status[1]; + uint8_t data_sorting_cmd[1]; + uint8_t data_sorting_status[1]; + uint8_t data_dd_request[1]; + uint8_t data_dd_ack[1]; + uint8_t data_idle_dis_pwd[1]; + uint8_t data_idle_en_pwd[1]; + uint8_t data_rawdata_ready_hb[1]; + uint8_t data_rawdata_ready_lb[1]; + uint8_t addr_ahb_addr[1]; + uint8_t data_ahb_dis[1]; + uint8_t data_ahb_en[1]; + uint8_t addr_event_addr[1]; + uint8_t addr_usb_detect[4]; +}; + +struct flash_operation { + uint8_t addr_spi200_trans_fmt[4]; + uint8_t addr_spi200_trans_ctrl[4]; + uint8_t addr_spi200_cmd[4]; + uint8_t addr_spi200_addr[4]; + uint8_t addr_spi200_data[4]; + uint8_t addr_spi200_bt_num[4]; + + uint8_t data_spi200_trans_fmt[4]; + uint8_t data_spi200_trans_ctrl_1[4]; + uint8_t data_spi200_trans_ctrl_2[4]; + uint8_t data_spi200_trans_ctrl_3[4]; + uint8_t data_spi200_trans_ctrl_4[4]; + uint8_t data_spi200_trans_ctrl_5[4]; + uint8_t data_spi200_cmd_1[4]; + uint8_t data_spi200_cmd_2[4]; + uint8_t data_spi200_cmd_3[4]; + uint8_t data_spi200_cmd_4[4]; + uint8_t data_spi200_cmd_5[4]; + uint8_t data_spi200_cmd_6[4]; + uint8_t data_spi200_cmd_7[4]; + uint8_t data_spi200_addr[4]; +}; + +struct sram_operation { + uint8_t addr_mkey[4]; + uint8_t addr_rawdata_addr[4]; + uint8_t addr_rawdata_end[4]; + uint8_t data_conti[4]; + uint8_t data_fin[4]; + uint8_t passwrd_start[2]; + uint8_t passwrd_end[2]; +}; + +struct driver_operation { + uint8_t addr_fw_define_flash_reload[4]; + uint8_t addr_fw_define_2nd_flash_reload[4]; + uint8_t addr_fw_define_int_is_edge[4]; + uint8_t addr_fw_define_rxnum_txnum_maxpt[4]; + uint8_t addr_fw_define_xy_res_enable[4]; + uint8_t addr_fw_define_x_y_res[4]; + uint8_t data_fw_define_flash_reload_dis[4]; + uint8_t data_fw_define_flash_reload_en[4]; + uint8_t data_fw_define_rxnum_txnum_maxpt_sorting[4]; + uint8_t data_fw_define_rxnum_txnum_maxpt_normal[4]; +}; + +struct zf_operation { + uint8_t addr_dis_flash_reload[4]; + uint8_t data_dis_flash_reload[4]; + uint8_t addr_system_reset[4]; + uint8_t data_system_reset[4]; + uint8_t data_sram_start_addr[4]; + uint8_t data_sram_clean[4]; + uint8_t data_cfg_info[4]; + uint8_t data_fw_cfg[4]; + uint8_t data_adc_cfg_1[4]; + uint8_t data_adc_cfg_2[4]; + uint8_t data_adc_cfg_3[4]; +}; + +struct himax_core_command_operation { + struct ic_operation *ic_op; + struct fw_operation *fw_op; + struct flash_operation *flash_op; + struct sram_operation *sram_op; + struct driver_operation *driver_op; + struct zf_operation *zf_op; +}; + +struct on_ic_operation { + uint8_t addr_ahb_addr_byte_0[1]; + uint8_t addr_ahb_rdata_byte_0[1]; + uint8_t addr_ahb_access_direction[1]; + uint8_t addr_conti[1]; + uint8_t addr_incr4[1]; + uint8_t adr_mcu_ctrl[1]; + uint8_t data_ahb_access_direction_read[1]; + uint8_t data_conti[1]; + uint8_t data_incr4[1]; + uint8_t cmd_mcu_on[1]; + uint8_t cmd_mcu_off[1]; + uint8_t adr_sleep_ctrl[1]; + uint8_t cmd_sleep_in[1]; + uint8_t adr_tcon_ctrl[4]; + uint8_t cmd_tcon_on[4]; + uint8_t adr_wdg_ctrl[4]; + uint8_t cmd_wdg_psw[4]; + uint8_t adr_wdg_cnt_ctrl[4]; + uint8_t cmd_wdg_cnt_clr[4]; +}; + +struct on_fw_operation { + uint8_t addr_smwp_enable[1]; + uint8_t addr_program_reload_from[4]; + uint8_t addr_raw_out_sel[1]; + uint8_t addr_flash_checksum[4]; + uint8_t data_flash_checksum[4]; + uint8_t addr_crc_value[4]; + uint8_t addr_reload_status[4]; + uint8_t addr_reload_crc32_result[4]; + uint8_t addr_reload_addr_from[4]; + uint8_t addr_reload_addr_cmd_beat[4]; + uint8_t addr_set_frame_addr[4]; + uint8_t addr_fw_mode_status[1]; + uint8_t addr_icid_addr[4]; + uint8_t addr_trigger_addr[4]; + uint8_t addr_fw_ver_start[1]; + uint8_t data_safe_mode_release_pw_active[4]; + uint8_t data_safe_mode_release_pw_reset[4]; + uint8_t data_clear[4]; + uint8_t addr_criteria_addr[1]; + uint8_t data_selftest_pass[1]; + uint8_t addr_reK_crtl[4]; + uint8_t data_reK_en[1]; + uint8_t data_reK_dis[1]; + uint8_t data_rst_init[1]; + uint8_t data_dc_set[1]; + uint8_t data_bank_set[1]; + uint8_t addr_selftest_addr_en[1]; + uint8_t addr_selftest_result_addr[1]; + uint8_t data_selftest_request[1]; + uint8_t data_thx_avg_mul_dc_lsb[1]; + uint8_t data_thx_avg_mul_dc_msb[1]; + uint8_t data_thx_mul_dc_up_low_bud[1]; + uint8_t data_thx_avg_slf_dc_lsb[1]; + uint8_t data_thx_avg_slf_dc_msb[1]; + uint8_t data_thx_slf_dc_up_low_bud[1]; + uint8_t data_thx_slf_bank_up[1]; + uint8_t data_thx_slf_bank_low[1]; + uint8_t data_idle_dis_pwd[1]; + uint8_t data_idle_en_pwd[1]; + uint8_t data_rawdata_ready_hb[1]; + uint8_t data_rawdata_ready_lb[1]; + uint8_t addr_ahb_addr[1]; + uint8_t data_ahb_dis[1]; + uint8_t data_ahb_en[1]; + uint8_t addr_event_addr[1]; + uint8_t addr_usb_detect[1]; +}; + +struct on_flash_operation { + uint8_t addr_ctrl_base[4]; + uint8_t addr_ctrl_auto[4]; + uint8_t data_main_erase[4]; + uint8_t data_auto[1]; + uint8_t data_main_read[1]; + uint8_t data_page_write[1]; + uint8_t data_sfr_read[1]; + uint8_t data_spp_read[1]; + uint8_t addr_ahb_ctrl[4]; + uint8_t data_ahb_squit[4]; + + uint8_t addr_unlock_0[4]; + uint8_t addr_unlock_4[4]; + uint8_t addr_unlock_8[4]; + uint8_t addr_unlock_c[4]; + uint8_t data_cmd0[4]; + uint8_t data_cmd1[4]; + uint8_t data_cmd2[4]; + uint8_t data_cmd3[4]; + uint8_t data_lock[4]; +}; + +struct on_sram_operation { + uint8_t addr_rawdata_addr[4]; + uint8_t addr_rawdata_end[4]; + uint8_t data_conti[4]; + uint8_t data_fin[4]; + uint8_t passwrd_start[2]; + uint8_t passwrd_end[2]; +}; + +struct on_driver_operation { + uint8_t addr_fw_define_int_is_edge[4]; + uint8_t addr_fw_rx_tx_maxpt_num[4]; + uint8_t addr_fw_xy_rev_int_edge[4]; + uint8_t addr_fw_define_x_y_res[4]; + uint8_t data_fw_define_rxnum_txnum_maxpt_sorting[4]; + uint8_t data_fw_define_rxnum_txnum_maxpt_normal[4]; +}; + +struct himax_on_core_command_operation { + struct on_ic_operation *ic_op; + struct on_fw_operation *fw_op; + struct on_flash_operation *flash_op; + struct on_sram_operation *sram_op; + struct on_driver_operation *driver_op; +}; + +struct himax_core_fp { +#ifdef CORE_IC + void (*fp_burst_enable)(uint8_t auto_add_4_byte); + int (*fp_register_read)(uint8_t *read_addr, uint32_t read_length, uint8_t *read_data, uint8_t cfg_flag); + int (*fp_flash_write_burst)(uint8_t *reg_byte, uint8_t *write_data); + void (*fp_flash_write_burst_length)(uint8_t *reg_byte, uint8_t *write_data, uint32_t length); + void (*fp_register_write)(uint8_t *write_addr, uint32_t write_length, uint8_t *write_data, uint8_t cfg_flag); + void (*fp_interface_on)(void); + void (*fp_sense_on)(uint8_t FlashMode); + void (*fp_tcon_on)(void); + bool (*fp_watch_dog_off)(void); + bool (*fp_sense_off)(void); + void (*fp_sleep_in)(void); + bool (*fp_wait_wip)(int Timing); + void (*fp_init_psl)(void); + void (*fp_resume_ic_action)(void); + void (*fp_suspend_ic_action)(void); + void (*fp_power_on_init)(void); +#endif + +#ifdef CORE_FW + void (*fp_parse_raw_data)(struct himax_report_data *hx_touch_data, int mul_num, int self_num, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data); + void (*fp_system_reset)(void); + bool (*fp_Calculate_CRC_with_AP)(unsigned char *FW_content, int CRC_from_FW, int mode); + uint32_t (*fp_check_CRC)(uint8_t *start_addr, int reload_length); + void (*fp_set_reload_cmd)(uint8_t *write_data, int idx, uint32_t cmd_from, uint32_t cmd_to, uint32_t cmd_beat); + bool (*fp_program_reload)(void); + void (*fp_set_SMWP_enable)(uint8_t SMWP_enable, bool suspended); + void (*fp_set_HSEN_enable)(uint8_t HSEN_enable, bool suspended); + void (*fp_diag_register_set)(uint8_t diag_command, uint8_t storage_type); +#ifdef HX_TP_SELF_TEST_DRIVER + void (*fp_control_reK)(bool enable); +#endif + int (*fp_chip_self_test)(void); + void (*fp_idle_mode)(int disable); + void (*fp_reload_disable)(int disable); + bool (*fp_check_chip_version)(void); + int (*fp_read_ic_trigger_type)(void); + int (*fp_read_i2c_status)(void); + void (*fp_read_FW_ver)(void); + bool (*fp_read_event_stack)(uint8_t *buf, uint8_t length); + void (*fp_return_event_stack)(void); + bool (*fp_calculateChecksum)(bool change_iref); + int (*fp_read_FW_status)(uint8_t *state_addr, uint8_t *tmp_addr); + void (*fp_irq_switch)(int switch_on); + int (*fp_assign_sorting_mode)(uint8_t *tmp_data); + int (*fp_check_sorting_mode)(uint8_t *tmp_data); + int (*fp_switch_mode)(int mode); + uint8_t (*fp_read_DD_status)(uint8_t *cmd_set, uint8_t *tmp_data); +#endif + +#ifdef CORE_FLASH + void (*fp_chip_erase)(void); + bool (*fp_block_erase)(int start_addr, int length); + bool (*fp_sector_erase)(int start_addr); + void (*fp_flash_programming)(uint8_t *FW_content, int FW_Size); + void (*fp_flash_page_write)(uint8_t *write_addr, int length, uint8_t *write_data); + int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_32k)(unsigned char *fw, int len, bool change_iref); + int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_60k)(unsigned char *fw, int len, bool change_iref); + int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_64k)(unsigned char *fw, int len, bool change_iref); + int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_124k)(unsigned char *fw, int len, bool change_iref); + int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_128k)(unsigned char *fw, int len, bool change_iref); + void (*fp_flash_dump_func)(uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer); + bool (*fp_flash_lastdata_check)(void); + bool (*fp_ahb_squit)(void); + void (*fp_flash_read)(uint8_t *r_data, int start_addr, int length); + bool (*fp_sfr_rw)(uint8_t *addr, int length, uint8_t *data, uint8_t rw_ctrl); + bool (*fp_lock_flash)(void); + bool (*fp_unlock_flash)(void); + void (*fp_init_auto_func)(void); +#endif + +#ifdef CORE_SRAM + void (*fp_sram_write)(uint8_t *FW_content); + bool (*fp_sram_verify)(uint8_t *FW_File, int FW_Size); + void (*fp_get_DSRAM_data)(uint8_t *info_data, bool DSRAM_Flag); +#endif + +#ifdef CORE_DRIVER + bool (*fp_chip_detect)(void); + void (*fp_chip_init)(void); + void (*fp_pin_reset)(void); + void (*fp_touch_information)(void); + void (*fp_reload_config)(void); + int (*fp_get_touch_data_size)(void); + void (*fp_usb_detect_set)(uint8_t *cable_config); + int (*fp_hand_shaking)(void); + int (*fp_determin_diag_rawdata)(int diag_command); + int (*fp_determin_diag_storage)(int diag_command); + int (*fp_cal_data_len)(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max); + bool (*fp_diag_check_sum)(struct himax_report_data *hx_touch_data); + void (*fp_diag_parse_raw_data)(struct himax_report_data *hx_touch_data, int mul_num, int self_num, uint8_t diag_cmd, int32_t *mutual_data, int32_t *self_data); + void (*fp_ic_reset)(uint8_t loadconfig, uint8_t int_off); + int (*fp_ic_esd_recovery)(int hx_esd_event, int hx_zero_event, int length); + void (*fp_esd_ic_reset)(void); + void (*fp_resend_cmd_func)(bool suspended); +#endif +#ifdef HX_ZERO_FLASH + void (*fp_sys_reset)(void); + void (*fp_clean_sram_0f)(uint8_t *addr, int write_len, int type); + void (*fp_write_sram_0f)(const struct firmware *fw_entry, uint8_t *addr, int start_index, uint32_t write_len); + void (*fp_firmware_update_0f)(const struct firmware *fw_entry); + void (*fp_0f_operation)(struct work_struct *work); +#ifdef HX_0F_DEBUG + void (*fp_read_sram_0f)(const struct firmware *fw_entry, uint8_t *addr, int start_index, int read_len); + void (*fp_read_all_sram)(uint8_t *addr, int read_len); + void (*fp_firmware_read_0f)(const struct firmware *fw_entry, int type); + void (*fp_0f_operation_check)(int type); +#endif +#endif +}; + +#ifdef HX_ESD_RECOVERY +extern int g_zero_event_count; +#endif + +extern struct ic_operation *pic_op; +extern struct fw_operation *pfw_op; +#ifdef HX_ZERO_FLASH +extern struct zf_operation *pzf_op; +#endif + diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_incell_core.c b/drivers/input/touchscreen/hxchipset/himax_ic_incell_core.c new file mode 100644 index 000000000000..a95fb26a3bc2 --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_ic_incell_core.c @@ -0,0 +1,2727 @@ +/* + * Himax Android Driver Sample Code for IC Core + * + * Copyright (C) 2018 Himax Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "himax_ic_core.h" + +struct himax_core_command_operation *g_core_cmd_op; +struct ic_operation *pic_op; +struct fw_operation *pfw_op; +struct flash_operation *pflash_op; +struct sram_operation *psram_op; +struct driver_operation *pdriver_op; +#ifdef HX_ZERO_FLASH +struct zf_operation *pzf_op; +#endif + +#ifdef CORE_IC +/* IC side start */ +static void himax_mcu_burst_enable(uint8_t auto_add_4_byte) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + /* I("%s,Entering\n",__func__); */ + tmp_data[0] = pic_op->data_conti[0]; + + if (himax_bus_write(pic_op->addr_conti[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + tmp_data[0] = (pic_op->data_incr4[0] | auto_add_4_byte); + + if (himax_bus_write(pic_op->addr_incr4[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } +} + +static int himax_mcu_register_read(uint8_t *read_addr, uint32_t read_length, uint8_t *read_data, uint8_t cfg_flag) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + int i = 0; + int address = 0; + + /* I("%s,Entering\n",__func__); */ + + if (cfg_flag == false) { + if (read_length > FLASH_RW_MAX_LEN) { + E("%s: read len over %d!\n", __func__, FLASH_RW_MAX_LEN); + return LENGTH_FAIL; + } + + if (read_length > FOUR_BYTE_DATA_SZ) + g_core_fp.fp_burst_enable(1); + else + g_core_fp.fp_burst_enable(0); + + address = (read_addr[3] << 24) + (read_addr[2] << 16) + (read_addr[1] << 8) + read_addr[0]; + i = address; + tmp_data[0] = (uint8_t)i; + tmp_data[1] = (uint8_t)(i >> 8); + tmp_data[2] = (uint8_t)(i >> 16); + tmp_data[3] = (uint8_t)(i >> 24); + + if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], tmp_data, FOUR_BYTE_DATA_SZ, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + + tmp_data[0] = pic_op->data_ahb_access_direction_read[0]; + + if (himax_bus_write(pic_op->addr_ahb_access_direction[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + + if (himax_bus_read(pic_op->addr_ahb_rdata_byte_0[0], read_data, read_length, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + + if (read_length > FOUR_BYTE_DATA_SZ) + g_core_fp.fp_burst_enable(0); + + } else { + if (himax_bus_read(read_addr[0], read_data, read_length, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + } + return NO_ERR; +} + +static int himax_mcu_flash_write_burst(uint8_t *reg_byte, uint8_t *write_data) +{ + uint8_t data_byte[FLASH_WRITE_BURST_SZ]; + int i = 0, j = 0; + int data_byte_sz = sizeof(data_byte); + + for (i = 0; i < FOUR_BYTE_ADDR_SZ; i++) + data_byte[i] = reg_byte[i]; + + for (j = FOUR_BYTE_ADDR_SZ; j < data_byte_sz; j++) + data_byte[j] = write_data[j - FOUR_BYTE_ADDR_SZ]; + + if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], data_byte, data_byte_sz, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + return NO_ERR; +} + +static void himax_mcu_flash_write_burst_length(uint8_t *reg_byte, uint8_t *write_data, uint32_t length) +{ + uint8_t *data_byte; + int i = 0, j = 0; + + /* + * if (length + FOUR_BYTE_ADDR_SZ > FLASH_RW_MAX_LEN) { + * E("%s: write len over %d!\n", __func__, FLASH_RW_MAX_LEN); + * return; + * } + */ + + data_byte = kcalloc((length + 4), sizeof(uint8_t), GFP_KERNEL); + if (!data_byte) { + E("%s: allocate memory failed!\n", __func__); + return; + } + + for (i = 0; i < FOUR_BYTE_ADDR_SZ; i++) + data_byte[i] = reg_byte[i]; + + for (j = FOUR_BYTE_ADDR_SZ; j < length + FOUR_BYTE_ADDR_SZ; j++) + data_byte[j] = write_data[j - FOUR_BYTE_ADDR_SZ]; + + if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], data_byte, length + FOUR_BYTE_ADDR_SZ, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + kfree(data_byte); + return; + } + kfree(data_byte); +} + +static void himax_mcu_register_write(uint8_t *write_addr, uint32_t write_length, uint8_t *write_data, uint8_t cfg_flag) +{ + int i, address; + + /* I("%s,Entering\n", __func__); */ + if (cfg_flag == false) { + address = (write_addr[3] << 24) + (write_addr[2] << 16) + (write_addr[1] << 8) + write_addr[0]; + + for (i = address; i < address + write_length; i++) { + if (write_length > FOUR_BYTE_DATA_SZ) + g_core_fp.fp_burst_enable(1); + else + g_core_fp.fp_burst_enable(0); + + g_core_fp.fp_flash_write_burst_length(write_addr, write_data, write_length); + } + } else if (cfg_flag == true) { + if (himax_bus_write(write_addr[0], write_data, write_length, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + } else { + E("%s: cfg_flag = %d, value is wrong!\n", __func__, cfg_flag); + return; + } +} + +static int himax_write_read_reg(uint8_t *tmp_addr, uint8_t *tmp_data, uint8_t hb, uint8_t lb) +{ + int cnt = 0; + + do { + g_core_fp.fp_flash_write_burst(tmp_addr, tmp_data); + msleep(20); + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, 0); + /* + * I("%s:Now tmp_data[0]=0x%02X,[1]=0x%02X,[2]=0x%02X,[3]=0x%02X\n", + * __func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + */ + } while ((tmp_data[1] != hb && tmp_data[0] != lb) && cnt++ < 100); + + if (cnt == 99) + return HX_RW_REG_FAIL; + + I("Now register 0x%08X : high byte=0x%02X,low byte=0x%02X\n", tmp_addr[3], tmp_data[1], tmp_data[0]); + return NO_ERR; +} + +static void himax_mcu_interface_on(void) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + uint8_t tmp_data2[FOUR_BYTE_DATA_SZ]; + int cnt = 0; + + /* Read a dummy register to wake up I2C.*/ + if (himax_bus_read(pic_op->addr_ahb_rdata_byte_0[0], tmp_data, FOUR_BYTE_DATA_SZ, HIMAX_I2C_RETRY_TIMES) < 0) {/* to knock I2C*/ + E("%s: i2c access fail!\n", __func__); + return; + } + + do { + /* + *=========================================== + * Enable continuous burst mode : 0x13 ==> 0x31 + *=========================================== + */ + tmp_data[0] = pic_op->data_conti[0]; + + if (himax_bus_write(pic_op->addr_conti[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + /* + *=========================================== + * AHB address auto +4 : 0x0D ==> 0x11 + * Do not AHB address auto +4 : 0x0D ==> 0x10 + *=========================================== + */ + tmp_data[0] = pic_op->data_incr4[0]; + + if (himax_bus_write(pic_op->addr_incr4[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + /* Check cmd */ + if (himax_bus_read(pic_op->addr_conti[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail: addr_conti!\n", __func__); + return; + } + if (himax_bus_read(pic_op->addr_incr4[0], tmp_data2, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail: addr_incr4!\n", __func__); + return; + } + if (tmp_data[0] == pic_op->data_conti[0] && tmp_data2[0] == pic_op->data_incr4[0]) + break; + + msleep(20); + } while (++cnt < 10); + + if (cnt > 0) + I("%s:Polling burst mode: %d times", __func__, cnt); + +} + +static bool himax_mcu_wait_wip(int Timing) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + int retry_cnt = 0; + + /* + *===================================== + * SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_fmt, pflash_op->data_spi200_trans_fmt); + tmp_data[0] = 0x01; + + do { + /* + *===================================== + * SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003 + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_1); + /* + *===================================== + * SPI Command : 0x8000_0024 ==> 0x0000_0005 + * read 0x8000_002C for 0x01, means wait success + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_1); + tmp_data[0] = tmp_data[1] = tmp_data[2] = tmp_data[3] = 0xFF; + g_core_fp.fp_register_read(pflash_op->addr_spi200_data, 4, tmp_data, 0); + + if ((tmp_data[0] & 0x01) == 0x00) + return true; + + retry_cnt++; + + if (tmp_data[0] != 0x00 || tmp_data[1] != 0x00 || tmp_data[2] != 0x00 || tmp_data[3] != 0x00) + I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, buffer[1]=%d, buffer[2]=%d, buffer[3]=%d\n", + __func__, retry_cnt, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + + if (retry_cnt > 100) { + E("%s: Wait wip error!\n", __func__); + return false; + } + + msleep(Timing); + } while ((tmp_data[0] & 0x01) == 0x01); + + return true; +} + +static void himax_mcu_sense_on(uint8_t FlashMode) +{ + /* uint8_t tmp_addr[FOUR_BYTE_ADDR_SZ]; */ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + int retry = 0; + + I("Enter %s\n", __func__); + g_core_fp.fp_interface_on(); + g_core_fp.fp_register_write(pfw_op->addr_ctrl_fw_isr, + sizeof(pfw_op->data_clear), pfw_op->data_clear, false); + msleep(20); + + if (!FlashMode) { +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + /* ===AHBI2C_SystemReset========== */ + g_core_fp.fp_system_reset(); +#endif + } else { + do { + /* + * tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x98; + * tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x53; + */ + g_core_fp.fp_register_write(pfw_op->addr_safe_mode_release_pw, + sizeof(pfw_op->data_safe_mode_release_pw_active), pfw_op->data_safe_mode_release_pw_active, false); + /* tmp_addr[0] = 0xE4; */ + g_core_fp.fp_register_read(pfw_op->addr_flag_reset_event, FOUR_BYTE_DATA_SZ, tmp_data, 0); + I("%s:Read status from IC = %X,%X\n", __func__, tmp_data[0], tmp_data[1]); + } while ((tmp_data[1] != 0x01 || tmp_data[0] != 0x00) && retry++ < 5); + + if (retry >= 5) { + E("%s: Fail:\n", __func__); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + /* ===AHBI2C_System Reset========== */ + g_core_fp.fp_system_reset(); +#endif + } else { + I("%s:OK and Read status from IC = %X,%X\n", __func__, tmp_data[0], tmp_data[1]); + /* reset code */ + tmp_data[0] = 0x00; + + if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) + E("%s: i2c access fail!\n", __func__); + + if (himax_bus_write(pic_op->adr_i2c_psw_ub[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) + E("%s: i2c access fail!\n", __func__); + + /* + * tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x98; + * tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + */ + g_core_fp.fp_register_write(pfw_op->addr_safe_mode_release_pw, + sizeof(pfw_op->data_safe_mode_release_pw_reset), pfw_op->data_safe_mode_release_pw_reset, false); + } + } +} + +static bool himax_mcu_sense_off(void) +{ + uint8_t cnt = 0; + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + + do { + /* + *=========================================== + * I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 + *=========================================== + */ + tmp_data[0] = pic_op->data_i2c_psw_lb[0]; + + if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /* + *=========================================== + * I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 + *=========================================== + */ + tmp_data[0] = pic_op->data_i2c_psw_ub[0]; + + if (himax_bus_write(pic_op->adr_i2c_psw_ub[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /* + *====================== + * Check enter_save_mode + *====================== + */ + g_core_fp.fp_register_read(pic_op->addr_cs_central_state, FOUR_BYTE_ADDR_SZ, tmp_data, 0); + I("%s: Check enter_save_mode data[0]=%X\n", __func__, tmp_data[0]); + + if (tmp_data[0] == 0x0C) { + /* + *===================================== + * Reset TCON + *===================================== + */ + g_core_fp.fp_flash_write_burst(pic_op->addr_tcon_on_rst, pic_op->data_rst); + msleep(20); + tmp_data[3] = pic_op->data_rst[3]; + tmp_data[2] = pic_op->data_rst[2]; + tmp_data[1] = pic_op->data_rst[1]; + tmp_data[0] = pic_op->data_rst[0] | 0x01; + g_core_fp.fp_flash_write_burst(pic_op->addr_tcon_on_rst, tmp_data); + /* + *===================================== + * Reset ADC + *===================================== + */ + g_core_fp.fp_flash_write_burst(pic_op->addr_adc_on_rst, pic_op->data_rst); + msleep(20); + tmp_data[3] = pic_op->data_rst[3]; + tmp_data[2] = pic_op->data_rst[2]; + tmp_data[1] = pic_op->data_rst[1]; + tmp_data[0] = pic_op->data_rst[0] | 0x01; + g_core_fp.fp_flash_write_burst(pic_op->addr_adc_on_rst, tmp_data); + return true; + } + + msleep(20); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#endif + + } while (cnt++ < 15); + + return false; +} + +static void himax_mcu_init_psl(void) /*power saving level*/ +{ + /* + *============================================================== + * SCU_Power_State_PW : 0x9000_00A0 ==> 0x0000_0000 (Reset PSL) + *============================================================== + */ + g_core_fp.fp_register_write(pic_op->addr_psl, sizeof(pic_op->data_rst), pic_op->data_rst, false); + I("%s: power saving level reset OK!\n", __func__); +} + +static void himax_mcu_resume_ic_action(void) +{ + /* Nothing to do */ +} + +static void himax_mcu_suspend_ic_action(void) +{ + /* Nothing to do */ +} + +static void himax_mcu_power_on_init(void) +{ + I("%s:\n", __func__); + g_core_fp.fp_touch_information(); + /* RawOut select initial */ + g_core_fp.fp_register_write(pfw_op->addr_raw_out_sel, sizeof(pfw_op->data_clear), pfw_op->data_clear, false); + /* DSRAM func initial */ + g_core_fp.fp_assign_sorting_mode(pfw_op->data_clear); + g_core_fp.fp_sense_on(0x00); +} + +/* IC side end */ +#endif + +#ifdef CORE_FW +/* FW side start */ +static void diag_mcu_parse_raw_data(struct himax_report_data *hx_touch_data, int mul_num, int self_num, uint8_t diag_cmd, int32_t *mutual_data, int32_t *self_data) +{ + int RawDataLen_word; + int index = 0; + int temp1, temp2, i; + + if (hx_touch_data->hx_rawdata_buf[0] == pfw_op->data_rawdata_ready_lb[0] + && hx_touch_data->hx_rawdata_buf[1] == pfw_op->data_rawdata_ready_hb[0] + && hx_touch_data->hx_rawdata_buf[2] > 0 + && hx_touch_data->hx_rawdata_buf[3] == diag_cmd) { + RawDataLen_word = hx_touch_data->rawdata_size / 2; + index = (hx_touch_data->hx_rawdata_buf[2] - 1) * RawDataLen_word; + + /* + * I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num); + * I("RawDataLen=%d , RawDataLen_word=%d , hx_touch_info_size=%d\n", RawDataLen, RawDataLen_word, hx_touch_info_size); + */ + for (i = 0; i < RawDataLen_word; i++) { + temp1 = index + i; + + if (temp1 < mul_num) /* mutual */ + mutual_data[index + i] = ((int8_t)hx_touch_data->hx_rawdata_buf[i * 2 + 4 + 1]) * 256 + hx_touch_data->hx_rawdata_buf[i * 2 + 4]; + + else { /* self */ + temp1 = i + index; + temp2 = self_num + mul_num; + + if (temp1 >= temp2) + break; + + self_data[i + index - mul_num] = (((int8_t)hx_touch_data->hx_rawdata_buf[i * 2 + 4 + 1]) << 8) + + hx_touch_data->hx_rawdata_buf[i * 2 + 4]; + } + } + } +} + +static void himax_mcu_system_reset(void) +{ + /* + * tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x18; + * tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x55; + */ + g_core_fp.fp_register_write(pfw_op->addr_system_reset, sizeof(pfw_op->data_system_reset), pfw_op->data_system_reset, false); +} + +static bool himax_mcu_Calculate_CRC_with_AP(unsigned char *FW_content, int CRC_from_FW, int mode) +{ + return true; +} + +static uint32_t himax_mcu_check_CRC(uint8_t *start_addr, int reload_length) +{ + uint32_t result = 0; + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + int cnt = 0, ret = 0; + int length = reload_length / FOUR_BYTE_DATA_SZ; + /* + * CRC4 // 0x8005_0020 <= from, 0x8005_0028 <= 0x0099_length + * tmp_addr[3] = 0x80; tmp_addr[2] = 0x05; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + */ + ret = g_core_fp.fp_flash_write_burst(pfw_op->addr_reload_addr_from, start_addr); + if (ret < NO_ERR) { + E("%s: i2c access fail!\n", __func__); + return HW_CRC_FAIL; + } + /* tmp_addr[3] = 0x80; tmp_addr[2] = 0x05; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; */ + tmp_data[3] = 0x00; tmp_data[2] = 0x99; tmp_data[1] = (length >> 8); tmp_data[0] = length; + ret = g_core_fp.fp_flash_write_burst(pfw_op->addr_reload_addr_cmd_beat, tmp_data); + if (ret < NO_ERR) { + E("%s: i2c access fail!\n", __func__); + return HW_CRC_FAIL; + } + cnt = 0; + + do { + /* tmp_addr[3] = 0x80; tmp_addr[2] = 0x05; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; */ + ret = g_core_fp.fp_register_read(pfw_op->addr_reload_status, FOUR_BYTE_DATA_SZ, tmp_data, 0); + if (ret < NO_ERR) { + E("%s: i2c access fail!\n", __func__); + return HW_CRC_FAIL; + } + + if ((tmp_data[0] & 0x01) != 0x01) { + /* tmp_addr[3] = 0x80; tmp_addr[2] = 0x05; tmp_addr[1] = 0x00; tmp_addr[0] = 0x18; */ + ret = g_core_fp.fp_register_read(pfw_op->addr_reload_crc32_result, FOUR_BYTE_DATA_SZ, tmp_data, 0); + if (ret < NO_ERR) { + E("%s: i2c access fail!\n", __func__); + return HW_CRC_FAIL; + } + I("%s: tmp_data[3]=%X, tmp_data[2]=%X, tmp_data[1]=%X, tmp_data[0]=%X\n", __func__, tmp_data[3], tmp_data[2], tmp_data[1], tmp_data[0]); + result = ((tmp_data[3] << 24) + (tmp_data[2] << 16) + (tmp_data[1] << 8) + tmp_data[0]); + break; + } + } while (cnt++ < 100); + + return result; +} + +static void himax_mcu_set_reload_cmd(uint8_t *write_data, int idx, uint32_t cmd_from, uint32_t cmd_to, uint32_t cmd_beat) +{ + int index = idx * 12; + int i; + + for (i = 3; i >= 0; i--) { + write_data[index + i] = (cmd_from >> (8 * i)); + write_data[index + 4 + i] = (cmd_to >> (8 * i)); + write_data[index + 8 + i] = (cmd_beat >> (8 * i)); + } +} + +static bool himax_mcu_program_reload(void) +{ + return true; +} + +static void himax_mcu_set_SMWP_enable(uint8_t SMWP_enable, bool suspended) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + uint8_t back_data[FOUR_BYTE_DATA_SZ]; + uint8_t retry_cnt = 0; + + do { + if (SMWP_enable) { + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, tmp_data, 4); + g_core_fp.fp_flash_write_burst(pfw_op->addr_smwp_enable, tmp_data); + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, back_data, 4); + } else { + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + g_core_fp.fp_flash_write_burst(pfw_op->addr_smwp_enable, tmp_data); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, back_data, 4); + } + + g_core_fp.fp_register_read(pfw_op->addr_smwp_enable, FOUR_BYTE_DATA_SZ, tmp_data, 0); + /* I("%s: tmp_data[0]=%d, SMWP_enable=%d, retry_cnt=%d\n", __func__, tmp_data[0],SMWP_enable,retry_cnt); */ + retry_cnt++; + } while ((tmp_data[3] != back_data[3] || tmp_data[2] != back_data[2] || tmp_data[1] != back_data[1] || tmp_data[0] != back_data[0]) && retry_cnt < HIMAX_REG_RETRY_TIMES); +} + +static void himax_mcu_set_HSEN_enable(uint8_t HSEN_enable, bool suspended) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + uint8_t back_data[FOUR_BYTE_DATA_SZ]; + uint8_t retry_cnt = 0; + + do { + if (HSEN_enable) { + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, tmp_data, 4); + g_core_fp.fp_flash_write_burst(pfw_op->addr_hsen_enable, tmp_data); + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, back_data, 4); + } else { + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + g_core_fp.fp_flash_write_burst(pfw_op->addr_hsen_enable, tmp_data); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, back_data, 4); + } + + g_core_fp.fp_register_read(pfw_op->addr_hsen_enable, FOUR_BYTE_DATA_SZ, tmp_data, 0); + /* I("%s: tmp_data[0]=%d, HSEN_enable=%d, retry_cnt=%d\n", __func__, tmp_data[0],HSEN_enable,retry_cnt); */ + retry_cnt++; + } while ((tmp_data[3] != back_data[3] || tmp_data[2] != back_data[2] || tmp_data[1] != back_data[1] || tmp_data[0] != back_data[0]) && retry_cnt < HIMAX_REG_RETRY_TIMES); +} + +static void himax_mcu_usb_detect_set(uint8_t *cable_config) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + uint8_t back_data[FOUR_BYTE_DATA_SZ]; + uint8_t retry_cnt = 0; + + do { + if (cable_config[1] == 0x01) { + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, tmp_data, 4); + g_core_fp.fp_flash_write_burst(pfw_op->addr_usb_detect, tmp_data); + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, back_data, 4); + I("%s: USB detect status IN!\n", __func__); + } else { + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + g_core_fp.fp_flash_write_burst(pfw_op->addr_usb_detect, tmp_data); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, back_data, 4); + I("%s: USB detect status OUT!\n", __func__); + } + + g_core_fp.fp_register_read(pfw_op->addr_usb_detect, FOUR_BYTE_DATA_SZ, tmp_data, 0); + /* I("%s: tmp_data[0]=%d, USB detect=%d, retry_cnt=%d\n", __func__, tmp_data[0],cable_config[1] ,retry_cnt); */ + retry_cnt++; + } while ((tmp_data[3] != back_data[3] || tmp_data[2] != back_data[2] || tmp_data[1] != back_data[1] || tmp_data[0] != back_data[0]) && retry_cnt < HIMAX_REG_RETRY_TIMES); +} + +static void himax_mcu_diag_register_set(uint8_t diag_command, uint8_t storage_type) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + + if (diag_command > 0 && storage_type % 8 > 0) + tmp_data[0] = diag_command + 0x08; + else + tmp_data[0] = diag_command; + I("diag_command = %d, tmp_data[0] = %X\n", diag_command, tmp_data[0]); + g_core_fp.fp_interface_on(); + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; + g_core_fp.fp_flash_write_burst(pfw_op->addr_raw_out_sel, tmp_data); + g_core_fp.fp_register_read(pfw_op->addr_raw_out_sel, FOUR_BYTE_DATA_SZ, tmp_data, 0); + I("%s: tmp_data[3]=0x%02X,tmp_data[2]=0x%02X,tmp_data[1]=0x%02X,tmp_data[0]=0x%02X!\n", + __func__, tmp_data[3], tmp_data[2], tmp_data[1], tmp_data[0]); +} + +static int himax_mcu_chip_self_test(void) +{ + uint8_t tmp_data[FLASH_WRITE_BURST_SZ]; + uint8_t self_test_info[20]; + int pf_value = 0x00; + uint8_t test_result_id = 0; + int i; + + memset(tmp_data, 0x00, sizeof(tmp_data)); + g_core_fp.fp_interface_on(); + g_core_fp.fp_sense_off(); + g_core_fp.fp_burst_enable(1); + /* 0x10007f18 -> 0x00006AA6 */ + g_core_fp.fp_flash_write_burst(pfw_op->addr_selftest_addr_en, pfw_op->data_selftest_request); + /* Set criteria 0x10007F1C [0,1]=aa/up,down=, [2-3]=key/up,down, [4-5]=avg/up,down */ + tmp_data[0] = pfw_op->data_criteria_aa_top[0]; + tmp_data[1] = pfw_op->data_criteria_aa_bot[0]; + tmp_data[2] = pfw_op->data_criteria_key_top[0]; + tmp_data[3] = pfw_op->data_criteria_key_bot[0]; + tmp_data[4] = pfw_op->data_criteria_avg_top[0]; + tmp_data[5] = pfw_op->data_criteria_avg_bot[0]; + tmp_data[6] = 0x00; + tmp_data[7] = 0x00; + g_core_fp.fp_flash_write_burst_length(pfw_op->addr_criteria_addr, tmp_data, FLASH_WRITE_BURST_SZ); + /* 0x10007294 -> 0x0000190 //SET IIR_MAX FRAMES */ + g_core_fp.fp_flash_write_burst(pfw_op->addr_set_frame_addr, pfw_op->data_set_frame); + /* Disable IDLE Mode */ + g_core_fp.fp_idle_mode(1); + /* 0x10007f00 -> 0x0000A55A //Disable Flash Reload */ + g_core_fp.fp_reload_disable(1); + /* start selftest // leave safe mode */ + g_core_fp.fp_sense_on(0x01); + + /* Hand shaking -> 0x10007f18 waiting 0xA66A */ + for (i = 0; i < 1000; i++) { + g_core_fp.fp_register_read(pfw_op->addr_selftest_addr_en, 4, tmp_data, 0); + I("%s: tmp_data[0] = 0x%02X,tmp_data[1] = 0x%02X,tmp_data[2] = 0x%02X,tmp_data[3] = 0x%02X, cnt=%d\n", + __func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3], i); + msleep(20); + + if (tmp_data[1] == pfw_op->data_selftest_ack_hb[0] && tmp_data[0] == pfw_op->data_selftest_ack_lb[0]) { + I("%s Data ready goto moving data\n", __func__); + break; + } + } + + g_core_fp.fp_sense_off(); + msleep(20); + /* + *===================================== + * Read test result ID : 0x10007f24 ==> bit[2][1][0] = [key][AA][avg] => 0xF = PASS + *===================================== + */ + g_core_fp.fp_register_read(pfw_op->addr_selftest_result_addr, 20, self_test_info, 0); + test_result_id = self_test_info[0]; + I("%s: check test result, test_result_id=%x, test_result=%x\n", __func__ + , test_result_id, self_test_info[0]); + I("raw top 1 = %d\n", self_test_info[3] * 256 + self_test_info[2]); + I("raw top 2 = %d\n", self_test_info[5] * 256 + self_test_info[4]); + I("raw top 3 = %d\n", self_test_info[7] * 256 + self_test_info[6]); + I("raw last 1 = %d\n", self_test_info[9] * 256 + self_test_info[8]); + I("raw last 2 = %d\n", self_test_info[11] * 256 + self_test_info[10]); + I("raw last 3 = %d\n", self_test_info[13] * 256 + self_test_info[12]); + I("raw key 1 = %d\n", self_test_info[15] * 256 + self_test_info[14]); + I("raw key 2 = %d\n", self_test_info[17] * 256 + self_test_info[16]); + I("raw key 3 = %d\n", self_test_info[19] * 256 + self_test_info[18]); + + if (test_result_id == pfw_op->data_selftest_pass[0]) { + I("[Himax]: self-test pass\n"); + pf_value = 0x0; + } else { + E("[Himax]: self-test fail\n"); + /* + * E("[Himax]: bank_avg = %d, bank_max = %d,%d,%d, bank_min = %d,%d,%d, key = %d,%d,%d\n", + * tmp_data[1],tmp_data[2],tmp_data[3],tmp_data[4],tmp_data[5],tmp_data[6],tmp_data[7], + * tmp_data[8],tmp_data[9],tmp_data[10]); + */ + pf_value = 0x1; + } + + /* Enable IDLE Mode */ + g_core_fp.fp_idle_mode(0); + /* 0x10007f00 -> 0x00000000 //Enable Flash Reload //recovery */ + g_core_fp.fp_reload_disable(0); + g_core_fp.fp_sense_on(0x00); + msleep(120); + return pf_value; +} + +static void himax_mcu_idle_mode(int disable) +{ + int retry = 20; + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + uint8_t switch_cmd = 0x00; + + I("%s:entering\n", __func__); + + do { + I("%s,now %d times\n!", __func__, retry); + g_core_fp.fp_register_read(pfw_op->addr_fw_mode_status, FOUR_BYTE_DATA_SZ, tmp_data, 0); + + if (disable) + switch_cmd = pfw_op->data_idle_dis_pwd[0]; + else + switch_cmd = pfw_op->data_idle_en_pwd[0]; + + tmp_data[0] = switch_cmd; + g_core_fp.fp_flash_write_burst(pfw_op->addr_fw_mode_status, tmp_data); + g_core_fp.fp_register_read(pfw_op->addr_fw_mode_status, FOUR_BYTE_DATA_SZ, tmp_data, 0); + I("%s:After turn ON/OFF IDLE Mode [0] = 0x%02X,[1] = 0x%02X,[2] = 0x%02X,[3] = 0x%02X\n", + __func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + retry--; + msleep(20); + } while ((tmp_data[0] != switch_cmd) && retry > 0); + + I("%s: setting OK!\n", __func__); +} + +static void himax_mcu_reload_disable(int disable) +{ + I("%s:entering\n", __func__); + + if (disable) /* reload disable */ + g_core_fp.fp_flash_write_burst(pdriver_op->addr_fw_define_flash_reload, pdriver_op->data_fw_define_flash_reload_dis); + else /* reload enable */ + g_core_fp.fp_flash_write_burst(pdriver_op->addr_fw_define_flash_reload, pdriver_op->data_fw_define_flash_reload_en); + + I("%s: setting OK!\n", __func__); +} + +static bool himax_mcu_check_chip_version(void) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + uint8_t ret_data = false; + int i = 0; + + for (i = 0; i < 5; i++) { + g_core_fp.fp_register_read(pfw_op->addr_icid_addr, FOUR_BYTE_DATA_SZ, tmp_data, 0); + I("%s:Read driver IC ID = %X,%X,%X\n", __func__, tmp_data[3], tmp_data[2], tmp_data[1]); + + if ((tmp_data[3] == 0x83) && (tmp_data[2] == 0x10) && (tmp_data[1] == 0x2a)) { + strlcpy(private_ts->chip_name, HX_83102A_SERIES_PWON, 30); + ret_data = true; + break; + } + + ret_data = false; + E("%s:Read driver ID register Fail:\n", __func__); + } + + return ret_data; +} + +static int himax_mcu_read_ic_trigger_type(void) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + int trigger_type = false; + + g_core_fp.fp_register_read(pfw_op->addr_trigger_addr, FOUR_BYTE_DATA_SZ, tmp_data, 0); + + if ((tmp_data[0] & 0x01) == 1) + trigger_type = true; + + return trigger_type; +} + +static int himax_mcu_read_i2c_status(void) +{ + return i2c_error_count; +} + +static void himax_mcu_read_FW_ver(void) +{ + uint8_t data[FOUR_BYTE_DATA_SZ]; + uint8_t data_2[FOUR_BYTE_DATA_SZ]; + int retry = 200; + int reload_status = 0; + + g_core_fp.fp_sense_on(0x00); + + while (reload_status == 0) { + /* cmd[3] = 0x10; cmd[2] = 0x00; cmd[1] = 0x7f; cmd[0] = 0x00; */ + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_flash_reload, FOUR_BYTE_DATA_SZ, data, 0); + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_2nd_flash_reload, FOUR_BYTE_DATA_SZ, data_2, 0); + + if ((data[1] == 0x3A && data[0] == 0xA3) + || (data_2[1] == 0x72 && data_2[0] == 0xC0)) { + I("reload OK!\n"); + reload_status = 1; + break; + } else if (retry == 0) { + E("reload 20 times! fail\n"); + ic_data->vendor_panel_ver = 0; + ic_data->vendor_fw_ver = 0; + ic_data->vendor_config_ver = 0; + ic_data->vendor_touch_cfg_ver = 0; + ic_data->vendor_display_cfg_ver = 0; + ic_data->vendor_cid_maj_ver = 0; + ic_data->vendor_cid_min_ver = 0; + return; + } + + retry--; + msleep(20); + if (retry % 10 == 0) + I("reload fail ,delay 10ms retry=%d\n", retry); + + } + + I("%s : data[0]=0x%2.2X,data[1]=0x%2.2X,data_2[0]=0x%2.2X,data_2[1]=0x%2.2X\n", __func__, data[0], data[1], data_2[0], data_2[1]); + I("reload_status=%d\n", reload_status); + /* + *===================================== + * Read FW version : 0x1000_7004 but 05,06 are the real addr for FW Version + *===================================== + */ + g_core_fp.fp_sense_off(); + g_core_fp.fp_register_read(pfw_op->addr_fw_ver_addr, FOUR_BYTE_DATA_SZ, data, 0); + ic_data->vendor_panel_ver = data[0]; + ic_data->vendor_fw_ver = data[1] << 8 | data[2]; + I("PANEL_VER : %X\n", ic_data->vendor_panel_ver); + I("FW_VER : %X\n", ic_data->vendor_fw_ver); + g_core_fp.fp_register_read(pfw_op->addr_fw_cfg_addr, FOUR_BYTE_DATA_SZ, data, 0); + ic_data->vendor_config_ver = data[2] << 8 | data[3]; + /* I("CFG_VER : %X\n",ic_data->vendor_config_ver); */ + ic_data->vendor_touch_cfg_ver = data[2]; + I("TOUCH_VER : %X\n", ic_data->vendor_touch_cfg_ver); + ic_data->vendor_display_cfg_ver = data[3]; + I("DISPLAY_VER : %X\n", ic_data->vendor_display_cfg_ver); + g_core_fp.fp_register_read(pfw_op->addr_fw_vendor_addr, FOUR_BYTE_DATA_SZ, data, 0); + ic_data->vendor_cid_maj_ver = data[2]; + ic_data->vendor_cid_min_ver = data[3]; + I("CID_VER : %X\n", (ic_data->vendor_cid_maj_ver << 8 | ic_data->vendor_cid_min_ver)); +} + +static bool himax_mcu_read_event_stack(uint8_t *buf, uint8_t length) +{ + uint8_t cmd[FOUR_BYTE_DATA_SZ]; + /* AHB_I2C Burst Read Off */ + cmd[0] = pfw_op->data_ahb_dis[0]; + + if (himax_bus_write(pfw_op->addr_ahb_addr[0], cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return 0; + } + + if (himax_bus_read(pfw_op->addr_event_addr[0], buf, length, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return 0; + } + /* AHB_I2C Burst Read On */ + cmd[0] = pfw_op->data_ahb_en[0]; + + if (himax_bus_write(pfw_op->addr_ahb_addr[0], cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return 0; + } + + return 1; +} + +static void himax_mcu_return_event_stack(void) +{ + int retry = 20, i; + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + + I("%s:entering\n", __func__); + + do { + I("now %d times\n!", retry); + + for (i = 0; i < FOUR_BYTE_DATA_SZ; i++) + tmp_data[i] = psram_op->addr_rawdata_end[i]; + + g_core_fp.fp_flash_write_burst(psram_op->addr_rawdata_addr, tmp_data); + g_core_fp.fp_register_read(psram_op->addr_rawdata_addr, FOUR_BYTE_DATA_SZ, tmp_data, 0); + retry--; + msleep(20); + } while ((tmp_data[1] != psram_op->addr_rawdata_end[1] && tmp_data[0] != psram_op->addr_rawdata_end[0]) && retry > 0); + + I("%s: End of setting!\n", __func__); +} + +static bool himax_mcu_calculateChecksum(bool change_iref) +{ + uint8_t CRC_result = 0, i; + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + + for (i = 0; i < FOUR_BYTE_DATA_SZ; i++) + tmp_data[i] = psram_op->addr_rawdata_end[i]; + + CRC_result = g_core_fp.fp_check_CRC(tmp_data, FW_SIZE_64k); + msleep(50); + + return (CRC_result == 0) ? true : false; +} + +static int himax_mcu_read_FW_status(uint8_t *state_addr, uint8_t *tmp_addr) +{ + uint8_t i; + uint8_t req_size = 0; + uint8_t status_addr[FOUR_BYTE_DATA_SZ]; /* 0x10007F44 */ + uint8_t cmd_addr[FOUR_BYTE_DATA_SZ]; /* 0x900000F8 */ + + if (state_addr[0] == 0x01) { + state_addr[1] = 0x04; + + for (i = 0; i < FOUR_BYTE_DATA_SZ; i++) { + /* 0x10007F44 */ + state_addr[i + 2] = pfw_op->addr_fw_dbg_msg_addr[i]; + status_addr[i] = pfw_op->addr_fw_dbg_msg_addr[i]; + } + + req_size = 0x04; + g_core_fp.fp_register_read(status_addr, req_size, tmp_addr, 0); + } else if (state_addr[0] == 0x02) { + state_addr[1] = 0x30; + + for (i = 0; i < FOUR_BYTE_DATA_SZ; i++) { + /* 0x10007F44 */ + state_addr[i + 2] = pfw_op->addr_fw_dbg_msg_addr[i]; + cmd_addr[i] = pfw_op->addr_fw_dbg_msg_addr[i]; + } + + req_size = 0x30; + g_core_fp.fp_register_read(cmd_addr, req_size, tmp_addr, 0); + } + + return NO_ERR; +} + +static void himax_mcu_irq_switch(int switch_on) +{ + if (switch_on) { + if (private_ts->use_irq) + himax_int_enable(switch_on); + else + hrtimer_start(&private_ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + } else { + if (private_ts->use_irq) + himax_int_enable(switch_on); + else { + hrtimer_cancel(&private_ts->timer); + cancel_work_sync(&private_ts->work); + } + } +} + +static int himax_mcu_assign_sorting_mode(uint8_t *tmp_data) +{ + + I("%s:Now tmp_data[3]=0x%02X,tmp_data[2]=0x%02X,tmp_data[1]=0x%02X,tmp_data[0]=0x%02X\n", + __func__, tmp_data[3], tmp_data[2], tmp_data[1], tmp_data[0]); + g_core_fp.fp_flash_write_burst(pfw_op->addr_sorting_mode_en, tmp_data); + + return NO_ERR; +} + +static int himax_mcu_check_sorting_mode(uint8_t *tmp_data) +{ + + g_core_fp.fp_register_read(pfw_op->addr_sorting_mode_en, FOUR_BYTE_DATA_SZ, tmp_data, 0); + I("%s: tmp_data[0]=%x,tmp_data[1]=%x\n", __func__, tmp_data[0], tmp_data[1]); + + return NO_ERR; +} + +static int himax_mcu_switch_mode(int mode) +{ + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + uint8_t mode_write_cmd; + uint8_t mode_read_cmd; + int result = -1; + int retry = 200; + + I("%s: Entering\n", __func__); + + if (mode == 0) { + /* normal mode */ + mode_write_cmd = pfw_op->data_normal_cmd[0]; + mode_read_cmd = pfw_op->data_normal_status[0]; + } else { + /* sorting mode */ + mode_write_cmd = pfw_op->data_sorting_cmd[0]; + mode_read_cmd = pfw_op->data_sorting_status[0]; + } + + g_core_fp.fp_sense_off(); + /* g_core_fp.fp_interface_on();*/ + /* clean up FW status */ + + /* + * tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + * tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + */ + g_core_fp.fp_flash_write_burst(psram_op->addr_rawdata_addr, psram_op->addr_rawdata_end); + /* tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x7F; tmp_addr[0] = 0x04;*/ + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = mode_write_cmd; + tmp_data[0] = mode_write_cmd; + g_core_fp.fp_assign_sorting_mode(tmp_data); + g_core_fp.fp_idle_mode(1); + g_core_fp.fp_reload_disable(1); + + /* To stable the sorting*/ + if (mode) { + /* + * tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x70; tmp_addr[0] = 0xF4; + * tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x08; + */ + g_core_fp.fp_flash_write_burst(pdriver_op->addr_fw_define_rxnum_txnum_maxpt, pdriver_op->data_fw_define_rxnum_txnum_maxpt_sorting); + } else { + g_core_fp.fp_flash_write_burst(pfw_op->addr_set_frame_addr, pfw_op->data_set_frame); + /* + * tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x70; tmp_addr[0] = 0xF4; + * tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x14; + */ + g_core_fp.fp_flash_write_burst(pdriver_op->addr_fw_define_rxnum_txnum_maxpt, pdriver_op->data_fw_define_rxnum_txnum_maxpt_normal); + } + + g_core_fp.fp_sense_on(0x01); + + while (retry != 0) { + I("[%d] %s Read\n", retry, __func__); + /* tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x7F; tmp_addr[0] = 0x04; */ + g_core_fp.fp_check_sorting_mode(tmp_data); + msleep(100); + I("mode_read_cmd(0)=0x%2.2X,mode_read_cmd(1)=0x%2.2X\n", tmp_data[0], tmp_data[1]); + + if (tmp_data[0] == mode_read_cmd && tmp_data[1] == mode_read_cmd) { + I("Read OK!\n"); + result = 0; + break; + } + + /* tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0xA8; */ + g_core_fp.fp_register_read(pfw_op->addr_chk_fw_status, FOUR_BYTE_DATA_SZ, tmp_data, 0); + + if (tmp_data[0] == 0x00 && tmp_data[1] == 0x00 && tmp_data[2] == 0x00 && tmp_data[3] == 0x00) { + E("%s,: FW Stop!\n", __func__); + break; + } + + retry--; + } + + if (result == 0) { + if (mode == 0) + return HX_NORMAL_MODE; /* normal mode */ + else + return HX_SORTING_MODE; /* sorting mode */ + } else + return HX_CHANGE_MODE_FAIL; /* change mode fail */ + +} + +static uint8_t himax_mcu_read_DD_status(uint8_t *cmd_set, uint8_t *tmp_data) +{ + int cnt = 0; + uint8_t req_size = cmd_set[0]; + + cmd_set[3] = pfw_op->data_dd_request[0]; + g_core_fp.fp_register_write(pfw_op->addr_dd_handshak_addr, FOUR_BYTE_DATA_SZ, cmd_set, 0); + I("%s: cmd_set[0] = 0x%02X,cmd_set[1] = 0x%02X,cmd_set[2] = 0x%02X,cmd_set[3] = 0x%02X\n", + __func__, cmd_set[0], cmd_set[1], cmd_set[2], cmd_set[3]); + + /* Doing hand shaking 0xAA -> 0xBB */ + for (cnt = 0; cnt < 100; cnt++) { + g_core_fp.fp_register_read(pfw_op->addr_dd_handshak_addr, FOUR_BYTE_DATA_SZ, tmp_data, 0); + msleep(20); + + if (tmp_data[3] == pfw_op->data_dd_ack[0]) { + I("%s Data ready goto moving data\n", __func__); + break; + } else if (cnt >= 99) { + I("%s Data not ready in FW\n", __func__); + return FW_NOT_READY; + } + } + + g_core_fp.fp_register_read(pfw_op->addr_dd_data_addr, req_size, tmp_data, 0); + return NO_ERR; +} +/* FW side end */ +#endif + +#ifdef CORE_FLASH +/* FLASH side start */ +static void himax_mcu_chip_erase(void) +{ + g_core_fp.fp_interface_on(); + + /* Reset power saving level */ + if (g_core_fp.fp_init_psl != NULL) + g_core_fp.fp_init_psl(); + + /* + *===================================== + * SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_fmt, pflash_op->data_spi200_trans_fmt); + /* + *===================================== + * Chip Erase + * Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 + * 2. 0x8000_0024 ==> 0x0000_0006 + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_2); + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_2); + /* + *===================================== + * Chip Erase + * Erase Command : 0x8000_0024 ==> 0x0000_00C7 + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_3); + msleep(2000); + + if (!g_core_fp.fp_wait_wip(100)) + E("%s: Chip_Erase Fail\n", __func__); + +} + +/* complete not yet */ +static bool himax_mcu_block_erase(int start_addr, int length) +{ + uint32_t page_prog_start = 0; + uint32_t block_size = 0x10000; + + g_core_fp.fp_interface_on(); + + g_core_fp.fp_init_psl(); + + /* + *===================================== + * SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_fmt, pflash_op->data_spi200_trans_fmt); + + for (page_prog_start = start_addr; page_prog_start < start_addr + length; page_prog_start = page_prog_start + block_size) { + /* + *===================================== + * Chip Erase + * Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 + * 2. 0x8000_0024 ==> 0x0000_0006 + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_2); + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_2); + /* + *===================================== + * Block Erase + * Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr + * 0x8000_0020 ==> 0x6700_0000 //control + * 0x8000_0024 ==> 0x0000_0052 //BE + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_addr, pflash_op->data_spi200_addr); + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_3); + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_4); + msleep(1000); + + if (!g_core_fp.fp_wait_wip(100)) { + E("%s:Erase Fail\n", __func__); + return false; + } + } + + I("%s:END\n", __func__); + return true; +} + +static bool himax_mcu_sector_erase(int start_addr) +{ + return true; +} + +static void himax_mcu_flash_programming(uint8_t *FW_content, int FW_Size) +{ + int page_prog_start = 0, i = 0, j = 0, k = 0; + int program_length = PROGRAM_SZ; + uint8_t tmp_data[FOUR_BYTE_DATA_SZ]; + uint8_t buring_data[FLASH_RW_MAX_LEN]; /* Read for flash data, 128K */ + + /* 4 bytes for 0x80002C padding */ + g_core_fp.fp_interface_on(); + /* + *===================================== + * SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_fmt, pflash_op->data_spi200_trans_fmt); + + for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start += FLASH_RW_MAX_LEN) { + /* + *===================================== + * Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 + * 2. 0x8000_0024 ==> 0x0000_0006 + *===================================== + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_2); + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_2); + /* + *================================= + * SPI Transfer Control + * Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000 + * Set read start address : 0x8000_0028 ==> 0x0000_0000 + *================================= + * data bytes should be 0x6100_0000 + ((word_number)*4-1)*4096 = 0x6100_0000 + 0xFF000 = 0x610F_F000 + * Programmable size = 1 page = 256 bytes, word_number = 256 byte / 4 = 64 + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_4); + + /* Flash start address 1st : 0x0000_0000 */ + if (page_prog_start < 0x100) { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = (uint8_t)page_prog_start; + } else if (page_prog_start >= 0x100 && page_prog_start < 0x10000) { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000) { + tmp_data[3] = 0x00; + tmp_data[2] = (uint8_t)(page_prog_start >> 16); + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } + + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_addr, tmp_data); + + /* + *================================= + * Send 16 bytes data : 0x8000_002C ==> 16 bytes data + *================================= + */ + for (i = 0; i < FOUR_BYTE_ADDR_SZ; i++) + buring_data[i] = pflash_op->addr_spi200_data[i]; + + for (i = page_prog_start, j = 0; i < 16 + page_prog_start; i++, j++)/* <------ bin file */ + buring_data[j + FOUR_BYTE_ADDR_SZ] = FW_content[i]; + + if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], buring_data, FOUR_BYTE_ADDR_SZ + 16, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + /* + *================================= + * Write command : 0x8000_0024 ==> 0x0000_0002 + *================================= + */ + g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_6); + + /* + *================================= + * Send 240 bytes data : 0x8000_002C ==> 240 bytes data + *================================= + */ + for (j = 0; j < 5; j++) { + for (i = (page_prog_start + 16 + (j * 48)), k = 0; i < (page_prog_start + 16 + (j * 48)) + program_length; i++, k++) + buring_data[k + FOUR_BYTE_ADDR_SZ] = FW_content[i]; + + if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], buring_data, program_length + FOUR_BYTE_ADDR_SZ, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + } + + if (!g_core_fp.fp_wait_wip(1)) + E("%s:Flash_Programming Fail\n", __func__); + } +} + +static void himax_mcu_flash_page_write(uint8_t *write_addr, int length, uint8_t *write_data) +{ +} + +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_32k(unsigned char *fw, int len, bool change_iref) +{ + /* Not use */ + return 0; +} + +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_60k(unsigned char *fw, int len, bool change_iref) +{ + /* Not use */ + return 0; +} + +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_64k(unsigned char *fw, int len, bool change_iref) +{ + int burnFW_success = 0; + + if (len != FW_SIZE_64k) { + E("%s: The file size is not 64K bytes\n", __func__); + return false; + } + +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + /* + * tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x18; + * tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x55; + */ + g_core_fp.fp_system_reset(); +#endif + g_core_fp.fp_sense_off(); + g_core_fp.fp_chip_erase(); + g_core_fp.fp_flash_programming(fw, FW_SIZE_64k); + + if (g_core_fp.fp_check_CRC(pfw_op->addr_program_reload_from, FW_SIZE_64k) == 0) + burnFW_success = 1; + + /* RawOut select initial */ + g_core_fp.fp_register_write(pfw_op->addr_raw_out_sel, sizeof(pfw_op->data_clear), pfw_op->data_clear, false); + /* DSRAM func initial */ + g_core_fp.fp_assign_sorting_mode(pfw_op->data_clear); + +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + /* + * System reset + * tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x18; + * tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x55; + */ + g_core_fp.fp_system_reset(); +#endif + return burnFW_success; +} + +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_124k(unsigned char *fw, int len, bool change_iref) +{ + /* Not use */ + return 0; +} + +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_128k(unsigned char *fw, int len, bool change_iref) +{ + /* Not use */ + return 0; +} + +static void himax_mcu_flash_dump_func(uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer) +{ + uint8_t tmp_addr[FOUR_BYTE_DATA_SZ]; + uint8_t buffer[256]; + int page_prog_start = 0; + + g_core_fp.fp_sense_off(); + g_core_fp.fp_burst_enable(1); + + for (page_prog_start = 0; page_prog_start < Flash_Size; page_prog_start += 128) { + /* + *================================= + * SPI Transfer Control + * Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF + * Set read start address : 0x8000_0028 ==> 0x0000_0000 + * Set command : 0x8000_0024 ==> 0x0000_003B + *================================= + */ + tmp_addr[0] = page_prog_start % 0x100; + tmp_addr[1] = (page_prog_start >> 8) % 0x100; + tmp_addr[2] = (page_prog_start >> 16) % 0x100; + tmp_addr[3] = page_prog_start / 0x1000000; + himax_mcu_register_read(tmp_addr, 128, buffer, 0); + memcpy(&flash_buffer[page_prog_start], buffer, 128); + } + + g_core_fp.fp_burst_enable(0); + g_core_fp.fp_sense_on(0x01); +} + +static bool himax_mcu_flash_lastdata_check(void) +{ + uint8_t tmp_addr[4]; + uint32_t start_addr = 0xFF80; + uint32_t temp_addr = 0; + uint32_t flash_page_len = 0x80; + uint8_t flash_tmp_buffer[128]; + + for (temp_addr = start_addr; temp_addr < (start_addr + flash_page_len); temp_addr = temp_addr + flash_page_len) { + /* I("temp_addr=%d,tmp_addr[0]=0x%2X, tmp_addr[1]=0x%2X,tmp_addr[2]=0x%2X,tmp_addr[3]=0x%2X\n", temp_addr,tmp_addr[0], tmp_addr[1], tmp_addr[2],tmp_addr[3]); */ + tmp_addr[0] = temp_addr % 0x100; + tmp_addr[1] = (temp_addr >> 8) % 0x100; + tmp_addr[2] = (temp_addr >> 16) % 0x100; + tmp_addr[3] = temp_addr / 0x1000000; + g_core_fp.fp_register_read(tmp_addr, flash_page_len, &flash_tmp_buffer[0], 0); + } + + if ((!flash_tmp_buffer[flash_page_len-4]) && (!flash_tmp_buffer[flash_page_len-3]) && (!flash_tmp_buffer[flash_page_len-2]) && (!flash_tmp_buffer[flash_page_len-1])) + return 1;/* FAIL */ + + I("flash_buffer[FFFC]=0x%2X,flash_buffer[FFFD]=0x%2X,flash_buffer[FFFE]=0x%2X,flash_buffer[FFFF]=0x%2X\n", + flash_tmp_buffer[flash_page_len-4], flash_tmp_buffer[flash_page_len-3], flash_tmp_buffer[flash_page_len-2], flash_tmp_buffer[flash_page_len-1]); + return 0;/* PASS */ +} +/* FLASH side end */ +#endif + +#ifdef CORE_SRAM +/* SRAM side start */ +static void himax_mcu_sram_write(uint8_t *FW_content) +{ +} + +static bool himax_mcu_sram_verify(uint8_t *FW_File, int FW_Size) +{ + return true; +} + +static void himax_mcu_get_DSRAM_data(uint8_t *info_data, bool DSRAM_Flag) +{ + int i = 0; + unsigned char tmp_addr[FOUR_BYTE_ADDR_SZ]; + unsigned char tmp_data[FOUR_BYTE_DATA_SZ]; + uint8_t max_i2c_size = MAX_I2C_TRANS_SZ; + uint8_t x_num = ic_data->HX_RX_NUM; + uint8_t y_num = ic_data->HX_TX_NUM; + /* int m_key_num = 0; */ + int total_size = (x_num * y_num + x_num + y_num) * 2 + 4; + int total_size_temp; + int mutual_data_size = x_num * y_num * 2; + int total_read_times = 0; + int address = 0; + uint8_t *temp_info_data; /* max mkey size = 8 */ + uint16_t check_sum_cal = 0; + int fw_run_flag = -1; + + temp_info_data = kcalloc((total_size + 8), sizeof(uint8_t), GFP_KERNEL); + if (!temp_info_data) { + E("%s: allocate memory failed!\n", __func__); + return; + } + /* + *1. Read number of MKey R100070E8H to determin data size + * m_key_num = ic_data->HX_BT_NUM; + * I("%s,m_key_num=%d\n",__func__ ,m_key_num); + * total_size += m_key_num * 2; + *2. Start DSRAM Rawdata and Wait Data Ready + *=====tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + */ + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = psram_op->passwrd_start[1]; + tmp_data[0] = psram_op->passwrd_start[0]; + fw_run_flag = himax_write_read_reg(psram_op->addr_rawdata_addr, tmp_data, psram_op->passwrd_end[1], psram_op->passwrd_end[0]); + + if (fw_run_flag < 0) { + I("%s Data NOT ready => bypass\n", __func__); + kfree(temp_info_data); + return; + } + + /* 3. Read RawData */ + total_size_temp = total_size; + /* ====tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; */ + I("%s: tmp_data[0] = 0x%02X,tmp_data[1] = 0x%02X,tmp_data[2] = 0x%02X,tmp_data[3] = 0x%02X\n", + __func__, psram_op->addr_rawdata_addr[0], psram_op->addr_rawdata_addr[1], psram_op->addr_rawdata_addr[2], psram_op->addr_rawdata_addr[3]); + tmp_addr[0] = psram_op->addr_rawdata_addr[0]; + tmp_addr[1] = psram_op->addr_rawdata_addr[1]; + tmp_addr[2] = psram_op->addr_rawdata_addr[2]; + tmp_addr[3] = psram_op->addr_rawdata_addr[3]; + + if (total_size % max_i2c_size == 0) + total_read_times = total_size / max_i2c_size; + else + total_read_times = total_size / max_i2c_size + 1; + + for (i = 0; i < total_read_times; i++) { + address = (psram_op->addr_rawdata_addr[3] << 24) + + (psram_op->addr_rawdata_addr[2] << 16) + + (psram_op->addr_rawdata_addr[1] << 8) + + psram_op->addr_rawdata_addr[0] + i * max_i2c_size; + I("%s address = %08X\n", __func__, address); + + tmp_addr[3] = (uint8_t)((address >> 24) & 0x00FF); + tmp_addr[2] = (uint8_t)((address >> 16) & 0x00FF); + tmp_addr[1] = (uint8_t)((address >> 8) & 0x00FF); + tmp_addr[0] = (uint8_t)((address) & 0x00FF); + + if (total_size_temp >= max_i2c_size) { + g_core_fp.fp_register_read(tmp_addr, max_i2c_size, &temp_info_data[i * max_i2c_size], 0); + total_size_temp = total_size_temp - max_i2c_size; + } else { + /* I("last total_size_temp=%d\n",total_size_temp); */ + g_core_fp.fp_register_read(tmp_addr, total_size_temp % max_i2c_size, &temp_info_data[i * max_i2c_size], 0); + } + } + + /* 4. FW stop outputing */ + /* I("DSRAM_Flag=%d\n",DSRAM_Flag); */ + if (DSRAM_Flag == false) { + /* + * I("Return to Event Stack!\n"); + * ====tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + * ====tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + */ + g_core_fp.fp_flash_write_burst(psram_op->addr_rawdata_addr, psram_op->data_fin); + } else { + /* + * I("Continue to SRAM!\n"); + * =====tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + * =====tmp_data[3] = 0x11; tmp_data[2] = 0x22; tmp_data[1] = 0x33; tmp_data[0] = 0x44; + */ + g_core_fp.fp_flash_write_burst(psram_op->addr_rawdata_addr, psram_op->data_conti); + } + + /* 5. Data Checksum Check */ + for (i = 2; i < total_size; i += 2) /* 2:PASSWORD NOT included */ + check_sum_cal += (temp_info_data[i + 1] * 256 + temp_info_data[i]); + + if (check_sum_cal % 0x10000 != 0) { + I("%s check_sum_cal fail=%2X\n", __func__, check_sum_cal); + kfree(temp_info_data); + return; + } + + memcpy(info_data, &temp_info_data[4], mutual_data_size * sizeof(uint8_t)); + /* I("%s checksum PASS\n", __func__); */ + + kfree(temp_info_data); +} +/* SRAM side end */ +#endif + +#ifdef CORE_DRIVER +static bool himax_mcu_detect_ic(void) +{ + I("%s: use default incell detect.\n", __func__); + + return 0; +} + + +static void himax_mcu_init_ic(void) +{ + I("%s: use default incell init.\n", __func__); +} + + +#ifdef HX_RST_PIN_FUNC +static void himax_mcu_pin_reset(void) +{ + I("%s: Now reset the Touch chip.\n", __func__); + himax_rst_gpio_set(private_ts->rst_gpio, 0); + msleep(20); + himax_rst_gpio_set(private_ts->rst_gpio, 1); + msleep(50); +} + +static void himax_mcu_ic_reset(uint8_t loadconfig, uint8_t int_off) +{ + struct himax_ts_data *ts = private_ts; + + HX_HW_RESET_ACTIVATE = 1; + I("%s,status: loadconfig=%d,int_off=%d\n", __func__, loadconfig, int_off); + + if (ts->rst_gpio >= 0) { + if (int_off) + g_core_fp.fp_irq_switch(0); + + g_core_fp.fp_pin_reset(); + + if (loadconfig) + g_core_fp.fp_reload_config(); + + if (int_off) + g_core_fp.fp_irq_switch(1); + } +} +#endif + +static void himax_mcu_touch_information(void) +{ +#ifndef HX_FIX_TOUCH_INFO + char data[EIGHT_BYTE_DATA_SZ] = {0}; + + /* cmd[3] = 0x10; cmd[2] = 0x00; cmd[1] = 0x70; cmd[0] = 0xF4; */ + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_rxnum_txnum_maxpt, EIGHT_BYTE_DATA_SZ, data, 0); + ic_data->HX_RX_NUM = data[2]; + ic_data->HX_TX_NUM = data[3]; + ic_data->HX_MAX_PT = data[4]; + /* + * I("%s : HX_RX_NUM=%d,ic_data->HX_TX_NUM=%d,ic_data->HX_MAX_PT=%d\n",__func__,ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_MAX_PT); + * cmd[3] = 0x10; cmd[2] = 0x00; cmd[1] = 0x70; cmd[0] = 0xFA; + */ + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_xy_res_enable, FOUR_BYTE_DATA_SZ, data, 0); + + /* I("%s : c_data->HX_XY_REVERSE=0x%2.2X\n",__func__,data[1]); */ + if ((data[1] & 0x04) == 0x04) + ic_data->HX_XY_REVERSE = true; + else + ic_data->HX_XY_REVERSE = false; + + /* cmd[3] = 0x10; cmd[2] = 0x00; cmd[1] = 0x70; cmd[0] = 0xFC; */ + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_x_y_res, FOUR_BYTE_DATA_SZ, data, 0); + ic_data->HX_Y_RES = data[0] * 256 + data[1]; + ic_data->HX_X_RES = data[2] * 256 + data[3]; + /* + * I("%s : ic_data->HX_Y_RES=%d,ic_data->HX_X_RES=%d\n",__func__,ic_data->HX_Y_RES,ic_data->HX_X_RES); + * cmd[3] = 0x10; cmd[2] = 0x00; cmd[1] = 0x70; cmd[0] = 0x89; + */ + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_int_is_edge, FOUR_BYTE_DATA_SZ, data, 0); + + /* + * I("%s : data[0]=0x%2.2X,data[1]=0x%2.2X,data[2]=0x%2.2X,data[3]=0x%2.2X\n",__func__,data[0],data[1],data[2],data[3]); + * I("data[0] & 0x01 = %d\n",(data[0] & 0x01)); + */ + if ((data[0] & 0x01) == 1) + ic_data->HX_INT_IS_EDGE = true; + else + ic_data->HX_INT_IS_EDGE = false; + + if (ic_data->HX_RX_NUM > 40) + ic_data->HX_RX_NUM = 32; + + + if (ic_data->HX_TX_NUM > 20) + ic_data->HX_TX_NUM = 18; + + if (ic_data->HX_MAX_PT > 10) + ic_data->HX_MAX_PT = 10; + + if (ic_data->HX_Y_RES > 2000) + ic_data->HX_Y_RES = 1280; + + if (ic_data->HX_X_RES > 2000) + ic_data->HX_X_RES = 720; + + /* 1. Read number of MKey R100070E8H to determin data size */ + /* ====tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x70; tmp_addr[0] = 0xE8; */ + g_core_fp.fp_register_read(psram_op->addr_mkey, FOUR_BYTE_DATA_SZ, data, 0); + /* + * I("%s: tmp_data[0] = 0x%02X,tmp_data[1] = 0x%02X,tmp_data[2] = 0x%02X,tmp_data[3] = 0x%02X\n", + * __func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + */ + ic_data->HX_BT_NUM = data[0] & 0x03; +#else + ic_data->HX_RX_NUM = FIX_HX_RX_NUM; + ic_data->HX_TX_NUM = FIX_HX_TX_NUM; + ic_data->HX_BT_NUM = FIX_HX_BT_NUM; + ic_data->HX_X_RES = FIX_HX_X_RES; + ic_data->HX_Y_RES = FIX_HX_Y_RES; + ic_data->HX_MAX_PT = FIX_HX_MAX_PT; + ic_data->HX_XY_REVERSE = FIX_HX_XY_REVERSE; + ic_data->HX_INT_IS_EDGE = FIX_HX_INT_IS_EDGE; +#endif + I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d\n", __func__, ic_data->HX_RX_NUM, ic_data->HX_TX_NUM, ic_data->HX_MAX_PT); + I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d\n", __func__, ic_data->HX_XY_REVERSE, ic_data->HX_Y_RES, ic_data->HX_X_RES); + I("%s:HX_INT_IS_EDGE =%d\n", __func__, ic_data->HX_INT_IS_EDGE); +} + +static void himax_mcu_reload_config(void) +{ + if (himax_report_data_init()) + E("%s: allocate data fail\n", __func__); + + g_core_fp.fp_sense_on(0x00); +} + +static int himax_mcu_get_touch_data_size(void) +{ + return HIMAX_TOUCH_DATA_SIZE; +} + +static int himax_mcu_hand_shaking(void) +{ + /* 0:Running, 1:Stop, 2:I2C Fail */ + int result = 0; + return result; +} + +static int himax_mcu_determin_diag_rawdata(int diag_command) +{ + return diag_command % 10; +} + +static int himax_mcu_determin_diag_storage(int diag_command) +{ + return diag_command / 10; +} + +static int himax_mcu_cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max) +{ + int RawDataLen; + + if (raw_cnt_rmd != 0x00) + RawDataLen = MAX_I2C_TRANS_SZ - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 1; + else + RawDataLen = MAX_I2C_TRANS_SZ - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 1; + + return RawDataLen; +} + +static bool himax_mcu_diag_check_sum(struct himax_report_data *hx_touch_data) +{ + uint16_t check_sum_cal = 0; + int i; + + /* Check 128th byte CRC */ + for (i = 0, check_sum_cal = 0; i < (hx_touch_data->touch_all_size - hx_touch_data->touch_info_size); i += 2) + check_sum_cal += (hx_touch_data->hx_rawdata_buf[i + 1] * FLASH_RW_MAX_LEN + hx_touch_data->hx_rawdata_buf[i]); + + if (check_sum_cal % HX64K != 0) { + I("%s fail=%2X\n", __func__, check_sum_cal); + return 0; + } + + return 1; +} + +static void himax_mcu_diag_parse_raw_data(struct himax_report_data *hx_touch_data, int mul_num, int self_num, uint8_t diag_cmd, int32_t *mutual_data, int32_t *self_data) +{ + diag_mcu_parse_raw_data(hx_touch_data, mul_num, self_num, diag_cmd, mutual_data, self_data); +} + +#ifdef HX_ESD_RECOVERY +static int himax_mcu_ic_esd_recovery(int hx_esd_event, int hx_zero_event, int length) +{ + int ret_val = NO_ERR; + + if (g_zero_event_count > 5) { + g_zero_event_count = 0; + I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n"); + ret_val = HX_ESD_EVENT; + goto END_FUNCTION; + } + + if (hx_esd_event == length) { + g_zero_event_count = 0; + ret_val = HX_ESD_EVENT; + goto END_FUNCTION; + } else if (hx_zero_event == length) { + g_zero_event_count++; + I("[HIMAX TP MSG]: ALL Zero event is %d times.\n", g_zero_event_count); + ret_val = HX_ZERO_EVENT_COUNT; + goto END_FUNCTION; + } + +END_FUNCTION: + return ret_val; +} + +static void himax_mcu_esd_ic_reset(void) +{ + HX_ESD_RESET_ACTIVATE = 0; +#ifdef HX_RST_PIN_FUNC + himax_mcu_pin_reset(); +#endif + I("%s:\n", __func__); +} +#endif +#endif + +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || defined(HX_USB_DETECT_GLOBAL) +static void himax_mcu_resend_cmd_func(bool suspended) +{ +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) + struct himax_ts_data *ts = private_ts; +#endif +#ifdef HX_SMART_WAKEUP + g_core_fp.fp_set_SMWP_enable(ts->SMWP_enable, suspended); +#endif +#ifdef HX_HIGH_SENSE + g_core_fp.fp_set_HSEN_enable(ts->HSEN_enable, suspended); +#endif +#ifdef HX_USB_DETECT_GLOBAL + himax_cable_detect_func(true); +#endif +} +#endif + +#ifdef HX_ZERO_FLASH +int G_POWERONOF = 1; +void himax_mcu_sys_reset(void) +{ + /* 0x10007f00 -> 0x00009AA9 //Disable Flash Reload */ + g_core_fp.fp_flash_write_burst(pzf_op->addr_dis_flash_reload, pzf_op->data_dis_flash_reload); + msleep(20); + g_core_fp.fp_register_write(pzf_op->addr_system_reset, 4, pzf_op->data_system_reset, false); +} +void himax_mcu_clean_sram_0f(uint8_t *addr, int write_len, int type) +{ + int total_read_times = 0; + int max_bus_size = MAX_I2C_TRANS_SZ; + int total_size_temp = 0; + int total_size = 0; + int address = 0; + int i = 0; + + uint8_t fix_data = 0x00; + uint8_t tmp_addr[4]; + uint8_t tmp_data[MAX_I2C_TRANS_SZ] = {0}; + + I("%s, Entering\n", __func__); + + total_size = write_len; + + if (total_size > 4096) + max_bus_size = 4096; + + total_size_temp = write_len; + + g_core_fp.fp_burst_enable(1); + + tmp_addr[3] = addr[3]; + tmp_addr[2] = addr[2]; + tmp_addr[1] = addr[1]; + tmp_addr[0] = addr[0]; + I("%s, write addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n", + __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + + switch (type) { + case 0: + fix_data = 0x00; + break; + case 1: + fix_data = 0xAA; + break; + case 2: + fix_data = 0xBB; + break; + } + + for (i = 0; i < MAX_I2C_TRANS_SZ; i++) + tmp_data[i] = fix_data; + + + I("%s, total size=%d\n", __func__, total_size); + + if (total_size_temp % max_bus_size == 0) + total_read_times = total_size_temp / max_bus_size; + else + total_read_times = total_size_temp / max_bus_size + 1; + + for (i = 0; i < (total_read_times); i++) { + I("[log]write %d time start!\n", i); + if (total_size_temp >= max_bus_size) { + g_core_fp.fp_flash_write_burst_length(tmp_addr, tmp_data, max_bus_size); + total_size_temp = total_size_temp - max_bus_size; + } else { + I("last total_size_temp=%d\n", total_size_temp); + g_core_fp.fp_flash_write_burst_length(tmp_addr, tmp_data, total_size_temp % max_bus_size); + } + address = ((i+1) * max_bus_size); + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF); + tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); + + msleep(20); + } + + I("%s, END\n", __func__); +} + +void himax_mcu_write_sram_0f(const struct firmware *fw_entry, uint8_t *addr, int start_index, uint32_t write_len) +{ + int total_read_times = 0; + int max_bus_size = MAX_I2C_TRANS_SZ; + int total_size_temp = 0; + int total_size = 0; + int address = 0; + int i = 0; + + uint8_t tmp_addr[4]; + uint8_t *tmp_data; + uint32_t now_addr; + + I("%s, ---Entering\n", __func__); + + total_size = fw_entry->size; + + total_size_temp = write_len; + + if (write_len > 4096) + max_bus_size = 4096; + else + max_bus_size = write_len; + + g_core_fp.fp_burst_enable(1); + + tmp_addr[3] = addr[3]; + tmp_addr[2] = addr[2]; + tmp_addr[1] = addr[1]; + tmp_addr[0] = addr[0]; + I("%s, write addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n", + __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + now_addr = (addr[3] << 24) + (addr[2] << 16) + (addr[1] << 8) + addr[0]; + I("now addr= 0x%08X\n", now_addr); + + I("%s, total size=%d\n", __func__, total_size); + + + tmp_data = kcalloc(total_size, sizeof(uint8_t), GFP_KERNEL); + if (!tmp_data) { + E("%s: allocate memory failed!\n", __func__); + return; + } + memcpy(tmp_data, fw_entry->data, total_size); + + /* + * for(i = 0;i<10;i++) + * { + * I("[%d] 0x%2.2X", i, tmp_data[i]); + * } + * I("\n"); + */ + if (total_size_temp % max_bus_size == 0) + total_read_times = total_size_temp / max_bus_size; + else + total_read_times = total_size_temp / max_bus_size + 1; + + for (i = 0; i < (total_read_times); i++) { + I("[log]write %d time start!\n", i); + I("[log]addr[3]=0x%02X, addr[2]=0x%02X, addr[1]=0x%02X, addr[0]=0x%02X!\n", tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + + if (total_size_temp >= max_bus_size) { + g_core_fp.fp_flash_write_burst_length(tmp_addr, &(tmp_data[start_index+i * max_bus_size]), max_bus_size); + total_size_temp = total_size_temp - max_bus_size; + } else { + I("last total_size_temp=%d\n", total_size_temp); + g_core_fp.fp_flash_write_burst_length(tmp_addr, &(tmp_data[start_index+i * max_bus_size]), total_size_temp % max_bus_size); + } + + I("[log]write %d time end!\n", i); + address = ((i+1) * max_bus_size); + tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); + + if (tmp_addr[0] < addr[0]) + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF) + 1; + else + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF); + + udelay(100); + } + I("%s, ----END\n", __func__); + kfree(tmp_data); +} + +void himax_mcu_firmware_update_0f(const struct firmware *fw_entry) +{ + int retry = 0; + int crc = -1; + + I("%s, Entering\n", __func__); + + g_core_fp.fp_register_write(pzf_op->addr_system_reset, 4, pzf_op->data_system_reset, false); + + g_core_fp.fp_sense_off(); + + /* first 48K */ + do { + g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_sram_start_addr, 0, HX_48K_SZ); + crc = g_core_fp.fp_check_CRC(pzf_op->data_sram_start_addr, HX_48K_SZ); + if (crc == 0) { + I("%s, HW CRC OK in %d time\n", __func__, retry); + break; + } + E("%s, HW CRC FAIL in %d time !\n", __func__, retry); + + retry++; + } while (crc != 0 && retry < 3); + + if (crc != 0) { + E("Last time CRC Fail!\n"); + return; + } + + /* clean */ + if (G_POWERONOF == 1) + g_core_fp.fp_clean_sram_0f(pzf_op->data_sram_clean, HX_32K_SZ, 0); + + /* last 16k */ + /* config info */ + if (G_POWERONOF == 1) + g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_cfg_info, HX_48K_SZ, 132); + else + g_core_fp.fp_clean_sram_0f(pzf_op->data_cfg_info, 132, 2); + + /* FW config */ + if (G_POWERONOF == 1) + g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_fw_cfg, 0xC0FE, 512); + else + g_core_fp.fp_clean_sram_0f(pzf_op->data_fw_cfg, 512, 1); + + /* ADC config */ + if (G_POWERONOF == 1) + g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_adc_cfg_1, 0xD000, 376); + else + g_core_fp.fp_clean_sram_0f(pzf_op->data_adc_cfg_1, 376, 2); + + if (G_POWERONOF == 1) + g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_adc_cfg_2, 0xD178, 376); + else + g_core_fp.fp_clean_sram_0f(pzf_op->data_adc_cfg_2, 376, 2); + + if (G_POWERONOF == 1) + g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_adc_cfg_3, 0xD000, 376); + else + g_core_fp.fp_clean_sram_0f(pzf_op->data_adc_cfg_3, 376, 2); + + msleep(20); + g_core_fp.fp_sys_reset(); + msleep(20); + I("%s:End\n", __func__); + himax_int_enable(1); + + I("%s, END\n", __func__); +} + +void himax_mcu_0f_operation(struct work_struct *work) +{ + int err = NO_ERR; + const struct firmware *fw_entry = NULL; + char *firmware_name = "himax.bin"; + + I("%s, Entering\n", __func__); + I("file name = %s\n", firmware_name); + err = request_firmware(&fw_entry, firmware_name, private_ts->dev); + if (err < 0) { + E("%s, fail in line%d error code=%d\n", __func__, __LINE__, err); + return; + } + g_core_fp.fp_firmware_update_0f(fw_entry); + release_firmware(fw_entry); + + I("%s, END\n", __func__); +} + +#ifdef HX_0F_DEBUG +void himax_mcu_read_sram_0f(const struct firmware *fw_entry, uint8_t *addr, int start_index, int read_len) +{ + int total_read_times = 0; + int max_i2c_size = MAX_I2C_TRANS_SZ; + int total_size_temp = 0; + int total_size = 0; + int address = 0; + int i = 0, j = 0; + int not_same = 0; + + uint8_t tmp_addr[4]; + uint8_t *temp_info_data; + int *not_same_buff; + + I("%s, Entering\n", __func__); + + g_core_fp.fp_burst_enable(1); + total_size = read_len; + total_size_temp = read_len; + temp_info_data = kcalloc(total_size, sizeof(uint8_t), GFP_KERNEL); + if (!temp_info_data) { + E("%s: allocate memory failed: temp_info_data!\n", __func__); + return; + } + not_same_buff = kcalloc(total_size, sizeof(int), GFP_KERNEL); + if (!not_same_buff) { + kfree(temp_info_data); + E("%s: allocate memory failed: not_same_buff!\n", __func__); + return; + } + + tmp_addr[3] = addr[3]; + tmp_addr[2] = addr[2]; + tmp_addr[1] = addr[1]; + tmp_addr[0] = addr[0]; + I("%s, read addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n", + __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + + I("%s, total size=%d\n", __func__, total_size); + + g_core_fp.fp_burst_enable(1); + + if (total_size % max_i2c_size == 0) + total_read_times = total_size / max_i2c_size; + else + total_read_times = total_size / max_i2c_size + 1; + + for (i = 0; i < (total_read_times); i++) { + if (total_size_temp >= max_i2c_size) { + g_core_fp.fp_register_read(tmp_addr, max_i2c_size, &temp_info_data[i*max_i2c_size], false); + total_size_temp = total_size_temp - max_i2c_size; + } else + g_core_fp.fp_register_read(tmp_addr, total_size_temp % max_i2c_size, &temp_info_data[i*max_i2c_size], false); + + address = ((i+1) * max_i2c_size); + tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); + if (tmp_addr[0] < addr[0]) + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF) + 1; + else + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF); + + msleep(20); + } + I("%s, READ Start\n", __func__); + I("%s, start_index = %d\n", __func__, start_index); + j = start_index; + for (i = 0; i < read_len; i++, j++) { + if (fw_entry->data[j] != temp_info_data[i]) { + not_same++; + not_same_buff[i] = 1; + } + + I("0x%2.2X, ", temp_info_data[i]); + + if (i > 0 && i%16 == 15) + I("\n"); + } + I("%s, READ END\n", __func__); + I("%s, Not Same count=%d\n", __func__, not_same); + if (not_same != 0) { + j = start_index; + for (i = 0; i < read_len; i++, j++) { + if (not_same_buff[i] == 1) + I("bin = [%d] 0x%2.2X\n", i, fw_entry->data[j]); + } + for (i = 0; i < read_len; i++, j++) { + if (not_same_buff[i] == 1) + I("sram = [%d] 0x%2.2X\n", i, temp_info_data[i]); + } + } + I("%s, READ END\n", __func__); + I("%s, Not Same count=%d\n", __func__, not_same); + I("%s, END\n", __func__); + + kfree(not_same_buff); + kfree(temp_info_data); +} + +void himax_mcu_read_all_sram(uint8_t *addr, int read_len) +{ + int total_read_times = 0; + int max_bus_size = MAX_I2C_TRANS_SZ; + int total_size_temp = 0; + int total_size = 0; + int address = 0; + int i = 0; + /* + * struct file *fn; + * struct filename *vts_name; + */ + + uint8_t tmp_addr[4]; + uint8_t *temp_info_data; + + I("%s, Entering\n", __func__); + + g_core_fp.fp_burst_enable(1); + total_size = read_len; + total_size_temp = read_len; + temp_info_data = kcalloc(total_size, sizeof(uint8_t), GFP_KERNEL); + if (!temp_info_data) { + E("%s: allocate memory failed!\n", __func__); + return; + } + + tmp_addr[3] = addr[3]; + tmp_addr[2] = addr[2]; + tmp_addr[1] = addr[1]; + tmp_addr[0] = addr[0]; + I("%s, read addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n", + __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + + I("%s, total size=%d\n", __func__, total_size); + + if (total_size % max_bus_size == 0) + total_read_times = total_size / max_bus_size; + else + total_read_times = total_size / max_bus_size + 1; + + for (i = 0; i < (total_read_times); i++) { + if (total_size_temp >= max_bus_size) + g_core_fp.fp_register_read(tmp_addr, max_bus_size, &temp_info_data[i*max_bus_size], false); + total_size_temp = total_size_temp - max_bus_size; + else + g_core_fp.fp_register_read(tmp_addr, total_size_temp % max_bus_size, &temp_info_data[i*max_bus_size], false); + + address = ((i+1) * max_bus_size); + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF); + tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); + + msleep(20); + } + I("%s, NOW addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n", + __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + /* + * for(i = 0;i 0 && i%16 == 15) + * printk("\n"); + * } + */ + + /* need modify */ + /* + * I("Now Write File start!\n"); + * vts_name = getname_kernel("/sdcard/dump_dsram.txt"); + * fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0); + * if (!IS_ERR (fn)) { + * I("%s create file and ready to write\n", __func__); + * fn->f_op->write(fn, temp_info_data, read_len*sizeof(uint8_t), &fn->f_pos); + * filp_close(fn, NULL); + * } + * I("Now Write File End!\n"); + */ + + I("%s, END\n", __func__); + + kfree(temp_info_data); +} + +void himax_mcu_firmware_read_0f(const struct firmware *fw_entry, int type) +{ + uint8_t tmp_addr[4]; + + I("%s, Entering\n", __func__); + if (type == 0) { + /* first 48K */ + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_sram_start_addr, 0, HX_48K_SZ); + g_core_fp.fp_read_all_sram(tmp_addr, 0xC000); + } else { + /* last 16k */ + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_cfg_info, 0xC000, 132); + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_fw_cfg, 0xC0FE, 512); + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_adc_cfg_1, 0xD000, 376); + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_adc_cfg_2, 0xD178, 376); + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_adc_cfg_3, 0xD000, 376); + g_core_fp.fp_read_all_sram(pzf_op->data_sram_clean, HX_32K_SZ); + } + I("%s, END\n", __func__); +} + +void himax_mcu_0f_operation_check(int type) +{ + int err = NO_ERR; + const struct firmware *fw_entry = NULL; + char *firmware_name = "himax.bin"; + + I("%s, Entering\n", __func__); + I("file name = %s\n", firmware_name); + + err = request_firmware(&fw_entry, firmware_name, private_ts->dev); + if (err < 0) { + E("%s, fail in line%d error code=%d\n", __func__, __LINE__, err); + return; + } + + I("first 4 bytes 0x%2X, 0x%2X, 0x%2X, 0x%2X !\n", fw_entry->data[0], fw_entry->data[1], fw_entry->data[2], fw_entry->data[3]); + I("next 4 bytes 0x%2X, 0x%2X, 0x%2X, 0x%2X !\n", fw_entry->data[4], fw_entry->data[5], fw_entry->data[6], fw_entry->data[7]); + I("and next 4 bytes 0x%2X, 0x%2X, 0x%2X, 0x%2X !\n", fw_entry->data[8], fw_entry->data[9], fw_entry->data[10], fw_entry->data[11]); + + g_core_fp.fp_firmware_read_0f(fw_entry, type); + + release_firmware(fw_entry); + I("%s, END\n", __func__); + +} +#endif + +#endif + +#ifdef CORE_INIT +/* init start */ +static void himax_mcu_fp_init(void) +{ +#ifdef CORE_IC + g_core_fp.fp_burst_enable = himax_mcu_burst_enable; + g_core_fp.fp_register_read = himax_mcu_register_read; + g_core_fp.fp_flash_write_burst = himax_mcu_flash_write_burst; + g_core_fp.fp_flash_write_burst_length = himax_mcu_flash_write_burst_length; + g_core_fp.fp_register_write = himax_mcu_register_write; + g_core_fp.fp_interface_on = himax_mcu_interface_on; + g_core_fp.fp_sense_on = himax_mcu_sense_on; + g_core_fp.fp_sense_off = himax_mcu_sense_off; + g_core_fp.fp_wait_wip = himax_mcu_wait_wip; + g_core_fp.fp_init_psl = himax_mcu_init_psl; + g_core_fp.fp_resume_ic_action = himax_mcu_resume_ic_action; + g_core_fp.fp_suspend_ic_action = himax_mcu_suspend_ic_action; + g_core_fp.fp_power_on_init = himax_mcu_power_on_init; +#endif +#ifdef CORE_FW + g_core_fp.fp_system_reset = himax_mcu_system_reset; + g_core_fp.fp_Calculate_CRC_with_AP = himax_mcu_Calculate_CRC_with_AP; + g_core_fp.fp_check_CRC = himax_mcu_check_CRC; + g_core_fp.fp_set_reload_cmd = himax_mcu_set_reload_cmd; + g_core_fp.fp_program_reload = himax_mcu_program_reload; + g_core_fp.fp_set_SMWP_enable = himax_mcu_set_SMWP_enable; + g_core_fp.fp_set_HSEN_enable = himax_mcu_set_HSEN_enable; + g_core_fp.fp_usb_detect_set = himax_mcu_usb_detect_set; + g_core_fp.fp_diag_register_set = himax_mcu_diag_register_set; + g_core_fp.fp_chip_self_test = himax_mcu_chip_self_test; + g_core_fp.fp_idle_mode = himax_mcu_idle_mode; + g_core_fp.fp_reload_disable = himax_mcu_reload_disable; + g_core_fp.fp_check_chip_version = himax_mcu_check_chip_version; + g_core_fp.fp_read_ic_trigger_type = himax_mcu_read_ic_trigger_type; + g_core_fp.fp_read_i2c_status = himax_mcu_read_i2c_status; + g_core_fp.fp_read_FW_ver = himax_mcu_read_FW_ver; + g_core_fp.fp_read_event_stack = himax_mcu_read_event_stack; + g_core_fp.fp_return_event_stack = himax_mcu_return_event_stack; + g_core_fp.fp_calculateChecksum = himax_mcu_calculateChecksum; + g_core_fp.fp_read_FW_status = himax_mcu_read_FW_status; + g_core_fp.fp_irq_switch = himax_mcu_irq_switch; + g_core_fp.fp_assign_sorting_mode = himax_mcu_assign_sorting_mode; + g_core_fp.fp_check_sorting_mode = himax_mcu_check_sorting_mode; + g_core_fp.fp_switch_mode = himax_mcu_switch_mode; + g_core_fp.fp_read_DD_status = himax_mcu_read_DD_status; +#endif +#ifdef CORE_FLASH + g_core_fp.fp_chip_erase = himax_mcu_chip_erase; + g_core_fp.fp_block_erase = himax_mcu_block_erase; + g_core_fp.fp_sector_erase = himax_mcu_sector_erase; + g_core_fp.fp_flash_programming = himax_mcu_flash_programming; + g_core_fp.fp_flash_page_write = himax_mcu_flash_page_write; + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k = himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_32k; + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k = himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_60k; + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k = himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_64k; + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k = himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_124k; + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k = himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_128k; + g_core_fp.fp_flash_dump_func = himax_mcu_flash_dump_func; + g_core_fp.fp_flash_lastdata_check = himax_mcu_flash_lastdata_check; +#endif +#ifdef CORE_SRAM + g_core_fp.fp_sram_write = himax_mcu_sram_write; + g_core_fp.fp_sram_verify = himax_mcu_sram_verify; + g_core_fp.fp_get_DSRAM_data = himax_mcu_get_DSRAM_data; +#endif +#ifdef CORE_DRIVER + g_core_fp.fp_chip_detect = himax_mcu_detect_ic; + g_core_fp.fp_chip_init = himax_mcu_init_ic; +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_pin_reset = himax_mcu_pin_reset; + g_core_fp.fp_ic_reset = himax_mcu_ic_reset; +#endif + g_core_fp.fp_touch_information = himax_mcu_touch_information; + g_core_fp.fp_reload_config = himax_mcu_reload_config; + g_core_fp.fp_get_touch_data_size = himax_mcu_get_touch_data_size; + g_core_fp.fp_hand_shaking = himax_mcu_hand_shaking; + g_core_fp.fp_determin_diag_rawdata = himax_mcu_determin_diag_rawdata; + g_core_fp.fp_determin_diag_storage = himax_mcu_determin_diag_storage; + g_core_fp.fp_cal_data_len = himax_mcu_cal_data_len; + g_core_fp.fp_diag_check_sum = himax_mcu_diag_check_sum; + g_core_fp.fp_diag_parse_raw_data = himax_mcu_diag_parse_raw_data; +#ifdef HX_ESD_RECOVERY + g_core_fp.fp_ic_esd_recovery = himax_mcu_ic_esd_recovery; + g_core_fp.fp_esd_ic_reset = himax_mcu_esd_ic_reset; +#endif +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || defined(HX_USB_DETECT_GLOBAL) + g_core_fp.fp_resend_cmd_func = himax_mcu_resend_cmd_func; +#endif +#endif +#ifdef HX_ZERO_FLASH + g_core_fp.fp_sys_reset = himax_mcu_sys_reset; + g_core_fp.fp_clean_sram_0f = himax_mcu_clean_sram_0f; + g_core_fp.fp_write_sram_0f = himax_mcu_write_sram_0f; + g_core_fp.fp_firmware_update_0f = himax_mcu_firmware_update_0f; + g_core_fp.fp_0f_operation = himax_mcu_0f_operation; +#ifdef HX_0F_DEBUG + g_core_fp.fp_read_sram_0f = himax_mcu_read_sram_0f; + g_core_fp.fp_read_all_sram = himax_mcu_read_all_sram; + g_core_fp.fp_firmware_read_0f = himax_mcu_firmware_read_0f; + g_core_fp.fp_0f_operation_check = himax_mcu_0f_operation_check; +#endif +#endif +} + +void himax_mcu_in_cmd_struct_init(void) +{ + I("%s: Entering!\n", __func__); + g_core_cmd_op = kzalloc(sizeof(struct himax_core_command_operation), GFP_KERNEL); + if (!g_core_cmd_op) + return; + + g_core_cmd_op->ic_op = kzalloc(sizeof(struct ic_operation), GFP_KERNEL); + if (!g_core_cmd_op->ic_op) { + E("%s: allocate memory failed: g_core_cmd_op->ic_op!\n", __func__); + goto err_alloc_ic_op; + } + + g_core_cmd_op->fw_op = kzalloc(sizeof(struct fw_operation), GFP_KERNEL); + if (!g_core_cmd_op->fw_op) { + E("%s: allocate memory failed: g_core_cmd_op->fw_op!\n", __func__); + goto err_alloc_fw_op; + } + + g_core_cmd_op->flash_op = kzalloc(sizeof(struct flash_operation), GFP_KERNEL); + if (!g_core_cmd_op->flash_op) { + E("%s: allocate memory failed: g_core_cmd_op->flash_op!\n", __func__); + goto err_alloc_flash_op; + } + + g_core_cmd_op->sram_op = kzalloc(sizeof(struct sram_operation), GFP_KERNEL); + if (!g_core_cmd_op->sram_op) { + E("%s: allocate memory failed: g_core_cmd_op->sram_op!\n", __func__); + goto err_alloc_sram_op; + } + + g_core_cmd_op->driver_op = kzalloc(sizeof(struct driver_operation), GFP_KERNEL); + if (!g_core_cmd_op->driver_op) { + E("%s: allocate memory failed: g_core_cmd_op->driver_op!\n", __func__); + goto err_alloc_driver_op; + } + + pic_op = g_core_cmd_op->ic_op; + pfw_op = g_core_cmd_op->fw_op; + pflash_op = g_core_cmd_op->flash_op; + psram_op = g_core_cmd_op->sram_op; + pdriver_op = g_core_cmd_op->driver_op; +#ifdef HX_ZERO_FLASH + g_core_cmd_op->zf_op = kzalloc(sizeof(struct zf_operation), GFP_KERNEL); + if (!g_core_cmd_op->zf_op){ + E("%s: allocate memory failed: g_core_cmd_op->zf_op!\n", __func__); + goto err_alloc_zf_op; + } + + pzf_op = g_core_cmd_op->zf_op; +#endif + himax_mcu_fp_init(); + return; + +#ifdef HX_ZERO_FLASH +err_alloc_zf_op: + kfree(g_core_cmd_op->driver_op); +#endif +err_alloc_driver_op: + kfree(g_core_cmd_op->sram_op); +err_alloc_sram_op: + kfree(g_core_cmd_op->flash_op); +err_alloc_flash_op: + kfree(g_core_cmd_op->fw_op); +err_alloc_fw_op: + kfree(g_core_cmd_op->ic_op); +err_alloc_ic_op: + kfree(g_core_cmd_op); +} + +/* + *static void himax_mcu_in_cmd_struct_free(void) + *{ + * pic_op = NULL; + * pfw_op = NULL; + * pflash_op = NULL; + * psram_op = NULL; + * pdriver_op = NULL; + * kfree(g_core_cmd_op); + * kfree(g_core_cmd_op->ic_op); + * kfree(g_core_cmd_op->flash_op); + * kfree(g_core_cmd_op->sram_op); + * kfree(g_core_cmd_op->driver_op); + *} + */ + +void himax_in_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len) +{ + /* I("%s: Entering!\n", __func__); */ + switch (len) { + case 1: + cmd[0] = addr; + /* I("%s: cmd[0] = 0x%02X\n", __func__, cmd[0]); */ + break; + + case 2: + cmd[0] = addr % 0x100; + cmd[1] = (addr >> 8) % 0x100; + /* I("%s: cmd[0] = 0x%02X,cmd[1] = 0x%02X\n", __func__, cmd[0], cmd[1]); */ + break; + + case 4: + cmd[0] = addr % 0x100; + cmd[1] = (addr >> 8) % 0x100; + cmd[2] = (addr >> 16) % 0x100; + cmd[3] = addr / 0x1000000; + /* + * I("%s: cmd[0] = 0x%02X,cmd[1] = 0x%02X,cmd[2] = 0x%02X,cmd[3] = 0x%02X\n", + * __func__, cmd[0], cmd[1], cmd[2], cmd[3]); + */ + break; + + default: + E("%s: input length fault,len = %d!", __func__, len); + } +} + +void himax_mcu_in_cmd_init(void) +{ + I("%s: Entering!\n", __func__); +#ifdef CORE_IC + himax_in_parse_assign_cmd(ic_adr_ahb_addr_byte_0, pic_op->addr_ahb_addr_byte_0, sizeof(pic_op->addr_ahb_addr_byte_0)); + himax_in_parse_assign_cmd(ic_adr_ahb_rdata_byte_0, pic_op->addr_ahb_rdata_byte_0, sizeof(pic_op->addr_ahb_rdata_byte_0)); + himax_in_parse_assign_cmd(ic_adr_ahb_access_direction, pic_op->addr_ahb_access_direction, sizeof(pic_op->addr_ahb_access_direction)); + himax_in_parse_assign_cmd(ic_adr_conti, pic_op->addr_conti, sizeof(pic_op->addr_conti)); + himax_in_parse_assign_cmd(ic_adr_incr4, pic_op->addr_incr4, sizeof(pic_op->addr_incr4)); + himax_in_parse_assign_cmd(ic_adr_i2c_psw_lb, pic_op->adr_i2c_psw_lb, sizeof(pic_op->adr_i2c_psw_lb)); + himax_in_parse_assign_cmd(ic_adr_i2c_psw_ub, pic_op->adr_i2c_psw_ub, sizeof(pic_op->adr_i2c_psw_ub)); + himax_in_parse_assign_cmd(ic_cmd_ahb_access_direction_read, pic_op->data_ahb_access_direction_read, sizeof(pic_op->data_ahb_access_direction_read)); + himax_in_parse_assign_cmd(ic_cmd_conti, pic_op->data_conti, sizeof(pic_op->data_conti)); + himax_in_parse_assign_cmd(ic_cmd_incr4, pic_op->data_incr4, sizeof(pic_op->data_incr4)); + himax_in_parse_assign_cmd(ic_cmd_i2c_psw_lb, pic_op->data_i2c_psw_lb, sizeof(pic_op->data_i2c_psw_lb)); + himax_in_parse_assign_cmd(ic_cmd_i2c_psw_ub, pic_op->data_i2c_psw_ub, sizeof(pic_op->data_i2c_psw_ub)); + himax_in_parse_assign_cmd(ic_adr_tcon_on_rst, pic_op->addr_tcon_on_rst, sizeof(pic_op->addr_tcon_on_rst)); + himax_in_parse_assign_cmd(ic_addr_adc_on_rst, pic_op->addr_adc_on_rst, sizeof(pic_op->addr_adc_on_rst)); + himax_in_parse_assign_cmd(ic_adr_psl, pic_op->addr_psl, sizeof(pic_op->addr_psl)); + himax_in_parse_assign_cmd(ic_adr_cs_central_state, pic_op->addr_cs_central_state, sizeof(pic_op->addr_cs_central_state)); + himax_in_parse_assign_cmd(ic_cmd_rst, pic_op->data_rst, sizeof(pic_op->data_rst)); +#endif +#ifdef CORE_FW + himax_in_parse_assign_cmd(fw_addr_system_reset, pfw_op->addr_system_reset, sizeof(pfw_op->addr_system_reset)); + himax_in_parse_assign_cmd(fw_addr_safe_mode_release_pw, pfw_op->addr_safe_mode_release_pw, sizeof(pfw_op->addr_safe_mode_release_pw)); + himax_in_parse_assign_cmd(fw_addr_ctrl_fw, pfw_op->addr_ctrl_fw_isr, sizeof(pfw_op->addr_ctrl_fw_isr)); + himax_in_parse_assign_cmd(fw_addr_flag_reset_event, pfw_op->addr_flag_reset_event, sizeof(pfw_op->addr_flag_reset_event)); + himax_in_parse_assign_cmd(fw_addr_hsen_enable, pfw_op->addr_hsen_enable, sizeof(pfw_op->addr_hsen_enable)); + himax_in_parse_assign_cmd(fw_addr_smwp_enable, pfw_op->addr_smwp_enable, sizeof(pfw_op->addr_smwp_enable)); + himax_in_parse_assign_cmd(fw_addr_program_reload_from, pfw_op->addr_program_reload_from, sizeof(pfw_op->addr_program_reload_from)); + himax_in_parse_assign_cmd(fw_addr_program_reload_to, pfw_op->addr_program_reload_to, sizeof(pfw_op->addr_program_reload_to)); + himax_in_parse_assign_cmd(fw_addr_program_reload_page_write, pfw_op->addr_program_reload_page_write, sizeof(pfw_op->addr_program_reload_page_write)); + himax_in_parse_assign_cmd(fw_addr_raw_out_sel, pfw_op->addr_raw_out_sel, sizeof(pfw_op->addr_raw_out_sel)); + himax_in_parse_assign_cmd(fw_addr_reload_status, pfw_op->addr_reload_status, sizeof(pfw_op->addr_reload_status)); + himax_in_parse_assign_cmd(fw_addr_reload_crc32_result, pfw_op->addr_reload_crc32_result, sizeof(pfw_op->addr_reload_crc32_result)); + himax_in_parse_assign_cmd(fw_addr_reload_addr_from, pfw_op->addr_reload_addr_from, sizeof(pfw_op->addr_reload_addr_from)); + himax_in_parse_assign_cmd(fw_addr_reload_addr_cmd_beat, pfw_op->addr_reload_addr_cmd_beat, sizeof(pfw_op->addr_reload_addr_cmd_beat)); + himax_in_parse_assign_cmd(fw_addr_selftest_addr_en, pfw_op->addr_selftest_addr_en, sizeof(pfw_op->addr_selftest_addr_en)); + himax_in_parse_assign_cmd(fw_addr_criteria_addr, pfw_op->addr_criteria_addr, sizeof(pfw_op->addr_criteria_addr)); + himax_in_parse_assign_cmd(fw_addr_set_frame_addr, pfw_op->addr_set_frame_addr, sizeof(pfw_op->addr_set_frame_addr)); + himax_in_parse_assign_cmd(fw_addr_selftest_result_addr, pfw_op->addr_selftest_result_addr, sizeof(pfw_op->addr_selftest_result_addr)); + himax_in_parse_assign_cmd(fw_addr_sorting_mode_en, pfw_op->addr_sorting_mode_en, sizeof(pfw_op->addr_sorting_mode_en)); + himax_in_parse_assign_cmd(fw_addr_fw_mode_status, pfw_op->addr_fw_mode_status, sizeof(pfw_op->addr_fw_mode_status)); + himax_in_parse_assign_cmd(fw_addr_icid_addr, pfw_op->addr_icid_addr, sizeof(pfw_op->addr_icid_addr)); + himax_in_parse_assign_cmd(fw_addr_trigger_addr, pfw_op->addr_trigger_addr, sizeof(pfw_op->addr_trigger_addr)); + himax_in_parse_assign_cmd(fw_addr_fw_ver_addr, pfw_op->addr_fw_ver_addr, sizeof(pfw_op->addr_fw_ver_addr)); + himax_in_parse_assign_cmd(fw_addr_fw_cfg_addr, pfw_op->addr_fw_cfg_addr, sizeof(pfw_op->addr_fw_cfg_addr)); + himax_in_parse_assign_cmd(fw_addr_fw_vendor_addr, pfw_op->addr_fw_vendor_addr, sizeof(pfw_op->addr_fw_vendor_addr)); + himax_in_parse_assign_cmd(fw_addr_fw_state_addr, pfw_op->addr_fw_state_addr, sizeof(pfw_op->addr_fw_state_addr)); + himax_in_parse_assign_cmd(fw_addr_fw_dbg_msg_addr, pfw_op->addr_fw_dbg_msg_addr, sizeof(pfw_op->addr_fw_dbg_msg_addr)); + himax_in_parse_assign_cmd(fw_addr_chk_fw_status, pfw_op->addr_chk_fw_status, sizeof(pfw_op->addr_chk_fw_status)); + himax_in_parse_assign_cmd(fw_addr_dd_handshak_addr, pfw_op->addr_dd_handshak_addr, sizeof(pfw_op->addr_dd_handshak_addr)); + himax_in_parse_assign_cmd(fw_addr_dd_data_addr, pfw_op->addr_dd_data_addr, sizeof(pfw_op->addr_dd_data_addr)); + himax_in_parse_assign_cmd(fw_data_system_reset, pfw_op->data_system_reset, sizeof(pfw_op->data_system_reset)); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_active, pfw_op->data_safe_mode_release_pw_active, sizeof(pfw_op->data_safe_mode_release_pw_active)); + himax_in_parse_assign_cmd(fw_data_clear, pfw_op->data_clear, sizeof(pfw_op->data_clear)); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, pfw_op->data_safe_mode_release_pw_reset, sizeof(pfw_op->data_safe_mode_release_pw_reset)); + himax_in_parse_assign_cmd(fw_data_program_reload_start, pfw_op->data_program_reload_start, sizeof(pfw_op->data_program_reload_start)); + himax_in_parse_assign_cmd(fw_data_program_reload_compare, pfw_op->data_program_reload_compare, sizeof(pfw_op->data_program_reload_compare)); + himax_in_parse_assign_cmd(fw_data_program_reload_break, pfw_op->data_program_reload_break, sizeof(pfw_op->data_program_reload_break)); + himax_in_parse_assign_cmd(fw_data_selftest_request, pfw_op->data_selftest_request, sizeof(pfw_op->data_selftest_request)); + himax_in_parse_assign_cmd(fw_data_criteria_aa_top, pfw_op->data_criteria_aa_top, sizeof(pfw_op->data_criteria_aa_top)); + himax_in_parse_assign_cmd(fw_data_criteria_aa_bot, pfw_op->data_criteria_aa_bot, sizeof(pfw_op->data_criteria_aa_bot)); + himax_in_parse_assign_cmd(fw_data_criteria_key_top, pfw_op->data_criteria_key_top, sizeof(pfw_op->data_criteria_key_top)); + himax_in_parse_assign_cmd(fw_data_criteria_key_bot, pfw_op->data_criteria_key_bot, sizeof(pfw_op->data_criteria_key_bot)); + himax_in_parse_assign_cmd(fw_data_criteria_avg_top, pfw_op->data_criteria_avg_top, sizeof(pfw_op->data_criteria_avg_top)); + himax_in_parse_assign_cmd(fw_data_criteria_avg_bot, pfw_op->data_criteria_avg_bot, sizeof(pfw_op->data_criteria_avg_bot)); + himax_in_parse_assign_cmd(fw_data_set_frame, pfw_op->data_set_frame, sizeof(pfw_op->data_set_frame)); + himax_in_parse_assign_cmd(fw_data_selftest_ack_hb, pfw_op->data_selftest_ack_hb, sizeof(pfw_op->data_selftest_ack_hb)); + himax_in_parse_assign_cmd(fw_data_selftest_ack_lb, pfw_op->data_selftest_ack_lb, sizeof(pfw_op->data_selftest_ack_lb)); + himax_in_parse_assign_cmd(fw_data_selftest_pass, pfw_op->data_selftest_pass, sizeof(pfw_op->data_selftest_pass)); + himax_in_parse_assign_cmd(fw_data_normal_cmd, pfw_op->data_normal_cmd, sizeof(pfw_op->data_normal_cmd)); + himax_in_parse_assign_cmd(fw_data_normal_status, pfw_op->data_normal_status, sizeof(pfw_op->data_normal_status)); + himax_in_parse_assign_cmd(fw_data_sorting_cmd, pfw_op->data_sorting_cmd, sizeof(pfw_op->data_sorting_cmd)); + himax_in_parse_assign_cmd(fw_data_sorting_status, pfw_op->data_sorting_status, sizeof(pfw_op->data_sorting_status)); + himax_in_parse_assign_cmd(fw_data_dd_request, pfw_op->data_dd_request, sizeof(pfw_op->data_dd_request)); + himax_in_parse_assign_cmd(fw_data_dd_ack, pfw_op->data_dd_ack, sizeof(pfw_op->data_dd_ack)); + himax_in_parse_assign_cmd(fw_data_idle_dis_pwd, pfw_op->data_idle_dis_pwd, sizeof(pfw_op->data_idle_dis_pwd)); + himax_in_parse_assign_cmd(fw_data_idle_en_pwd, pfw_op->data_idle_en_pwd, sizeof(pfw_op->data_idle_en_pwd)); + himax_in_parse_assign_cmd(fw_data_rawdata_ready_hb, pfw_op->data_rawdata_ready_hb, sizeof(pfw_op->data_rawdata_ready_hb)); + himax_in_parse_assign_cmd(fw_data_rawdata_ready_lb, pfw_op->data_rawdata_ready_lb, sizeof(pfw_op->data_rawdata_ready_lb)); + himax_in_parse_assign_cmd(fw_addr_ahb_addr, pfw_op->addr_ahb_addr, sizeof(pfw_op->addr_ahb_addr)); + himax_in_parse_assign_cmd(fw_data_ahb_dis, pfw_op->data_ahb_dis, sizeof(pfw_op->data_ahb_dis)); + himax_in_parse_assign_cmd(fw_data_ahb_en, pfw_op->data_ahb_en, sizeof(pfw_op->data_ahb_en)); + himax_in_parse_assign_cmd(fw_addr_event_addr, pfw_op->addr_event_addr, sizeof(pfw_op->addr_event_addr)); + himax_in_parse_assign_cmd(fw_usb_detect_addr, pfw_op->addr_usb_detect, sizeof(pfw_op->addr_usb_detect)); +#endif +#ifdef CORE_FLASH + himax_in_parse_assign_cmd(flash_addr_spi200_trans_fmt, pflash_op->addr_spi200_trans_fmt, sizeof(pflash_op->addr_spi200_trans_fmt)); + himax_in_parse_assign_cmd(flash_addr_spi200_trans_ctrl, pflash_op->addr_spi200_trans_ctrl, sizeof(pflash_op->addr_spi200_trans_ctrl)); + himax_in_parse_assign_cmd(flash_addr_spi200_cmd, pflash_op->addr_spi200_cmd, sizeof(pflash_op->addr_spi200_cmd)); + himax_in_parse_assign_cmd(flash_addr_spi200_addr, pflash_op->addr_spi200_addr, sizeof(pflash_op->addr_spi200_addr)); + himax_in_parse_assign_cmd(flash_addr_spi200_data, pflash_op->addr_spi200_data, sizeof(pflash_op->addr_spi200_data)); + himax_in_parse_assign_cmd(flash_addr_spi200_bt_num, pflash_op->addr_spi200_bt_num, sizeof(pflash_op->addr_spi200_bt_num)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_fmt, pflash_op->data_spi200_trans_fmt, sizeof(pflash_op->data_spi200_trans_fmt)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_ctrl_1, pflash_op->data_spi200_trans_ctrl_1, sizeof(pflash_op->data_spi200_trans_ctrl_1)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_ctrl_2, pflash_op->data_spi200_trans_ctrl_2, sizeof(pflash_op->data_spi200_trans_ctrl_2)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_ctrl_3, pflash_op->data_spi200_trans_ctrl_3, sizeof(pflash_op->data_spi200_trans_ctrl_3)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_ctrl_4, pflash_op->data_spi200_trans_ctrl_4, sizeof(pflash_op->data_spi200_trans_ctrl_4)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_ctrl_5, pflash_op->data_spi200_trans_ctrl_5, sizeof(pflash_op->data_spi200_trans_ctrl_5)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_1, pflash_op->data_spi200_cmd_1, sizeof(pflash_op->data_spi200_cmd_1)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_2, pflash_op->data_spi200_cmd_2, sizeof(pflash_op->data_spi200_cmd_2)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_3, pflash_op->data_spi200_cmd_3, sizeof(pflash_op->data_spi200_cmd_3)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_4, pflash_op->data_spi200_cmd_4, sizeof(pflash_op->data_spi200_cmd_4)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_5, pflash_op->data_spi200_cmd_5, sizeof(pflash_op->data_spi200_cmd_5)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_6, pflash_op->data_spi200_cmd_6, sizeof(pflash_op->data_spi200_cmd_6)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_7, pflash_op->data_spi200_cmd_7, sizeof(pflash_op->data_spi200_cmd_7)); + himax_in_parse_assign_cmd(flash_data_spi200_addr, pflash_op->data_spi200_addr, sizeof(pflash_op->data_spi200_addr)); +#endif +#ifdef CORE_SRAM + /* sram start */ + himax_in_parse_assign_cmd(sram_adr_mkey, psram_op->addr_mkey, sizeof(psram_op->addr_mkey)); + himax_in_parse_assign_cmd(sram_adr_rawdata_addr, psram_op->addr_rawdata_addr, sizeof(psram_op->addr_rawdata_addr)); + himax_in_parse_assign_cmd(sram_adr_rawdata_end, psram_op->addr_rawdata_end, sizeof(psram_op->addr_rawdata_end)); + himax_in_parse_assign_cmd(sram_cmd_conti, psram_op->data_conti, sizeof(psram_op->data_conti)); + himax_in_parse_assign_cmd(sram_cmd_fin, psram_op->data_fin, sizeof(psram_op->data_fin)); + himax_in_parse_assign_cmd(sram_passwrd_start, psram_op->passwrd_start, sizeof(psram_op->passwrd_start)); + himax_in_parse_assign_cmd(sram_passwrd_end, psram_op->passwrd_end, sizeof(psram_op->passwrd_end)); + /* sram end */ +#endif +#ifdef CORE_DRIVER + himax_in_parse_assign_cmd(driver_addr_fw_define_flash_reload, pdriver_op->addr_fw_define_flash_reload, sizeof(pdriver_op->addr_fw_define_flash_reload)); + himax_in_parse_assign_cmd(driver_addr_fw_define_2nd_flash_reload, pdriver_op->addr_fw_define_2nd_flash_reload, sizeof(pdriver_op->addr_fw_define_2nd_flash_reload)); + himax_in_parse_assign_cmd(driver_addr_fw_define_int_is_edge, pdriver_op->addr_fw_define_int_is_edge, sizeof(pdriver_op->addr_fw_define_int_is_edge)); + himax_in_parse_assign_cmd(driver_addr_fw_define_rxnum_txnum_maxpt, pdriver_op->addr_fw_define_rxnum_txnum_maxpt, sizeof(pdriver_op->addr_fw_define_rxnum_txnum_maxpt)); + himax_in_parse_assign_cmd(driver_addr_fw_define_xy_res_enable, pdriver_op->addr_fw_define_xy_res_enable, sizeof(pdriver_op->addr_fw_define_xy_res_enable)); + himax_in_parse_assign_cmd(driver_addr_fw_define_x_y_res, pdriver_op->addr_fw_define_x_y_res, sizeof(pdriver_op->addr_fw_define_x_y_res)); + himax_in_parse_assign_cmd(driver_data_fw_define_flash_reload_dis, pdriver_op->data_fw_define_flash_reload_dis, sizeof(pdriver_op->data_fw_define_flash_reload_dis)); + himax_in_parse_assign_cmd(driver_data_fw_define_flash_reload_en, pdriver_op->data_fw_define_flash_reload_en, sizeof(pdriver_op->data_fw_define_flash_reload_en)); + himax_in_parse_assign_cmd(driver_data_fw_define_rxnum_txnum_maxpt_sorting, pdriver_op->data_fw_define_rxnum_txnum_maxpt_sorting, sizeof(pdriver_op->data_fw_define_rxnum_txnum_maxpt_sorting)); + himax_in_parse_assign_cmd(driver_data_fw_define_rxnum_txnum_maxpt_normal, pdriver_op->data_fw_define_rxnum_txnum_maxpt_normal, sizeof(pdriver_op->data_fw_define_rxnum_txnum_maxpt_normal)); +#endif +#ifdef HX_ZERO_FLASH + himax_in_parse_assign_cmd(zf_addr_dis_flash_reload, pzf_op->addr_dis_flash_reload, sizeof(pzf_op->addr_dis_flash_reload)); + himax_in_parse_assign_cmd(zf_data_dis_flash_reload, pzf_op->data_dis_flash_reload, sizeof(pzf_op->data_dis_flash_reload)); + himax_in_parse_assign_cmd(zf_addr_system_reset, pzf_op->addr_system_reset, sizeof(pzf_op->addr_system_reset)); + himax_in_parse_assign_cmd(zf_data_system_reset, pzf_op->data_system_reset, sizeof(pzf_op->data_system_reset)); + himax_in_parse_assign_cmd(zf_data_sram_start_addr, pzf_op->data_sram_start_addr, sizeof(pzf_op->data_sram_start_addr)); + himax_in_parse_assign_cmd(zf_data_sram_clean, pzf_op->data_sram_clean, sizeof(pzf_op->data_sram_clean)); + himax_in_parse_assign_cmd(zf_data_cfg_info, pzf_op->data_cfg_info, sizeof(pzf_op->data_cfg_info)); + himax_in_parse_assign_cmd(zf_data_fw_cfg, pzf_op->data_fw_cfg, sizeof(pzf_op->data_fw_cfg)); + himax_in_parse_assign_cmd(zf_data_adc_cfg_1, pzf_op->data_adc_cfg_1, sizeof(pzf_op->data_adc_cfg_1)); + himax_in_parse_assign_cmd(zf_data_adc_cfg_2, pzf_op->data_adc_cfg_2, sizeof(pzf_op->data_adc_cfg_2)); + himax_in_parse_assign_cmd(zf_data_adc_cfg_3, pzf_op->data_adc_cfg_3, sizeof(pzf_op->data_adc_cfg_3)); +#endif +} + +/* init end */ +#endif diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.c b/drivers/input/touchscreen/hxchipset/himax_platform.c new file mode 100644 index 000000000000..95564672112b --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_platform.c @@ -0,0 +1,802 @@ +/* + * Himax Android Driver Sample Code for QCT platform + * + * Copyright (C) 2018 Himax Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "himax_platform.h" +#include "himax_common.h" + +int i2c_error_count; +int irq_enable_count; + +int himax_dev_set(struct himax_ts_data *ts) +{ + int ret = 0; + + ts->input_dev = input_allocate_device(); + if (ts->input_dev == NULL) { + ret = -ENOMEM; + E("%s: Failed to allocate input device\n", __func__); + return ret; + } + + ts->input_dev->name = "himax-touchscreen"; + return ret; +} + +int himax_input_register_device(struct input_dev *input_dev) +{ + return input_register_device(input_dev); +} + +#if defined(HX_PLATFOME_DEFINE_KEY) +void himax_platform_key(void) +{ + I("Nothing to be done! Plz cancel it!\n"); +} +#endif + +void himax_vk_parser(struct device_node *dt, + struct himax_i2c_platform_data *pdata) +{ + u32 data = 0; + uint8_t cnt = 0, i = 0; + uint32_t coords[4] = {0}; + struct device_node *node, *pp = NULL; + struct himax_virtual_key *vk; + + node = of_parse_phandle(dt, "virtualkey", 0); + if (node == NULL) { + I(" DT-No vk info in DT"); + return; + } + + cnt = of_get_child_count(node); + if (!cnt) { + of_node_put(node); + return; + } + + vk = kcalloc(cnt, sizeof(*vk), GFP_KERNEL); + if (!vk) { + E(" %s: allocate memory failed!", __func__); + of_node_put(node); + return; + } + + for_each_child_of_node(node, pp) { + if (of_property_read_u32(pp, "idx", &data) != 0) + continue; + vk[i].index = data; + + if (of_property_read_u32_array(pp, "range", coords, 4) != 0) + continue; + vk[i].x_range_min = coords[0], vk[i].x_range_max = coords[1]; + vk[i].y_range_min = coords[2], vk[i].y_range_max = coords[3]; + + i++; + } + + pdata->virtual_key = vk; + of_node_put(node); + + for (i = 0; i < cnt; i++) + I(" vk[%d] idx:%d x_min:%d, y_max:%d", i, pdata->virtual_key[i].index, + pdata->virtual_key[i].x_range_min, pdata->virtual_key[i].y_range_max); +} + +int himax_parse_dt(struct himax_ts_data *ts, struct himax_i2c_platform_data *pdata) +{ + int rc, coords_size = 0; + uint32_t coords[4] = {0}; + struct property *prop; + struct device_node *dt = private_ts->client->dev.of_node; + u32 data = 0; + + prop = of_find_property(dt, "himax,panel-coords", NULL); + if (prop) { + coords_size = prop->length / sizeof(u32); + + if (coords_size != 4) + D(" %s:Invalid panel coords size %d", __func__, coords_size); + } + + if (of_property_read_u32_array(dt, "himax,panel-coords", coords, coords_size) == 0) { + pdata->abs_x_min = coords[0], pdata->abs_x_max = coords[1]; + pdata->abs_y_min = coords[2], pdata->abs_y_max = coords[3]; + I(" DT-%s:panel-coords = %d, %d, %d, %d\n", __func__, pdata->abs_x_min, + pdata->abs_x_max, pdata->abs_y_min, pdata->abs_y_max); + } + + prop = of_find_property(dt, "himax,display-coords", NULL); + + if (prop) { + coords_size = prop->length / sizeof(u32); + + if (coords_size != 4) + D(" %s:Invalid display coords size %d", __func__, coords_size); + } + + rc = of_property_read_u32_array(dt, "himax,display-coords", coords, coords_size); + + if (rc && (rc != -EINVAL)) { + D(" %s:Fail to read display-coords %d\n", __func__, rc); + return rc; + } + + pdata->screenWidth = coords[1]; + pdata->screenHeight = coords[3]; + I(" DT-%s:display-coords = (%d, %d)", __func__, pdata->screenWidth, + pdata->screenHeight); + pdata->gpio_irq = of_get_named_gpio(dt, "himax,irq-gpio", 0); + + if (!gpio_is_valid(pdata->gpio_irq)) + I(" DT:gpio_irq value is not valid\n"); + + pdata->gpio_reset = of_get_named_gpio(dt, "himax,rst-gpio", 0); + + if (!gpio_is_valid(pdata->gpio_reset)) + I(" DT:gpio_rst value is not valid\n"); + + pdata->gpio_3v3_en = of_get_named_gpio(dt, "himax,3v3-gpio", 0); + + if (!gpio_is_valid(pdata->gpio_3v3_en)) + I(" DT:gpio_3v3_en value is not valid\n"); + + I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d", pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en); + + if (of_property_read_u32(dt, "himax,report_type", &data) == 0) { + pdata->protocol_type = data; + I(" DT:protocol_type=%d", pdata->protocol_type); + } + + himax_vk_parser(dt, pdata); + return 0; +} + +int himax_bus_read(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry) +{ + int retry; + struct i2c_client *client = private_ts->client; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &command, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = length, + .buf = data, + } + }; + + mutex_lock(&private_ts->rw_lock); + + for (retry = 0; retry < toRetry; retry++) { + if (i2c_transfer(client->adapter, msg, 2) == 2) + break; + + msleep(20); + } + + if (retry == toRetry) { + E("%s: i2c_read_block retry over %d\n", __func__, toRetry); + i2c_error_count = toRetry; + mutex_unlock(&private_ts->rw_lock); + return -EIO; + } + + mutex_unlock(&private_ts->rw_lock); + return 0; +} + +int himax_bus_write(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry) +{ + int retry; + uint8_t buf[length + 1]; + struct i2c_client *client = private_ts->client; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = length + 1, + .buf = buf, + } + }; + + mutex_lock(&private_ts->rw_lock); + buf[0] = command; + memcpy(buf + 1, data, length); + + for (retry = 0; retry < toRetry; retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) + break; + + msleep(20); + } + + if (retry == toRetry) { + E("%s: i2c_write_block retry over %d\n", __func__, toRetry); + i2c_error_count = toRetry; + mutex_unlock(&private_ts->rw_lock); + return -EIO; + } + + mutex_unlock(&private_ts->rw_lock); + return 0; +} + +int himax_bus_write_command(uint8_t command, uint8_t toRetry) +{ + return himax_bus_write(command, NULL, 0, toRetry); +} + +int himax_bus_master_write(uint8_t *data, uint32_t length, uint8_t toRetry) +{ + int retry; + uint8_t buf[length]; + struct i2c_client *client = private_ts->client; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = length, + .buf = buf, + } + }; + + mutex_lock(&private_ts->rw_lock); + memcpy(buf, data, length); + + for (retry = 0; retry < toRetry; retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) + break; + + msleep(20); + } + + if (retry == toRetry) { + E("%s: i2c_write_block retry over %d\n", __func__, toRetry); + i2c_error_count = toRetry; + mutex_unlock(&private_ts->rw_lock); + return -EIO; + } + + mutex_unlock(&private_ts->rw_lock); + return 0; +} + +void himax_int_enable(int enable) +{ + int irqnum = 0; + + irqnum = private_ts->client->irq; + + if (enable == 1 && irq_enable_count == 0) { + enable_irq(irqnum); + irq_enable_count++; + private_ts->irq_enabled = 1; + } else if (enable == 0 && irq_enable_count == 1) { + disable_irq_nosync(irqnum); + irq_enable_count--; + private_ts->irq_enabled = 0; + } + + I("irq_enable_count = %d", irq_enable_count); +} + +#ifdef HX_RST_PIN_FUNC +void himax_rst_gpio_set(int pinnum, uint8_t value) +{ + gpio_direction_output(pinnum, value); +} +#endif + +uint8_t himax_int_gpio_read(int pinnum) +{ + return gpio_get_value(pinnum); +} + +#if defined(CONFIG_HMX_DB) +static int himax_regulator_configure(struct himax_i2c_platform_data *pdata) +{ + int retval; + struct i2c_client *client = private_ts->client; + + pdata->vcc_dig = regulator_get(&client->dev, "vdd"); + if (IS_ERR(pdata->vcc_dig)) { + E("%s: Failed to get regulator vdd\n", __func__); + retval = PTR_ERR(pdata->vcc_dig); + return retval; + } + + pdata->vcc_ana = regulator_get(&client->dev, "avdd"); + + if (IS_ERR(pdata->vcc_ana)) { + E("%s: Failed to get regulator avdd\n", __func__); + retval = PTR_ERR(pdata->vcc_ana); + regulator_put(pdata->vcc_ana); + return retval; + } + + return 0; +}; + +static int himax_power_on(struct himax_i2c_platform_data *pdata, bool on) +{ + int retval; + + if (on) { + retval = regulator_enable(pdata->vcc_dig); + + if (retval) { + E("%s: Failed to enable regulator vdd\n", __func__); + return retval; + } + + msleep(100); + retval = regulator_enable(pdata->vcc_ana); + + if (retval) { + E("%s: Failed to enable regulator avdd\n", __func__); + regulator_disable(pdata->vcc_dig); + return retval; + } + } else { + regulator_disable(pdata->vcc_dig); + regulator_disable(pdata->vcc_ana); + } + + return 0; +} + +int himax_gpio_power_config(struct himax_i2c_platform_data *pdata) +{ + int error; + struct i2c_client *client = private_ts->client; + + error = himax_regulator_configure(pdata); + if (error) { + E("Failed to initialize hardware\n"); + goto err_regulator_not_on; + } + +#ifdef HX_RST_PIN_FUNC + + if (gpio_is_valid(pdata->gpio_reset)) { + /* configure touchscreen reset out gpio */ + error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio"); + + if (error) { + E("unable to request gpio [%d]\n", pdata->gpio_reset); + goto err_regulator_on; + } + + error = gpio_direction_output(pdata->gpio_reset, 0); + + if (error) { + E("unable to set direction for gpio [%d]\n", pdata->gpio_reset); + goto err_gpio_reset_req; + } + } + +#endif + error = himax_power_on(pdata, true); + + if (error) { + E("Failed to power on hardware\n"); + goto err_gpio_reset_req; + } + + if (gpio_is_valid(pdata->gpio_irq)) { + /* configure touchscreen irq gpio */ + error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq"); + + if (error) { + E("unable to request gpio [%d]\n", pdata->gpio_irq); + goto err_power_on; + } + + error = gpio_direction_input(pdata->gpio_irq); + + if (error) { + E("unable to set direction for gpio [%d]\n", pdata->gpio_irq); + goto err_gpio_irq_req; + } + + client->irq = gpio_to_irq(pdata->gpio_irq); + } else { + E("irq gpio not provided\n"); + goto err_power_on; + } + + msleep(20); +#ifdef HX_RST_PIN_FUNC + + if (gpio_is_valid(pdata->gpio_reset)) { + error = gpio_direction_output(pdata->gpio_reset, 1); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_irq_req; + } + } + +#endif + return 0; +err_gpio_irq_req: + + if (gpio_is_valid(pdata->gpio_irq)) + gpio_free(pdata->gpio_irq); + +err_power_on: + himax_power_on(pdata, false); +err_gpio_reset_req: +#ifdef HX_RST_PIN_FUNC + + if (gpio_is_valid(pdata->gpio_reset)) + gpio_free(pdata->gpio_reset); + +err_regulator_on: +#endif +err_regulator_not_on: + return error; +} + +#else +int himax_gpio_power_config(struct himax_i2c_platform_data *pdata) +{ + int error = 0; + struct i2c_client *client = private_ts->client; +#ifdef HX_RST_PIN_FUNC + + if (pdata->gpio_reset >= 0) { + error = gpio_request(pdata->gpio_reset, "himax-reset"); + + if (error < 0) { + E("%s: request reset pin failed\n", __func__); + return error; + } + + error = gpio_direction_output(pdata->gpio_reset, 0); + + if (error) { + E("unable to set direction for gpio [%d]\n", pdata->gpio_reset); + return error; + } + } + +#endif + + if (pdata->gpio_3v3_en >= 0) { + error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en"); + + if (error < 0) { + E("%s: request 3v3_en pin failed\n", __func__); + return error; + } + + gpio_direction_output(pdata->gpio_3v3_en, 1); + I("3v3_en pin =%d\n", gpio_get_value(pdata->gpio_3v3_en)); + } + + if (gpio_is_valid(pdata->gpio_irq)) { + /* configure touchscreen irq gpio */ + error = gpio_request(pdata->gpio_irq, "himax_gpio_irq"); + + if (error) { + E("unable to request gpio [%d]\n", pdata->gpio_irq); + return error; + } + + error = gpio_direction_input(pdata->gpio_irq); + + if (error) { + E("unable to set direction for gpio [%d]\n", pdata->gpio_irq); + return error; + } + + client->irq = gpio_to_irq(pdata->gpio_irq); + } else { + E("irq gpio not provided\n"); + return error; + } + + msleep(20); +#ifdef HX_RST_PIN_FUNC + + if (pdata->gpio_reset >= 0) { + error = gpio_direction_output(pdata->gpio_reset, 1); + + if (error) { + E("unable to set direction for gpio [%d]\n", pdata->gpio_reset); + return error; + } + } + +#endif + return error; +} + +#endif + +static void himax_ts_isr_func(struct himax_ts_data *ts) +{ + himax_ts_work(ts); +} + +irqreturn_t himax_ts_thread(int irq, void *ptr) +{ + himax_ts_isr_func((struct himax_ts_data *)ptr); + + return IRQ_HANDLED; +} + +static void himax_ts_work_func(struct work_struct *work) +{ + struct himax_ts_data *ts; + + ts = container_of(work, struct himax_ts_data, work); + himax_ts_work(ts); +} + +int himax_int_register_trigger(void) +{ + int ret = 0; + struct himax_ts_data *ts = private_ts; + struct i2c_client *client = private_ts->client; + + if (ic_data->HX_INT_IS_EDGE) { + I("%s edge triiger falling\n ", __func__); + ret = request_threaded_irq(client->irq, NULL, himax_ts_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, ts); + } else { + I("%s level trigger low\n ", __func__); + ret = request_threaded_irq(client->irq, NULL, himax_ts_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts); + } + + return ret; +} + +int himax_int_en_set(void) +{ + int ret = NO_ERR; + + ret = himax_int_register_trigger(); + return ret; +} + +int himax_ts_register_interrupt(void) +{ + struct himax_ts_data *ts = private_ts; + struct i2c_client *client = private_ts->client; + int ret = 0; + + ts->irq_enabled = 0; + + /* Work functon */ + if (client->irq) {/* INT mode */ + ts->use_irq = 1; + ret = himax_int_register_trigger(); + + if (ret == 0) { + ts->irq_enabled = 1; + irq_enable_count = 1; + I("%s: irq enabled at qpio: %d\n", __func__, client->irq); +#ifdef HX_SMART_WAKEUP + irq_set_irq_wake(client->irq, 1); +#endif + } else { + ts->use_irq = 0; + E("%s: request_irq failed\n", __func__); + } + } else + I("%s: client->irq is empty, use polling mode.\n", __func__); + + /* if use polling mode need to disable HX_ESD_RECOVERY function */ + if (!ts->use_irq) { + ts->himax_wq = create_singlethread_workqueue("himax_touch"); + INIT_WORK(&ts->work, himax_ts_work_func); + hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ts->timer.function = himax_ts_timer_func; + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + I("%s: polling mode enabled\n", __func__); + } + + return ret; +} + +static int himax_common_suspend(struct device *dev) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + + I("%s: enter\n", __func__); + himax_chip_common_suspend(ts); + return 0; +} + +static int himax_common_resume(struct device *dev) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + + I("%s: enter\n", __func__); + himax_chip_common_resume(ts); + return 0; +} + + +#if defined(CONFIG_DRM) + +int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) +{ + struct msm_drm_notifier *evdata = data; + int *blank; + struct himax_ts_data *ts = + container_of(self, struct himax_ts_data, fb_notif); + + if (!evdata || (evdata->id != 0)) + return 0; + + I("DRM %s\n", __func__); + + if (evdata->data && event == MSM_DRM_EVENT_BLANK && ts && ts->client) { + blank = evdata->data; + + switch (*blank) { + case MSM_DRM_BLANK_UNBLANK: + himax_common_resume(&ts->client->dev); + break; + case MSM_DRM_BLANK_POWERDOWN: + himax_common_suspend(&ts->client->dev); + break; + } + } + + return 0; +} + +#elif defined(CONFIG_FB) + +int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct himax_ts_data *ts = + container_of(self, struct himax_ts_data, fb_notif); + + if (!evdata || (evdata->id != 0)) + return 0; + + I("FB %s\n", __func__); + + if (evdata && evdata->data && event == FB_EVENT_BLANK && ts && + ts->client) { + blank = evdata->data; + + switch (*blank) { + case FB_BLANK_UNBLANK: + himax_common_resume(&ts->client->dev); + break; + case FB_BLANK_POWERDOWN: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_NORMAL: + himax_common_suspend(&ts->client->dev); + break; + } + } + + return 0; +} +#endif + +int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int ret = 0; + struct himax_ts_data *ts; + + I("%s:Enter\n", __func__); + + /* Check I2C functionality */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + E("%s: i2c check functionality error\n", __func__); + ret = -ENODEV; + goto err_check_functionality_failed; + } + + ts = kzalloc(sizeof(struct himax_ts_data), GFP_KERNEL); + if (ts == NULL) { + E("%s: allocate himax_ts_data failed\n", __func__); + ret = -ENOMEM; + goto err_alloc_data_failed; + } + + i2c_set_clientdata(client, ts); + ts->client = client; + ts->dev = &client->dev; + mutex_init(&ts->rw_lock); + private_ts = ts; + + ret = himax_chip_common_init(); + +err_alloc_data_failed: +err_check_functionality_failed: + + return ret; +} + +int himax_chip_common_remove(struct i2c_client *client) +{ + himax_chip_common_deinit(); + + return 0; +} + +static const struct i2c_device_id himax_common_ts_id[] = { + {HIMAX_common_NAME, 0 }, + {} +}; + +static const struct dev_pm_ops himax_common_pm_ops = { +#if (!defined(CONFIG_FB) && !defined(CONFIG_DRM)) + .suspend = himax_common_suspend, + .resume = himax_common_resume, +#endif +}; + +#ifdef CONFIG_OF +static const struct of_device_id himax_match_table[] = { + {.compatible = "himax,hxcommon" }, + {}, +}; +#else +#define himax_match_table NULL +#endif + +static struct i2c_driver himax_common_driver = { + .id_table = himax_common_ts_id, + .probe = himax_chip_common_probe, + .remove = himax_chip_common_remove, + .driver = { + .name = HIMAX_common_NAME, + .owner = THIS_MODULE, + .of_match_table = himax_match_table, +#ifdef CONFIG_PM + .pm = &himax_common_pm_ops, +#endif + }, +}; + +static int __init himax_common_init(void) +{ + I("Himax common touch panel driver init\n"); + i2c_add_driver(&himax_common_driver); + + return 0; +} + +static void __exit himax_common_exit(void) +{ + i2c_del_driver(&himax_common_driver); +} + +module_init(himax_common_init); +module_exit(himax_common_exit); + +MODULE_DESCRIPTION("Himax_common driver"); +MODULE_LICENSE("GPL v2"); + diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.h b/drivers/input/touchscreen/hxchipset/himax_platform.h new file mode 100644 index 000000000000..ac6e37d55dce --- /dev/null +++ b/drivers/input/touchscreen/hxchipset/himax_platform.h @@ -0,0 +1,136 @@ +/* + * Himax Android Driver Sample Code for QCT platform + * + * Copyright (C) 2018 Himax Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef HIMAX_PLATFORM_H +#define HIMAX_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_HMX_DB) + #include +#endif + +#define HIMAX_I2C_RETRY_TIMES 10 + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) +#define D(x...) pr_debug("[HXTP] " x) +#define I(x...) pr_info("[HXTP] " x) +#define W(x...) pr_warn("[HXTP][WARNING] " x) +#define E(x...) pr_err("[HXTP][ERROR] " x) +#define DIF(x...) \ +do { \ + if (debug_flag) \ + pr_debug("[HXTP][DEBUG] " x) \ + } while (0) +#else +#define D(x...) +#define I(x...) +#define W(x...) +#define E(x...) +#define DIF(x...) +#endif + +#if defined(CONFIG_HMX_DB) + /* Analog voltage @2.7 V */ + #define HX_VTG_MIN_UV 2700000 + #define HX_VTG_MAX_UV 3300000 + #define HX_ACTIVE_LOAD_UA 15000 + #define HX_LPM_LOAD_UA 10 + /* Digital voltage @1.8 V */ + #define HX_VTG_DIG_MIN_UV 1800000 + #define HX_VTG_DIG_MAX_UV 1800000 + #define HX_ACTIVE_LOAD_DIG_UA 10000 + #define HX_LPM_LOAD_DIG_UA 10 + + #define HX_I2C_VTG_MIN_UV 1800000 + #define HX_I2C_VTG_MAX_UV 1800000 + #define HX_I2C_LOAD_UA 10000 + #define HX_I2C_LPM_LOAD_UA 10 +#endif + +#define HIMAX_common_NAME "himax_tp" +#define HIMAX_I2C_ADDR 0x48 +#define INPUT_DEV_NAME "himax-touchscreen" + +struct himax_i2c_platform_data { + int abs_x_min; + int abs_x_max; + int abs_x_fuzz; + int abs_y_min; + int abs_y_max; + int abs_y_fuzz; + int abs_pressure_min; + int abs_pressure_max; + int abs_pressure_fuzz; + int abs_width_min; + int abs_width_max; + int screenWidth; + int screenHeight; + uint8_t fw_version; + uint8_t tw_id; + uint8_t powerOff3V3; + uint8_t cable_config[2]; + uint8_t protocol_type; + int gpio_irq; + int gpio_reset; + int gpio_3v3_en; + int (*power)(int on); + void (*reset)(void); + struct himax_virtual_key *virtual_key; + struct kobject *vk_obj; + struct kobj_attribute *vk2Use; + + int hx_config_size; +#if defined(CONFIG_HMX_DB) + bool i2c_pull_up; + bool digital_pwr_regulator; + int reset_gpio; + u32 reset_gpio_flags; + int irq_gpio; + u32 irq_gpio_flags; + + struct regulator *vcc_ana; /* For Dragon Board */ + struct regulator *vcc_dig; /* For Dragon Board */ + struct regulator *vcc_i2c; /* For Dragon Board */ +#endif +}; + +extern int i2c_error_count; +extern int irq_enable_count; +extern int himax_bus_read(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry); +extern int himax_bus_write(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry); +extern int himax_bus_write_command(uint8_t command, uint8_t toRetry); +extern int himax_bus_master_write(uint8_t *data, uint32_t length, uint8_t toRetry); +extern void himax_int_enable(int enable); +extern int himax_ts_register_interrupt(void); +extern uint8_t himax_int_gpio_read(int pinnum); + +extern int himax_gpio_power_config(struct himax_i2c_platform_data *pdata); + + +#if defined(CONFIG_DRM) || defined(CONFIG_FB) + extern int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); +#endif + +#if defined(HX_PLATFOME_DEFINE_KEY) + extern void himax_platform_key(void) +#endif + +#endif -- GitLab From 02a300f7796f700b5e3bed2690008a6041cffe5f Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Mon, 25 Jun 2018 11:24:10 +0530 Subject: [PATCH 0924/1299] msm: driver to create cld80211 nl family at bootup time Create cnss_genl driver to create a netlink family cld80211 and make it available to cld driver and applications when they query for it. This driver creates multicast groups to facilitate communication from cld driver to userspace and allows cld driver to register for different commands from user space Change-Id: I0795dd08b6429fad60187fee724b3fd3ccfa5603 Signed-off-by: Srinivas Dasari CRs-Fixed: 1100401 --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/Makefile | 1 + drivers/net/wireless/cnss_genl/Kconfig | 7 + drivers/net/wireless/cnss_genl/Makefile | 1 + drivers/net/wireless/cnss_genl/cnss_nl.c | 207 +++++++++++++++++++++++ include/net/cnss_nl.h | 100 +++++++++++ 6 files changed, 317 insertions(+) create mode 100644 drivers/net/wireless/cnss_genl/Kconfig create mode 100644 drivers/net/wireless/cnss_genl/Makefile create mode 100644 drivers/net/wireless/cnss_genl/cnss_nl.c create mode 100644 include/net/cnss_nl.h diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 9bb402595b63..5537982115e0 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -136,5 +136,6 @@ config CLD_LL_CORE support. source "drivers/net/wireless/cnss_utils/Kconfig" +source "drivers/net/wireless/cnss_genl/Kconfig" endif # WLAN diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 3548c468a8c7..328b12251678 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -30,3 +30,4 @@ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/ obj-$(CONFIG_CNSS_UTILS) += cnss_utils/ +obj-$(CONFIG_CNSS_GENL) += cnss_genl/ diff --git a/drivers/net/wireless/cnss_genl/Kconfig b/drivers/net/wireless/cnss_genl/Kconfig new file mode 100644 index 000000000000..f1b8a586ec90 --- /dev/null +++ b/drivers/net/wireless/cnss_genl/Kconfig @@ -0,0 +1,7 @@ +config CNSS_GENL + tristate "CNSS Generic Netlink Socket Driver" + ---help--- + This module creates generic netlink family "CLD80211". This can be + used by cld driver and userspace utilities to communicate over + netlink sockets. This module creates different multicast groups to + facilitate the same. diff --git a/drivers/net/wireless/cnss_genl/Makefile b/drivers/net/wireless/cnss_genl/Makefile new file mode 100644 index 000000000000..9431c9e596bb --- /dev/null +++ b/drivers/net/wireless/cnss_genl/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_CNSS_GENL) := cnss_nl.o diff --git a/drivers/net/wireless/cnss_genl/cnss_nl.c b/drivers/net/wireless/cnss_genl/cnss_nl.c new file mode 100644 index 000000000000..464a0361f473 --- /dev/null +++ b/drivers/net/wireless/cnss_genl/cnss_nl.c @@ -0,0 +1,207 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#define CLD80211_GENL_NAME "cld80211" + +#define CLD80211_MULTICAST_GROUP_SVC_MSGS "svc_msgs" +#define CLD80211_MULTICAST_GROUP_HOST_LOGS "host_logs" +#define CLD80211_MULTICAST_GROUP_FW_LOGS "fw_logs" +#define CLD80211_MULTICAST_GROUP_PER_PKT_STATS "per_pkt_stats" +#define CLD80211_MULTICAST_GROUP_DIAG_EVENTS "diag_events" +#define CLD80211_MULTICAST_GROUP_FATAL_EVENTS "fatal_events" +#define CLD80211_MULTICAST_GROUP_OEM_MSGS "oem_msgs" + +static const struct genl_multicast_group nl_mcgrps[] = { + [CLD80211_MCGRP_SVC_MSGS] = { .name = + CLD80211_MULTICAST_GROUP_SVC_MSGS}, + [CLD80211_MCGRP_HOST_LOGS] = { .name = + CLD80211_MULTICAST_GROUP_HOST_LOGS}, + [CLD80211_MCGRP_FW_LOGS] = { .name = + CLD80211_MULTICAST_GROUP_FW_LOGS}, + [CLD80211_MCGRP_PER_PKT_STATS] = { .name = + CLD80211_MULTICAST_GROUP_PER_PKT_STATS}, + [CLD80211_MCGRP_DIAG_EVENTS] = { .name = + CLD80211_MULTICAST_GROUP_DIAG_EVENTS}, + [CLD80211_MCGRP_FATAL_EVENTS] = { .name = + CLD80211_MULTICAST_GROUP_FATAL_EVENTS}, + [CLD80211_MCGRP_OEM_MSGS] = { .name = + CLD80211_MULTICAST_GROUP_OEM_MSGS}, +}; + +struct cld_ops { + cld80211_cb cb; + void *cb_ctx; +}; + +struct cld80211_nl_data { + struct cld_ops cld_ops[CLD80211_MAX_COMMANDS]; +}; + +static struct cld80211_nl_data nl_data; + +static inline struct cld80211_nl_data *get_local_ctx(void) +{ + return &nl_data; +} + +static struct genl_ops nl_ops[CLD80211_MAX_COMMANDS]; + +/* policy for the attributes */ +static const struct nla_policy cld80211_policy[CLD80211_ATTR_MAX + 1] = { + [CLD80211_ATTR_VENDOR_DATA] = { .type = NLA_NESTED }, + [CLD80211_ATTR_DATA] = { .type = NLA_BINARY, + .len = CLD80211_MAX_NL_DATA }, +}; + +static int cld80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, + struct genl_info *info) +{ + u8 cmd_id = ops->cmd; + struct cld80211_nl_data *nl = get_local_ctx(); + + if (cmd_id < 1 || cmd_id > CLD80211_MAX_COMMANDS) { + pr_err("CLD80211: Command Not supported: %u\n", cmd_id); + return -EOPNOTSUPP; + } + info->user_ptr[0] = nl->cld_ops[cmd_id - 1].cb; + info->user_ptr[1] = nl->cld_ops[cmd_id - 1].cb_ctx; + + return 0; +} + +/* The netlink family */ +static struct genl_family cld80211_fam __ro_after_init = { + .name = CLD80211_GENL_NAME, + .hdrsize = 0, /* no private header */ + .version = 1, /* no particular meaning now */ + .maxattr = CLD80211_ATTR_MAX, + .netnsok = true, + .pre_doit = cld80211_pre_doit, + .post_doit = NULL, + .module = THIS_MODULE, + .ops = nl_ops, + .n_ops = ARRAY_SIZE(nl_ops), + .mcgrps = nl_mcgrps, + .n_mcgrps = ARRAY_SIZE(nl_mcgrps), +}; + +int register_cld_cmd_cb(u8 cmd_id, cld80211_cb func, void *cb_ctx) +{ + struct cld80211_nl_data *nl = get_local_ctx(); + + pr_debug("CLD80211: Registering command: %d\n", cmd_id); + if (!cmd_id || cmd_id > CLD80211_MAX_COMMANDS) { + pr_debug("CLD80211: invalid command: %d\n", cmd_id); + return -EINVAL; + } + + nl->cld_ops[cmd_id - 1].cb = func; + nl->cld_ops[cmd_id - 1].cb_ctx = cb_ctx; + + return 0; +} +EXPORT_SYMBOL(register_cld_cmd_cb); + +int deregister_cld_cmd_cb(u8 cmd_id) +{ + struct cld80211_nl_data *nl = get_local_ctx(); + + pr_debug("CLD80211: De-registering command: %d\n", cmd_id); + if (!cmd_id || cmd_id > CLD80211_MAX_COMMANDS) { + pr_debug("CLD80211: invalid command: %d\n", cmd_id); + return -EINVAL; + } + + nl->cld_ops[cmd_id - 1].cb = NULL; + nl->cld_ops[cmd_id - 1].cb_ctx = NULL; + + return 0; +} +EXPORT_SYMBOL(deregister_cld_cmd_cb); + +struct genl_family *cld80211_get_genl_family(void) +{ + return &cld80211_fam; +} +EXPORT_SYMBOL(cld80211_get_genl_family); + +static int cld80211_doit(struct sk_buff *skb, struct genl_info *info) +{ + cld80211_cb cld_cb; + void *cld_ctx; + + cld_cb = info->user_ptr[0]; + + if (!cld_cb) { + pr_err("CLD80211: Not supported\n"); + return -EOPNOTSUPP; + } + cld_ctx = info->user_ptr[1]; + + if (info->attrs[CLD80211_ATTR_VENDOR_DATA]) { + cld_cb(nla_data(info->attrs[CLD80211_ATTR_VENDOR_DATA]), + nla_len(info->attrs[CLD80211_ATTR_VENDOR_DATA]), + cld_ctx, info->snd_portid); + } else { + pr_err("CLD80211: No CLD80211_ATTR_VENDOR_DATA\n"); + return -EINVAL; + } + return 0; +} + +static int __cld80211_init(void) +{ + int err, i; + + memset(&nl_ops[0], 0, sizeof(nl_ops)); + + pr_info("CLD80211: Initializing\n"); + for (i = 0; i < CLD80211_MAX_COMMANDS; i++) { + nl_ops[i].cmd = i + 1; + nl_ops[i].doit = cld80211_doit; + nl_ops[i].flags = GENL_ADMIN_PERM; + nl_ops[i].policy = cld80211_policy; + } + + err = genl_register_family(&cld80211_fam); + if (err) { + pr_err("CLD80211: Failed to register cld80211 family: %d\n", + err); + } + + return err; +} + +static void __cld80211_exit(void) +{ + genl_unregister_family(&cld80211_fam); +} + +static int __init cld80211_init(void) +{ + return __cld80211_init(); +} + +static void __exit cld80211_exit(void) +{ + __cld80211_exit(); +} + +module_init(cld80211_init); +module_exit(cld80211_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("CNSS generic netlink module"); diff --git a/include/net/cnss_nl.h b/include/net/cnss_nl.h new file mode 100644 index 000000000000..128cb3d0c6f3 --- /dev/null +++ b/include/net/cnss_nl.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _NET_CNSS_GENETLINK_H_ +#define _NET_CNSS_GENETLINK_H_ + +#define CLD80211_MAX_COMMANDS 40 +#define CLD80211_MAX_NL_DATA 4096 + +/** + * enum cld80211_attr - Driver/Application embeds the data in nlmsg with the + * help of below attributes + * + * @CLD80211_ATTR_VENDOR_DATA: Embed all other attributes in this nested + * attribute. + * @CLD80211_ATTR_DATA: Embed complete data in this attribute + * + * Any new message in future can be added as another attribute + */ +enum cld80211_attr { + CLD80211_ATTR_VENDOR_DATA = 1, + CLD80211_ATTR_DATA, + /* add new attributes above here */ + + __CLD80211_ATTR_AFTER_LAST, + CLD80211_ATTR_MAX = __CLD80211_ATTR_AFTER_LAST - 1 +}; + +/** + * enum cld80211_multicast_groups - List of multicast groups supported + * + * @CLD80211_MCGRP_SVC_MSGS: WLAN service message will be sent to this group. + * Ex: Status ind messages + * @CLD80211_MCGRP_HOST_LOGS: All logging related messages from driver will be + * sent to this multicast group + * @CLD80211_MCGRP_FW_LOGS: Firmware logging messages will be sent to this group + * @CLD80211_MCGRP_PER_PKT_STATS: Messages related packet stats debugging infra + * will be sent to this group + * @CLD80211_MCGRP_DIAG_EVENTS: Driver/Firmware status logging diag events will + * be sent to this group + * @CLD80211_MCGRP_FATAL_EVENTS: Any fatal message generated in driver/firmware + * will be sent to this group + * @CLD80211_MCGRP_OEM_MSGS: All OEM message will be sent to this group + * Ex: LOWI messages + */ +enum cld80211_multicast_groups { + CLD80211_MCGRP_SVC_MSGS, + CLD80211_MCGRP_HOST_LOGS, + CLD80211_MCGRP_FW_LOGS, + CLD80211_MCGRP_PER_PKT_STATS, + CLD80211_MCGRP_DIAG_EVENTS, + CLD80211_MCGRP_FATAL_EVENTS, + CLD80211_MCGRP_OEM_MSGS, +}; + +/** + * typedef cld80211_cb - Callback to be called when an nlmsg is received with + * the registered cmd_id command from userspace + * @data: Payload of the message to be sent to driver + * @data_len: Length of the payload + * @cb_ctx: callback context to be returned to driver when the callback + * is called + * @pid: process id of the sender + */ +typedef void (*cld80211_cb)(const void *data, int data_len, + void *cb_ctx, int pid); + +/** + * register_cld_cmd_cb() - Allows cld driver to register for commands with + * callback + * @cmd_id: Command to be registered. Valid range [1, CLD80211_MAX_COMMANDS] + * @cb: Callback to be called when an nlmsg is received with cmd_id command + * from userspace + * @cb_ctx: context provided by driver; Send this as cb_ctx of func() + * to driver + */ +int register_cld_cmd_cb(u8 cmd_id, cld80211_cb cb, void *cb_ctx); + +/** + * deregister_cld_cmd_cb() - Allows cld driver to de-register the command it + * has already registered + * @cmd_id: Command to be deregistered. + */ +int deregister_cld_cmd_cb(u8 cmd_id); + +/** + * cld80211_get_genl_family() - Returns current netlink family context + */ +struct genl_family *cld80211_get_genl_family(void); + +#endif /* _NET_CNSS_GENETLINK_H_ */ -- GitLab From 72e45b07094094046b091dd8aa0a2f67482da760 Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Thu, 14 Jun 2018 11:03:55 +0530 Subject: [PATCH 0925/1299] usb: phy: Add snapshot of USB QUSB PHY driver This change adds USB QUSB PHY driver used on QTI MSM platforms. This snapshot is taken as of msm-4.9 commit ("Merge "qseecom: fix a race condition when loading TA""). Change-Id: I4931bb022b7a921da0feae45988e3d01240965aa Signed-off-by: Pratham Pratap --- .../devicetree/bindings/usb/qcom,msm-phy.txt | 90 ++ drivers/usb/phy/Kconfig | 10 + drivers/usb/phy/Makefile | 1 + drivers/usb/phy/phy-msm-qusb.c | 1269 +++++++++++++++++ 4 files changed, 1370 insertions(+) create mode 100644 drivers/usb/phy/phy-msm-qusb.c diff --git a/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt b/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt index 95a5977fe66b..3aeb49eda1e6 100644 --- a/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt +++ b/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt @@ -138,3 +138,93 @@ Example: "phy_phy_reset"; }; + +QUSB2 High-Speed PHY + +Required properties: + - compatible: Should be "qcom,qusb2phy" or "qcom,qusb2phy-v2" + - reg: Address and length of the QUSB2 PHY register set + - reg-names: Should be "qusb_phy_base". + - -supply: phandle to the regulator device tree node + Required supplies are: + "vdd" : vdd supply for digital circuit operation + "vdda18" : 1.8v high-voltage analog supply + "vdda33" : 3.3v high-voltage analog supply + - clocks: a list of phandles to the PHY clocks. Use as per + Documentation/devicetree/bindings/clock/clock-bindings.txt + - clock-names: Names of the clocks in 1-1 correspondence with the "clocks" + property. "ref_clk_src" is a mandatory clock. + - qcom,vdd-voltage-level: This property must be a list of three integer + values (no, min, max) where each value represents either a voltage in + microvolts or a value corresponding to voltage corner + - phy_type: Should be one of "ulpi" or "utmi". ChipIdea core uses "ulpi" mode. + - resets: reset specifier pair consists of phandle for the reset controller + and reset lines used by this controller. + - reset-names: reset signal name strings sorted in the same order as the resets + property. + - qcom,qusb-phy-reg-offset: Provides important phy register offsets in an order defined in phy driver. + +Optional properties: + - reg-names: Additional registers corresponding with the following: + "efuse_addr": EFUSE address to read and update analog tune parameter. + "emu_phy_base" : phy base address used for programming emulation target phy. + "ref_clk_addr" : ref_clk bcr address used for on/off ref_clk before reset. + "tcsr_clamp_dig_n" : To enable/disable digital clamp to the phy. When + de-asserted, it will prevent random leakage from qusb2 phy resulting from + out of sequence turn on/off of 1p8, 3p3 and DVDD regulators. + "refgen_north_bg_reg" : address used to read REFGEN status for overriding QUSB PHY register. + - clocks: a list of phandles to the PHY clocks. Use as per + Documentation/devicetree/bindings/clock/clock-bindings.txt + - clock-names: Names of the clocks in 1-1 correspondence with the "clocks" + property. "cfg_ahb_clk" and "ref_clk" are optional clocks. + - qcom,qusb-phy-init-seq: QUSB PHY initialization sequence with value,reg pair. + - qcom,qusb-phy-host-init-seq: QUSB PHY initialization sequence for host mode + with value,reg pair. + - qcom,emu-init-seq : emulation initialization sequence with value,reg pair. + - qcom,phy-pll-reset-seq : emulation PLL reset sequence with value,reg pair. + - qcom,emu-dcm-reset-seq : emulation DCM reset sequence with value,reg pair. + - qcom,efuse-bit-pos: start bit position within EFUSE register + - qcom,efuse-num-bits: Number of bits to read from EFUSE register + - qcom,emulation: Indicates that we are running on emulation platform. + - qcom,hold-reset: Indicates that hold QUSB PHY into reset state. + - qcom,phy-clk-scheme: Should be one of "cml" or "cmos" if ref_clk_addr is provided. + - qcom,major-rev: provide major revision number to differentiate power up sequence. default is 2.0 + - pinctrl-names/pinctrl-0/1: The GPIOs configured as output function. Names represents "active" + state when attached in host mode and "suspend" state when detached. + - qcom,tune2-efuse-correction: The value to be adjusted from fused value for + improved rise/fall times. + - qcom,host-chirp-erratum: Indicates host chirp fix is required. + - qcom,override-bias-ctrl2: Indicates override is done from driver for + BIAS_CTRL2 register. + - nvmem-cells: specifies the handle to represent the SoC revision. + usually it is defined by qfprom device node. + - nvmem-cell-names: specifies the given nvmem cell name as defined in + qfprom node. + +Example: + qusb_phy: qusb@f9b39000 { + compatible = "qcom,qusb2phy"; + reg = <0x00079000 0x7000>; + reg-names = "qusb_phy_base"; + vdd-supply = <&pm8994_s2_corner>; + vdda18-supply = <&pm8994_l6>; + vdda33-supply = <&pm8994_l24>; + qcom,vdd-voltage-level = <1 5 7>; + qcom,qusb-phy-reg-offset = + <0x240 /* QUSB2PHY_PORT_TUNE1 */ + 0x1a0 /* QUSB2PHY_PLL_COMMON_STATUS_ONE */ + 0x210 /* QUSB2PHY_PWR_CTRL1 */ + 0x230 /* QUSB2PHY_INTR_CTRL */ + 0x0a8 /* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE */ + 0x254 /* QUSB2PHY_TEST1 */ + 0x198>; /* QUSB2PHY_PLL_BIAS_CONTROL_2 */ + qcom,efuse-bit-pos = <21>; + qcom,efuse-num-bits = <3>; + + clocks = <&clock_rpm clk_ln_bb_clk>, + <&clock_gcc clk_gcc_rx2_usb1_clkref_clk>, + <&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>; + clock-names = "ref_clk_src", "ref_clk", "cfg_ahb_clk"; + resets = <&clock_gcc GCC_QUSB2PHY_PRIM_BCR>; + reset-names = "phy_reset"; + }; diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 6181449a2726..e8a50972075e 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -216,6 +216,16 @@ config USB_MSM_SSPHY_QMP set for its control sequences, normally paired with newer DWC3-based SuperSpeed controllers. +config MSM_QUSB_PHY + tristate "MSM QUSB2 PHY Driver" + depends on ARCH_QCOM + select USB_PHY + help + Enable this to support the QUSB2 PHY on MSM chips. This driver supports + the high-speed PHY which is usually paired with either the ChipIdea or + Synopsys DWC3 USB IPs on MSM SOCs. This driver expects to configure the + PHY with a dedicated register I/O memory region. + config MSM_HSUSB_PHY tristate "MSM HSUSB PHY Driver" depends on ARCH_QCOM diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 5b625a692b74..7bbed6e30052 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -31,5 +31,6 @@ obj-$(CONFIG_USB_ULPI) += phy-ulpi.o obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o obj-$(CONFIG_KEYSTONE_USB_PHY) += phy-keystone.o obj-$(CONFIG_USB_MSM_SSPHY_QMP) += phy-msm-ssusb-qmp.o +obj-$(CONFIG_MSM_QUSB_PHY) += phy-msm-qusb.o obj-$(CONFIG_MSM_HSUSB_PHY) += phy-msm-snps-hs.o obj-$(CONFIG_MSM_SNPS_FEMTO_PHY) += phy-qcom-snps-28nm-hs.o diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c new file mode 100644 index 000000000000..47db12bef9c6 --- /dev/null +++ b/drivers/usb/phy/phy-msm-qusb.c @@ -0,0 +1,1269 @@ +/* + * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define QUSB2PHY_PLL_STATUS 0x38 +#define QUSB2PHY_PLL_LOCK BIT(5) + +#define QUSB2PHY_PORT_QC1 0x70 +#define VDM_SRC_EN BIT(4) +#define VDP_SRC_EN BIT(2) + +#define QUSB2PHY_PORT_QC2 0x74 +#define RDM_UP_EN BIT(1) +#define RDP_UP_EN BIT(3) +#define RPUM_LOW_EN BIT(4) +#define RPUP_LOW_EN BIT(5) + +#define QUSB2PHY_PORT_POWERDOWN 0xB4 +#define CLAMP_N_EN BIT(5) +#define FREEZIO_N BIT(1) +#define POWER_DOWN BIT(0) + +#define QUSB2PHY_PORT_TEST_CTRL 0xB8 + +#define QUSB2PHY_PWR_CTRL1 0x210 +#define PWR_CTRL1_CLAMP_N_EN BIT(1) +#define PWR_CTRL1_POWR_DOWN BIT(0) + +#define QUSB2PHY_PLL_COMMON_STATUS_ONE 0x1A0 +#define CORE_READY_STATUS BIT(0) + +#define QUSB2PHY_PORT_UTMI_CTRL1 0xC0 +#define TERM_SELECT BIT(4) +#define XCVR_SELECT_FS BIT(2) +#define OP_MODE_NON_DRIVE BIT(0) + +#define QUSB2PHY_PORT_UTMI_CTRL2 0xC4 +#define UTMI_ULPI_SEL BIT(7) +#define UTMI_TEST_MUX_SEL BIT(6) + +#define QUSB2PHY_PLL_TEST 0x04 +#define CLK_REF_SEL BIT(7) + +#define QUSB2PHY_PORT_TUNE1 0x80 +#define QUSB2PHY_PORT_TUNE2 0x84 +#define QUSB2PHY_PORT_TUNE3 0x88 +#define QUSB2PHY_PORT_TUNE4 0x8C +#define QUSB2PHY_PORT_TUNE5 0x90 + +/* Get TUNE2's high nibble value read from efuse */ +#define TUNE2_HIGH_NIBBLE_VAL(val, pos, mask) ((val >> pos) & mask) + +#define QUSB2PHY_PORT_INTR_CTRL 0xBC +#define CHG_DET_INTR_EN BIT(4) +#define DMSE_INTR_HIGH_SEL BIT(3) +#define DMSE_INTR_EN BIT(2) +#define DPSE_INTR_HIGH_SEL BIT(1) +#define DPSE_INTR_EN BIT(0) + +#define QUSB2PHY_PORT_UTMI_STATUS 0xF4 +#define LINESTATE_DP BIT(0) +#define LINESTATE_DM BIT(1) + + +#define QUSB2PHY_1P8_VOL_MIN 1800000 /* uV */ +#define QUSB2PHY_1P8_VOL_MAX 1800000 /* uV */ +#define QUSB2PHY_1P8_HPM_LOAD 30000 /* uA */ + +#define QUSB2PHY_3P3_VOL_MIN 3075000 /* uV */ +#define QUSB2PHY_3P3_VOL_MAX 3200000 /* uV */ +#define QUSB2PHY_3P3_HPM_LOAD 30000 /* uA */ + +#define QUSB2PHY_REFCLK_ENABLE BIT(0) + +static unsigned int tune1; +module_param(tune1, uint, 0644); +MODULE_PARM_DESC(tune1, "QUSB PHY TUNE1"); + +static unsigned int tune2; +module_param(tune2, uint, 0644); +MODULE_PARM_DESC(tune2, "QUSB PHY TUNE2"); + +static unsigned int tune3; +module_param(tune3, uint, 0644); +MODULE_PARM_DESC(tune3, "QUSB PHY TUNE3"); + +static unsigned int tune4; +module_param(tune4, uint, 0644); +MODULE_PARM_DESC(tune4, "QUSB PHY TUNE4"); + +static unsigned int tune5; +module_param(tune5, uint, 0644); +MODULE_PARM_DESC(tune5, "QUSB PHY TUNE5"); + + +struct qusb_phy { + struct usb_phy phy; + void __iomem *base; + void __iomem *tune2_efuse_reg; + void __iomem *ref_clk_base; + void __iomem *tcsr_clamp_dig_n; + + struct clk *ref_clk_src; + struct clk *ref_clk; + struct clk *cfg_ahb_clk; + struct reset_control *phy_reset; + struct clk *iface_clk; + struct clk *core_clk; + + struct regulator *gdsc; + struct regulator *vdd; + struct regulator *vdda33; + struct regulator *vdda18; + int vdd_levels[3]; /* none, low, high */ + int init_seq_len; + int *qusb_phy_init_seq; + u32 major_rev; + + u32 tune2_val; + int tune2_efuse_bit_pos; + int tune2_efuse_num_of_bits; + int tune2_efuse_correction; + + bool power_enabled; + bool clocks_enabled; + bool cable_connected; + bool suspended; + bool ulpi_mode; + bool dpdm_enable; + bool is_se_clk; + + struct regulator_desc dpdm_rdesc; + struct regulator_dev *dpdm_rdev; + + /* emulation targets specific */ + void __iomem *emu_phy_base; + bool emulation; + int *emu_init_seq; + int emu_init_seq_len; + int *phy_pll_reset_seq; + int phy_pll_reset_seq_len; + int *emu_dcm_reset_seq; + int emu_dcm_reset_seq_len; + bool put_into_high_z_state; + struct mutex phy_lock; +}; + +static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on) +{ + dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d on:%d\n", + __func__, qphy->clocks_enabled, on); + + if (!qphy->clocks_enabled && on) { + clk_prepare_enable(qphy->ref_clk_src); + clk_prepare_enable(qphy->ref_clk); + clk_prepare_enable(qphy->iface_clk); + clk_prepare_enable(qphy->core_clk); + clk_prepare_enable(qphy->cfg_ahb_clk); + qphy->clocks_enabled = true; + } + + if (qphy->clocks_enabled && !on) { + clk_disable_unprepare(qphy->cfg_ahb_clk); + /* + * FSM depedency beween iface_clk and core_clk. + * Hence turned off core_clk before iface_clk. + */ + clk_disable_unprepare(qphy->core_clk); + clk_disable_unprepare(qphy->iface_clk); + clk_disable_unprepare(qphy->ref_clk); + clk_disable_unprepare(qphy->ref_clk_src); + qphy->clocks_enabled = false; + } + + dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d\n", __func__, + qphy->clocks_enabled); +} + +static int qusb_phy_gdsc(struct qusb_phy *qphy, bool on) +{ + int ret; + + if (IS_ERR_OR_NULL(qphy->gdsc)) + return -EPERM; + + if (on) { + dev_dbg(qphy->phy.dev, "TURNING ON GDSC\n"); + ret = regulator_enable(qphy->gdsc); + if (ret) { + dev_err(qphy->phy.dev, "unable to enable gdsc\n"); + return ret; + } + } else { + dev_dbg(qphy->phy.dev, "TURNING OFF GDSC\n"); + ret = regulator_disable(qphy->gdsc); + if (ret) { + dev_err(qphy->phy.dev, "unable to disable gdsc\n"); + return ret; + } + } + + return ret; +} + +static int qusb_phy_config_vdd(struct qusb_phy *qphy, int high) +{ + int min, ret; + + min = high ? 1 : 0; /* low or none? */ + ret = regulator_set_voltage(qphy->vdd, qphy->vdd_levels[min], + qphy->vdd_levels[2]); + if (ret) { + dev_err(qphy->phy.dev, "unable to set voltage for qusb vdd\n"); + return ret; + } + + dev_dbg(qphy->phy.dev, "min_vol:%d max_vol:%d\n", + qphy->vdd_levels[min], qphy->vdd_levels[2]); + return ret; +} + +static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on) +{ + int ret = 0; + + dev_dbg(qphy->phy.dev, "%s turn %s regulators. power_enabled:%d\n", + __func__, on ? "on" : "off", qphy->power_enabled); + + if (qphy->power_enabled == on) { + dev_dbg(qphy->phy.dev, "PHYs' regulators are already ON.\n"); + return 0; + } + + if (!on) + goto disable_vdda33; + + ret = qusb_phy_config_vdd(qphy, true); + if (ret) { + dev_err(qphy->phy.dev, "Unable to config VDD:%d\n", + ret); + goto err_vdd; + } + + ret = regulator_enable(qphy->vdd); + if (ret) { + dev_err(qphy->phy.dev, "Unable to enable VDD\n"); + goto unconfig_vdd; + } + + ret = regulator_set_load(qphy->vdda18, QUSB2PHY_1P8_HPM_LOAD); + if (ret < 0) { + dev_err(qphy->phy.dev, "Unable to set HPM of vdda18:%d\n", ret); + goto disable_vdd; + } + + ret = regulator_set_voltage(qphy->vdda18, QUSB2PHY_1P8_VOL_MIN, + QUSB2PHY_1P8_VOL_MAX); + if (ret) { + dev_err(qphy->phy.dev, + "Unable to set voltage for vdda18:%d\n", ret); + goto put_vdda18_lpm; + } + + ret = regulator_enable(qphy->vdda18); + if (ret) { + dev_err(qphy->phy.dev, "Unable to enable vdda18:%d\n", ret); + goto unset_vdda18; + } + + ret = regulator_set_load(qphy->vdda33, QUSB2PHY_3P3_HPM_LOAD); + if (ret < 0) { + dev_err(qphy->phy.dev, "Unable to set HPM of vdda33:%d\n", ret); + goto disable_vdda18; + } + + ret = regulator_set_voltage(qphy->vdda33, QUSB2PHY_3P3_VOL_MIN, + QUSB2PHY_3P3_VOL_MAX); + if (ret) { + dev_err(qphy->phy.dev, + "Unable to set voltage for vdda33:%d\n", ret); + goto put_vdda33_lpm; + } + + ret = regulator_enable(qphy->vdda33); + if (ret) { + dev_err(qphy->phy.dev, "Unable to enable vdda33:%d\n", ret); + goto unset_vdd33; + } + + qphy->power_enabled = true; + + pr_debug("%s(): QUSB PHY's regulators are turned ON.\n", __func__); + return ret; + +disable_vdda33: + ret = regulator_disable(qphy->vdda33); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdda33:%d\n", ret); + +unset_vdd33: + ret = regulator_set_voltage(qphy->vdda33, 0, QUSB2PHY_3P3_VOL_MAX); + if (ret) + dev_err(qphy->phy.dev, + "Unable to set (0) voltage for vdda33:%d\n", ret); + +put_vdda33_lpm: + ret = regulator_set_load(qphy->vdda33, 0); + if (ret < 0) + dev_err(qphy->phy.dev, "Unable to set (0) HPM of vdda33\n"); + +disable_vdda18: + ret = regulator_disable(qphy->vdda18); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdda18:%d\n", ret); + +unset_vdda18: + ret = regulator_set_voltage(qphy->vdda18, 0, QUSB2PHY_1P8_VOL_MAX); + if (ret) + dev_err(qphy->phy.dev, + "Unable to set (0) voltage for vdda18:%d\n", ret); + +put_vdda18_lpm: + ret = regulator_set_load(qphy->vdda18, 0); + if (ret < 0) + dev_err(qphy->phy.dev, "Unable to set LPM of vdda18\n"); + +disable_vdd: + ret = regulator_disable(qphy->vdd); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdd:%d\n", + ret); + +unconfig_vdd: + ret = qusb_phy_config_vdd(qphy, false); + if (ret) + dev_err(qphy->phy.dev, "Unable unconfig VDD:%d\n", + ret); +err_vdd: + qphy->power_enabled = false; + dev_dbg(qphy->phy.dev, "QUSB PHY's regulators are turned OFF.\n"); + return ret; +} + +static void qusb_phy_get_tune2_param(struct qusb_phy *qphy) +{ + u8 num_of_bits; + u32 bit_mask = 1; + u8 reg_val; + + pr_debug("%s(): num_of_bits:%d bit_pos:%d\n", __func__, + qphy->tune2_efuse_num_of_bits, + qphy->tune2_efuse_bit_pos); + + /* get bit mask based on number of bits to use with efuse reg */ + if (qphy->tune2_efuse_num_of_bits) { + num_of_bits = qphy->tune2_efuse_num_of_bits; + bit_mask = (bit_mask << num_of_bits) - 1; + } + + /* + * Read EFUSE register having TUNE2 parameter's high nibble. + * If efuse register shows value as 0x0, then use previous value + * as it is. Otherwise use efuse register based value for this purpose. + */ + qphy->tune2_val = readl_relaxed(qphy->tune2_efuse_reg); + pr_debug("%s(): bit_mask:%d efuse based tune2 value:%d\n", + __func__, bit_mask, qphy->tune2_val); + + qphy->tune2_val = TUNE2_HIGH_NIBBLE_VAL(qphy->tune2_val, + qphy->tune2_efuse_bit_pos, bit_mask); + + /* Update higher nibble of TUNE2 value for better rise/fall times */ + if (qphy->tune2_efuse_correction && qphy->tune2_val) { + if (qphy->tune2_efuse_correction > 5 || + qphy->tune2_efuse_correction < -10) + pr_warn("Correction value is out of range : %d\n", + qphy->tune2_efuse_correction); + else + qphy->tune2_val = qphy->tune2_val + + qphy->tune2_efuse_correction; + } + + reg_val = readb_relaxed(qphy->base + QUSB2PHY_PORT_TUNE2); + if (qphy->tune2_val) { + reg_val &= 0x0f; + reg_val |= (qphy->tune2_val << 4); + } + + qphy->tune2_val = reg_val; +} + +static void qusb_phy_write_seq(void __iomem *base, u32 *seq, int cnt, + unsigned long delay) +{ + int i; + + pr_debug("Seq count:%d\n", cnt); + for (i = 0; i < cnt; i = i+2) { + pr_debug("write 0x%02x to 0x%02x\n", seq[i], seq[i+1]); + writel_relaxed(seq[i], base + seq[i+1]); + if (delay) + usleep_range(delay, (delay + 2000)); + } +} + +static int qusb_phy_init(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + int ret, reset_val = 0; + u8 reg; + bool pll_lock_fail = false; + + dev_dbg(phy->dev, "%s\n", __func__); + + ret = qusb_phy_enable_power(qphy, true); + if (ret) + return ret; + + qusb_phy_enable_clocks(qphy, true); + + /* + * ref clock is enabled by default after power on reset. Linux clock + * driver will disable this clock as part of late init if peripheral + * driver(s) does not explicitly votes for it. Linux clock driver also + * does not disable the clock until late init even if peripheral + * driver explicitly requests it and cannot defer the probe until late + * init. Hence, Explicitly disable the clock using register write to + * allow QUSB PHY PLL to lock properly. + */ + if (qphy->ref_clk_base) { + writel_relaxed((readl_relaxed(qphy->ref_clk_base) & + ~QUSB2PHY_REFCLK_ENABLE), + qphy->ref_clk_base); + /* Make sure that above write complete to get ref clk OFF */ + wmb(); + } + + /* Perform phy reset */ + ret = reset_control_assert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset assert failed\n", __func__); + usleep_range(100, 150); + ret = reset_control_deassert(qphy->phy_reset); + if (ret) + dev_err(phy->dev, "%s: phy_reset deassert failed\n", __func__); + + if (qphy->emulation) { + if (qphy->emu_init_seq) + qusb_phy_write_seq(qphy->emu_phy_base, + qphy->emu_init_seq, qphy->emu_init_seq_len, 0); + + if (qphy->qusb_phy_init_seq) + qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq, + qphy->init_seq_len, 0); + + /* Wait for 5ms as per QUSB2 RUMI sequence */ + usleep_range(5000, 7000); + + if (qphy->phy_pll_reset_seq) + qusb_phy_write_seq(qphy->base, qphy->phy_pll_reset_seq, + qphy->phy_pll_reset_seq_len, 10000); + + if (qphy->emu_dcm_reset_seq) + qusb_phy_write_seq(qphy->emu_phy_base, + qphy->emu_dcm_reset_seq, + qphy->emu_dcm_reset_seq_len, 10000); + + return 0; + } + + /* Disable the PHY */ + if (qphy->major_rev < 2) + writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + else + writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) | + PWR_CTRL1_POWR_DOWN, + qphy->base + QUSB2PHY_PWR_CTRL1); + + /* configure for ULPI mode if requested */ + if (qphy->ulpi_mode) + writel_relaxed(0x0, qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); + + /* save reset value to override based on clk scheme */ + if (qphy->ref_clk_base) + reset_val = readl_relaxed(qphy->base + QUSB2PHY_PLL_TEST); + + if (qphy->qusb_phy_init_seq) + qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq, + qphy->init_seq_len, 0); + + /* + * Check for EFUSE value only if tune2_efuse_reg is available + * and try to read EFUSE value only once i.e. not every USB + * cable connect case. + */ + if (qphy->tune2_efuse_reg && !tune2) { + if (!qphy->tune2_val) + qusb_phy_get_tune2_param(qphy); + + pr_debug("%s(): Programming TUNE2 parameter as:%x\n", __func__, + qphy->tune2_val); + writel_relaxed(qphy->tune2_val, + qphy->base + QUSB2PHY_PORT_TUNE2); + } + + /* If tune modparam set, override tune value */ + + pr_debug("%s():userspecified modparams TUNEX val:0x%x %x %x %x %x\n", + __func__, tune1, tune2, tune3, tune4, tune5); + if (tune1) + writel_relaxed(tune1, + qphy->base + QUSB2PHY_PORT_TUNE1); + + if (tune2) + writel_relaxed(tune2, + qphy->base + QUSB2PHY_PORT_TUNE2); + + if (tune3) + writel_relaxed(tune3, + qphy->base + QUSB2PHY_PORT_TUNE3); + + if (tune4) + writel_relaxed(tune4, + qphy->base + QUSB2PHY_PORT_TUNE4); + + if (tune5) + writel_relaxed(tune5, + qphy->base + QUSB2PHY_PORT_TUNE5); + + /* ensure above writes are completed before re-enabling PHY */ + wmb(); + + /* Enable the PHY */ + if (qphy->major_rev < 2) + writel_relaxed(CLAMP_N_EN | FREEZIO_N, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + else + writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) & + ~PWR_CTRL1_POWR_DOWN, + qphy->base + QUSB2PHY_PWR_CTRL1); + + /* Ensure above write is completed before turning ON ref clk */ + wmb(); + + /* Require to get phy pll lock successfully */ + usleep_range(150, 160); + + /* Turn on phy ref_clk if DIFF_CLK else select SE_CLK */ + if (qphy->ref_clk_base) { + if (!qphy->is_se_clk) { + reset_val &= ~CLK_REF_SEL; + writel_relaxed((readl_relaxed(qphy->ref_clk_base) | + QUSB2PHY_REFCLK_ENABLE), + qphy->ref_clk_base); + } else { + reset_val |= CLK_REF_SEL; + writel_relaxed(reset_val, + qphy->base + QUSB2PHY_PLL_TEST); + } + + /* Make sure above write is completed to get PLL source clock */ + wmb(); + + /* Required to get PHY PLL lock successfully */ + usleep_range(100, 110); + } + + if (qphy->major_rev < 2) { + reg = readb_relaxed(qphy->base + QUSB2PHY_PLL_STATUS); + dev_dbg(phy->dev, "QUSB2PHY_PLL_STATUS:%x\n", reg); + if (!(reg & QUSB2PHY_PLL_LOCK)) + pll_lock_fail = true; + } else { + reg = readb_relaxed(qphy->base + + QUSB2PHY_PLL_COMMON_STATUS_ONE); + dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg); + if (!(reg & CORE_READY_STATUS)) + pll_lock_fail = true; + } + + if (pll_lock_fail) { + dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg); + WARN_ON(1); + } + + return 0; +} + +static void qusb_phy_shutdown(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + dev_dbg(phy->dev, "%s\n", __func__); + + qusb_phy_enable_clocks(qphy, true); + + /* Disable the PHY */ + if (qphy->major_rev < 2) + writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + else + writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) | + PWR_CTRL1_POWR_DOWN, + qphy->base + QUSB2PHY_PWR_CTRL1); + + /* Make sure above write complete before turning off clocks */ + wmb(); + + qusb_phy_enable_clocks(qphy, false); +} +/** + * Performs QUSB2 PHY suspend/resume functionality. + * + * @uphy - usb phy pointer. + * @suspend - to enable suspend or not. 1 - suspend, 0 - resume + * + */ +static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + u32 linestate = 0, intr_mask = 0; + + if (qphy->suspended && suspend) { + dev_dbg(phy->dev, "%s: USB PHY is already suspended\n", + __func__); + return 0; + } + + if (suspend) { + /* Bus suspend case */ + if (qphy->cable_connected || + (qphy->phy.flags & PHY_HOST_MODE)) { + /* Clear all interrupts */ + writel_relaxed(0x00, + qphy->base + QUSB2PHY_PORT_INTR_CTRL); + + linestate = readl_relaxed(qphy->base + + QUSB2PHY_PORT_UTMI_STATUS); + + /* + * D+/D- interrupts are level-triggered, but we are + * only interested if the line state changes, so enable + * the high/low trigger based on current state. In + * other words, enable the triggers _opposite_ of what + * the current D+/D- levels are. + * e.g. if currently D+ high, D- low (HS 'J'/Suspend), + * configure the mask to trigger on D+ low OR D- high + */ + intr_mask = DPSE_INTR_EN | DMSE_INTR_EN; + if (!(linestate & LINESTATE_DP)) /* D+ low */ + intr_mask |= DPSE_INTR_HIGH_SEL; + if (!(linestate & LINESTATE_DM)) /* D- low */ + intr_mask |= DMSE_INTR_HIGH_SEL; + + writel_relaxed(intr_mask, + qphy->base + QUSB2PHY_PORT_INTR_CTRL); + + if (linestate & (LINESTATE_DP | LINESTATE_DM)) { + /* enable phy auto-resume */ + writel_relaxed(0x0C, + qphy->base + QUSB2PHY_PORT_TEST_CTRL); + /* flush the previous write before next write */ + wmb(); + writel_relaxed(0x04, + qphy->base + QUSB2PHY_PORT_TEST_CTRL); + } + + + dev_dbg(phy->dev, "%s: intr_mask = %x\n", + __func__, intr_mask); + + /* Makes sure that above write goes through */ + wmb(); + + qusb_phy_enable_clocks(qphy, false); + } else { /* Disconnect case */ + mutex_lock(&qphy->phy_lock); + /* Disable all interrupts */ + writel_relaxed(0x00, + qphy->base + QUSB2PHY_PORT_INTR_CTRL); + + /* Disable PHY */ + writel_relaxed(POWER_DOWN | + readl_relaxed(qphy->base + + QUSB2PHY_PORT_POWERDOWN), + qphy->base + QUSB2PHY_PORT_POWERDOWN); + /* Make sure that above write is completed */ + wmb(); + + qusb_phy_enable_clocks(qphy, false); + if (qphy->tcsr_clamp_dig_n) + writel_relaxed(0x0, + qphy->tcsr_clamp_dig_n); + /* Do not disable power rails if there is vote for it */ + if (!qphy->dpdm_enable) + qusb_phy_enable_power(qphy, false); + else + dev_dbg(phy->dev, "race with rm_pulldown. Keep ldo ON\n"); + mutex_unlock(&qphy->phy_lock); + + /* + * Set put_into_high_z_state to true so next USB + * cable connect, DPF_DMF request performs PHY + * reset and put it into high-z state. For bootup + * with or without USB cable, it doesn't require + * to put QUSB PHY into high-z state. + */ + qphy->put_into_high_z_state = true; + } + qphy->suspended = true; + } else { + /* Bus suspend case */ + if (qphy->cable_connected || + (qphy->phy.flags & PHY_HOST_MODE)) { + qusb_phy_enable_clocks(qphy, true); + /* Clear all interrupts on resume */ + writel_relaxed(0x00, + qphy->base + QUSB2PHY_PORT_INTR_CTRL); + } else { + qusb_phy_enable_power(qphy, true); + if (qphy->tcsr_clamp_dig_n) + writel_relaxed(0x1, + qphy->tcsr_clamp_dig_n); + qusb_phy_enable_clocks(qphy, true); + } + qphy->suspended = false; + } + + return 0; +} + +static int qusb_phy_notify_connect(struct usb_phy *phy, + enum usb_device_speed speed) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + qphy->cable_connected = true; + + dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n", + qphy->cable_connected); + return 0; +} + +static int qusb_phy_notify_disconnect(struct usb_phy *phy, + enum usb_device_speed speed) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + qphy->cable_connected = false; + + dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n", + qphy->cable_connected); + return 0; +} + +static int qusb_phy_dpdm_regulator_enable(struct regulator_dev *rdev) +{ + int ret = 0; + struct qusb_phy *qphy = rdev_get_drvdata(rdev); + + dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n", + __func__, qphy->dpdm_enable); + + mutex_lock(&qphy->phy_lock); + if (!qphy->dpdm_enable) { + ret = qusb_phy_enable_power(qphy, true); + if (ret < 0) { + dev_dbg(qphy->phy.dev, + "dpdm regulator enable failed:%d\n", ret); + mutex_unlock(&qphy->phy_lock); + return ret; + } + qphy->dpdm_enable = true; + if (qphy->put_into_high_z_state) { + if (qphy->tcsr_clamp_dig_n) + writel_relaxed(0x1, + qphy->tcsr_clamp_dig_n); + + qusb_phy_gdsc(qphy, true); + qusb_phy_enable_clocks(qphy, true); + + dev_dbg(qphy->phy.dev, "RESET QUSB PHY\n"); + ret = reset_control_assert(qphy->phy_reset); + if (ret) + dev_err(qphy->phy.dev, "phyassert failed\n"); + usleep_range(100, 150); + ret = reset_control_deassert(qphy->phy_reset); + if (ret) + dev_err(qphy->phy.dev, "deassert failed\n"); + + /* + * Phy in non-driving mode leaves Dp and Dm + * lines in high-Z state. Controller power + * collapse is not switching phy to non-driving + * mode causing charger detection failure. Bring + * phy to non-driving mode by overriding + * controller output via UTMI interface. + */ + writel_relaxed(TERM_SELECT | XCVR_SELECT_FS | + OP_MODE_NON_DRIVE, + qphy->base + QUSB2PHY_PORT_UTMI_CTRL1); + writel_relaxed(UTMI_ULPI_SEL | + UTMI_TEST_MUX_SEL, + qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); + + + /* Disable PHY */ + writel_relaxed(CLAMP_N_EN | FREEZIO_N | + POWER_DOWN, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + /* Make sure that above write is completed */ + wmb(); + + qusb_phy_enable_clocks(qphy, false); + qusb_phy_gdsc(qphy, false); + } + } + mutex_unlock(&qphy->phy_lock); + + return ret; +} + +static int qusb_phy_dpdm_regulator_disable(struct regulator_dev *rdev) +{ + int ret = 0; + struct qusb_phy *qphy = rdev_get_drvdata(rdev); + + dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n", + __func__, qphy->dpdm_enable); + + mutex_lock(&qphy->phy_lock); + if (qphy->dpdm_enable) { + if (!qphy->cable_connected) { + if (qphy->tcsr_clamp_dig_n) + writel_relaxed(0x0, + qphy->tcsr_clamp_dig_n); + dev_dbg(qphy->phy.dev, "turn off for HVDCP case\n"); + ret = qusb_phy_enable_power(qphy, false); + if (ret < 0) { + dev_dbg(qphy->phy.dev, + "dpdm regulator disable failed:%d\n", + ret); + mutex_unlock(&qphy->phy_lock); + return ret; + } + } + qphy->dpdm_enable = false; + } + mutex_unlock(&qphy->phy_lock); + + return ret; +} + +static int qusb_phy_dpdm_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct qusb_phy *qphy = rdev_get_drvdata(rdev); + + dev_dbg(qphy->phy.dev, "%s qphy->dpdm_enable = %d\n", __func__, + qphy->dpdm_enable); + return qphy->dpdm_enable; +} + +static struct regulator_ops qusb_phy_dpdm_regulator_ops = { + .enable = qusb_phy_dpdm_regulator_enable, + .disable = qusb_phy_dpdm_regulator_disable, + .is_enabled = qusb_phy_dpdm_regulator_is_enabled, +}; + +static int qusb_phy_regulator_init(struct qusb_phy *qphy) +{ + struct device *dev = qphy->phy.dev; + struct regulator_config cfg = {}; + struct regulator_init_data *init_data; + + init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); + if (!init_data) + return -ENOMEM; + + init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS; + qphy->dpdm_rdesc.owner = THIS_MODULE; + qphy->dpdm_rdesc.type = REGULATOR_VOLTAGE; + qphy->dpdm_rdesc.ops = &qusb_phy_dpdm_regulator_ops; + qphy->dpdm_rdesc.name = kbasename(dev->of_node->full_name); + + cfg.dev = dev; + cfg.init_data = init_data; + cfg.driver_data = qphy; + cfg.of_node = dev->of_node; + + qphy->dpdm_rdev = devm_regulator_register(dev, &qphy->dpdm_rdesc, &cfg); + if (IS_ERR(qphy->dpdm_rdev)) + return PTR_ERR(qphy->dpdm_rdev); + + return 0; +} + +static int qusb_phy_probe(struct platform_device *pdev) +{ + struct qusb_phy *qphy; + struct device *dev = &pdev->dev; + struct resource *res; + int ret = 0, size = 0; + const char *phy_type; + bool hold_phy_reset; + + qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); + if (!qphy) + return -ENOMEM; + + qphy->phy.dev = dev; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "qusb_phy_base"); + qphy->base = devm_ioremap_resource(dev, res); + if (IS_ERR(qphy->base)) + return PTR_ERR(qphy->base); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "emu_phy_base"); + if (res) { + qphy->emu_phy_base = devm_ioremap_resource(dev, res); + if (IS_ERR(qphy->emu_phy_base)) { + dev_dbg(dev, "couldn't ioremap emu_phy_base\n"); + qphy->emu_phy_base = NULL; + } + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "tune2_efuse_addr"); + if (res) { + qphy->tune2_efuse_reg = devm_ioremap_nocache(dev, res->start, + resource_size(res)); + if (!IS_ERR_OR_NULL(qphy->tune2_efuse_reg)) { + ret = of_property_read_u32(dev->of_node, + "qcom,tune2-efuse-bit-pos", + &qphy->tune2_efuse_bit_pos); + if (!ret) { + ret = of_property_read_u32(dev->of_node, + "qcom,tune2-efuse-num-bits", + &qphy->tune2_efuse_num_of_bits); + } + of_property_read_u32(dev->of_node, + "qcom,tune2-efuse-correction", + &qphy->tune2_efuse_correction); + + if (ret) { + dev_err(dev, "DT Value for tune2 efuse is invalid.\n"); + return -EINVAL; + } + } + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "ref_clk_addr"); + if (res) { + qphy->ref_clk_base = devm_ioremap_nocache(dev, + res->start, resource_size(res)); + if (IS_ERR(qphy->ref_clk_base)) { + dev_dbg(dev, "ref_clk_address is not available.\n"); + return PTR_ERR(qphy->ref_clk_base); + } + + ret = of_property_read_string(dev->of_node, + "qcom,phy-clk-scheme", &phy_type); + if (ret) { + dev_err(dev, "error need qsub_phy_clk_scheme.\n"); + return ret; + } + + if (!strcasecmp(phy_type, "cml")) { + qphy->is_se_clk = false; + } else if (!strcasecmp(phy_type, "cmos")) { + qphy->is_se_clk = true; + } else { + dev_err(dev, "erro invalid qusb_phy_clk_scheme\n"); + return -EINVAL; + } + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "tcsr_clamp_dig_n_1p8"); + if (res) { + qphy->tcsr_clamp_dig_n = devm_ioremap_nocache(dev, + res->start, resource_size(res)); + if (IS_ERR(qphy->tcsr_clamp_dig_n)) { + dev_err(dev, "err reading tcsr_clamp_dig_n\n"); + qphy->tcsr_clamp_dig_n = NULL; + } + } + + qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src"); + if (IS_ERR(qphy->ref_clk_src)) + dev_dbg(dev, "clk get failed for ref_clk_src\n"); + + qphy->ref_clk = devm_clk_get(dev, "ref_clk"); + if (IS_ERR(qphy->ref_clk)) + dev_dbg(dev, "clk get failed for ref_clk\n"); + else + clk_set_rate(qphy->ref_clk, 19200000); + + qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb_clk"); + if (IS_ERR(qphy->cfg_ahb_clk)) + return PTR_ERR(qphy->cfg_ahb_clk); + + qphy->phy_reset = devm_reset_control_get(dev, "phy_reset"); + if (IS_ERR(qphy->phy_reset)) + return PTR_ERR(qphy->phy_reset); + + if (of_property_match_string(dev->of_node, + "clock-names", "iface_clk") >= 0) { + qphy->iface_clk = devm_clk_get(dev, "iface_clk"); + if (IS_ERR(qphy->iface_clk)) { + ret = PTR_ERR(qphy->iface_clk); + qphy->iface_clk = NULL; + if (ret == -EPROBE_DEFER) + return ret; + dev_err(dev, "couldn't get iface_clk(%d)\n", ret); + } + } + + if (of_property_match_string(dev->of_node, + "clock-names", "core_clk") >= 0) { + qphy->core_clk = devm_clk_get(dev, "core_clk"); + if (IS_ERR(qphy->core_clk)) { + ret = PTR_ERR(qphy->core_clk); + qphy->core_clk = NULL; + if (ret == -EPROBE_DEFER) + return ret; + dev_err(dev, "couldn't get core_clk(%d)\n", ret); + } + } + + qphy->gdsc = devm_regulator_get(dev, "USB3_GDSC"); + if (IS_ERR(qphy->gdsc)) + qphy->gdsc = NULL; + + qphy->emulation = of_property_read_bool(dev->of_node, + "qcom,emulation"); + + of_get_property(dev->of_node, "qcom,emu-init-seq", &size); + if (size) { + qphy->emu_init_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->emu_init_seq) { + qphy->emu_init_seq_len = + (size / sizeof(*qphy->emu_init_seq)); + if (qphy->emu_init_seq_len % 2) { + dev_err(dev, "invalid emu_init_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,emu-init-seq", + qphy->emu_init_seq, + qphy->emu_init_seq_len); + } else { + dev_dbg(dev, "error allocating memory for emu_init_seq\n"); + } + } + + size = 0; + of_get_property(dev->of_node, "qcom,phy-pll-reset-seq", &size); + if (size) { + qphy->phy_pll_reset_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->phy_pll_reset_seq) { + qphy->phy_pll_reset_seq_len = + (size / sizeof(*qphy->phy_pll_reset_seq)); + if (qphy->phy_pll_reset_seq_len % 2) { + dev_err(dev, "invalid phy_pll_reset_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,phy-pll-reset-seq", + qphy->phy_pll_reset_seq, + qphy->phy_pll_reset_seq_len); + } else { + dev_dbg(dev, "error allocating memory for phy_pll_reset_seq\n"); + } + } + + size = 0; + of_get_property(dev->of_node, "qcom,emu-dcm-reset-seq", &size); + if (size) { + qphy->emu_dcm_reset_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->emu_dcm_reset_seq) { + qphy->emu_dcm_reset_seq_len = + (size / sizeof(*qphy->emu_dcm_reset_seq)); + if (qphy->emu_dcm_reset_seq_len % 2) { + dev_err(dev, "invalid emu_dcm_reset_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,emu-dcm-reset-seq", + qphy->emu_dcm_reset_seq, + qphy->emu_dcm_reset_seq_len); + } else { + dev_dbg(dev, "error allocating memory for emu_dcm_reset_seq\n"); + } + } + + size = 0; + of_get_property(dev->of_node, "qcom,qusb-phy-init-seq", &size); + if (size) { + qphy->qusb_phy_init_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->qusb_phy_init_seq) { + qphy->init_seq_len = + (size / sizeof(*qphy->qusb_phy_init_seq)); + if (qphy->init_seq_len % 2) { + dev_err(dev, "invalid init_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,qusb-phy-init-seq", + qphy->qusb_phy_init_seq, + qphy->init_seq_len); + } else { + dev_err(dev, "error allocating memory for phy_init_seq\n"); + } + } + + qphy->ulpi_mode = false; + ret = of_property_read_string(dev->of_node, "phy_type", &phy_type); + + if (!ret) { + if (!strcasecmp(phy_type, "ulpi")) + qphy->ulpi_mode = true; + } else { + dev_err(dev, "error reading phy_type property\n"); + return ret; + } + + hold_phy_reset = of_property_read_bool(dev->of_node, "qcom,hold-reset"); + + /* use default major revision as 2 */ + qphy->major_rev = 2; + ret = of_property_read_u32(dev->of_node, "qcom,major-rev", + &qphy->major_rev); + + ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level", + (u32 *) qphy->vdd_levels, + ARRAY_SIZE(qphy->vdd_levels)); + if (ret) { + dev_err(dev, "error reading qcom,vdd-voltage-level property\n"); + return ret; + } + + qphy->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(qphy->vdd)) { + dev_err(dev, "unable to get vdd supply\n"); + return PTR_ERR(qphy->vdd); + } + + qphy->vdda33 = devm_regulator_get(dev, "vdda33"); + if (IS_ERR(qphy->vdda33)) { + dev_err(dev, "unable to get vdda33 supply\n"); + return PTR_ERR(qphy->vdda33); + } + + qphy->vdda18 = devm_regulator_get(dev, "vdda18"); + if (IS_ERR(qphy->vdda18)) { + dev_err(dev, "unable to get vdda18 supply\n"); + return PTR_ERR(qphy->vdda18); + } + + mutex_init(&qphy->phy_lock); + platform_set_drvdata(pdev, qphy); + + qphy->phy.label = "msm-qusb-phy"; + qphy->phy.init = qusb_phy_init; + qphy->phy.set_suspend = qusb_phy_set_suspend; + qphy->phy.shutdown = qusb_phy_shutdown; + qphy->phy.type = USB_PHY_TYPE_USB2; + qphy->phy.notify_connect = qusb_phy_notify_connect; + qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; + + /* + * On some platforms multiple QUSB PHYs are available. If QUSB PHY is + * not used, there is leakage current seen with QUSB PHY related voltage + * rail. Hence keep QUSB PHY into reset state explicitly here. + */ + if (hold_phy_reset) { + ret = reset_control_assert(qphy->phy_reset); + if (ret) + dev_err(dev, "%s:phy_reset assert failed\n", __func__); + } + + ret = usb_add_phy_dev(&qphy->phy); + if (ret) + return ret; + + ret = qusb_phy_regulator_init(qphy); + if (ret) + usb_remove_phy(&qphy->phy); + + /* de-assert clamp dig n to reduce leakage on 1p8 upon boot up */ + if (qphy->tcsr_clamp_dig_n) + writel_relaxed(0x0, qphy->tcsr_clamp_dig_n); + + return ret; +} + +static int qusb_phy_remove(struct platform_device *pdev) +{ + struct qusb_phy *qphy = platform_get_drvdata(pdev); + + usb_remove_phy(&qphy->phy); + + if (qphy->clocks_enabled) { + clk_disable_unprepare(qphy->cfg_ahb_clk); + clk_disable_unprepare(qphy->ref_clk); + clk_disable_unprepare(qphy->ref_clk_src); + qphy->clocks_enabled = false; + } + + qusb_phy_enable_power(qphy, false); + + return 0; +} + +static const struct of_device_id qusb_phy_id_table[] = { + { .compatible = "qcom,qusb2phy", }, + { }, +}; +MODULE_DEVICE_TABLE(of, qusb_phy_id_table); + +static struct platform_driver qusb_phy_driver = { + .probe = qusb_phy_probe, + .remove = qusb_phy_remove, + .driver = { + .name = "msm-qusb-phy", + .of_match_table = of_match_ptr(qusb_phy_id_table), + }, +}; + +module_platform_driver(qusb_phy_driver); + +MODULE_DESCRIPTION("MSM QUSB2 PHY driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From c97097963b9955133fc2f7e7e5919c2330b463db Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Wed, 27 Jun 2018 16:48:49 +0530 Subject: [PATCH 0926/1299] drivers: mailbox: rpmh: Correct matching of tcs command sequence Fix sanity check to match new commands with existing sequence. Also add check for selected slot to be less than maximum available slots. Change-Id: Ib3fc3d87d53d3ac47e53119b0cd4b998d19656ba Signed-off-by: Maulik Shah --- drivers/mailbox/qcom-rpmh-mailbox.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mailbox/qcom-rpmh-mailbox.c b/drivers/mailbox/qcom-rpmh-mailbox.c index 2677ed0c3b3e..0162ad6e0a1a 100644 --- a/drivers/mailbox/qcom-rpmh-mailbox.c +++ b/drivers/mailbox/qcom-rpmh-mailbox.c @@ -694,9 +694,10 @@ static int find_match(struct tcs_mbox *tcs, struct tcs_cmd *cmd, int len) } /* sanity check to ensure the seq is same */ for (j = 1; j < len; j++) { - WARN((tcs->cmd_addr[i + j] != cmd[j].addr), - "Message does not match previous sequence.\n"); + if (tcs->cmd_addr[i + j] != cmd[j].addr) { + pr_debug("Message does not match previous sequence.\n"); return -EINVAL; + } } found = true; break; @@ -724,12 +725,12 @@ static int find_slots(struct tcs_mbox *tcs, struct tcs_mbox_msg *msg) do { slot = bitmap_find_next_zero_area(tcs->slots, MAX_TCS_SLOTS, n, msg->num_payload, 0); - if (slot == MAX_TCS_SLOTS) + if (slot >= MAX_TCS_SLOTS) break; n += tcs->ncpt; } while (slot + msg->num_payload - 1 >= n); - return (slot != MAX_TCS_SLOTS) ? slot : -ENOMEM; + return (slot < MAX_TCS_SLOTS) ? slot : -ENOMEM; } static int tcs_mbox_write(struct mbox_chan *chan, struct tcs_mbox_msg *msg, -- GitLab From 798fed8b1a043c14b2e6271b934ca52faf7d4b35 Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Thu, 21 Jun 2018 18:18:23 -0400 Subject: [PATCH 0927/1299] drm/msm/sde: re-init delayed work in sde encoder enable When multidisplay is enabled, delayed_off_work can be submitted to different crtc worker thread and violate kernel's rule for delayed task that work must not be used with >1 worker. This change will re-initialize the delayed work to allow it submitted to different worker. CRs-Fixed: 2267120 Change-Id: I65ff4bc67eed31bdfc86e308a9d8968f46c76b62 Signed-off-by: Xiaowen Wu --- drivers/gpu/drm/msm/sde/sde_encoder.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index df29b32c9a51..4d2f22b24b7c 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -2937,6 +2937,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) "input handler registration failed, rc = %d\n", ret); } + sde_enc->delayed_off_work.work.worker = NULL; + ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF); if (ret) { SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n", -- GitLab From c570dfabc61a57e78e500f415c6cd629e34f6a74 Mon Sep 17 00:00:00 2001 From: Carter Cooper Date: Mon, 21 May 2018 15:46:00 -0600 Subject: [PATCH 0928/1299] msm: kgsl: List ACK waiters when invalid HFI ACK received If an ACK is received that is unknown, report the error and perform a snapshot. Change-Id: I757c55e00d1f92a2dd909a53a48a46e14630dca2 Signed-off-by: Carter Cooper --- drivers/gpu/msm/kgsl_gmu.c | 2 +- drivers/gpu/msm/kgsl_hfi.c | 31 +++++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index 4a4912b26a2d..718a2f35d257 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -1339,7 +1339,7 @@ static int gmu_probe(struct kgsl_device *device, disable_irq(gmu->gmu_interrupt_num); disable_irq(hfi->hfi_interrupt_num); - tasklet_init(&hfi->tasklet, hfi_receiver, (unsigned long)gmu); + tasklet_init(&hfi->tasklet, hfi_receiver, (unsigned long)device); INIT_LIST_HEAD(&hfi->msglist); spin_lock_init(&hfi->msglock); hfi->kgsldev = device; diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c index 0b855c047a0a..354258ca647d 100644 --- a/drivers/gpu/msm/kgsl_hfi.c +++ b/drivers/gpu/msm/kgsl_hfi.c @@ -231,13 +231,15 @@ void hfi_init(struct kgsl_hfi *hfi, struct gmu_memdesc *mem_addr, #define HDR_CMP_SEQNUM(out_hdr, in_hdr) \ (MSG_HDR_GET_SEQNUM(out_hdr) == MSG_HDR_GET_SEQNUM(in_hdr)) -static void receive_ack_cmd(struct gmu_device *gmu, void *rcvd) +static void receive_ack_cmd(struct kgsl_device *device, + struct gmu_device *gmu, void *rcvd) { uint32_t *ack = rcvd; uint32_t hdr = ack[0]; uint32_t req_hdr = ack[1]; struct kgsl_hfi *hfi = &gmu->hfi; struct pending_cmd *cmd = NULL; + uint32_t waiters[64], i = 0, j; trace_kgsl_hfi_receive(MSG_HDR_GET_ID(req_hdr), MSG_HDR_GET_SIZE(req_hdr), @@ -251,11 +253,21 @@ static void receive_ack_cmd(struct gmu_device *gmu, void *rcvd) spin_unlock_bh(&hfi->msglock); return; } + if (i < 64) + waiters[i++] = cmd->sent_hdr; } spin_unlock_bh(&hfi->msglock); - dev_err(&gmu->pdev->dev, - "HFI ACK(0x%x) Cannot find sender\n", req_hdr); + dev_err_ratelimited(&gmu->pdev->dev, + "HFI ACK: Cannot find sender for 0x%8.8X\n", req_hdr); + /* Didn't find the sender, list all the waiters */ + for (j = 0; j < i && j < 64; j++) { + dev_err_ratelimited(&gmu->pdev->dev, + "HFI ACK: Waiters: 0x%8.8X\n", waiters[j]); + } + + adreno_set_gpu_fault(ADRENO_DEVICE(device), ADRENO_GMU_FAULT); + adreno_dispatcher_schedule(device); } #define MSG_HDR_SET_SEQNUM(hdr, num) \ @@ -519,11 +531,12 @@ static void receive_debug_req(struct gmu_device *gmu, void *rcvd) cmd->type, cmd->timestamp, cmd->data); } -static void hfi_v1_receiver(struct gmu_device *gmu, uint32_t *rcvd) +static void hfi_v1_receiver(struct kgsl_device *device, + struct gmu_device *gmu, uint32_t *rcvd) { /* V1 ACK Handler */ if (MSG_HDR_GET_TYPE(rcvd[0]) == HFI_V1_MSG_ACK) { - receive_ack_cmd(gmu, rcvd); + receive_ack_cmd(device, gmu, rcvd); return; } @@ -545,6 +558,7 @@ static void hfi_v1_receiver(struct gmu_device *gmu, uint32_t *rcvd) void hfi_receiver(unsigned long data) { + struct kgsl_device *device; struct gmu_device *gmu; uint32_t rcvd[MAX_RCVD_SIZE]; int read_queue[] = { @@ -556,7 +570,8 @@ void hfi_receiver(unsigned long data) if (!data) return; - gmu = (struct gmu_device *)data; + device = (struct kgsl_device *)data; + gmu = KGSL_GMU_DEVICE(device); /* While we are here, check all of the queues for messages */ for (q = 0; q < ARRAY_SIZE(read_queue); q++) { @@ -564,13 +579,13 @@ void hfi_receiver(unsigned long data) rcvd, sizeof(rcvd)) > 0) { /* Special case if we're v1 */ if (HFI_VER_MAJOR(&gmu->hfi) < 2) { - hfi_v1_receiver(gmu, rcvd); + hfi_v1_receiver(device, gmu, rcvd); continue; } /* V2 ACK Handler */ if (MSG_HDR_GET_TYPE(rcvd[0]) == HFI_MSG_ACK) { - receive_ack_cmd(gmu, rcvd); + receive_ack_cmd(device, gmu, rcvd); continue; } -- GitLab From 5e8037d91a751825cd55ebc68fa7944d5cd35db5 Mon Sep 17 00:00:00 2001 From: Govinda Rajulu Chenna Date: Thu, 21 Jun 2018 11:07:48 -0400 Subject: [PATCH 0929/1299] drm/msm/dp: add mst bandwidth alloc/dealloc implementation This change implements the bandwidth/rate-governing allocation logic for stream on and deallocates the bandwidth from both source and receiver devices during stream shutdown. CRs-Fixed: 2265294 Change-Id: Iea02d8c0227cca159f07a9fc88499ed6ce501d21 Signed-off-by: Govinda Rajulu Chenna --- drivers/gpu/drm/msm/dp/dp_catalog.c | 52 ++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 2 + drivers/gpu/drm/msm/dp/dp_ctrl.c | 120 +++++++++++++++++++++++++++- drivers/gpu/drm/msm/dp/dp_ctrl.h | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 102 ++++++++++++++++++----- drivers/gpu/drm/msm/dp/dp_display.h | 2 +- drivers/gpu/drm/msm/dp/dp_drm.c | 2 +- drivers/gpu/drm/msm/dp/dp_mst_drm.c | 70 ++++++++++++++-- drivers/gpu/drm/msm/dp/dp_panel.c | 12 ++- drivers/gpu/drm/msm/dp/dp_panel.h | 6 +- 10 files changed, 334 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 6519a035d831..24d597b8932f 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -1573,6 +1573,57 @@ static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl, dp_write(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off, slot_reg_2); } +static void dp_catalog_ctrl_channel_dealloc(struct dp_catalog_ctrl *ctrl, + u32 ch, u32 ch_start_slot, u32 tot_slot_cnt) +{ + struct dp_catalog_private *catalog; + struct dp_io_data *io_data = NULL; + u32 i, slot_reg_1, slot_reg_2, slot; + u32 reg_off = 0; + + if (!ctrl || ch >= DP_STREAM_MAX) { + pr_err("invalid input. ch %d\n", ch); + return; + } + + if (ch_start_slot > DP_MAX_TIME_SLOTS || + (ch_start_slot + tot_slot_cnt > DP_MAX_TIME_SLOTS)) { + pr_err("invalid slots start %d, tot %d\n", + ch_start_slot, tot_slot_cnt); + return; + } + + catalog = dp_catalog_get_priv(ctrl); + + io_data = catalog->io.dp_link; + + pr_debug("dealloc ch %d, start_slot %d, tot_slot %d\n", + ch, ch_start_slot, tot_slot_cnt); + + if (ch == DP_STREAM_1) + reg_off = DP_DP1_TIMESLOT_1_32 - DP_DP0_TIMESLOT_1_32; + + slot_reg_1 = dp_read(catalog, io_data, DP_DP0_TIMESLOT_1_32 + reg_off); + slot_reg_2 = dp_read(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off); + + ch_start_slot = ch_start_slot - 1; + for (i = 0; i < tot_slot_cnt; i++) { + if (ch_start_slot < 33) { + slot_reg_1 &= ~BIT(ch_start_slot); + } else { + slot = ch_start_slot - 33; + slot_reg_2 &= ~BIT(slot); + } + ch_start_slot++; + } + + pr_debug("dealloc ch:%d slot_reg_1:%d, slot_reg_2:%d\n", ch, + slot_reg_1, slot_reg_2); + + dp_write(catalog, io_data, DP_DP0_TIMESLOT_1_32 + reg_off, slot_reg_1); + dp_write(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off, slot_reg_2); +} + static void dp_catalog_ctrl_update_rg(struct dp_catalog_ctrl *ctrl, u32 ch, u32 x_int, u32 y_frac_enum) { @@ -2111,6 +2162,7 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser) .read_act_complete_sts = dp_catalog_ctrl_read_act_complete_sts, .channel_alloc = dp_catalog_ctrl_channel_alloc, .update_rg = dp_catalog_ctrl_update_rg, + .channel_dealloc = dp_catalog_ctrl_channel_dealloc, }; struct dp_catalog_audio audio = { .init = dp_catalog_audio_init, diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 22dd72c16a0f..c9f1995930ad 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -125,6 +125,8 @@ struct dp_catalog_ctrl { u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt); void (*update_rg)(struct dp_catalog_ctrl *ctrl, u32 ch, u32 x_int, u32 y_frac_enum); + void (*channel_dealloc)(struct dp_catalog_ctrl *ctrl, + u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt); }; #define HEADER_BYTE_2_BIT 0 diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 38bf81205f74..779451c2a99d 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "dp_ctrl.h" @@ -843,6 +844,81 @@ static void dp_ctrl_send_video(struct dp_ctrl_private *ctrl) ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO); } +static void dp_ctrl_mst_calculate_rg(struct dp_ctrl_private *ctrl, + struct dp_panel *panel, u32 *p_x_int, u32 *p_y_frac_enum) +{ + u64 min_slot_cnt, max_slot_cnt; + u64 raw_target_sc, target_sc_fixp; + u64 ts_denom, ts_enum, ts_int; + u64 pclk = panel->pinfo.pixel_clk_khz; + u64 lclk = panel->link_info.rate; + u64 lanes = panel->link_info.num_lanes; + u64 bpp = panel->pinfo.bpp; + u64 pbn = panel->pbn; + u64 numerator, denominator, temp, temp1, temp2; + u32 x_int = 0, y_frac_enum = 0; + u64 target_strm_sym, ts_int_fixp, ts_frac_fixp, y_frac_enum_fixp; + + /* min_slot_cnt */ + numerator = pclk * bpp * 64 * 1000; + denominator = lclk * lanes * 8 * 1000; + min_slot_cnt = drm_fixp_from_fraction(numerator, denominator); + + /* max_slot_cnt */ + numerator = pbn * 54 * 1000; + denominator = lclk * lanes; + max_slot_cnt = drm_fixp_from_fraction(numerator, denominator); + + /* raw_target_sc */ + numerator = max_slot_cnt + min_slot_cnt; + denominator = drm_fixp_from_fraction(2, 1); + raw_target_sc = drm_fixp_div(numerator, denominator); + + /* target_sc */ + temp = drm_fixp_from_fraction(256 * lanes, 1); + numerator = drm_fixp_mul(raw_target_sc, temp); + denominator = drm_fixp_from_fraction(256 * lanes, 1); + target_sc_fixp = drm_fixp_div(numerator, denominator); + + ts_enum = 256 * lanes; + ts_denom = drm_fixp_from_fraction(256 * lanes, 1); + ts_int = drm_fixp2int(target_sc_fixp); + + temp = drm_fixp2int_ceil(raw_target_sc); + if (temp != ts_int) { + temp = drm_fixp_from_fraction(ts_int, 1); + temp1 = raw_target_sc - temp; + temp2 = drm_fixp_mul(temp1, ts_denom); + ts_enum = drm_fixp2int(temp2); + } + + /* target_strm_sym */ + ts_int_fixp = drm_fixp_from_fraction(ts_int, 1); + ts_frac_fixp = drm_fixp_from_fraction(ts_enum, drm_fixp2int(ts_denom)); + temp = ts_int_fixp + ts_frac_fixp; + temp1 = drm_fixp_from_fraction(lanes, 1); + target_strm_sym = drm_fixp_mul(temp, temp1); + + /* x_int */ + x_int = drm_fixp2int(target_strm_sym); + + /* y_enum_frac */ + temp = drm_fixp_from_fraction(x_int, 1); + temp1 = target_strm_sym - temp; + temp2 = drm_fixp_from_fraction(256, 1); + y_frac_enum_fixp = drm_fixp_mul(temp1, temp2); + + temp1 = drm_fixp2int(y_frac_enum_fixp); + temp2 = drm_fixp2int_ceil(y_frac_enum_fixp); + + y_frac_enum = (u32)((temp1 == temp2) ? temp1 : temp1 + 1); + + *p_x_int = x_int; + *p_y_frac_enum = y_frac_enum; + + pr_debug("x_int: %d, y_frac_enum: %d\n", x_int, y_frac_enum); +} + static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, struct dp_panel *panel) { @@ -862,9 +938,7 @@ static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, lanes = ctrl->link->link_params.lane_count; bw_code = ctrl->link->link_params.bw_code; - x_int = (u32)(lanes * panel->channel_total_slots); - y_frac_enum = (u32)(256 * ((lanes * lanes * - panel->channel_total_slots) - x_int)); + dp_ctrl_mst_calculate_rg(ctrl, panel, &x_int, &y_frac_enum); ctrl->catalog->update_rg(ctrl->catalog, panel->stream_id, x_int, y_frac_enum); @@ -932,6 +1006,45 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) return rc; } +static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl, + struct dp_panel *panel) +{ + struct dp_ctrl_private *ctrl; + bool act_complete; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + if (!ctrl->mst_mode) + return; + + ctrl->catalog->channel_dealloc(ctrl->catalog, + panel->stream_id, + panel->channel_start_slot, + panel->channel_total_slots); + + ctrl->catalog->trigger_act(ctrl->catalog); + msleep(20); /* needs 1 frame time */ + ctrl->catalog->read_act_complete_sts(ctrl->catalog, &act_complete); + + if (!act_complete) + pr_err("mst stream_off act trigger complete failed\n"); + else + DP_MST_DEBUG("mst stream_off ACT trigger complete SUCCESS\n"); +} + +static void dp_ctrl_stream_pre_off(struct dp_ctrl *dp_ctrl, + struct dp_panel *panel) +{ + if (!dp_ctrl || !panel) { + pr_err("invalid input\n"); + return; + } + + dp_ctrl_push_idle(dp_ctrl, panel->stream_id); + + dp_ctrl_mst_stream_pre_off(dp_ctrl, panel); +} + static void dp_ctrl_stream_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) { struct dp_ctrl_private *ctrl; @@ -1107,6 +1220,7 @@ struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in) dp_ctrl->process_phy_test_request = dp_ctrl_process_phy_test_request; dp_ctrl->stream_on = dp_ctrl_stream_on; dp_ctrl->stream_off = dp_ctrl_stream_off; + dp_ctrl->stream_pre_off = dp_ctrl_stream_pre_off; return dp_ctrl; error: diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index e36543ae4a7b..716fad77e734 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -36,6 +36,7 @@ struct dp_ctrl { int (*link_maintenance)(struct dp_ctrl *dp_ctrl); int (*stream_on)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); void (*stream_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); + void (*stream_pre_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); }; struct dp_ctrl_in { diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index f0214b398617..837b99806127 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -798,12 +798,17 @@ static void dp_display_handle_maintenance_req(struct dp_display_private *dp) int idx; struct dp_panel *dp_panel; + mutex_lock(&dp->session_lock); + for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) { if (!dp->active_panels[idx]) continue; dp_panel = dp->active_panels[idx]; + dp->ctrl->stream_pre_off(dp->ctrl, dp_panel); + dp->ctrl->stream_off(dp->ctrl, dp_panel); + mutex_lock(&dp_panel->audio->ops_lock); if (dp_panel->audio_supported) @@ -818,11 +823,15 @@ static void dp_display_handle_maintenance_req(struct dp_display_private *dp) dp_panel = dp->active_panels[idx]; + dp->ctrl->stream_on(dp->ctrl, dp_panel); + if (dp_panel->audio_supported) dp_panel->audio->on(dp_panel->audio); mutex_unlock(&dp_panel->audio->ops_lock); } + + mutex_unlock(&dp->session_lock); } static void dp_display_mst_attention(struct dp_display_private *dp) @@ -1048,6 +1057,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) panel_in.catalog = &dp->catalog->panel; panel_in.link = dp->link; panel_in.connector = dp->dp_display.base_connector; + panel_in.base_panel = NULL; dp->panel = dp_panel_get(&panel_in); if (IS_ERR(dp->panel)) { @@ -1198,14 +1208,45 @@ static int dp_display_set_mode(struct dp_display *dp_display, void *panel, return 0; } -static int dp_display_prepare(struct dp_display *dp, void *panel) +static int dp_display_prepare(struct dp_display *dp_display, void *panel) { + struct dp_display_private *dp; + struct dp_panel *dp_panel; + + if (!dp_display || !panel) { + pr_err("invalid input\n"); + return -EINVAL; + } + + dp_panel = panel; + if (!dp_panel->connector) { + pr_err("invalid connector input\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + mutex_lock(&dp->session_lock); + + if (atomic_read(&dp->aborted)) + goto end; + + dp->aux->init(dp->aux, dp->parser->aux_cfg); + + if (dp->debug->psm_enabled) { + dp->link->psm_config(dp->link, &dp->panel->link_info, false); + dp->debug->psm_enabled = false; + } + +end: + mutex_unlock(&dp->session_lock); + return 0; } static int dp_display_set_stream_info(struct dp_display *dp_display, void *panel, u32 ch_id, u32 ch_start_slot, - u32 ch_tot_slots) + u32 ch_tot_slots, u32 pbn) { int rc = 0; struct dp_panel *dp_panel; @@ -1217,7 +1258,7 @@ static int dp_display_set_stream_info(struct dp_display *dp_display, dp_panel = panel; dp_panel->set_stream_info(dp_panel, ch_id, - ch_start_slot, ch_tot_slots); + ch_start_slot, ch_tot_slots, pbn); return rc; } @@ -1266,13 +1307,6 @@ static int dp_display_enable(struct dp_display *dp_display, void *panel) goto end; } - dp->aux->init(dp->aux, dp->parser->aux_cfg); - - if (dp->debug->psm_enabled) { - dp->link->psm_config(dp->link, &dp->panel->link_info, false); - dp->debug->psm_enabled = false; - } - rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active); if (rc) goto end; @@ -1355,9 +1389,8 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) static int dp_display_stream_pre_disable(struct dp_display_private *dp, struct dp_panel *dp_panel) { - dp->ctrl->push_idle(dp->ctrl, dp_panel->stream_id); - dp_panel->audio->deregister_ext_disp(dp_panel->audio); + dp->ctrl->stream_pre_off(dp->ctrl, dp_panel); return 0; } @@ -1390,17 +1423,17 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) dp->hdcp.ops->off(dp->hdcp.data); } - if (dp->usbpd->hpd_high && !dp_display_is_sink_count_zero(dp) && - dp->usbpd->alt_mode_cfg_done) { - if (dp_panel->audio_supported) - dp_panel->audio->off(dp_panel->audio); + if (dp_panel->audio_supported) + dp_panel->audio->off(dp_panel->audio); + + rc = dp_display_stream_pre_disable(dp, dp_panel); + if (dp->usbpd->hpd_high && !dp_display_is_sink_count_zero(dp) && + dp->usbpd->alt_mode_cfg_done && !dp->mst.mst_active) { dp->link->psm_config(dp->link, &dp->panel->link_info, true); dp->debug->psm_enabled = true; } - rc = dp_display_stream_pre_disable(dp, dp_panel); - end: mutex_unlock(&dp->session_lock); return 0; @@ -1455,10 +1488,7 @@ static int dp_display_disable(struct dp_display *dp_display, void *panel) dp->dp_display.is_sst_connected = false; } - dp->aux->deinit(dp->aux); dp->power_on = false; - dp->aux->state = DP_STATE_CTRL_POWERED_OFF; - complete_all(&dp->notification_comp); end: mutex_unlock(&dp->session_lock); return 0; @@ -1509,8 +1539,35 @@ static struct dp_debug *dp_get_debug(struct dp_display *dp_display) return dp->debug; } -static int dp_display_unprepare(struct dp_display *dp, void *panel) +static int dp_display_unprepare(struct dp_display *dp_display, void *panel) { + struct dp_display_private *dp; + + if (!dp_display || !panel) { + pr_err("invalid input\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + mutex_lock(&dp->session_lock); + + if (dp->active_stream_cnt) + goto end; + + if (atomic_read(&dp->aborted)) + goto end; + + if (!dp->mst.mst_active) { + dp->aux->deinit(dp->aux); + dp->aux->state = DP_STATE_CTRL_POWERED_OFF; + } + + complete_all(&dp->notification_comp); + +end: + mutex_unlock(&dp->session_lock); + return 0; } @@ -1739,6 +1796,7 @@ static int dp_display_mst_connector_install(struct dp_display *dp_display, panel_in.catalog = &dp->catalog->panel; panel_in.link = dp->link; panel_in.connector = connector; + panel_in.base_panel = dp->panel; dp_panel = dp_panel_get(&panel_in); if (IS_ERR(dp_panel)) { diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 6c878d1c356a..3f34d35566b4 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -87,7 +87,7 @@ struct dp_display { struct dp_mst_caps *mst_caps); int (*set_stream_info)(struct dp_display *dp_display, void *panel, u32 ch_id, u32 ch_start_slot, - u32 ch_tot_slots); + u32 ch_tot_slots, u32 pbn); }; int dp_display_get_num_of_displays(void); diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index a985969dc3af..19ff327db830 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -155,7 +155,7 @@ static void dp_bridge_pre_enable(struct drm_bridge *drm_bridge) } /* for SST force stream id, start slot and total slots to 0 */ - dp->set_stream_info(dp, bridge->dp_panel, 0, 0, 0); + dp->set_stream_info(dp, bridge->dp_panel, 0, 0, 0, 0); rc = dp->enable(dp, bridge->dp_panel); if (rc) { diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c index c9726552e216..4633c633b6b9 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -58,6 +58,10 @@ struct dp_drm_mst_fw_helper_ops { int slots); int (*get_ch_start_slot)(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int channel_id); + void (*reset_vcpi_slots)(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port); + void (*deallocate_vcpi)(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port); }; struct dp_mst_sim_port { @@ -192,6 +196,16 @@ static int drm_dp_sim_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr) return 0; } +static void drm_dp_sim_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port) +{ +} + +static void drm_dp_sim_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port) +{ +} + static enum drm_connector_status drm_dp_sim_mst_detect_port( struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, @@ -268,6 +282,8 @@ static const struct dp_drm_mst_fw_helper_ops drm_dp_mst_fw_helper_ops = { .topology_mgr_set_mst = drm_dp_mst_topology_mgr_set_mst, .get_ch_start_slot = _drm_dp_mst_get_ch_start_slot, .atomic_release_vcpi_slots = drm_dp_atomic_release_vcpi_slots, + .reset_vcpi_slots = drm_dp_mst_reset_vcpi_slots, + .deallocate_vcpi = drm_dp_mst_deallocate_vcpi, }; static const struct dp_drm_mst_fw_helper_ops drm_dp_sim_mst_fw_helper_ops = { @@ -282,6 +298,8 @@ static const struct dp_drm_mst_fw_helper_ops drm_dp_sim_mst_fw_helper_ops = { .topology_mgr_set_mst = drm_dp_sim_mst_topology_mgr_set_mst, .get_ch_start_slot = _drm_dp_sim_mst_get_ch_start_slot, .atomic_release_vcpi_slots = drm_dp_sim_atomic_release_vcpi_slots, + .reset_vcpi_slots = drm_dp_sim_reset_vcpi_slots, + .deallocate_vcpi = drm_dp_sim_deallocate_vcpi, }; /* DP MST Bridge OPs */ @@ -352,7 +370,7 @@ static bool _dp_mst_compute_config(struct dp_mst_bridge *dp_bridge) DP_MST_DEBUG("enter\n"); - bpp = 24; + bpp = dp_bridge->dp_mode.timing.bpp; mst_pbn = mst->mst_fw_cbs->calc_pbn_mode( dp_bridge->drm_mode.crtc_clock, bpp); @@ -425,6 +443,44 @@ static void _dp_mst_bridge_pre_enable_part2(struct dp_mst_bridge *dp_bridge) dp_bridge->id); } +static void _dp_mst_bridge_pre_disable_part1(struct dp_mst_bridge *dp_bridge) +{ + struct dp_display *dp_display = dp_bridge->display; + struct sde_connector *c_conn = + to_sde_connector(dp_bridge->connector); + struct dp_mst_private *mst = dp_display->dp_mst_prv_info; + struct drm_dp_mst_port *port = c_conn->mst_port; + + DP_MST_DEBUG("enter\n"); + + mst->mst_fw_cbs->reset_vcpi_slots(&mst->mst_mgr, port); + + mst->mst_fw_cbs->update_payload_part1(&mst->mst_mgr); + + DP_MST_DEBUG("mst bridge [%d] _pre disable part-1 complete\n", + dp_bridge->id); +} + +static void _dp_mst_bridge_pre_disable_part2(struct dp_mst_bridge *dp_bridge) +{ + struct dp_display *dp_display = dp_bridge->display; + struct dp_mst_private *mst = dp_display->dp_mst_prv_info; + struct sde_connector *c_conn = + to_sde_connector(dp_bridge->connector); + struct drm_dp_mst_port *port = c_conn->mst_port; + + DP_MST_DEBUG("enter\n"); + + mst->mst_fw_cbs->check_act_status(&mst->mst_mgr); + + mst->mst_fw_cbs->update_payload_part2(&mst->mst_mgr); + + mst->mst_fw_cbs->deallocate_vcpi(&mst->mst_mgr, port); + + DP_MST_DEBUG("mst bridge [%d] _pre disable part-2 complete\n", + dp_bridge->id); +} + static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge) { int rc = 0; @@ -454,9 +510,6 @@ static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge) return; } - _dp_mst_compute_config(bridge); - _dp_mst_bridge_pre_enable_part1(bridge); - rc = dp->prepare(dp, bridge->dp_panel); if (rc) { pr_err("[%d] DP display prepare failed, rc=%d\n", @@ -464,8 +517,11 @@ static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge) return; } + _dp_mst_compute_config(bridge); + _dp_mst_bridge_pre_enable_part1(bridge); + dp->set_stream_info(dp, bridge->dp_panel, bridge->id, - bridge->start_slot, bridge->slots); + bridge->start_slot, bridge->slots, bridge->pbn); rc = dp->enable(dp, bridge->dp_panel); if (rc) { @@ -533,6 +589,8 @@ static void dp_mst_bridge_disable(struct drm_bridge *drm_bridge) sde_connector_helper_bridge_disable(bridge->connector); + _dp_mst_bridge_pre_disable_part1(bridge); + rc = dp->pre_disable(dp, bridge->dp_panel); if (rc) { pr_err("[%d] DP display pre disable failed, rc=%d\n", @@ -540,6 +598,8 @@ static void dp_mst_bridge_disable(struct drm_bridge *drm_bridge) return; } + _dp_mst_bridge_pre_disable_part2(bridge); + DP_MST_DEBUG("mst bridge [%d] disable complete\n", bridge->id); } diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 28ef79db94b5..86744209216f 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -1188,7 +1188,7 @@ static void dp_panel_edid_deregister(struct dp_panel_private *panel) static int dp_panel_set_stream_info(struct dp_panel *dp_panel, enum dp_stream_id stream_id, u32 ch_start_slot, - u32 ch_tot_slots) + u32 ch_tot_slots, u32 pbn) { if (!dp_panel || stream_id > DP_STREAM_MAX) { pr_err("invalid input. stream_id: %d\n", stream_id); @@ -1198,6 +1198,7 @@ static int dp_panel_set_stream_info(struct dp_panel *dp_panel, dp_panel->stream_id = stream_id; dp_panel->channel_start_slot = ch_start_slot; dp_panel->channel_total_slots = ch_tot_slots; + dp_panel->pbn = pbn; return 0; } @@ -1257,7 +1258,7 @@ static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel) if (!panel->custom_edid) sde_free_edid((void **)&dp_panel->edid_ctrl); - dp_panel_set_stream_info(dp_panel, DP_STREAM_MAX, 0, 0); + dp_panel_set_stream_info(dp_panel, DP_STREAM_MAX, 0, 0, 0); memset(&dp_panel->pinfo, 0, sizeof(dp_panel->pinfo)); memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta)); panel->panel_on = false; @@ -1643,6 +1644,13 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in) dp_panel->stream_id = DP_STREAM_MAX; dp_panel->connector = in->connector; + if (in->base_panel) { + memcpy(dp_panel->dpcd, in->base_panel->dpcd, + DP_RECEIVER_CAP_SIZE + 1); + memcpy(&dp_panel->link_info, &in->base_panel->link_info, + sizeof(dp_panel->link_info)); + } + dp_panel->init = dp_panel_init_panel_info; dp_panel->deinit = dp_panel_deinit_panel_info; dp_panel->hw_cfg = dp_panel_hw_cfg; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 600af83c09ff..f9c95441f6e0 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -53,12 +53,15 @@ struct dp_display_mode { u32 capabilities; }; +struct dp_panel; + struct dp_panel_in { struct device *dev; struct dp_aux *aux; struct dp_link *link; struct dp_catalog_panel *catalog; struct drm_connector *connector; + struct dp_panel *base_panel; }; struct dp_audio; @@ -87,6 +90,7 @@ struct dp_panel { u32 channel_start_slot; u32 channel_total_slots; + u32 pbn; /* DRM connector assosiated with this panel */ struct drm_connector *connector; @@ -115,7 +119,7 @@ struct dp_panel { int (*set_stream_info)(struct dp_panel *dp_panel, enum dp_stream_id stream_id, u32 ch_start_slot, - u32 ch_tot_slots); + u32 ch_tot_slots, u32 pbn); int (*read_sink_status)(struct dp_panel *dp_panel, u8 *sts, u32 size); int (*update_edid)(struct dp_panel *dp_panel, struct edid *edid); -- GitLab From 773f28304473708c8fbcf0e0144e010b6cdcf3da Mon Sep 17 00:00:00 2001 From: "Joel Fernandes (Google)" Date: Mon, 25 Jun 2018 17:08:22 -0700 Subject: [PATCH 0930/1299] FROMLIST: trace: Reorder display of TGID to be after PID Currently ftrace displays data in trace output like so: _-----=> irqs-off / _----=> need-resched | / _---=> hardirq/softirq || / _--=> preempt-depth ||| / delay TASK-PID CPU TGID |||| TIMESTAMP FUNCTION | | | | |||| | | bash-1091 [000] ( 1091) d..2 28.313544: sched_switch: However Android's trace visualization tools expect a slightly different format due to an out-of-tree patch patch that was been carried for a decade, notice that the TGID and CPU fields are reversed: _-----=> irqs-off / _----=> need-resched | / _---=> hardirq/softirq || / _--=> preempt-depth ||| / delay TASK-PID TGID CPU |||| TIMESTAMP FUNCTION | | | | |||| | | bash-1091 ( 1091) [002] d..2 64.965177: sched_switch: From kernel v4.13 onwards, during which TGID was introduced, tracing with systrace on all Android kernels will break (most Android kernels have been on 4.9 with Android patches, so this issues hasn't been seen yet). From v4.13 onwards things will break. The chrome browser's tracing tools also embed the systrace viewer which uses the legacy TGID format and updates to that are known to be difficult to make. Considering this, I suggest we make this change to the upstream kernel and backport it to all Android kernels. I believe this feature is merged recently enough into the upstream kernel that it shouldn't be a problem. Also logically, IMO it makes more sense to group the TGID with the TASK-PID and the CPU after these. Change-Id: I54f389729e79ffee05f20218fb67513dcd55d726 Fixes: 441dae8f2f29 ("tracing: Add support for display of tgid in trace output") Cc: jreck@google.com Cc: tkjos@google.com Signed-off-by: Joel Fernandes (Google) --- kernel/trace/trace.c | 8 ++++---- kernel/trace/trace_output.c | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 520ecaf61dc4..e268750bd4ad 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3359,8 +3359,8 @@ static void print_func_help_header(struct trace_buffer *buf, struct seq_file *m, print_event_info(buf, m); - seq_printf(m, "# TASK-PID CPU# %s TIMESTAMP FUNCTION\n", tgid ? "TGID " : ""); - seq_printf(m, "# | | | %s | |\n", tgid ? " | " : ""); + seq_printf(m, "# TASK-PID %s CPU# TIMESTAMP FUNCTION\n", tgid ? "TGID " : ""); + seq_printf(m, "# | | %s | | |\n", tgid ? " | " : ""); } static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file *m, @@ -3380,9 +3380,9 @@ static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file tgid ? tgid_space : space); seq_printf(m, "# %s||| / delay\n", tgid ? tgid_space : space); - seq_printf(m, "# TASK-PID CPU#%s|||| TIMESTAMP FUNCTION\n", + seq_printf(m, "# TASK-PID %sCPU# |||| TIMESTAMP FUNCTION\n", tgid ? " TGID " : space); - seq_printf(m, "# | | | %s|||| | |\n", + seq_printf(m, "# | | %s | |||| | |\n", tgid ? " | " : space); } diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 9fbaa809d747..416f7fead5fa 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -594,8 +594,7 @@ int trace_print_context(struct trace_iterator *iter) trace_find_cmdline(entry->pid, comm); - trace_seq_printf(s, "%16s-%-5d [%03d] ", - comm, entry->pid, iter->cpu); + trace_seq_printf(s, "%16s-%-5d ", comm, entry->pid); if (tr->trace_flags & TRACE_ITER_RECORD_TGID) { unsigned int tgid = trace_find_tgid(entry->pid); @@ -606,6 +605,8 @@ int trace_print_context(struct trace_iterator *iter) trace_seq_printf(s, "(%5d) ", tgid); } + trace_seq_printf(s, "[%03d] ", iter->cpu); + if (tr->trace_flags & TRACE_ITER_IRQ_INFO) trace_print_lat_fmt(s, entry); -- GitLab From 8c23301f1fc530cc1e9fcb63ca38bc2bdec81084 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Thu, 28 Jun 2018 11:27:14 -0700 Subject: [PATCH 0931/1299] msm: gsi: increase the stop_channel timeout Increase the GSI_STOP_CMD_TIMEOUT_MS from 20 to 50 to resolve the interrupt coming too late issue Change-Id: Iff3303678996a4b4be50740bdb0813f123399d69 Signed-off-by: Skylar Chang --- drivers/platform/msm/gsi/gsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index ee789cc0b92f..74ee0cd2c08e 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -22,7 +22,7 @@ #include "gsi_reg.h" #define GSI_CMD_TIMEOUT (5*HZ) -#define GSI_STOP_CMD_TIMEOUT_MS 20 +#define GSI_STOP_CMD_TIMEOUT_MS 50 #define GSI_MAX_CH_LOW_WEIGHT 15 #define GSI_RESET_WA_MIN_SLEEP 1000 -- GitLab From 4a3fe6dbd3ea43c7d5570254ddf5477a03a0952c Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Thu, 28 Jun 2018 11:08:52 -0700 Subject: [PATCH 0932/1299] dwc3: gadget: Don't set DWC3_EP_END_TRANSFER_PENDING with GSI endpoint DWC3_EP_END_TRANSFER_PENDING is used with per endpoint's flag to wait for END xfer command completion. As GSI endpoint related interrupt is not received on APPS processor and being routed to other EE, this flag never get clears once sending END xfer command first time. This results into no END xfer command send with GSI endpoint causing USB controller accessing any active previous stale TRB on setting run/stop bit which results into unmapped access related SMMU page fault. Hence fix this issue by not setting DWC3_EP_END_TRANSFER_PENDING with GSI endpoint. Change-Id: I8e494b571ac2e5ab9a9dae8c6cec1b328f339ca3 Signed-off-by: Mayank Rana --- drivers/usb/dwc3/gadget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 61840a952489..17ec0f581847 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3088,7 +3088,8 @@ void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) dep->flags &= ~DWC3_EP_BUSY; if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) { - dep->flags |= DWC3_EP_END_TRANSFER_PENDING; + if (dep->endpoint.ep_type != EP_TYPE_GSI) + dep->flags |= DWC3_EP_END_TRANSFER_PENDING; udelay(100); } } -- GitLab From 8cb0dc7ab6447342b32d94aea5eabcb83dd64e9b Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Wed, 27 Jun 2018 19:00:06 -0700 Subject: [PATCH 0933/1299] net: qrtr: Move broadcast address change Since the expected address format is different on remote endpoints, move the address change logic into node_enqueue. This helps consolidate the address change for other control packets that need to be added to qrtr core logic. Change-Id: I414e4c9c944b34d14592e500c39ca58802ef8f38 Signed-off-by: Chris Lew --- net/qrtr/qrtr.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index c46e05f2ec53..55d2fa24c78b 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -314,8 +314,13 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb, hdr->type = cpu_to_le32(type); hdr->src_node_id = cpu_to_le32(from->sq_node); hdr->src_port_id = cpu_to_le32(from->sq_port); - hdr->dst_node_id = cpu_to_le32(to->sq_node); - hdr->dst_port_id = cpu_to_le32(to->sq_port); + if (to->sq_port == QRTR_PORT_CTRL) { + hdr->dst_node_id = cpu_to_le32(node->nid); + hdr->dst_port_id = cpu_to_le32(QRTR_NODE_BCAST); + } else { + hdr->dst_node_id = cpu_to_le32(to->sq_node); + hdr->dst_port_id = cpu_to_le32(to->sq_port); + } hdr->size = cpu_to_le32(len); hdr->confirm_rx = !!confirm_rx; @@ -829,14 +834,10 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, if (!skbn) break; skb_set_owner_w(skbn, skb->sk); - to->sq_node = cpu_to_le32(node->nid); - to->sq_port = QRTR_NODE_BCAST; qrtr_node_enqueue(node, skbn, type, from, to); } mutex_unlock(&qrtr_node_lock); - to->sq_node = QRTR_NODE_BCAST; - to->sq_port = QRTR_PORT_CTRL; qrtr_local_enqueue(node, skb, type, from, to); return 0; -- GitLab From 255adfc762d55981e9d43bbc27937cec05facbfc Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 1 Jun 2018 10:47:20 -0700 Subject: [PATCH 0934/1299] net: qrtr: Implement outgoing flow control It is possible to flood a remote with messages and cause memory exhaustion. To avoid this scenario implement the following flow control handshake. After sending 10 packets to a remote port, set a control flag on the message and wait for a confirm rx packet from that remote port before sending more data. Change-Id: I81c641d4be6d2014df3f0392d140690f6afac2ac Signed-off-by: Bjorn Andersson Git-Commit: 347753ab1cdac06af321950337a54b03f8203960 Git-Repo: https://github.com/andersson/kernel.git [clew@codeaurora.org: Add commit text and fix checkpatch warnings. Use the control packet instead of header addresses for resume tx and fix missing mutex init. Change flow to atomic_t to ensure the compiler orders the flow control set and signal correctly.] Signed-off-by: Chris Lew --- net/qrtr/qrtr.c | 148 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 139 insertions(+), 9 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 8b2b9256d6bc..c46e05f2ec53 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -15,6 +15,7 @@ #include #include #include /* For TIOCINQ/OUTQ */ +#include #include @@ -120,6 +121,9 @@ static DEFINE_MUTEX(qrtr_port_lock); * @ep: endpoint * @ref: reference count for node * @nid: node id + * @qrtr_tx_flow: remote port tx flow control list + * @resume_tx: wait until remote port acks control flag + * @qrtr_tx_lock: lock for qrtr_tx_flow * @rx_queue: receive queue * @work: scheduled work struct for recv work * @item: list item for broadcast list @@ -130,11 +134,22 @@ struct qrtr_node { struct kref ref; unsigned int nid; + struct radix_tree_root qrtr_tx_flow; + struct wait_queue_head resume_tx; + struct mutex qrtr_tx_lock; /* for qrtr_tx_flow */ + struct sk_buff_head rx_queue; struct work_struct work; struct list_head item; }; +struct qrtr_tx_flow { + atomic_t pending; +}; + +#define QRTR_TX_FLOW_HIGH 10 +#define QRTR_TX_FLOW_LOW 5 + static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb, int type, struct sockaddr_qrtr *from, struct sockaddr_qrtr *to); @@ -149,9 +164,9 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, */ static void __qrtr_node_release(struct kref *kref) { - struct qrtr_node *node = container_of(kref, struct qrtr_node, ref); struct radix_tree_iter iter; - void **slot; + struct qrtr_node *node = container_of(kref, struct qrtr_node, ref); + void __rcu **slot; if (node->nid != QRTR_EP_NID_AUTO) { radix_tree_for_each_slot(slot, &qrtr_nodes, &iter, 0) { @@ -163,6 +178,12 @@ static void __qrtr_node_release(struct kref *kref) list_del(&node->item); mutex_unlock(&qrtr_node_lock); + /* Free tx flow counters */ + radix_tree_for_each_slot(slot, &node->qrtr_tx_flow, &iter, 0) { + radix_tree_iter_delete(&node->qrtr_tx_flow, &iter, slot); + kfree(*slot); + } + skb_queue_purge(&node->rx_queue); kfree(node); } @@ -183,15 +204,111 @@ static void qrtr_node_release(struct qrtr_node *node) kref_put_mutex(&node->ref, __qrtr_node_release, &qrtr_node_lock); } +/** + * qrtr_tx_resume() - reset flow control counter + * @node: qrtr_node that the QRTR_TYPE_RESUME_TX packet arrived on + * @skb: skb for resume tx control packet + */ +static void qrtr_tx_resume(struct qrtr_node *node, struct sk_buff *skb) +{ + struct qrtr_ctrl_pkt *pkt; + struct qrtr_tx_flow *flow; + unsigned long key; + int dest_node; + int dest_port; + + pkt = (struct qrtr_ctrl_pkt *)skb->data; + if (le32_to_cpu(pkt->cmd) != QRTR_TYPE_RESUME_TX) + return; + + dest_node = le32_to_cpu(pkt->client.node); + dest_port = le32_to_cpu(pkt->client.port); + key = (u64)dest_node << 32 | dest_port; + + flow = radix_tree_lookup(&node->qrtr_tx_flow, key); + if (flow) + atomic_set(&flow->pending, 0); + + wake_up_interruptible_all(&node->resume_tx); +} + +/** + * qrtr_tx_wait() - flow control for outgoing packets + * @node: qrtr_node that the packet is to be send to + * @dest_node: node id of the destination + * @dest_port: port number of the destination + * @type: type of message + * + * The flow control scheme is based around the low and high "watermarks". When + * the low watermark is passed the confirm_rx flag is set on the outgoing + * message, which will trigger the remote to send a control message of the type + * QRTR_TYPE_RESUME_TX to reset the counter. If the high watermark is hit + * further transmision should be paused. + * + * Return: 1 if confirm_rx should be set, 0 otherwise or errno failure + */ +static int qrtr_tx_wait(struct qrtr_node *node, int dest_node, int dest_port, + int type) +{ + struct qrtr_tx_flow *flow; + unsigned long key = (u64)dest_node << 32 | dest_port; + int confirm_rx = 0; + int ret; + + /* Never set confirm_rx on non-data packets */ + if (type != QRTR_TYPE_DATA) + return 0; + + mutex_lock(&node->qrtr_tx_lock); + flow = radix_tree_lookup(&node->qrtr_tx_flow, key); + if (!flow) { + flow = kzalloc(sizeof(*flow), GFP_KERNEL); + if (!flow) + return 1; + else + radix_tree_insert(&node->qrtr_tx_flow, key, flow); + } + mutex_unlock(&node->qrtr_tx_lock); + + for (;;) { + ret = wait_event_interruptible(node->resume_tx, + atomic_read(&flow->pending) < + QRTR_TX_FLOW_HIGH || !node->ep); + if (ret) + return ret; + + if (!node->ep) + return -EPIPE; + + mutex_lock(&node->qrtr_tx_lock); + if (atomic_read(&flow->pending) < QRTR_TX_FLOW_HIGH) { + atomic_inc(&flow->pending); + confirm_rx = atomic_read(&flow->pending) == QRTR_TX_FLOW_LOW; + mutex_unlock(&node->qrtr_tx_lock); + break; + } + mutex_unlock(&node->qrtr_tx_lock); + } + + return confirm_rx; +} + /* Pass an outgoing packet socket buffer to the endpoint driver. */ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb, int type, struct sockaddr_qrtr *from, struct sockaddr_qrtr *to) { struct qrtr_hdr_v1 *hdr; + int confirm_rx; size_t len = skb->len; int rc = -ENODEV; + confirm_rx = qrtr_tx_wait(node, to->sq_node, to->sq_port, type); + if (confirm_rx < 0) { + kfree_skb(skb); + return confirm_rx; + } + hdr = skb_push(skb, sizeof(*hdr)); hdr->version = cpu_to_le32(QRTR_PROTO_VER_1); hdr->type = cpu_to_le32(type); @@ -201,7 +318,7 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb, hdr->dst_port_id = cpu_to_le32(to->sq_port); hdr->size = cpu_to_le32(len); - hdr->confirm_rx = 0; + hdr->confirm_rx = !!confirm_rx; skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr)); @@ -321,7 +438,8 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) if (len != ALIGN(size, 4) + hdrlen) goto err; - if (cb->dst_port != QRTR_PORT_CTRL && cb->type != QRTR_TYPE_DATA) + if (cb->dst_port != QRTR_PORT_CTRL && cb->type != QRTR_TYPE_DATA && + cb->type != QRTR_TYPE_RESUME_TX) goto err; skb_put_data(skb, data + hdrlen, size); @@ -381,14 +499,19 @@ static void qrtr_node_rx_work(struct work_struct *work) cb = (struct qrtr_cb *)skb->cb; qrtr_node_assign(node, cb->src_node); - ipc = qrtr_port_lookup(cb->dst_port); - if (!ipc) { - kfree_skb(skb); + if (cb->type == QRTR_TYPE_RESUME_TX) { + qrtr_tx_resume(node, skb); + consume_skb(skb); } else { - if (sock_queue_rcv_skb(&ipc->sk, skb)) + ipc = qrtr_port_lookup(cb->dst_port); + if (!ipc) { kfree_skb(skb); + } else { + if (sock_queue_rcv_skb(&ipc->sk, skb)) + kfree_skb(skb); - qrtr_port_put(ipc); + qrtr_port_put(ipc); + } } } } @@ -419,6 +542,10 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid) node->nid = QRTR_EP_NID_AUTO; node->ep = ep; + mutex_init(&node->qrtr_tx_lock); + INIT_RADIX_TREE(&node->qrtr_tx_flow, GFP_KERNEL); + init_waitqueue_head(&node->resume_tx); + qrtr_node_assign(node, nid); mutex_lock(&qrtr_node_lock); @@ -453,6 +580,9 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep) qrtr_local_enqueue(NULL, skb, QRTR_TYPE_BYE, &src, &dst); } + /* Wake up any transmitters waiting for resume-tx from the node */ + wake_up_interruptible_all(&node->resume_tx); + qrtr_node_release(node); ep->node = NULL; } -- GitLab From 3373eb77cd6d5575611aaf51007e6cf2f2c4b301 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Thu, 7 Jun 2018 11:55:06 -0700 Subject: [PATCH 0935/1299] net: qrtr: Add socket mode optimization A remote endpoint should not need to know when a client socket is freed if the socket never established commnication with the endpoint. Add a mode to keep track of which endpoints a socket communicates with. There are three modes a socket can be in: INIT - Socket has not sent anything or only local messages, only send client close to local services. SINGLE - Socket has sent messages to a single ept, send event to this single ept. MULTI - Socket has sent messages to multiple epts, broadcast release of this socket. Change-Id: I3cd56ba32f670b1e35d74ed8975b90b32eac7012 Signed-off-by: Chris Lew --- net/qrtr/qrtr.c | 66 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 55d2fa24c78b..6bcbe6ee149c 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -28,6 +28,10 @@ #define QRTR_MIN_EPH_SOCKET 0x4000 #define QRTR_MAX_EPH_SOCKET 0x7fff +/* qrtr socket states */ +#define QRTR_STATE_MULTI -2 +#define QRTR_STATE_INIT -1 + /** * struct qrtr_hdr_v1 - (I|R)PCrouter packet header version 1 * @version: protocol version @@ -94,6 +98,8 @@ struct qrtr_sock { struct sock sk; struct sockaddr_qrtr us; struct sockaddr_qrtr peer; + + int state; }; static inline struct qrtr_sock *qrtr_sk(struct sock *sk) @@ -619,29 +625,59 @@ static void qrtr_port_put(struct qrtr_sock *ipc) sock_put(&ipc->sk); } -/* Remove port assignment. */ -static void qrtr_port_remove(struct qrtr_sock *ipc) +static void qrtr_send_del_client(struct qrtr_sock *ipc) { struct qrtr_ctrl_pkt *pkt; - struct sk_buff *skb; - int port = ipc->us.sq_port; struct sockaddr_qrtr to; + struct qrtr_node *node; + struct sk_buff *skbn; + struct sk_buff *skb; + int type = QRTR_TYPE_DEL_CLIENT; + + skb = qrtr_alloc_ctrl_packet(&pkt); + if (!skb) + return; to.sq_family = AF_QIPCRTR; to.sq_node = QRTR_NODE_BCAST; to.sq_port = QRTR_PORT_CTRL; - skb = qrtr_alloc_ctrl_packet(&pkt); - if (skb) { - pkt->cmd = cpu_to_le32(QRTR_TYPE_DEL_CLIENT); - pkt->client.node = cpu_to_le32(ipc->us.sq_node); - pkt->client.port = cpu_to_le32(ipc->us.sq_port); + pkt->cmd = cpu_to_le32(QRTR_TYPE_DEL_CLIENT); + pkt->client.node = cpu_to_le32(ipc->us.sq_node); + pkt->client.port = cpu_to_le32(ipc->us.sq_port); - skb_set_owner_w(skb, &ipc->sk); - qrtr_bcast_enqueue(NULL, skb, QRTR_TYPE_DEL_CLIENT, &ipc->us, - &to); + skb_set_owner_w(skb, &ipc->sk); + + if (ipc->state == QRTR_STATE_MULTI) { + qrtr_bcast_enqueue(NULL, skb, type, &ipc->us, &to); + return; } + if (ipc->state > QRTR_STATE_INIT) { + node = qrtr_node_lookup(ipc->state); + if (!node) + goto exit; + + skbn = skb_clone(skb, GFP_KERNEL); + if (!skbn) { + qrtr_node_release(node); + goto exit; + } + + skb_set_owner_w(skbn, &ipc->sk); + qrtr_node_enqueue(node, skbn, type, &ipc->us, &to); + qrtr_node_release(node); + } +exit: + qrtr_local_enqueue(NULL, skb, type, &ipc->us, &to); +} + +/* Remove port assignment. */ +static void qrtr_port_remove(struct qrtr_sock *ipc) +{ + int port = ipc->us.sq_port; + + qrtr_send_del_client(ipc); if (port == QRTR_PORT_CTRL) port = 0; @@ -903,6 +939,11 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) release_sock(sk); return -ECONNRESET; } + + if (ipc->state > QRTR_STATE_INIT && ipc->state != node->nid) + ipc->state = QRTR_STATE_MULTI; + else if (ipc->state == QRTR_STATE_INIT) + ipc->state = node->nid; } plen = (len + 3) & ~3; @@ -1224,6 +1265,7 @@ static int qrtr_create(struct net *net, struct socket *sock, ipc->us.sq_family = AF_QIPCRTR; ipc->us.sq_node = qrtr_local_nid; ipc->us.sq_port = 0; + ipc->state = QRTR_STATE_INIT; return 0; } -- GitLab From eae37c6a20373564910cabdfc1abcd76e2497430 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Thu, 28 Jun 2018 12:00:33 -0700 Subject: [PATCH 0936/1299] msm: ipa: remove extra mhi_device_get_sync() Remove the extra get() from mhi device to allow LPM. Change-Id: I5026361ad569985adf4e5a32893e35dbce862a54 Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c index ef10f940fe28..2b78ba4b5ba1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c @@ -771,7 +771,6 @@ static int imp_mhi_probe_cb(struct mhi_device *mhi_dev, mutex_unlock(&imp_ctx->mutex); IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); - mhi_device_get_sync(imp_ctx->md.mhi_dev); IMP_FUNC_EXIT(); -- GitLab From 04b8490b9ce3c9b8d96c211487d8545f817747f5 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Thu, 28 Jun 2018 12:26:57 -0700 Subject: [PATCH 0937/1299] usb: phy: Don't free phy memory from remove() API USB PHY drivers are using managed allocation (i.e. devm_kzalloc()) with its probe() API. Hence remove usage of kfree() from remove() API as allocated memory would be freed on driver detach itself. This avoids multiple free of allocated PHY related memory. Change-Id: Ia89bebe3d9d4d6020a5c72247e0f2970a1e2dd94 Signed-off-by: Mayank Rana --- drivers/usb/phy/phy-msm-snps-hs.c | 3 --- drivers/usb/phy/phy-msm-ssusb-qmp.c | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/usb/phy/phy-msm-snps-hs.c b/drivers/usb/phy/phy-msm-snps-hs.c index a3624a15b125..3b67f831c340 100644 --- a/drivers/usb/phy/phy-msm-snps-hs.c +++ b/drivers/usb/phy/phy-msm-snps-hs.c @@ -682,9 +682,6 @@ static int msm_hsphy_remove(struct platform_device *pdev) msm_hsphy_enable_clocks(phy, false); msm_hsphy_enable_power(phy, false); - - kfree(phy); - return 0; } diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c index 9321891e4533..b57ad1e25f1c 100644 --- a/drivers/usb/phy/phy-msm-ssusb-qmp.c +++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c @@ -1091,7 +1091,6 @@ static int msm_ssphy_qmp_remove(struct platform_device *pdev) usb_remove_phy(&phy->phy); msm_ssphy_qmp_enable_clks(phy, false); msm_ssusb_qmp_ldo_enable(phy, 0); - kfree(phy); return 0; } -- GitLab From 571150f8ce4ed3f71140bf67cb77bac65fddd2e4 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Wed, 13 Jun 2018 15:36:41 -0700 Subject: [PATCH 0938/1299] usb: pd: Add support to detect VCONN-Powered USB Device Identifying VCONN-Powered USB Device, allows to turn off VBUS regulator. Send discover identity SOP' request when VCONN is turned on, in PE_SRC_Startup state. Add new state to wait for receiving VDM ACK. If received ACK has product type VPD then turn off VBUS. Change-Id: I5f3666cb8d570d0289ff73b2df8ab173a8392854 Signed-off-by: Hemant Kumar --- drivers/usb/pd/policy_engine.c | 78 ++++++++++++++++++++++++++++------ drivers/usb/pd/qpnp-pdphy.c | 2 +- drivers/usb/pd/usbpd.h | 1 + 3 files changed, 68 insertions(+), 13 deletions(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 1045a88cfd37..3fdd7b22240b 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -43,6 +43,7 @@ enum usbpd_state { PE_ERROR_RECOVERY, PE_SRC_DISABLED, PE_SRC_STARTUP, + PE_SRC_STARTUP_WAIT_FOR_VDM_RESP, PE_SRC_SEND_CAPABILITIES, PE_SRC_SEND_CAPABILITIES_WAIT, /* substate to wait for Request */ PE_SRC_NEGOTIATE_CAPABILITY, @@ -79,6 +80,7 @@ static const char * const usbpd_state_strings[] = { "ERROR_RECOVERY", "SRC_Disabled", "SRC_Startup", + "SRC_Startup_Wait_for_VDM_Resp", "SRC_Send_Capabilities", "SRC_Send_Capabilities (Wait for Request)", "SRC_Negotiate_Capability", @@ -316,11 +318,12 @@ static void *usbpd_ipc_log; #define ID_HDR_USB_HOST BIT(31) #define ID_HDR_USB_DEVICE BIT(30) #define ID_HDR_MODAL_OPR BIT(26) -#define ID_HDR_PRODUCT_TYPE(n) ((n) >> 27) +#define ID_HDR_PRODUCT_TYPE(n) (((n) >> 27) & 0x7) #define ID_HDR_PRODUCT_PER_MASK (2 << 27) #define ID_HDR_PRODUCT_HUB 1 #define ID_HDR_PRODUCT_PER 2 #define ID_HDR_PRODUCT_AMA 5 +#define ID_HDR_PRODUCT_VPD 6 #define ID_HDR_VID 0x05c6 /* qcom */ #define PROD_VDO_PID 0x0a00 /* TBD */ @@ -456,6 +459,8 @@ static const unsigned int usbpd_extcon_cable[] = { EXTCON_NONE, }; +static void handle_vdm_tx(struct usbpd *pd, enum pd_sop_type sop_type); + enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd) { int ret; @@ -1000,9 +1005,8 @@ static void phy_msg_received(struct usbpd *pd, enum pd_sop_type sop, unsigned long flags; u16 header; - if (sop != SOP_MSG) { - usbpd_err(&pd->dev, "invalid msg type (%d) received; only SOP supported\n", - sop); + if (sop == SOPII_MSG) { + usbpd_err(&pd->dev, "only SOP/SOP' supported\n"); return; } @@ -1101,6 +1105,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) .msg_rx_cb = phy_msg_received, .shutdown_cb = phy_shutdown, .frame_filter_val = FRAME_FILTER_EN_SOP | + FRAME_FILTER_EN_SOPI | FRAME_FILTER_EN_HARD_RESET, }; union power_supply_propval val = {0}; @@ -1181,6 +1186,20 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) POWER_SUPPLY_PROP_PR_SWAP, &val); } + if (pd->vconn_enabled) { + /* + * wait for tVCONNStable (50ms), until SOPI becomes + * ready for communication. + */ + usleep_range(50000, 51000); + usbpd_send_svdm(pd, USBPD_SID, + USBPD_SVDM_DISCOVER_IDENTITY, + SVDM_CMD_TYPE_INITIATOR, 0, NULL, 0); + handle_vdm_tx(pd, SOPI_MSG); + pd->current_state = PE_SRC_STARTUP_WAIT_FOR_VDM_RESP; + kick_sm(pd, SENDER_RESPONSE_TIME); + return; + } /* * A sink might remove its terminations (during some Type-C * compliance tests or a sink attempting to do Try.SRC) @@ -1522,7 +1541,7 @@ int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos, int num_vdos) { struct vdm_tx *vdm_tx; - if (!pd->in_explicit_contract || pd->vdm_tx) + if (pd->vdm_tx) return -EBUSY; vdm_tx = kzalloc(sizeof(*vdm_tx), GFP_KERNEL); @@ -1538,7 +1557,8 @@ int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos, int num_vdos) pd->vdm_tx = vdm_tx; /* slight delay before queuing to prioritize handling of incoming VDM */ - kick_sm(pd, 2); + if (pd->in_explicit_contract) + kick_sm(pd, 2); return 0; } @@ -1559,6 +1579,7 @@ EXPORT_SYMBOL(usbpd_send_svdm); static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg) { + int ret; u32 vdm_hdr = rx_msg->data_len >= sizeof(u32) ? ((u32 *)rx_msg->payload)[0] : 0; @@ -1630,6 +1651,24 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg) kfree(pd->vdm_tx_retry); pd->vdm_tx_retry = NULL; + if (num_vdos && ID_HDR_PRODUCT_TYPE(vdos[0]) == + ID_HDR_PRODUCT_VPD) { + + usbpd_dbg(&pd->dev, "VPD detected turn off vbus\n"); + + if (pd->vbus_enabled) { + ret = regulator_disable(pd->vbus); + if (ret) + usbpd_err(&pd->dev, "Err disabling vbus (%d)\n", + ret); + else + pd->vbus_enabled = false; + } + } + + if (!pd->in_explicit_contract) + break; + pd->vdm_state = DISCOVERED_ID; usbpd_send_svdm(pd, USBPD_SID, USBPD_SVDM_DISCOVER_SVIDS, @@ -1767,7 +1806,7 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg) } } -static void handle_vdm_tx(struct usbpd *pd) +static void handle_vdm_tx(struct usbpd *pd, enum pd_sop_type sop_type) { int ret; unsigned long flags; @@ -1785,13 +1824,13 @@ static void handle_vdm_tx(struct usbpd *pd) spin_unlock_irqrestore(&pd->rx_lock, flags); ret = pd_send_msg(pd, MSG_VDM, pd->vdm_tx->data, - pd->vdm_tx->size, SOP_MSG); + pd->vdm_tx->size, sop_type); if (ret) { usbpd_err(&pd->dev, "Error (%d) sending VDM command %d\n", ret, SVDM_HDR_CMD(pd->vdm_tx->data[0])); /* retry when hitting PE_SRC/SNK_Ready again */ - if (ret != -EBUSY) + if (ret != -EBUSY && sop_type == SOP_MSG) usbpd_set_state(pd, pd->current_pr == PR_SRC ? PE_SRC_SEND_SOFT_RESET : PE_SNK_SEND_SOFT_RESET); @@ -1966,7 +2005,7 @@ static void usbpd_sm(struct work_struct *w) { struct usbpd *pd = container_of(w, struct usbpd, sm_work); union power_supply_propval val = {0}; - int ret; + int ret, ms; struct rx_msg *rx_msg = NULL; unsigned long flags; @@ -2142,6 +2181,21 @@ static void usbpd_sm(struct work_struct *w) } break; + case PE_SRC_STARTUP_WAIT_FOR_VDM_RESP: + if (IS_DATA(rx_msg, MSG_VDM)) + handle_vdm_rx(pd, rx_msg); + + /* tVCONNStable (50ms) elapsed */ + ms = FIRST_SOURCE_CAP_TIME - 50; + + /* if no vdm msg received SENDER_RESPONSE_TIME elapsed */ + if (!rx_msg) + ms -= SENDER_RESPONSE_TIME; + + pd->current_state = PE_SRC_SEND_CAPABILITIES; + kick_sm(pd, ms); + break; + case PE_SRC_STARTUP: usbpd_set_state(pd, PE_SRC_STARTUP); break; @@ -2275,7 +2329,7 @@ static void usbpd_sm(struct work_struct *w) pd->current_state = PE_DRS_SEND_DR_SWAP; kick_sm(pd, SENDER_RESPONSE_TIME); } else { - handle_vdm_tx(pd); + handle_vdm_tx(pd, SOP_MSG); } break; @@ -2689,7 +2743,7 @@ static void usbpd_sm(struct work_struct *w) pd->current_state = PE_DRS_SEND_DR_SWAP; kick_sm(pd, SENDER_RESPONSE_TIME); } else if (is_sink_tx_ok(pd)) { - handle_vdm_tx(pd); + handle_vdm_tx(pd, SOP_MSG); } break; diff --git a/drivers/usb/pd/qpnp-pdphy.c b/drivers/usb/pd/qpnp-pdphy.c index 81227a55e2cb..3a945ad9cb05 100644 --- a/drivers/usb/pd/qpnp-pdphy.c +++ b/drivers/usb/pd/qpnp-pdphy.c @@ -713,7 +713,7 @@ static irqreturn_t pdphy_msg_rx_irq(int irq, void *data) goto done; frame_type = rx_status & RX_FRAME_TYPE; - if (frame_type != SOP_MSG) { + if (frame_type == SOPII_MSG) { dev_err(pdphy->dev, "%s:unsupported frame type %d\n", __func__, frame_type); goto done; diff --git a/drivers/usb/pd/usbpd.h b/drivers/usb/pd/usbpd.h index 76ffbf6e3669..fbddd747514a 100644 --- a/drivers/usb/pd/usbpd.h +++ b/drivers/usb/pd/usbpd.h @@ -58,6 +58,7 @@ enum pd_spec_rev { /* enable msg and signal to be received by phy */ #define FRAME_FILTER_EN_SOP BIT(0) +#define FRAME_FILTER_EN_SOPI BIT(1) #define FRAME_FILTER_EN_HARD_RESET BIT(5) struct pd_phy_params { -- GitLab From e701a79b494053f0fb3508f7d28ee4f03b6dafd8 Mon Sep 17 00:00:00 2001 From: Narendra Muppalla Date: Tue, 5 Jun 2018 12:43:06 +0530 Subject: [PATCH 0939/1299] drm/msm/sde: Prevent multiple unblank event trigger In cases such as dynamic fps, resolution switch, currently unblank event is triggered every time when new modeset is required. Trigger the event only when active changed. Change-Id: I6387f576a804999f1e916a1852a4c21719de9e91 Signed-off-by: Jayant Shekhar Signed-off-by: Narendra Muppalla --- drivers/gpu/drm/msm/msm_atomic.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index cea416f42788..60d55d7e66d4 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -465,12 +465,15 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n", encoder->base.id, encoder->name); - blank = MSM_DRM_BLANK_UNBLANK; - notifier_data.data = ␣ - notifier_data.id = - new_conn_state->crtc->index; - msm_drm_notifier_call_chain(MSM_DRM_EARLY_EVENT_BLANK, + if (connector->state->crtc->state->active_changed) { + blank = MSM_DRM_BLANK_UNBLANK; + notifier_data.data = ␣ + notifier_data.id = + connector->state->crtc->index; + DRM_DEBUG_ATOMIC("Notify early unblank\n"); + msm_drm_notifier_call_chain(MSM_DRM_EARLY_EVENT_BLANK, ¬ifier_data); + } /* * Each encoder has at most one connector (since we always steal * it away), so we won't call enable hooks twice. @@ -519,8 +522,11 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, encoder->base.id, encoder->name); drm_bridge_enable(encoder->bridge); - msm_drm_notifier_call_chain(MSM_DRM_EVENT_BLANK, + if (connector->state->crtc->state->active_changed) { + DRM_DEBUG_ATOMIC("Notify unblank\n"); + msm_drm_notifier_call_chain(MSM_DRM_EVENT_BLANK, ¬ifier_data); + } } SDE_ATRACE_END("msm_enable"); } -- GitLab From bad01c2c070162c1af0a7c7a2f761b0ca1ae0def Mon Sep 17 00:00:00 2001 From: Narendra Muppalla Date: Wed, 20 Jun 2018 19:30:09 +0530 Subject: [PATCH 0940/1299] drm/msm: suppress display platform drivers bind/unbind feature Display platform drivers does not support the manual bind/unbind feature through sysfs. Suppress the bind/unbind calls using driver attribute. Change-Id: If583694c6bfe659e17e76a736f2fcfb52e6d1a01 Signed-off-by: Jayant Shekhar Signed-off-by: Narendra Muppalla --- drivers/gpu/drm/msm/dp/dp_display.c | 1 + drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 1 + drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 1 + drivers/gpu/drm/msm/dsi/dsi.c | 3 ++- drivers/gpu/drm/msm/edp/edp.c | 1 + drivers/gpu/drm/msm/hdmi/hdmi.c | 3 ++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 3 ++- drivers/gpu/drm/msm/msm_drv.c | 1 + drivers/gpu/drm/msm/msm_smmu.c | 1 + drivers/gpu/drm/msm/sde/sde_wb.c | 1 + drivers/gpu/drm/msm/sde_rsc.c | 1 + drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c | 1 + 12 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index f0214b398617..88c720b867cc 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1984,6 +1984,7 @@ static struct platform_driver dp_display_driver = { .driver = { .name = "msm-dp-display", .of_match_table = dp_dt_match, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 3263b55424b1..0cdca09fac88 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -1776,6 +1776,7 @@ static struct platform_driver dsi_ctrl_driver = { .driver = { .name = "drm_dsi_ctrl", .of_match_table = msm_dsi_of_match, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index d0ca32c99468..988f785bcd9a 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -4515,6 +4515,7 @@ static struct platform_driver dsi_display_driver = { .driver = { .name = "msm-dsi-display", .of_match_table = dsi_display_dt_match, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 98742d7af6dc..f40c4c524fff 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2015, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -172,6 +172,7 @@ static struct platform_driver dsi_driver = { .name = "msm_dsi", .of_match_table = dt_match, .pm = &dsi_pm_ops, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c index 59d8f1eb279d..b80ab1ae0e04 100644 --- a/drivers/gpu/drm/msm/edp/edp.c +++ b/drivers/gpu/drm/msm/edp/edp.c @@ -128,6 +128,7 @@ static struct platform_driver edp_driver = { .driver = { .name = "msm_edp", .of_match_table = dt_match, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 7b893d456bec..f3509e723c0f 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016, 2018 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -648,6 +648,7 @@ static struct platform_driver msm_hdmi_driver = { .driver = { .name = "hdmi_msm", .of_match_table = msm_hdmi_dt_match, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index 16e6a00fce4a..f25601b33ca9 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -1051,6 +1051,7 @@ static struct platform_driver mdp5_driver = { .name = "msm_mdp", .of_match_table = mdp5_dt_match, .pm = &mdp5_pm_ops, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 95d9955e89db..ffa0c30d4214 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -2046,6 +2046,7 @@ static struct platform_driver msm_platform_driver = { .name = "msm_drm", .of_match_table = dt_match, .pm = &msm_pm_ops, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c index 69ab06af5a09..4f6ab35eb1a9 100644 --- a/drivers/gpu/drm/msm/msm_smmu.c +++ b/drivers/gpu/drm/msm/msm_smmu.c @@ -564,6 +564,7 @@ static struct platform_driver msm_smmu_driver = { .driver = { .name = "msmdrm_smmu", .of_match_table = msm_smmu_dt_match, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/gpu/drm/msm/sde/sde_wb.c b/drivers/gpu/drm/msm/sde/sde_wb.c index 788884547c25..575d76785661 100644 --- a/drivers/gpu/drm/msm/sde/sde_wb.c +++ b/drivers/gpu/drm/msm/sde/sde_wb.c @@ -818,6 +818,7 @@ static struct platform_driver sde_wb_driver = { .driver = { .name = "sde_wb", .of_match_table = dt_match, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c index 0fa9758e72ce..ecd2fcb76e81 100644 --- a/drivers/gpu/drm/msm/sde_rsc.c +++ b/drivers/gpu/drm/msm/sde_rsc.c @@ -1472,6 +1472,7 @@ static struct platform_driver sde_rsc_platform_driver = { .driver = { .name = "sde_rsc", .of_match_table = dt_match, + .suppress_bind_attrs = true, }, }; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c index 7d8f5fc9caeb..26e564202ff7 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c @@ -3707,6 +3707,7 @@ static struct platform_driver rotator_driver = { .name = SDE_ROTATOR_DRV_NAME, .of_match_table = sde_rotator_dt_match, .pm = &sde_rotator_pm_ops, + .suppress_bind_attrs = true, }, }; -- GitLab From ad50bf626a15be944019a296ed70489bbd49b8bb Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Fri, 20 May 2016 16:58:41 -0700 Subject: [PATCH 0941/1299] mm: make faultaround produce old ptes Based on Kirill's patch [1]. Currently, faultaround code produces young pte. This can screw up vmscan behaviour[2], as it makes vmscan think that these pages are hot and not push them out on first round. During sparse file access faultaround gets more pages mapped and all of them are young. Under memory pressure, this makes vmscan swap out anon pages instead, or to drop other page cache pages which otherwise stay resident. Modify faultaround to produce old ptes if sysctl 'want_old_faultaround_pte' is set, so they can easily be reclaimed under memory pressure. This can to some extend defeat the purpose of faultaround on machines without hardware accessed bit as it will not help us with reducing the number of minor page faults. Making the faultaround ptes old results in a unixbench regression for some architectures [3][4]. But on some architectures like arm64 it is not found to cause any regression. unixbench shell8 scores on arm64 v8.2 hardware with CONFIG_ARM64_HW_AFDBM enabled (5 runs min, max, avg): Base: (741,748,744) With this patch: (739,748,743) So by default produce young ptes and provide a sysctl option to make the ptes old. [1] https://marc.info/?l=linux-mm&m=146348837703148 [2] https://lkml.org/lkml/2016/4/18/612 [3] https://marc.info/?l=linux-kernel&m=146582237922378&w=2 [4] https://marc.info/?l=linux-mm&m=146589376909424&w=2 Change-Id: I193185cc953bc33a44fc24963a9df9e555906d95 Acked-by: Kirill A. Shutemov Patch-mainline: linux-mm @ Fri, 19 Jan 2018 17:24:54 [vinmenon@codeaurora.org: enable by default since arm works well with old fault_around ptes + edit the links in commit message to fix checkpatch issues] Signed-off-by: Vinayak Menon --- Documentation/sysctl/vm.txt | 22 ++++++++++++++++++++++ include/linux/mm.h | 3 +++ kernel/sysctl.c | 9 +++++++++ mm/filemap.c | 10 ++++++++++ mm/memory.c | 4 ++++ 5 files changed, 48 insertions(+) diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index b60e950d3a6a..3213305f746a 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -65,6 +65,7 @@ Currently, these files are in /proc/sys/vm: - vfs_cache_pressure - watermark_scale_factor - zone_reclaim_mode +- want_old_faultaround_pte ============================================================== @@ -932,4 +933,25 @@ Allowing regular swap effectively restricts allocations to the local node unless explicitly overridden by memory policies or cpuset configurations. +============================================================= + +want_old_faultaround_pte: + +By default faultaround code produces young pte. When want_old_faultaround_pte is +set to 1, faultaround produces old ptes. + +During sparse file access faultaround gets more pages mapped and when all of +them are young (default), under memory pressure, this makes vmscan swap out anon +pages instead, or to drop other page cache pages which otherwise stay resident. +Setting want_old_faultaround_pte to 1 avoids this. + +Making the faultaround ptes old can result in performance regression on some +architectures. This is due to cycles spent in micro-faults which would take page +walk to set young bit in the pte. One such known test that shows a regression on +x86 is unixbench shell8. Set want_old_faultaround_pte to 1 on architectures +which does not show this regression or if the workload shows overall performance +benefit with old faultaround ptes. + +The default value is 0. + ============ End of Document ================================= diff --git a/include/linux/mm.h b/include/linux/mm.h index fc7e143892bb..21385142e63a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -294,6 +294,7 @@ extern pgprot_t protection_map[16]; #define FAULT_FLAG_INSTRUCTION 0x100 /* The fault was during an instruction fetch */ /* Speculative fault, not holding mmap_sem */ #define FAULT_FLAG_SPECULATIVE 0x200 +#define FAULT_FLAG_PREFAULT_OLD 0x400 /* Make faultaround ptes old */ #define FAULT_FLAG_TRACE \ { FAULT_FLAG_WRITE, "WRITE" }, \ @@ -2746,5 +2747,7 @@ void __init setup_nr_node_ids(void); static inline void setup_nr_node_ids(void) {} #endif +extern int want_old_faultaround_pte; + #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index daa2c9024ed0..0eafe9cd73f3 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1481,6 +1481,15 @@ static struct ctl_table vm_table[] = { .extra1 = &zero, .extra2 = &one_hundred, }, + { + .procname = "want_old_faultaround_pte", + .data = &want_old_faultaround_pte, + .maxlen = sizeof(want_old_faultaround_pte), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, #ifdef CONFIG_HUGETLB_PAGE { .procname = "nr_hugepages", diff --git a/mm/filemap.c b/mm/filemap.c index f7ccba83429b..e77e15d08670 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -48,6 +48,8 @@ #include +int want_old_faultaround_pte = 1; + /* * Shared mappings implemented 30.11.1994. It's not fully working yet, * though. @@ -2565,6 +2567,14 @@ void filemap_map_pages(struct vm_fault *vmf, if (vmf->pte) vmf->pte += iter.index - last_pgoff; last_pgoff = iter.index; + + if (want_old_faultaround_pte) { + if (iter.index == vmf->pgoff) + vmf->flags &= ~FAULT_FLAG_PREFAULT_OLD; + else + vmf->flags |= FAULT_FLAG_PREFAULT_OLD; + } + if (alloc_set_pte(vmf, NULL, page)) goto unlock; unlock_page(page); diff --git a/mm/memory.c b/mm/memory.c index d140ba280c1e..90030632a2b5 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3595,6 +3595,10 @@ int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg, entry = mk_pte(page, vmf->vma_page_prot); if (write) entry = maybe_mkwrite(pte_mkdirty(entry), vmf->vma_flags); + + if (vmf->flags & FAULT_FLAG_PREFAULT_OLD) + entry = pte_mkold(entry); + /* copy-on-write page */ if (write && !(vmf->vma_flags & VM_SHARED)) { inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES); -- GitLab From aaf0183b6a92dd61d3eb72fa031447d5197275ab Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 29 Jun 2018 11:19:18 +0530 Subject: [PATCH 0942/1299] drivers: soc: qcom: rpmh: Correctly set dirty flag Currently rpmh dirty flag is set for all cases regardless of data is really updated or not. Correct it to update for only those cases where data is updated. Change-Id: I2c87ffbf1bae23ddd4b4cb7dced213cac267df59 Signed-off-by: Maulik Shah --- drivers/soc/qcom/rpmh.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index aaad9caae0c2..7fbe88a81bd7 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -257,21 +257,28 @@ static struct rpmh_req *cache_rpm_request(struct rpmh_client *rc, switch (state) { case RPMH_ACTIVE_ONLY_STATE: case RPMH_AWAKE_STATE: - if (req->sleep_val != UINT_MAX) + if (req->sleep_val != UINT_MAX) { req->wake_val = cmd->data; + rpm->dirty = true; + } break; case RPMH_WAKE_ONLY_STATE: - req->wake_val = cmd->data; + if (req->wake_val != cmd->data) { + req->wake_val = cmd->data; + rpm->dirty = true; + } break; case RPMH_SLEEP_STATE: - req->sleep_val = cmd->data; + if (req->sleep_val != cmd->data) { + req->sleep_val = cmd->data; + rpm->dirty = true; + } break; default: break; }; unlock: - rpm->dirty = true; spin_unlock_irqrestore(&rpm->lock, flags); return req; -- GitLab From 774378a486fa37ce9ffdb0bd13eca76ef3970870 Mon Sep 17 00:00:00 2001 From: Prateek Sood Date: Mon, 11 Jun 2018 10:51:03 +0530 Subject: [PATCH 0943/1299] ARM: dts: msm: Include msm-id in overlay files for SM6150 Include msm-id in overlay files of all board types of SM6150. Change-Id: Ie28ec8e7a15e6b3f094ba99de0edaa907f964222 Signed-off-by: Prateek Sood --- arch/arm64/boot/dts/qcom/sm6150-cdp-overlay.dts | 1 + arch/arm64/boot/dts/qcom/sm6150-idp-overlay.dts | 1 + arch/arm64/boot/dts/qcom/sm6150-mtp-overlay.dts | 1 + arch/arm64/boot/dts/qcom/sm6150-rumi-overlay.dts | 1 + 4 files changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sm6150-cdp-overlay.dts index 36c64e4d5610..9ddfa9bbc06b 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-cdp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm6150-cdp-overlay.dts @@ -20,5 +20,6 @@ / { model = "Qualcomm Technologies, Inc. SM6150 CDP"; compatible = "qcom,sm6150-cdp", "qcom,sm6150", "qcom,cdp"; + qcom,msm-id = <355 0x0>; qcom,board-id = <1 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sm6150-idp-overlay.dts b/arch/arm64/boot/dts/qcom/sm6150-idp-overlay.dts index 4a3b42b71f70..ae891836ed6b 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-idp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm6150-idp-overlay.dts @@ -20,5 +20,6 @@ / { model = "Qualcomm Technologies, Inc. SM6150 IDP"; compatible = "qcom,sm6150-idp", "qcom,sm6150", "qcom,idp"; + qcom,msm-id = <355 0x0>; qcom,board-id = <34 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sm6150-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sm6150-mtp-overlay.dts index cdb2c0e4e556..b15202a05868 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-mtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm6150-mtp-overlay.dts @@ -20,5 +20,6 @@ / { model = "Qualcomm Technologies, Inc. SM6150 MTP"; compatible = "qcom,sm6150-mtp", "qcom,sm6150", "qcom,mtp"; + qcom,msm-id = <355 0x0>; qcom,board-id = <8 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sm6150-rumi-overlay.dts b/arch/arm64/boot/dts/qcom/sm6150-rumi-overlay.dts index 7b5115ecdb68..47b69d465511 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-rumi-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sm6150-rumi-overlay.dts @@ -20,5 +20,6 @@ / { model = "Qualcomm Technologies, Inc. SM6150 RUMI"; compatible = "qcom,sm6150-rumi", "qcom,sm6150", "qcom,rumi"; + qcom,msm-id = <355 0x0>; qcom,board-id = <15 0>; }; -- GitLab From 3a3dc31602f0309f6d36567b1364bdbb93479bf8 Mon Sep 17 00:00:00 2001 From: Narender Ankam Date: Mon, 18 Jun 2018 16:03:23 +0530 Subject: [PATCH 0944/1299] ARM: dts: msm: add dsi pll device node on qcs405 Add MDSS DSI 28LPM PLL device node on qcs405 target. Change-Id: Icaa5698a2e0d14c5933b153e611fd50526987dcf Signed-off-by: Narender Ankam --- arch/arm64/boot/dts/qcom/qcs405-mdss-pll.dtsi | 86 +++++++++++++++++++ arch/arm64/boot/dts/qcom/qcs405.dtsi | 1 + 2 files changed, 87 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs405-mdss-pll.dtsi diff --git a/arch/arm64/boot/dts/qcom/qcs405-mdss-pll.dtsi b/arch/arm64/boot/dts/qcom/qcs405-mdss-pll.dtsi new file mode 100644 index 000000000000..31243496e78b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs405-mdss-pll.dtsi @@ -0,0 +1,86 @@ +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + mdss_dsi0_pll: qcom,mdss_dsi_pll@1a94a00 { + compatible = "qcom,mdss_dsi_pll_28lpm"; + label = "MDSS DSI 0 PLL"; + cell-index = <0>; + #clock-cells = <1>; + + reg = <0x01a94a00 0xd4>, + <0x0184d074 0x8>; + reg-names = "pll_base", "gdsc_base"; + + clocks = <&clock_gcc GCC_MDSS_AHB_CLK>; + clock-names = "iface_clk"; + clock-rate = <0>; + + gdsc-supply = <&gdsc_mdss>; + + qcom,dsi-pll-ssc-en; + qcom,dsi-pll-ssc-mode = "down-spread"; + qcom,ssc-frequency-hz = <30000>; + qcom,ssc-ppm = <5000>; + + qcom,platform-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,platform-supply-entry@0 { + reg = <0>; + qcom,supply-name = "gdsc"; + qcom,supply-min-voltage = <0>; + qcom,supply-max-voltage = <0>; + qcom,supply-enable-load = <0>; + qcom,supply-disable-load = <0>; + }; + }; + }; + + mdss_dsi1_pll: qcom,mdss_dsi_pll@1a96a00 { + status="disabled"; + compatible = "qcom,mdss_dsi_pll_28lpm"; + label = "MDSS DSI 1 PLL"; + cell-index = <1>; + #clock-cells = <1>; + + reg = <0x01a96a00 0xd4>, + <0x0184d074 0x8>; + reg-names = "pll_base", "gdsc_base"; + + clocks = <&clock_gcc GCC_MDSS_AHB_CLK>; + clock-names = "iface_clk"; + clock-rate = <0>; + + gdsc-supply = <&gdsc_mdss>; + + qcom,dsi-pll-ssc-en; + qcom,dsi-pll-ssc-mode = "down-spread"; + qcom,ssc-frequency-hz = <30000>; + qcom,ssc-ppm = <5000>; + + qcom,platform-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,platform-supply-entry@0 { + reg = <0>; + qcom,supply-name = "gdsc"; + qcom,supply-min-voltage = <0>; + qcom,supply-max-voltage = <0>; + qcom,supply-enable-load = <0>; + qcom,supply-disable-load = <0>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 927b205c6929..7a7c900f3641 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -119,6 +119,7 @@ #include "qcs405-pm.dtsi" #include "msm-arm-smmu-qcs405.dtsi" #include "qcs405-gpu.dtsi" +#include "qcs405-mdss-pll.dtsi" &soc { #address-cells = <1>; -- GitLab From 08d732093785f985741f051ae14a1679578c0fec Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Fri, 20 May 2016 16:58:44 -0700 Subject: [PATCH 0945/1299] mm: disable fault around on emulated access bit architecture fault_around aims to reduce minor faults of file-backed pages via speculative ahead pte mapping and relying on readahead logic. However, on non-HW access bit architecture the benefit is highly limited because they should emulate the young bit with minor faults for reclaim's page aging algorithm. IOW, we cannot reduce minor faults on those architectures. I did quick a test on my ARM machine. 512M file mmap sequential every word read on eSATA drive 4 times. stddev is stable. = fault_around 4096 = elapsed time(usec): 6747645 = fault_around 65536 = elapsed time(usec): 6709263 0.5% gain. Even when I tested it with eMMC there is no gain because I guess with slow storage the major fault is the dominant factor. Also, fault_around has the side effect of shrinking slab more aggressively and causes higher vmpressure, so if such speculation fails, it can evict slab more which can result in page I/O (e.g., inode cache). In the end, it would make void any benefit of fault_around. So let's make the default "disabled" on those architectures. Change-Id: I5e6b74943c95f6779b3a6e463b4d0a8b27eaac01 Link: http://lkml.kernel.org/r/20160518014229.GB21538@bbox Signed-off-by: Minchan Kim Cc: Kirill A. Shutemov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Git-commit: d0834a6c2c5b0c76cfb806bd7dba6556d8b4edbb Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git [vinmenon@codeaurora.org: trivial merge conflict fixes] Signed-off-by: Vinayak Menon --- mm/memory.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mm/memory.c b/mm/memory.c index 90030632a2b5..b41012b9f5c2 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3657,8 +3657,16 @@ int finish_fault(struct vm_fault *vmf) return ret; } +/* + * If architecture emulates "accessed" or "young" bit without HW support, + * there is no much gain with fault_around. + */ static unsigned long fault_around_bytes __read_mostly = +#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS + PAGE_SIZE; +#else rounddown_pow_of_two(65536); +#endif #ifdef CONFIG_DEBUG_FS static int fault_around_bytes_get(void *data, u64 *val) -- GitLab From c29ede6917dd557be8722fc34ca9e4d2ffd51f1f Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Wed, 13 Jun 2018 20:59:29 +0530 Subject: [PATCH 0946/1299] ion: invalidate the pool pointers after free ion_system_heap_destroy_pools frees the pool, but does not invalidate the pointer. This can result in a double free if ion_system_heap_create_pools fails, and then causes ion_system_heap_create to call into ion_system_heap_destroy_pools again from the error path. This can happen in ion_system_heap_create when one of the secure pool creation fails. Change-Id: Ic73ca78722aa5a575cc4dd7c1caa560b518094f2 Signed-off-by: Vinayak Menon --- drivers/staging/android/ion/ion_system_heap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 1eaa9531413d..3accf2536817 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -2,7 +2,7 @@ * drivers/staging/android/ion/ion_system_heap.c * * Copyright (C) 2011 Google, Inc. - * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -587,8 +587,10 @@ static void ion_system_heap_destroy_pools(struct ion_page_pool **pools) int i; for (i = 0; i < NUM_ORDERS; i++) - if (pools[i]) + if (pools[i]) { ion_page_pool_destroy(pools[i]); + pools[i] = NULL; + } } /** -- GitLab From 4a928165242574c982cea4eec8c430e2489e136a Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Fri, 22 Jun 2018 17:18:58 -0700 Subject: [PATCH 0947/1299] iommu: arm-smmu: Add fault syndrome register-1 support The context bank Fault Syndrome Register 1, FSYNR1 is implementation defined. Add support for printing the FSYNR1 info during context fault. For targets that has this register unimplemented, the CPU read is RAZ. This can be interpreted as 'unimplemented' with the known knowledge that FSYNR1 is not implemented on the current target in use. Change-Id: Icb831a074511365af64bd3ab635fed15c2e53224 Signed-off-by: Sudarshan Rajagopalan --- drivers/iommu/arm-smmu-regs.h | 1 + drivers/iommu/arm-smmu.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/arm-smmu-regs.h b/drivers/iommu/arm-smmu-regs.h index bbdcd393ab3c..e82b686890a6 100644 --- a/drivers/iommu/arm-smmu-regs.h +++ b/drivers/iommu/arm-smmu-regs.h @@ -179,6 +179,7 @@ enum arm_smmu_s2cr_privcfg { #define ARM_SMMU_CB_FSRRESTORE 0x5c #define ARM_SMMU_CB_FAR 0x60 #define ARM_SMMU_CB_FSYNR0 0x68 +#define ARM_SMMU_CB_FSYNR1 0x6c #define ARM_SMMU_CB_S1_TLBIVA 0x600 #define ARM_SMMU_CB_S1_TLBIASID 0x610 #define ARM_SMMU_CB_S1_TLBIALL 0x618 diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index d2629d41078a..6727f9e99868 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1260,7 +1260,7 @@ static phys_addr_t arm_smmu_verify_fault(struct iommu_domain *domain, static irqreturn_t arm_smmu_context_fault(int irq, void *dev) { int flags, ret, tmp; - u32 fsr, fsynr, resume; + u32 fsr, fsynr0, fsynr1, frsynra, resume; unsigned long iova; struct iommu_domain *domain = dev; struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); @@ -1270,7 +1270,6 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) void __iomem *gr1_base; bool fatal_asf = smmu->options & ARM_SMMU_OPT_FATAL_ASF; phys_addr_t phys_soft; - u32 frsynra; bool non_fatal_fault = !!(smmu_domain->attributes & (1 << DOMAIN_ATTR_NON_FATAL_FAULTS)); @@ -1297,8 +1296,9 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) BUG(); } - fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0); - flags = fsynr & FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ; + fsynr0 = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0); + fsynr1 = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR1); + flags = fsynr0 & FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ; if (fsr & FSR_TF) flags |= IOMMU_FAULT_TRANSLATION; if (fsr & FSR_PF) @@ -1315,8 +1315,8 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) tmp = report_iommu_fault(domain, smmu->dev, iova, flags); if (!tmp || (tmp == -EBUSY)) { dev_dbg(smmu->dev, - "Context fault handled by client: iova=0x%08lx, fsr=0x%x, fsynr=0x%x, cb=%d\n", - iova, fsr, fsynr, cfg->cbndx); + "Context fault handled by client: iova=0x%08lx, cb=%d, fsr=0x%x, fsynr0=0x%x, fsynr1=0x%x\n", + iova, cfg->cbndx, fsr, fsynr0, fsynr1); dev_dbg(smmu->dev, "soft iova-to-phys=%pa\n", &phys_soft); ret = IRQ_HANDLED; @@ -1326,8 +1326,8 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) fsr); if (__ratelimit(&_rs)) { dev_err(smmu->dev, - "Unhandled context fault: iova=0x%08lx, fsr=0x%x, fsynr=0x%x, cb=%d\n", - iova, fsr, fsynr, cfg->cbndx); + "Unhandled context fault: iova=0x%08lx, cb=%d, fsr=0x%x, fsynr0=0x%x, fsynr1=0x%x\n", + iova, cfg->cbndx, fsr, fsynr0, fsynr1); dev_err(smmu->dev, "FAR = %016lx\n", (unsigned long)iova); dev_err(smmu->dev, -- GitLab From 3e735bc9f9c8ec1b33bff5bb74f6dfd14a4ea989 Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Thu, 14 Jun 2018 11:40:55 +0530 Subject: [PATCH 0948/1299] defconfig: msm: Enable QUSB PHY for SM6150 Enable QUSB PHY driver for SM6150. Change-Id: I37038705e7a948f5340708e42914ace5132db242 Signed-off-by: Pratham Pratap --- arch/arm64/configs/vendor/sdmsteppe-perf_defconfig | 1 + arch/arm64/configs/vendor/sdmsteppe_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index 483079168e77..442fa4c939eb 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -391,6 +391,7 @@ CONFIG_USB_ISP1760_HOST_ROLE=y CONFIG_NOP_USB_XCEIV=y CONFIG_USB_QCOM_EMU_PHY=y CONFIG_USB_MSM_SSPHY_QMP=y +CONFIG_MSM_QUSB_PHY=y CONFIG_MSM_HSUSB_PHY=y CONFIG_DUAL_ROLE_USB_INTF=y CONFIG_USB_GADGET=y diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index efb59b304f8c..edbe263d1a4d 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -402,6 +402,7 @@ CONFIG_USB_ISP1760_HOST_ROLE=y CONFIG_NOP_USB_XCEIV=y CONFIG_USB_QCOM_EMU_PHY=y CONFIG_USB_MSM_SSPHY_QMP=y +CONFIG_MSM_QUSB_PHY=y CONFIG_MSM_HSUSB_PHY=y CONFIG_DUAL_ROLE_USB_INTF=y CONFIG_USB_GADGET=y -- GitLab From 87d7e03d144a319d1009a824464329df3c4f1985 Mon Sep 17 00:00:00 2001 From: Vijaykumar Badiger Date: Tue, 26 Jun 2018 08:34:49 -0700 Subject: [PATCH 0949/1299] ARM: dts: msm: rename automotive device tree files for SA8155 Rename the Automotive device tree file names from sa8150 to sa8155. Change-Id: If875374b1d6944827cf9819fa1d03e1d4f7b7d1e Signed-off-by: Vijaykumar Badiger --- .../devicetree/bindings/arm/msm/msm.txt | 4 ++-- arch/arm64/boot/dts/qcom/Makefile | 12 ++++++------ ...r-overlay.dts => sa8155-adp-star-overlay.dts} | 4 ++-- .../{sa8150-adp-star.dts => sa8155-adp-star.dts} | 8 ++++---- ...sa8150-adp-star.dtsi => sa8155-adp-star.dtsi} | 2 +- ...mic-overlay.dtsi => sa8155-pmic-overlay.dtsi} | 0 ...8150-regulator.dtsi => sa8155-regulator.dtsi} | 0 .../boot/dts/qcom/{sa8150.dts => sa8155.dts} | 6 +++--- .../boot/dts/qcom/{sa8150.dtsi => sa8155.dtsi} | 12 ++++++------ ...-overlay.dts => sa8155p-adp-star-overlay.dts} | 4 ++-- ...sa8150p-adp-star.dts => sa8155p-adp-star.dts} | 8 ++++---- .../boot/dts/qcom/{sa8150p.dts => sa8155p.dts} | 6 +++--- .../boot/dts/qcom/{sa8150p.dtsi => sa8155p.dtsi} | 8 ++++---- drivers/soc/qcom/socinfo.c | 16 ++++++++-------- include/soc/qcom/socinfo.h | 16 ++++++++-------- 15 files changed, 53 insertions(+), 53 deletions(-) rename arch/arm64/boot/dts/qcom/{sa8150-adp-star-overlay.dts => sa8155-adp-star-overlay.dts} (87%) rename arch/arm64/boot/dts/qcom/{sa8150-adp-star.dts => sa8155-adp-star.dts} (78%) rename arch/arm64/boot/dts/qcom/{sa8150-adp-star.dtsi => sa8155-adp-star.dtsi} (98%) rename arch/arm64/boot/dts/qcom/{sa8150-pmic-overlay.dtsi => sa8155-pmic-overlay.dtsi} (100%) rename arch/arm64/boot/dts/qcom/{sa8150-regulator.dtsi => sa8155-regulator.dtsi} (100%) rename arch/arm64/boot/dts/qcom/{sa8150.dts => sa8155.dts} (85%) rename arch/arm64/boot/dts/qcom/{sa8150.dtsi => sa8155.dtsi} (96%) rename arch/arm64/boot/dts/qcom/{sa8150p-adp-star-overlay.dts => sa8155p-adp-star-overlay.dts} (87%) rename arch/arm64/boot/dts/qcom/{sa8150p-adp-star.dts => sa8155p-adp-star.dts} (77%) rename arch/arm64/boot/dts/qcom/{sa8150p.dts => sa8155p.dts} (84%) rename arch/arm64/boot/dts/qcom/{sa8150p.dtsi => sa8155p.dtsi} (81%) diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index 00b5ef73fe31..1741ef5653cc 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -163,8 +163,8 @@ compatible = "qcom,sm6150-idp" compatible = "qcom,qcs405-rumi" compatible = "qcom,qcs405-iot" compatible = "qcom,qcs403-iot" -compatible = "qcom,sa8150-adp-star" -compatible = "qcom,sa8150p-adp-star" +compatible = "qcom,sa8155-adp-star" +compatible = "qcom,sa8155p-adp-star" compatible = "qcom,adp-star" compatible = "qcom,sdxprairie-rumi" compatible = "qcom,sdxprairie-mtp" diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 3905ad363267..ee0aacda55d1 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -25,8 +25,8 @@ ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y) sm8150-rumi-overlay.dtbo \ sm8150-qrd-overlay.dtbo \ sm8150-qrd-dvt-overlay.dtbo \ - sa8150-adp-star-overlay.dtbo \ - sa8150p-adp-star-overlay.dtbo \ + sa8155-adp-star-overlay.dtbo \ + sa8155p-adp-star-overlay.dtbo \ sm8150p-cdp-overlay.dtbo \ sm8150p-mtp-overlay.dtbo \ sm8150p-qrd-overlay.dtbo \ @@ -40,8 +40,8 @@ sm8150-mtp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-rumi-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-qrd-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-qrd-dvt-overlay.dtbo-base := sm8150-v2.dtb -sa8150-adp-star-overlay.dtbo-base := sa8150.dtb -sa8150p-adp-star-overlay.dtbo-base := sa8150p.dtb +sa8155-adp-star-overlay.dtbo-base := sa8155.dtb +sa8155p-adp-star-overlay.dtbo-base := sa8155p.dtb sm8150-sdx50m-cdp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-sdx50m-mtp-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb sm8150-sdx50m-mtp-2.5k-panel-overlay.dtbo-base := sm8150.dtb sm8150-v2.dtb @@ -53,8 +53,8 @@ dtb-$(CONFIG_ARCH_SM8150) += sm8150-rumi.dtb \ sm8150-mtp.dtb \ sm8150-cdp.dtb \ sm8150-qrd.dtb \ - sa8150-adp-star.dtb \ - sa8150p-adp-star.dtb \ + sa8155-adp-star.dtb \ + sa8155p-adp-star.dtb \ sm8150-v2-rumi.dtb \ sm8150-v2-mtp.dtb \ sm8150-v2-cdp.dtb \ diff --git a/arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts b/arch/arm64/boot/dts/qcom/sa8155-adp-star-overlay.dts similarity index 87% rename from arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts rename to arch/arm64/boot/dts/qcom/sa8155-adp-star-overlay.dts index 627e06a4d415..611d29151e37 100644 --- a/arch/arm64/boot/dts/qcom/sa8150-adp-star-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sa8155-adp-star-overlay.dts @@ -13,11 +13,11 @@ /dts-v1/; /plugin/; -#include "sa8150-adp-star.dtsi" +#include "sa8155-adp-star.dtsi" / { model = "ADP-STAR"; - compatible = "qcom,sa8150-adp-star", "qcom,sa8150", + compatible = "qcom,sa8155-adp-star", "qcom,sa8155", "qcom,adp-star"; qcom,board-id = <25 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sa8150-adp-star.dts b/arch/arm64/boot/dts/qcom/sa8155-adp-star.dts similarity index 78% rename from arch/arm64/boot/dts/qcom/sa8150-adp-star.dts rename to arch/arm64/boot/dts/qcom/sa8155-adp-star.dts index 9b104006e485..d4322630a3a0 100644 --- a/arch/arm64/boot/dts/qcom/sa8150-adp-star.dts +++ b/arch/arm64/boot/dts/qcom/sa8155-adp-star.dts @@ -11,12 +11,12 @@ */ /dts-v1/; -#include "sa8150.dtsi" -#include "sa8150-adp-star.dtsi" +#include "sa8155.dtsi" +#include "sa8155-adp-star.dtsi" / { - model = "Qualcomm Technologies, Inc. SA8150 ADP-STAR"; - compatible = "qcom,sa8150-adp-star", "qcom,sa8150", + model = "Qualcomm Technologies, Inc. SA8155 ADP-STAR"; + compatible = "qcom,sa8155-adp-star", "qcom,sa8155", "qcom,adp-star"; qcom,board-id = <25 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sa8150-adp-star.dtsi b/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi similarity index 98% rename from arch/arm64/boot/dts/qcom/sa8150-adp-star.dtsi rename to arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi index 9631fbec0aa7..df8fb4d394b6 100644 --- a/arch/arm64/boot/dts/qcom/sa8150-adp-star.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi @@ -13,7 +13,7 @@ #include #include -#include "sa8150-pmic-overlay.dtsi" +#include "sa8155-pmic-overlay.dtsi" &qupv3_se0_spi { status = "ok"; diff --git a/arch/arm64/boot/dts/qcom/sa8150-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sa8155-pmic-overlay.dtsi similarity index 100% rename from arch/arm64/boot/dts/qcom/sa8150-pmic-overlay.dtsi rename to arch/arm64/boot/dts/qcom/sa8155-pmic-overlay.dtsi diff --git a/arch/arm64/boot/dts/qcom/sa8150-regulator.dtsi b/arch/arm64/boot/dts/qcom/sa8155-regulator.dtsi similarity index 100% rename from arch/arm64/boot/dts/qcom/sa8150-regulator.dtsi rename to arch/arm64/boot/dts/qcom/sa8155-regulator.dtsi diff --git a/arch/arm64/boot/dts/qcom/sa8150.dts b/arch/arm64/boot/dts/qcom/sa8155.dts similarity index 85% rename from arch/arm64/boot/dts/qcom/sa8150.dts rename to arch/arm64/boot/dts/qcom/sa8155.dts index cc1ce1f51a3e..0fbb4769485b 100644 --- a/arch/arm64/boot/dts/qcom/sa8150.dts +++ b/arch/arm64/boot/dts/qcom/sa8155.dts @@ -12,11 +12,11 @@ /dts-v1/; -#include "sa8150.dtsi" +#include "sa8155.dtsi" / { - model = "Qualcomm Technologies, Inc. SA8150 SoC"; - compatible = "qcom,sa8150"; + model = "Qualcomm Technologies, Inc. SA8155 SoC"; + compatible = "qcom,sa8155"; qcom,pmic-name = "PM8150"; qcom,board-id = <0 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sa8150.dtsi b/arch/arm64/boot/dts/qcom/sa8155.dtsi similarity index 96% rename from arch/arm64/boot/dts/qcom/sa8150.dtsi rename to arch/arm64/boot/dts/qcom/sa8155.dtsi index 1208a338712d..c404b40d1823 100644 --- a/arch/arm64/boot/dts/qcom/sa8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155.dtsi @@ -13,13 +13,13 @@ #include "sm8150.dtsi" / { - model = "Qualcomm Technologies, Inc. SA8150"; - compatible = "qcom,sa8150"; - qcom,msm-name = "SA8150"; + model = "Qualcomm Technologies, Inc. SA8155"; + compatible = "qcom,sa8155"; + qcom,msm-name = "SA8155"; qcom,msm-id = <362 0x10000>; }; -/* Remove regulator nodes specific to SA8150 */ +/* Remove regulator nodes specific to SA8155 */ &soc { /delete-node/ regulator-pm8150-s4; /delete-node/ rpmh-regulator-msslvl; @@ -68,8 +68,8 @@ /delete-node/ rpmh-regulator-ldof6; }; -/* Add regulator nodes specific to SA8150 */ -#include "sa8150-regulator.dtsi" +/* Add regulator nodes specific to SA8155 */ +#include "sa8155-regulator.dtsi" &cam_csiphy0 { mipi-csi-vdd-supply = <&pm8150_2_l8>; diff --git a/arch/arm64/boot/dts/qcom/sa8150p-adp-star-overlay.dts b/arch/arm64/boot/dts/qcom/sa8155p-adp-star-overlay.dts similarity index 87% rename from arch/arm64/boot/dts/qcom/sa8150p-adp-star-overlay.dts rename to arch/arm64/boot/dts/qcom/sa8155p-adp-star-overlay.dts index bcef0c4fade5..298df1df8ad1 100644 --- a/arch/arm64/boot/dts/qcom/sa8150p-adp-star-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sa8155p-adp-star-overlay.dts @@ -13,11 +13,11 @@ /dts-v1/; /plugin/; -#include "sa8150-adp-star.dtsi" +#include "sa8155-adp-star.dtsi" / { model = "ADP-STAR"; - compatible = "qcom,sa8150p-adp-star", "qcom,sa8150p", + compatible = "qcom,sa8155p-adp-star", "qcom,sa8155p", "qcom,adp-star"; qcom,board-id = <25 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sa8150p-adp-star.dts b/arch/arm64/boot/dts/qcom/sa8155p-adp-star.dts similarity index 77% rename from arch/arm64/boot/dts/qcom/sa8150p-adp-star.dts rename to arch/arm64/boot/dts/qcom/sa8155p-adp-star.dts index c51111d077c5..8a7aaea2e24c 100644 --- a/arch/arm64/boot/dts/qcom/sa8150p-adp-star.dts +++ b/arch/arm64/boot/dts/qcom/sa8155p-adp-star.dts @@ -11,12 +11,12 @@ */ /dts-v1/; -#include "sa8150p.dtsi" -#include "sa8150-adp-star.dtsi" +#include "sa8155p.dtsi" +#include "sa8155-adp-star.dtsi" / { - model = "Qualcomm Technologies, Inc. SA8150P ADP-STAR"; - compatible = "qcom,sa8150p-adp-star", "qcom,sa8150p", + model = "Qualcomm Technologies, Inc. SA8155P ADP-STAR"; + compatible = "qcom,sa8155p-adp-star", "qcom,sa8155p", "qcom,adp-star"; qcom,board-id = <25 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sa8150p.dts b/arch/arm64/boot/dts/qcom/sa8155p.dts similarity index 84% rename from arch/arm64/boot/dts/qcom/sa8150p.dts rename to arch/arm64/boot/dts/qcom/sa8155p.dts index ad2069a8e223..fc7a5e9f0daa 100644 --- a/arch/arm64/boot/dts/qcom/sa8150p.dts +++ b/arch/arm64/boot/dts/qcom/sa8155p.dts @@ -12,11 +12,11 @@ /dts-v1/; -#include "sa8150p.dtsi" +#include "sa8155p.dtsi" / { - model = "Qualcomm Technologies, Inc. SA8150P SoC"; - compatible = "qcom,sa8150p"; + model = "Qualcomm Technologies, Inc. SA8155P SoC"; + compatible = "qcom,sa8155p"; qcom,pmic-name = "PM8150"; qcom,board-id = <0 0>; }; diff --git a/arch/arm64/boot/dts/qcom/sa8150p.dtsi b/arch/arm64/boot/dts/qcom/sa8155p.dtsi similarity index 81% rename from arch/arm64/boot/dts/qcom/sa8150p.dtsi rename to arch/arm64/boot/dts/qcom/sa8155p.dtsi index 4b4b42dd567d..9b49c4fbd11b 100644 --- a/arch/arm64/boot/dts/qcom/sa8150p.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155p.dtsi @@ -10,11 +10,11 @@ * GNU General Public License for more details. */ -#include "sa8150.dtsi" +#include "sa8155.dtsi" / { - model = "Qualcomm Technologies, Inc. SA8150P "; - qcom,msm-name = "SA8150P"; - compatible = "qcom,sa8150p"; + model = "Qualcomm Technologies, Inc. SA8155P "; + qcom,msm-name = "SA8155P"; + compatible = "qcom,sa8155p"; qcom,msm-id = <367 0x10000>; }; diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index bd11f28cb4ae..3888b3c30a07 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -307,11 +307,11 @@ static struct msm_soc_info cpu_of_id[] = { /* sm8150 ID */ [339] = {MSM_CPU_SM8150, "SM8150"}, - /* sa8150 ID */ - [362] = {MSM_CPU_SA8150, "SA8150"}, + /* sa8155 ID */ + [362] = {MSM_CPU_SA8155, "SA8155"}, - /* sa8150P ID */ - [367] = {MSM_CPU_SA8150P, "SA8150P"}, + /* sa8155P ID */ + [367] = {MSM_CPU_SA8155P, "SA8155P"}, /* sdmshrike ID */ [340] = {MSM_CPU_SDMSHRIKE, "SDMSHRIKE"}, @@ -1183,13 +1183,13 @@ static void * __init setup_dummy_socinfo(void) dummy_socinfo.id = 339; strlcpy(dummy_socinfo.build_id, "sm8150 - ", sizeof(dummy_socinfo.build_id)); - } else if (early_machine_is_sa8150()) { + } else if (early_machine_is_sa8155()) { dummy_socinfo.id = 362; - strlcpy(dummy_socinfo.build_id, "sa8150 - ", + strlcpy(dummy_socinfo.build_id, "sa8155 - ", sizeof(dummy_socinfo.build_id)); - } else if (early_machine_is_sa8150p()) { + } else if (early_machine_is_sa8155p()) { dummy_socinfo.id = 367; - strlcpy(dummy_socinfo.build_id, "sa8150p - ", + strlcpy(dummy_socinfo.build_id, "sa8155p - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sdmshrike()) { dummy_socinfo.id = 340; diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h index 0a67a9e13c22..872cf496536a 100644 --- a/include/soc/qcom/socinfo.h +++ b/include/soc/qcom/socinfo.h @@ -59,10 +59,10 @@ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8996-cdp") #define early_machine_is_sm8150() \ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sm8150") -#define early_machine_is_sa8150() \ - of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sa8150") -#define early_machine_is_sa8150p() \ - of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sa8150p") +#define early_machine_is_sa8155() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sa8155") +#define early_machine_is_sa8155p() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sa8155p") #define early_machine_is_sdmshrike() \ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdmshrike") #define early_machine_is_sm6150() \ @@ -92,8 +92,8 @@ #define early_machine_is_apq8084() 0 #define early_machine_is_msm8996() 0 #define early_machine_is_sm8150() 0 -#define early_machine_is_sa8150() 0 -#define early_machine_is_sa8150p() 0 +#define early_machine_is_sa8155() 0 +#define early_machine_is_sa8155p() 0 #define early_machine_is_sdmshrike() 0 #define early_machine_is_sm6150() 0 #define early_machine_is_qcs405() 0 @@ -120,8 +120,8 @@ enum msm_cpu { MSM_CPU_8084, MSM_CPU_8996, MSM_CPU_SM8150, - MSM_CPU_SA8150, - MSM_CPU_SA8150P, + MSM_CPU_SA8155, + MSM_CPU_SA8155P, MSM_CPU_SDMSHRIKE, MSM_CPU_SM6150, MSM_CPU_QCS405, -- GitLab From 685351ad26f6980d2d27dece5978451fb9dd7eb9 Mon Sep 17 00:00:00 2001 From: Anirudh Ghayal Date: Wed, 27 Jun 2018 12:04:57 +0530 Subject: [PATCH 0950/1299] power: qpnp-qg: Update the QPNP QG driver from 4.9 kernel This implementation is based on snapshot of msm-4.9 commit 42e1de365776 ("ARM: dts: msm: Enable the dpdm-supply node for MSM8917/37"). Change-Id: I61c6a21f8e5a47b02387a1dfbeeed4bb821da139 Signed-off-by: Anirudh Ghayal --- .../bindings/power/supply/qcom/qpnp-qg.txt | 39 + .../power/supply/qcom/qg-battery-profile.c | 8 +- drivers/power/supply/qcom/qg-core.h | 36 + drivers/power/supply/qcom/qg-defs.h | 4 + drivers/power/supply/qcom/qg-reg.h | 47 +- drivers/power/supply/qcom/qg-sdam.c | 33 +- drivers/power/supply/qcom/qg-sdam.h | 4 + drivers/power/supply/qcom/qg-util.c | 16 + drivers/power/supply/qcom/qg-util.h | 1 + drivers/power/supply/qcom/qpnp-qg.c | 998 ++++++++++++++++-- include/uapi/linux/qg-profile.h | 2 + include/uapi/linux/qg.h | 18 +- 12 files changed, 1066 insertions(+), 140 deletions(-) diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt index afeb65dc86d0..0da71a3e163f 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt +++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt @@ -262,6 +262,45 @@ First Level Node - QGAUGE device capacity learning cycle. If this is not specified, then the default value is 0. Unit is in decipercentage. +- qcom,esr-disable + Usage: optional + Value type: + Definition: Boolean property to disable ESR estimation. If not defined + ESR estimation stays enabled for charge-cycles. + +- qcom,esr-discharge-enable + Usage: optional + Value type: + Definition: Boolean property to enable ESR estimation during discharge. + Only valid if 'qcom,esr-disable' is not defined. + +- qcom,esr-qual-current-ua + Usage: optional + Value type: + Definition: Minimum current differential in uA to qualify an ESR + reading as valid. If not defined the value defaults + to 130mA. + +- qcom,esr-qual-vbatt-uv + Usage: optional + Value type: + Definition: Minimum vbatt differential in uV to qualify an ESR + reading as valid. If not defined the value defaults + to 7mV. + +- qcom,esr-disable-soc + Usage: optional + Value type: + Definition: Minimum battery SOC below which ESR will not be + attempted by QG. If not defined the value defaults + to 10%. + +- qcom,qg-ext-sns + Usage: optional + Value type: + Definition: Boolean property to support external-rsense based + configuration. + ========================================================== Second Level Nodes - Peripherals managed by QGAUGE driver ========================================================== diff --git a/drivers/power/supply/qcom/qg-battery-profile.c b/drivers/power/supply/qcom/qg-battery-profile.c index c1f10977a508..beb6f519539e 100644 --- a/drivers/power/supply/qcom/qg-battery-profile.c +++ b/drivers/power/supply/qcom/qg-battery-profile.c @@ -398,10 +398,8 @@ int lookup_soc_ocv(u32 *soc, u32 ocv_uv, int batt_temp, bool charging) { u8 table_index = charging ? TABLE_SOC_OCV1 : TABLE_SOC_OCV2; - if (!the_battery || !the_battery->profile_node) { - pr_err("Battery profile not loaded\n"); + if (!the_battery || !the_battery->profile_node) return -ENODEV; - } *soc = interpolate_soc(&the_battery->profile[table_index], batt_temp, UV_TO_DECIUV(ocv_uv)); @@ -416,10 +414,8 @@ int qg_get_nominal_capacity(u32 *nom_cap_uah, int batt_temp, bool charging) u8 table_index = charging ? TABLE_FCC1 : TABLE_FCC2; u32 fcc_mah; - if (!the_battery || !the_battery->profile_node) { - pr_err("Battery profile not loaded\n"); + if (!the_battery || !the_battery->profile_node) return -ENODEV; - } fcc_mah = interpolate_single_row_lut( &the_battery->profile[table_index], diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h index 1591aa15a79a..54ef074f5fd9 100644 --- a/drivers/power/supply/qcom/qg-core.h +++ b/drivers/power/supply/qcom/qg-core.h @@ -14,6 +14,7 @@ #include #include "fg-alg.h" +#include "qg-defs.h" struct qg_batt_props { const char *batt_type_str; @@ -50,10 +51,25 @@ struct qg_dt { int rbat_conn_mohm; int ignore_shutdown_soc_secs; int cold_temp_threshold; + int esr_qual_i_ua; + int esr_qual_v_uv; + int esr_disable_soc; bool hold_soc_while_full; bool linearize_soc; bool cl_disable; bool cl_feedback_on; + bool esr_disable; + bool esr_discharge_enable; + bool qg_ext_sense; +}; + +struct qg_esr_data { + u32 pre_esr_v; + u32 pre_esr_i; + u32 post_esr_v; + u32 post_esr_i; + u32 esr; + bool valid; }; struct qpnp_qg { @@ -87,6 +103,7 @@ struct qpnp_qg { struct power_supply *batt_psy; struct power_supply *usb_psy; struct power_supply *parallel_psy; + struct qg_esr_data esr_data[QG_MAX_ESR_COUNT]; /* status variable */ u32 *debug_mask; @@ -102,10 +119,18 @@ struct qpnp_qg { bool charge_full; int charge_status; int charge_type; + int chg_iterm_ma; int next_wakeup_ms; + int esr_actual; + int esr_nominal; + int soh; + int soc_reporting_ready; + u32 fifo_done_count; u32 wa_flags; u32 seq_no; u32 charge_counter_uah; + u32 esr_avg; + u32 esr_last; ktime_t last_user_update_time; ktime_t last_fifo_update_time; struct iio_channel *batt_therm_chan; @@ -118,6 +143,7 @@ struct qpnp_qg { int pon_soc; int batt_soc; int cc_soc; + int full_soc; struct alarm alarm_timer; u32 sdam_data[SDAM_MAX]; @@ -128,6 +154,14 @@ struct qpnp_qg { struct cap_learning *cl; /* charge counter */ struct cycle_counter *counter; + /* ttf */ + struct ttf *ttf; +}; + +struct ocv_all { + u32 ocv_uv; + u32 ocv_raw; + char ocv_type[20]; }; enum ocv_type { @@ -135,6 +169,7 @@ enum ocv_type { S3_GOOD_OCV, S3_LAST_OCV, SDAM_PON_OCV, + PON_OCV_MAX, }; enum debug_mask { @@ -149,6 +184,7 @@ enum debug_mask { QG_DEBUG_BUS_READ = BIT(8), QG_DEBUG_BUS_WRITE = BIT(9), QG_DEBUG_ALG_CL = BIT(10), + QG_DEBUG_ESR = BIT(11), }; enum qg_irq { diff --git a/drivers/power/supply/qcom/qg-defs.h b/drivers/power/supply/qcom/qg-defs.h index 2061208ad55c..997ff701c77d 100644 --- a/drivers/power/supply/qcom/qg-defs.h +++ b/drivers/power/supply/qcom/qg-defs.h @@ -34,6 +34,7 @@ #define GOOD_OCV_VOTER "GOOD_OCV_VOTER" #define PROFILE_IRQ_DISABLE "NO_PROFILE_IRQ_DISABLE" #define QG_INIT_STATE_IRQ_DISABLE "QG_INIT_STATE_IRQ_DISABLE" +#define TTF_AWAKE_VOTER "TTF_AWAKE_VOTER" #define V_RAW_TO_UV(V_RAW) div_u64(194637ULL * (u64)V_RAW, 1000) #define I_RAW_TO_UA(I_RAW) div_s64(152588LL * (s64)I_RAW, 1000) @@ -44,6 +45,9 @@ #define UV_TO_DECIUV(a) (a / 100) #define DECIUV_TO_UV(a) (a * 100) +#define QG_MAX_ESR_COUNT 10 +#define QG_MIN_ESR_COUNT 2 + #define CAP(min, max, value) \ ((min > value) ? min : ((value > max) ? max : value)) diff --git a/drivers/power/supply/qcom/qg-reg.h b/drivers/power/supply/qcom/qg-reg.h index 66f9be11a7df..e0f400d05cd3 100644 --- a/drivers/power/supply/qcom/qg-reg.h +++ b/drivers/power/supply/qcom/qg-reg.h @@ -17,7 +17,9 @@ #define QG_TYPE 0x0D #define QG_STATUS1_REG 0x08 +#define QG_OK_BIT BIT(7) #define BATTERY_PRESENT_BIT BIT(0) +#define ESR_MEAS_DONE_BIT BIT(4) #define QG_STATUS2_REG 0x09 #define GOOD_OCV_BIT BIT(1) @@ -25,9 +27,13 @@ #define QG_STATUS3_REG 0x0A #define COUNT_FIFO_RT_MASK GENMASK(3, 0) +#define QG_STATUS4_REG 0x0B +#define ESR_MEAS_IN_PROGRESS_BIT BIT(4) + #define QG_INT_RT_STS_REG 0x10 #define FIFO_UPDATE_DONE_RT_STS_BIT BIT(3) #define VBAT_LOW_INT_RT_STS_BIT BIT(1) +#define BATTERY_MISSING_INT_RT_STS_BIT BIT(0) #define QG_INT_LATCHED_STS_REG 0x18 #define FIFO_UPDATE_DONE_INT_LAT_STS_BIT BIT(3) @@ -60,11 +66,25 @@ #define QG_S3_ENTRY_IBAT_THRESHOLD_REG 0x5E #define QG_S3_EXIT_IBAT_THRESHOLD_REG 0x5F +#define QG_S5_OCV_VALIDATE_MEAS_CTL1_REG 0x60 +#define ALLOW_S5_BIT BIT(7) + +#define QG_S7_PON_OCV_MEAS_CTL1_REG 0x64 +#define ADC_CONV_DLY_MASK GENMASK(3, 0) + +#define QG_ESR_MEAS_TRIG_REG 0x68 +#define HW_ESR_MEAS_START_BIT BIT(0) + #define QG_S7_PON_OCV_V_DATA0_REG 0x70 #define QG_S7_PON_OCV_I_DATA0_REG 0x72 #define QG_S3_GOOD_OCV_V_DATA0_REG 0x74 #define QG_S3_GOOD_OCV_I_DATA0_REG 0x76 +#define QG_PRE_ESR_V_DATA0_REG 0x78 +#define QG_PRE_ESR_I_DATA0_REG 0x7A +#define QG_POST_ESR_V_DATA0_REG 0x7C +#define QG_POST_ESR_I_DATA0_REG 0x7E + #define QG_V_ACCUM_DATA0_RT_REG 0x88 #define QG_I_ACCUM_DATA0_RT_REG 0x8B #define QG_ACCUM_CNT_RT_REG 0x8E @@ -80,15 +100,22 @@ #define QG_LAST_S3_SLEEP_V_DATA0_REG 0xCC /* SDAM offsets */ -#define QG_SDAM_VALID_OFFSET 0x46 -#define QG_SDAM_SOC_OFFSET 0x47 -#define QG_SDAM_TEMP_OFFSET 0x48 -#define QG_SDAM_RBAT_OFFSET 0x4A -#define QG_SDAM_OCV_OFFSET 0x4C -#define QG_SDAM_IBAT_OFFSET 0x50 -#define QG_SDAM_TIME_OFFSET 0x54 -#define QG_SDAM_CYCLE_COUNT_OFFSET 0x58 -#define QG_SDAM_LEARNED_CAPACITY_OFFSET 0x68 -#define QG_SDAM_PON_OCV_OFFSET 0x7C +#define QG_SDAM_VALID_OFFSET 0x46 /* 1-byte 0x46 */ +#define QG_SDAM_SOC_OFFSET 0x47 /* 1-byte 0x47 */ +#define QG_SDAM_TEMP_OFFSET 0x48 /* 2-byte 0x48-0x49 */ +#define QG_SDAM_RBAT_OFFSET 0x4A /* 2-byte 0x4A-0x4B */ +#define QG_SDAM_OCV_OFFSET 0x4C /* 4-byte 0x4C-0x4F */ +#define QG_SDAM_IBAT_OFFSET 0x50 /* 4-byte 0x50-0x53 */ +#define QG_SDAM_TIME_OFFSET 0x54 /* 4-byte 0x54-0x57 */ +#define QG_SDAM_CYCLE_COUNT_OFFSET 0x58 /* 16-byte 0x58-0x67 */ +#define QG_SDAM_LEARNED_CAPACITY_OFFSET 0x68 /* 2-byte 0x68-0x69 */ +#define QG_SDAM_ESR_CHARGE_DELTA_OFFSET 0x6A /* 4-byte 0x6A-0x6D */ +#define QG_SDAM_ESR_DISCHARGE_DELTA_OFFSET 0x6E /* 4-byte 0x6E-0x71 */ +#define QG_SDAM_ESR_CHARGE_SF_OFFSET 0x72 /* 2-byte 0x72-0x73 */ +#define QG_SDAM_ESR_DISCHARGE_SF_OFFSET 0x74 /* 2-byte 0x74-0x75 */ +#define QG_SDAM_MAX_OFFSET 0xA4 + +/* Below offset is used by PBS */ +#define QG_SDAM_PON_OCV_OFFSET 0xBC /* 2-byte 0xBC-0xBD */ #endif diff --git a/drivers/power/supply/qcom/qg-sdam.c b/drivers/power/supply/qcom/qg-sdam.c index 7bc4afac1b44..a7cb97e0e53d 100644 --- a/drivers/power/supply/qcom/qg-sdam.c +++ b/drivers/power/supply/qcom/qg-sdam.c @@ -68,6 +68,26 @@ static struct qg_sdam_info sdam_info[] = { .offset = QG_SDAM_PON_OCV_OFFSET, .length = 2, }, + [SDAM_ESR_CHARGE_DELTA] = { + .name = "SDAM_ESR_CHARGE_DELTA", + .offset = QG_SDAM_ESR_CHARGE_DELTA_OFFSET, + .length = 4, + }, + [SDAM_ESR_DISCHARGE_DELTA] = { + .name = "SDAM_ESR_DISCHARGE_DELTA", + .offset = QG_SDAM_ESR_DISCHARGE_DELTA_OFFSET, + .length = 4, + }, + [SDAM_ESR_CHARGE_SF] = { + .name = "SDAM_ESR_CHARGE_SF_OFFSET", + .offset = QG_SDAM_ESR_CHARGE_SF_OFFSET, + .length = 2, + }, + [SDAM_ESR_DISCHARGE_SF] = { + .name = "SDAM_ESR_DISCHARGE_SF_OFFSET", + .offset = QG_SDAM_ESR_DISCHARGE_SF_OFFSET, + .length = 2, + }, }; int qg_sdam_write(u8 param, u32 data) @@ -91,7 +111,7 @@ int qg_sdam_write(u8 param, u32 data) length = sdam_info[param].length; rc = regmap_bulk_write(chip->regmap, offset, (u8 *)&data, length); if (rc < 0) - pr_err("Failed to write offset=%0x4x param=%d value=%d\n", + pr_err("Failed to write offset=%0x4 param=%d value=%d\n", offset, param, data); else pr_debug("QG SDAM write param=%s value=%d\n", @@ -117,11 +137,12 @@ int qg_sdam_read(u8 param, u32 *data) return -EINVAL; } + *data = 0; offset = chip->sdam_base + sdam_info[param].offset; length = sdam_info[param].length; rc = regmap_raw_read(chip->regmap, offset, (u8 *)data, length); if (rc < 0) - pr_err("Failed to read offset=%0x4x param=%d\n", + pr_err("Failed to read offset=%0x4 param=%d\n", offset, param); else pr_debug("QG SDAM read param=%s value=%d\n", @@ -143,11 +164,11 @@ int qg_sdam_multibyte_write(u32 offset, u8 *data, u32 length) offset = chip->sdam_base + offset; rc = regmap_bulk_write(chip->regmap, offset, data, (size_t)length); if (rc < 0) { - pr_err("Failed to write offset=%0x4x value=%d\n", + pr_err("Failed to write offset=%0x4 value=%d\n", offset, *data); } else { for (i = 0; i < length; i++) - pr_debug("QG SDAM write offset=%0x4x value=%d\n", + pr_debug("QG SDAM write offset=%0x4 value=%d\n", offset++, data[i]); } @@ -167,10 +188,10 @@ int qg_sdam_multibyte_read(u32 offset, u8 *data, u32 length) offset = chip->sdam_base + offset; rc = regmap_raw_read(chip->regmap, offset, (u8 *)data, (size_t)length); if (rc < 0) { - pr_err("Failed to read offset=%0x4x\n", offset); + pr_err("Failed to read offset=%0x4\n", offset); } else { for (i = 0; i < length; i++) - pr_debug("QG SDAM read offset=%0x4x value=%d\n", + pr_debug("QG SDAM read offset=%0x4 value=%d\n", offset++, data[i]); } diff --git a/drivers/power/supply/qcom/qg-sdam.h b/drivers/power/supply/qcom/qg-sdam.h index 10e684f8ec40..45218a83776e 100644 --- a/drivers/power/supply/qcom/qg-sdam.h +++ b/drivers/power/supply/qcom/qg-sdam.h @@ -24,6 +24,10 @@ enum qg_sdam_param { SDAM_IBAT_UA, SDAM_TIME_SEC, SDAM_PON_OCV_UV, + SDAM_ESR_CHARGE_DELTA, + SDAM_ESR_DISCHARGE_DELTA, + SDAM_ESR_CHARGE_SF, + SDAM_ESR_DISCHARGE_SF, SDAM_MAX, }; diff --git a/drivers/power/supply/qcom/qg-util.c b/drivers/power/supply/qcom/qg-util.c index 9daa20479d6b..fc4396e7e95a 100644 --- a/drivers/power/supply/qcom/qg-util.c +++ b/drivers/power/supply/qcom/qg-util.c @@ -111,6 +111,22 @@ int qg_masked_write(struct qpnp_qg *chip, int addr, u32 mask, u32 val) return rc; } +int qg_read_raw_data(struct qpnp_qg *chip, int addr, u32 *data) +{ + int rc; + u8 reg[2] = {0}; + + rc = qg_read(chip, chip->qg_base + addr, ®[0], 2); + if (rc < 0) { + pr_err("Failed to read QG addr %d rc=%d\n", addr, rc); + return rc; + } + + *data = reg[0] | (reg[1] << 8); + + return rc; +} + int get_fifo_length(struct qpnp_qg *chip, u32 *fifo_length, bool rt) { int rc; diff --git a/drivers/power/supply/qcom/qg-util.h b/drivers/power/supply/qcom/qg-util.h index 385c9e072562..bb17afb4f5be 100644 --- a/drivers/power/supply/qcom/qg-util.h +++ b/drivers/power/supply/qcom/qg-util.h @@ -15,6 +15,7 @@ int qg_read(struct qpnp_qg *chip, u32 addr, u8 *val, int len); int qg_write(struct qpnp_qg *chip, u32 addr, u8 *val, int len); int qg_masked_write(struct qpnp_qg *chip, int addr, u32 mask, u32 val); +int qg_read_raw_data(struct qpnp_qg *chip, int addr, u32 *data); int get_fifo_length(struct qpnp_qg *chip, u32 *fifo_length, bool rt); int get_sample_count(struct qpnp_qg *chip, u32 *sample_count); int get_sample_interval(struct qpnp_qg *chip, u32 *sample_interval); diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index d111259f3ee8..bf7f00c7f164 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -25,11 +25,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "fg-alg.h" #include "qg-sdam.h" #include "qg-core.h" @@ -44,6 +46,16 @@ module_param_named( debug_mask, qg_debug_mask, int, 0600 ); +static int qg_esr_mod_count = 10; +module_param_named( + esr_mod_count, qg_esr_mod_count, int, 0600 +); + +static int qg_esr_count = 5; +module_param_named( + esr_count, qg_esr_count, int, 0600 +); + static bool is_battery_present(struct qpnp_qg *chip) { u8 reg = 0; @@ -212,6 +224,14 @@ static void qg_notify_charger(struct qpnp_qg *chip) } pr_debug("Notified charger on float voltage and FCC\n"); + + rc = power_supply_get_property(chip->batt_psy, + POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, &prop); + if (rc < 0) { + pr_err("Failed to get charge term current, rc=%d\n", rc); + return; + } + chip->chg_iterm_ma = prop.intval; } static bool is_batt_available(struct qpnp_qg *chip) @@ -229,7 +249,7 @@ static bool is_batt_available(struct qpnp_qg *chip) return true; } -static int qg_update_sdam_params(struct qpnp_qg *chip) +static int qg_store_soc_params(struct qpnp_qg *chip) { int rc, batt_temp = 0, i; unsigned long rtc_sec = 0; @@ -246,13 +266,11 @@ static int qg_update_sdam_params(struct qpnp_qg *chip) else chip->sdam_data[SDAM_TEMP] = (u32)batt_temp; - rc = qg_sdam_write_all(chip->sdam_data); - if (rc < 0) - pr_err("Failed to write to SDAM rc=%d\n", rc); - - for (i = 0; i < SDAM_MAX; i++) + for (i = 0; i <= SDAM_TIME_SEC; i++) { + rc |= qg_sdam_write(i, chip->sdam_data[i]); qg_dbg(chip, QG_DEBUG_STATUS, "SDAM write param %d value=%d\n", i, chip->sdam_data[i]); + } return rc; } @@ -434,6 +452,90 @@ static int qg_process_rt_fifo(struct qpnp_qg *chip) return rc; } +#define MIN_FIFO_FULL_TIME_MS 12000 +static int process_rt_fifo_data(struct qpnp_qg *chip, + bool update_vbat_low, bool update_smb) +{ + int rc = 0; + ktime_t now = ktime_get(); + s64 time_delta; + u8 fifo_length; + + /* + * Reject the FIFO read event if there are back-to-back requests + * This is done to gaurantee that there is always a minimum FIFO + * data to be processed, ignore this if vbat_low is set. + */ + time_delta = ktime_ms_delta(now, chip->last_user_update_time); + + qg_dbg(chip, QG_DEBUG_FIFO, "time_delta=%lld ms update_vbat_low=%d update_smb=%d\n", + time_delta, update_vbat_low, update_smb); + + if (time_delta > MIN_FIFO_FULL_TIME_MS || update_vbat_low + || update_smb) { + rc = qg_master_hold(chip, true); + if (rc < 0) { + pr_err("Failed to hold master, rc=%d\n", rc); + goto done; + } + + rc = qg_process_rt_fifo(chip); + if (rc < 0) { + pr_err("Failed to process FIFO real-time, rc=%d\n", rc); + goto done; + } + + if (update_vbat_low) { + /* change FIFO length */ + fifo_length = chip->vbat_low ? + chip->dt.s2_vbat_low_fifo_length : + chip->dt.s2_fifo_length; + rc = qg_update_fifo_length(chip, fifo_length); + if (rc < 0) + goto done; + + qg_dbg(chip, QG_DEBUG_STATUS, + "FIFO length updated to %d vbat_low=%d\n", + fifo_length, chip->vbat_low); + } + + if (update_smb) { + rc = qg_masked_write(chip, chip->qg_base + + QG_MODE_CTL1_REG, PARALLEL_IBAT_SENSE_EN_BIT, + chip->parallel_enabled ? + PARALLEL_IBAT_SENSE_EN_BIT : 0); + if (rc < 0) { + pr_err("Failed to update SMB_EN, rc=%d\n", rc); + goto done; + } + qg_dbg(chip, QG_DEBUG_STATUS, "Parallel SENSE %d\n", + chip->parallel_enabled); + } + + rc = qg_master_hold(chip, false); + if (rc < 0) { + pr_err("Failed to release master, rc=%d\n", rc); + goto done; + } + /* FIFOs restarted */ + chip->last_fifo_update_time = ktime_get(); + + /* signal the read thread */ + chip->data_ready = true; + wake_up_interruptible(&chip->qg_wait_q); + chip->last_user_update_time = now; + + /* vote to stay awake until userspace reads data */ + vote(chip->awake_votable, FIFO_RT_DONE_VOTER, true, 0); + } else { + qg_dbg(chip, QG_DEBUG_FIFO, "FIFO processing too early time_delta=%lld\n", + time_delta); + } +done: + qg_master_hold(chip, false); + return rc; +} + #define VBAT_LOW_HYST_UV 50000 /* 50mV */ static int qg_vbat_low_wa(struct qpnp_qg *chip) { @@ -562,82 +664,356 @@ static int qg_vbat_thresholds_config(struct qpnp_qg *chip) return rc; } -#define MIN_FIFO_FULL_TIME_MS 12000 -static int process_rt_fifo_data(struct qpnp_qg *chip, - bool vbat_low, bool update_smb) +static void qg_retrieve_esr_params(struct qpnp_qg *chip) { - int rc = 0; - ktime_t now = ktime_get(); - s64 time_delta; + u32 data = 0; + int rc; + + rc = qg_sdam_read(SDAM_ESR_CHARGE_DELTA, &data); + if (!rc && data) { + chip->kdata.param[QG_ESR_CHARGE_DELTA].data = data; + chip->kdata.param[QG_ESR_CHARGE_DELTA].valid = true; + qg_dbg(chip, QG_DEBUG_ESR, + "ESR_CHARGE_DELTA SDAM=%d\n", data); + } else if (rc < 0) { + pr_err("Failed to read ESR_CHARGE_DELTA rc=%d\n", rc); + } + + rc = qg_sdam_read(SDAM_ESR_DISCHARGE_DELTA, &data); + if (!rc && data) { + chip->kdata.param[QG_ESR_DISCHARGE_DELTA].data = data; + chip->kdata.param[QG_ESR_DISCHARGE_DELTA].valid = true; + qg_dbg(chip, QG_DEBUG_ESR, + "ESR_DISCHARGE_DELTA SDAM=%d\n", data); + } else if (rc < 0) { + pr_err("Failed to read ESR_DISCHARGE_DELTA rc=%d\n", rc); + } + + rc = qg_sdam_read(SDAM_ESR_CHARGE_SF, &data); + if (!rc && data) { + data = CAP(QG_ESR_SF_MIN, QG_ESR_SF_MAX, data); + chip->kdata.param[QG_ESR_CHARGE_SF].data = data; + chip->kdata.param[QG_ESR_CHARGE_SF].valid = true; + qg_dbg(chip, QG_DEBUG_ESR, + "ESR_CHARGE_SF SDAM=%d\n", data); + } else if (rc < 0) { + pr_err("Failed to read ESR_CHARGE_SF rc=%d\n", rc); + } + + rc = qg_sdam_read(SDAM_ESR_DISCHARGE_SF, &data); + if (!rc && data) { + data = CAP(QG_ESR_SF_MIN, QG_ESR_SF_MAX, data); + chip->kdata.param[QG_ESR_DISCHARGE_SF].data = data; + chip->kdata.param[QG_ESR_DISCHARGE_SF].valid = true; + qg_dbg(chip, QG_DEBUG_ESR, + "ESR_DISCHARGE_SF SDAM=%d\n", data); + } else if (rc < 0) { + pr_err("Failed to read ESR_DISCHARGE_SF rc=%d\n", rc); + } +} + +static void qg_store_esr_params(struct qpnp_qg *chip) +{ + unsigned int esr; + + if (chip->udata.param[QG_ESR_CHARGE_DELTA].valid) { + esr = chip->udata.param[QG_ESR_CHARGE_DELTA].data; + qg_sdam_write(SDAM_ESR_CHARGE_DELTA, esr); + qg_dbg(chip, QG_DEBUG_ESR, + "SDAM store ESR_CHARGE_DELTA=%d\n", esr); + } + + if (chip->udata.param[QG_ESR_DISCHARGE_DELTA].valid) { + esr = chip->udata.param[QG_ESR_DISCHARGE_DELTA].data; + qg_sdam_write(SDAM_ESR_DISCHARGE_DELTA, esr); + qg_dbg(chip, QG_DEBUG_ESR, + "SDAM store ESR_DISCHARGE_DELTA=%d\n", esr); + } + + if (chip->udata.param[QG_ESR_CHARGE_SF].valid) { + esr = chip->udata.param[QG_ESR_CHARGE_SF].data; + qg_sdam_write(SDAM_ESR_CHARGE_SF, esr); + qg_dbg(chip, QG_DEBUG_ESR, + "SDAM store ESR_CHARGE_SF=%d\n", esr); + } + + if (chip->udata.param[QG_ESR_DISCHARGE_SF].valid) { + esr = chip->udata.param[QG_ESR_DISCHARGE_SF].data; + qg_sdam_write(SDAM_ESR_DISCHARGE_SF, esr); + qg_dbg(chip, QG_DEBUG_ESR, + "SDAM store ESR_DISCHARGE_SF=%d\n", esr); + } +} + +#define MAX_ESR_RETRY_COUNT 10 +#define ESR_SD_PERCENT 10 +static int qg_process_esr_data(struct qpnp_qg *chip) +{ + int i; + int pre_i, post_i, pre_v, post_v, first_pre_i = 0; + int diff_v, diff_i, esr_avg = 0, count = 0; + + for (i = 0; i < qg_esr_count; i++) { + if (!chip->esr_data[i].valid) + continue; + + pre_i = chip->esr_data[i].pre_esr_i; + pre_v = chip->esr_data[i].pre_esr_v; + post_i = chip->esr_data[i].post_esr_i; + post_v = chip->esr_data[i].post_esr_v; + + /* + * Check if any of the pre/post readings have changed + * signs by comparing it with the first valid + * pre_i value. + */ + if (!first_pre_i) + first_pre_i = pre_i; + + if ((first_pre_i < 0 && pre_i > 0) || + (first_pre_i > 0 && post_i < 0) || + (first_pre_i < 0 && post_i > 0)) { + qg_dbg(chip, QG_DEBUG_ESR, + "ESR-sign mismatch %d reject all data\n", i); + esr_avg = count = 0; + break; + } + + /* calculate ESR */ + diff_v = abs(post_v - pre_v); + diff_i = abs(post_i - pre_i); + + if (!diff_v || !diff_i || + (diff_i < chip->dt.esr_qual_i_ua) || + (diff_v < chip->dt.esr_qual_v_uv)) { + qg_dbg(chip, QG_DEBUG_ESR, + "ESR (%d) V/I %duA %duV fails qualification\n", + i, diff_i, diff_v); + chip->esr_data[i].valid = false; + continue; + } + + chip->esr_data[i].esr = + DIV_ROUND_CLOSEST(diff_v * 1000, diff_i); + qg_dbg(chip, QG_DEBUG_ESR, + "ESR qualified: i=%d pre_i=%d pre_v=%d post_i=%d post_v=%d esr_diff_v=%d esr_diff_i=%d esr=%d\n", + i, pre_i, pre_v, post_i, post_v, + diff_v, diff_i, chip->esr_data[i].esr); + + esr_avg += chip->esr_data[i].esr; + count++; + } + + if (!count) { + qg_dbg(chip, QG_DEBUG_ESR, + "No ESR samples qualified, ESR not found\n"); + chip->esr_avg = 0; + return 0; + } + + esr_avg /= count; + qg_dbg(chip, QG_DEBUG_ESR, + "ESR all sample average=%d count=%d apply_SD=%d\n", + esr_avg, count, (esr_avg * ESR_SD_PERCENT) / 100); /* - * Reject the FIFO read event if there are back-to-back requests - * This is done to gaurantee that there is always a minimum FIFO - * data to be processed, ignore this if vbat_low is set. + * Reject ESR samples which do not fall in + * 10% the standard-deviation */ - time_delta = ktime_ms_delta(now, chip->last_user_update_time); + count = 0; + for (i = 0; i < qg_esr_count; i++) { + if (!chip->esr_data[i].valid) + continue; + + if ((abs(chip->esr_data[i].esr - esr_avg) <= + (esr_avg * ESR_SD_PERCENT) / 100)) { + /* valid ESR */ + chip->esr_avg += chip->esr_data[i].esr; + count++; + qg_dbg(chip, QG_DEBUG_ESR, + "Valid ESR after SD (%d) %d mOhm\n", + i, chip->esr_data[i].esr); + } else { + qg_dbg(chip, QG_DEBUG_ESR, + "ESR (%d) %d falls-out of SD(%d)\n", + i, chip->esr_data[i].esr, ESR_SD_PERCENT); + } + } - qg_dbg(chip, QG_DEBUG_FIFO, "time_delta=%lld ms vbat_low=%d\n", - time_delta, vbat_low); + if (count >= QG_MIN_ESR_COUNT) { + chip->esr_avg /= count; + qg_dbg(chip, QG_DEBUG_ESR, "Average estimated ESR %d mOhm\n", + chip->esr_avg); + } else { + qg_dbg(chip, QG_DEBUG_ESR, + "Not enough ESR samples, ESR not found\n"); + chip->esr_avg = 0; + } - if (time_delta > MIN_FIFO_FULL_TIME_MS || vbat_low || update_smb) { - rc = qg_master_hold(chip, true); - if (rc < 0) { - pr_err("Failed to hold master, rc=%d\n", rc); - goto done; - } + return 0; +} - rc = qg_process_rt_fifo(chip); +static int qg_esr_estimate(struct qpnp_qg *chip) +{ + int rc, i, ibat; + u8 esr_done_count, reg0 = 0, reg1 = 0; + bool is_charging = false; + + if (chip->dt.esr_disable) + return 0; + + /* + * Charge - enable ESR estimation only during fast-charging. + * Discharge - enable ESR estimation only if enabled via DT. + */ + if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING && + chip->charge_type != POWER_SUPPLY_CHARGE_TYPE_FAST) { + qg_dbg(chip, QG_DEBUG_ESR, + "Skip ESR, Not in fast-charge (CC)\n"); + return 0; + } + + if (chip->charge_status != POWER_SUPPLY_STATUS_CHARGING && + !chip->dt.esr_discharge_enable) + return 0; + + if (chip->batt_soc != INT_MIN && (chip->batt_soc < + chip->dt.esr_disable_soc)) { + qg_dbg(chip, QG_DEBUG_ESR, + "Skip ESR, batt-soc below %d\n", + chip->dt.esr_disable_soc); + return 0; + } + + qg_dbg(chip, QG_DEBUG_ESR, "FIFO done count=%d ESR mod count=%d\n", + chip->fifo_done_count, qg_esr_mod_count); + + if ((chip->fifo_done_count % qg_esr_mod_count) != 0) + return 0; + + if (qg_esr_count > QG_MAX_ESR_COUNT) + qg_esr_count = QG_MAX_ESR_COUNT; + + if (qg_esr_count < QG_MIN_ESR_COUNT) + qg_esr_count = QG_MIN_ESR_COUNT; + + /* clear all data */ + chip->esr_avg = 0; + memset(&chip->esr_data, 0, sizeof(chip->esr_data)); + + rc = qg_master_hold(chip, true); + if (rc < 0) { + pr_err("Failed to hold master, rc=%d\n", rc); + goto done; + } + + for (i = 0; i < qg_esr_count; i++) { + /* Fire ESR measurement */ + rc = qg_masked_write(chip, + chip->qg_base + QG_ESR_MEAS_TRIG_REG, + HW_ESR_MEAS_START_BIT, HW_ESR_MEAS_START_BIT); if (rc < 0) { - pr_err("Failed to process FIFO real-time, rc=%d\n", rc); - goto done; + pr_err("Failed to start ESR rc=%d\n", rc); + continue; } - if (vbat_low) { - /* change FIFO length */ - rc = qg_update_fifo_length(chip, - chip->dt.s2_vbat_low_fifo_length); + esr_done_count = reg0 = reg1 = 0; + do { + /* delay for ESR processing to complete */ + msleep(50); + + esr_done_count++; + + rc = qg_read(chip, + chip->qg_base + QG_STATUS1_REG, ®0, 1); + if (rc < 0) + continue; + + rc = qg_read(chip, + chip->qg_base + QG_STATUS4_REG, ®1, 1); + if (rc < 0) + continue; + + /* check ESR-done status */ + if (!(reg1 & ESR_MEAS_IN_PROGRESS_BIT) && + (reg0 & ESR_MEAS_DONE_BIT)) { + qg_dbg(chip, QG_DEBUG_ESR, + "ESR measurement done %d count %d\n", + i, esr_done_count); + break; + } + } while (esr_done_count < MAX_ESR_RETRY_COUNT); + + if (esr_done_count == MAX_ESR_RETRY_COUNT) { + pr_err("Failed to get ESR done for %d iteration\n", i); + continue; + } else { + /* found a valid ESR, read pre-post data */ + rc = qg_read_raw_data(chip, QG_PRE_ESR_V_DATA0_REG, + &chip->esr_data[i].pre_esr_v); if (rc < 0) goto done; - qg_dbg(chip, QG_DEBUG_STATUS, - "FIFO length updated to %d vbat_low=%d\n", - chip->dt.s2_vbat_low_fifo_length, - vbat_low); - } + rc = qg_read_raw_data(chip, QG_PRE_ESR_I_DATA0_REG, + &chip->esr_data[i].pre_esr_i); + if (rc < 0) + goto done; - if (update_smb) { - rc = qg_masked_write(chip, chip->qg_base + - QG_MODE_CTL1_REG, PARALLEL_IBAT_SENSE_EN_BIT, - chip->parallel_enabled ? - PARALLEL_IBAT_SENSE_EN_BIT : 0); - if (rc < 0) { - pr_err("Failed to update SMB_EN, rc=%d\n", rc); + rc = qg_read_raw_data(chip, QG_POST_ESR_V_DATA0_REG, + &chip->esr_data[i].post_esr_v); + if (rc < 0) goto done; - } - qg_dbg(chip, QG_DEBUG_STATUS, "Parallel SENSE %d\n", - chip->parallel_enabled); - } - rc = qg_master_hold(chip, false); - if (rc < 0) { - pr_err("Failed to release master, rc=%d\n", rc); - goto done; + rc = qg_read_raw_data(chip, QG_POST_ESR_I_DATA0_REG, + &chip->esr_data[i].post_esr_i); + if (rc < 0) + goto done; + + chip->esr_data[i].pre_esr_v = + V_RAW_TO_UV(chip->esr_data[i].pre_esr_v); + ibat = sign_extend32(chip->esr_data[i].pre_esr_i, 15); + chip->esr_data[i].pre_esr_i = I_RAW_TO_UA(ibat); + chip->esr_data[i].post_esr_v = + V_RAW_TO_UV(chip->esr_data[i].post_esr_v); + ibat = sign_extend32(chip->esr_data[i].post_esr_i, 15); + chip->esr_data[i].post_esr_i = I_RAW_TO_UA(ibat); + + chip->esr_data[i].valid = true; + + if ((int)chip->esr_data[i].pre_esr_i < 0) + is_charging = true; + + qg_dbg(chip, QG_DEBUG_ESR, + "ESR values for %d iteration pre_v=%d pre_i=%d post_v=%d post_i=%d\n", + i, chip->esr_data[i].pre_esr_v, + (int)chip->esr_data[i].pre_esr_i, + chip->esr_data[i].post_esr_v, + (int)chip->esr_data[i].post_esr_i); } - /* FIFOs restarted */ - chip->last_fifo_update_time = ktime_get(); + /* delay before the next ESR measurement */ + msleep(200); + } - /* signal the read thread */ - chip->data_ready = true; - wake_up_interruptible(&chip->qg_wait_q); - chip->last_user_update_time = now; + rc = qg_process_esr_data(chip); + if (rc < 0) + pr_err("Failed to process ESR data rc=%d\n", rc); - /* vote to stay awake until userspace reads data */ - vote(chip->awake_votable, FIFO_RT_DONE_VOTER, true, 0); - } else { - qg_dbg(chip, QG_DEBUG_FIFO, "FIFO processing too early time_delta=%lld\n", - time_delta); + rc = qg_master_hold(chip, false); + if (rc < 0) { + pr_err("Failed to release master, rc=%d\n", rc); + goto done; + } + + if (chip->esr_avg) { + chip->kdata.param[QG_ESR].data = chip->esr_avg; + chip->kdata.param[QG_ESR].valid = true; + qg_dbg(chip, QG_DEBUG_ESR, "ESR_SW=%d during %s\n", + chip->esr_avg, is_charging ? "CHARGE" : "DISCHARGE"); + qg_retrieve_esr_params(chip); + chip->esr_actual = chip->esr_avg; } + + return 0; done: qg_master_hold(chip, false); return rc; @@ -655,6 +1031,9 @@ static void process_udata_work(struct work_struct *work) if (chip->udata.param[QG_BATT_SOC].valid) chip->batt_soc = chip->udata.param[QG_BATT_SOC].data; + if (chip->udata.param[QG_FULL_SOC].valid) + chip->full_soc = chip->udata.param[QG_FULL_SOC].data; + if (chip->udata.param[QG_SOC].valid) { qg_dbg(chip, QG_DEBUG_SOC, "udata SOC=%d last SOC=%d\n", chip->udata.param[QG_SOC].data, chip->catch_up_soc); @@ -670,7 +1049,7 @@ static void process_udata_work(struct work_struct *work) chip->udata.param[QG_RBAT_MOHM].data; chip->sdam_data[SDAM_VALID] = 1; - rc = qg_update_sdam_params(chip); + rc = qg_store_soc_params(chip); if (rc < 0) pr_err("Failed to update SDAM params, rc=%d\n", rc); } @@ -679,16 +1058,23 @@ static void process_udata_work(struct work_struct *work) chip->charge_counter_uah = chip->udata.param[QG_CHARGE_COUNTER].data; - vote(chip->awake_votable, UDATA_READY_VOTER, false, 0); -} + if (chip->udata.param[QG_ESR].valid) + chip->esr_last = chip->udata.param[QG_ESR].data; -static irqreturn_t qg_default_irq_handler(int irq, void *data) -{ - struct qpnp_qg *chip = data; + if (chip->esr_actual != -EINVAL && chip->udata.param[QG_ESR].valid) { + chip->esr_nominal = chip->udata.param[QG_ESR].data; + if (chip->qg_psy) + power_supply_changed(chip->qg_psy); + } - qg_dbg(chip, QG_DEBUG_IRQ, "IRQ triggered\n"); + if (!chip->dt.esr_disable) + qg_store_esr_params(chip); - return IRQ_HANDLED; + qg_dbg(chip, QG_DEBUG_STATUS, "udata update: batt_soc=%d cc_soc=%d full_soc=%d qg_esr=%d\n", + (chip->batt_soc != INT_MIN) ? chip->batt_soc : -EINVAL, + (chip->cc_soc != INT_MIN) ? chip->cc_soc : -EINVAL, + chip->full_soc, chip->esr_last); + vote(chip->awake_votable, UDATA_READY_VOTER, false, 0); } #define MAX_FIFO_DELTA_PERCENT 10 @@ -718,6 +1104,9 @@ static irqreturn_t qg_fifo_update_done_handler(int irq, void *data) goto done; } + if (++chip->fifo_done_count == U32_MAX) + chip->fifo_done_count = 0; + rc = qg_vbat_thresholds_config(chip); if (rc < 0) pr_err("Failed to apply VBAT EMPTY config rc=%d\n", rc); @@ -728,6 +1117,12 @@ static irqreturn_t qg_fifo_update_done_handler(int irq, void *data) goto done; } + rc = qg_esr_estimate(chip); + if (rc < 0) { + pr_err("Failed to estimate ESR, rc=%d\n", rc); + goto done; + } + rc = get_fifo_done_time(chip, false, &hw_delta_ms); if (rc < 0) hw_delta_ms = 0; @@ -767,9 +1162,14 @@ static irqreturn_t qg_vbat_low_handler(int irq, void *data) pr_err("Failed to read RT status, rc=%d\n", rc); goto done; } + /* ignore VBAT low if battery is missing */ + if ((status & BATTERY_MISSING_INT_RT_STS_BIT) || + chip->battery_missing) + goto done; + chip->vbat_low = !!(status & VBAT_LOW_INT_RT_STS_BIT); - rc = process_rt_fifo_data(chip, chip->vbat_low, false); + rc = process_rt_fifo_data(chip, true, false); if (rc < 0) pr_err("Failed to process RT FIFO data, rc=%d\n", rc); @@ -783,8 +1183,20 @@ static irqreturn_t qg_vbat_empty_handler(int irq, void *data) { struct qpnp_qg *chip = data; u32 ocv_uv = 0; + int rc; + u8 status = 0; qg_dbg(chip, QG_DEBUG_IRQ, "IRQ triggered\n"); + + rc = qg_read(chip, chip->qg_base + QG_INT_RT_STS_REG, &status, 1); + if (rc < 0) + pr_err("Failed to read RT status rc=%d\n", rc); + + /* ignore VBAT empty if battery is missing */ + if ((status & BATTERY_MISSING_INT_RT_STS_BIT) || + chip->battery_missing) + return IRQ_HANDLED; + pr_warn("VBATT EMPTY SOC = 0\n"); chip->catch_up_soc = 0; @@ -795,7 +1207,7 @@ static irqreturn_t qg_vbat_empty_handler(int irq, void *data) chip->sdam_data[SDAM_OCV_UV] = ocv_uv; chip->sdam_data[SDAM_VALID] = 1; - qg_update_sdam_params(chip); + qg_store_soc_params(chip); if (chip->qg_psy) power_supply_changed(chip->qg_psy); @@ -845,7 +1257,6 @@ static irqreturn_t qg_good_ocv_handler(int irq, void *data) static struct qg_irq_info qg_irqs[] = { [QG_BATT_MISSING_IRQ] = { .name = "qg-batt-missing", - .handler = qg_default_irq_handler, }, [QG_VBATT_LOW_IRQ] = { .name = "qg-vbat-low", @@ -869,11 +1280,9 @@ static struct qg_irq_info qg_irqs[] = { }, [QG_FSM_STAT_CHG_IRQ] = { .name = "qg-fsm-state-chg", - .handler = qg_default_irq_handler, }, [QG_EVENT_IRQ] = { .name = "qg-event", - .handler = qg_default_irq_handler, }, }; @@ -972,7 +1381,7 @@ static int qg_get_learned_capacity(void *data, int64_t *learned_cap_uah) return -ENODEV; if (chip->battery_missing || !chip->profile_loaded) - return -EPERM; + return -ENODEV; rc = qg_sdam_multibyte_read(QG_SDAM_LEARNED_CAPACITY_OFFSET, (u8 *)&cc_mah, 2); @@ -997,7 +1406,7 @@ static int qg_store_learned_capacity(void *data, int64_t learned_cap_uah) return -ENODEV; if (chip->battery_missing || !learned_cap_uah) - return -EPERM; + return -ENODEV; cc_mah = div64_s64(learned_cap_uah, 1000); rc = qg_sdam_multibyte_write(QG_SDAM_LEARNED_CAPACITY_OFFSET, @@ -1037,7 +1446,7 @@ static int qg_restore_cycle_count(void *data, u16 *buf, int length) return -ENODEV; if (chip->battery_missing || !chip->profile_loaded) - return -EPERM; + return -ENODEV; if (!buf || length > BUCKET_COUNT) return -EINVAL; @@ -1065,7 +1474,7 @@ static int qg_store_cycle_count(void *data, u16 *buf, int id, int length) return -ENODEV; if (chip->battery_missing || !chip->profile_loaded) - return -EPERM; + return -ENODEV; if (!buf || length > BUCKET_COUNT * 2 || id < 0 || id > BUCKET_COUNT - 1 || @@ -1196,6 +1605,87 @@ static int qg_get_battery_capacity(struct qpnp_qg *chip, int *soc) return 0; } +static int qg_get_ttf_param(void *data, enum ttf_param param, int *val) +{ + union power_supply_propval prop = {0, }; + struct qpnp_qg *chip = data; + int rc = 0; + int64_t temp = 0; + + if (!chip) + return -ENODEV; + + if (chip->battery_missing || !chip->profile_loaded) + return -ENODEV; + + switch (param) { + case TTF_MSOC: + rc = qg_get_battery_capacity(chip, val); + break; + case TTF_VBAT: + rc = qg_get_battery_voltage(chip, val); + break; + case TTF_IBAT: + rc = qg_get_battery_current(chip, val); + break; + case TTF_FCC: + if (chip->qg_psy) { + rc = power_supply_get_property(chip->qg_psy, + POWER_SUPPLY_PROP_CHARGE_FULL, &prop); + if (rc >= 0) { + temp = div64_u64(prop.intval, 1000); + *val = div64_u64(chip->full_soc * temp, + QG_SOC_FULL); + } + } + break; + case TTF_MODE: + *val = TTF_MODE_NORMAL; + break; + case TTF_ITERM: + if (chip->chg_iterm_ma == INT_MIN) + *val = 0; + else + *val = chip->chg_iterm_ma; + break; + case TTF_RBATT: + rc = qg_sdam_read(SDAM_RBAT_MOHM, val); + if (!rc) + *val *= 1000; + break; + case TTF_VFLOAT: + *val = chip->bp.float_volt_uv; + break; + case TTF_CHG_TYPE: + *val = chip->charge_type; + break; + case TTF_CHG_STATUS: + *val = chip->charge_status; + break; + default: + pr_err("Unsupported property %d\n", param); + rc = -EINVAL; + break; + } + + return rc; +} + +static int qg_ttf_awake_voter(void *data, bool val) +{ + struct qpnp_qg *chip = data; + + if (!chip) + return -ENODEV; + + if (chip->battery_missing || !chip->profile_loaded) + return -ENODEV; + + vote(chip->awake_votable, TTF_AWAKE_VOTER, val, 0); + + return 0; +} + static int qg_psy_set_property(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *pval) @@ -1223,6 +1713,17 @@ static int qg_psy_set_property(struct power_supply *psy, chip->cl->learned_cap_uah = pval->intval; mutex_unlock(&chip->cl->lock); break; + case POWER_SUPPLY_PROP_SOH: + chip->soh = pval->intval; + qg_dbg(chip, QG_DEBUG_STATUS, "SOH update: SOH=%d esr_actual=%d esr_nominal=%d\n", + chip->soh, chip->esr_actual, chip->esr_nominal); + break; + case POWER_SUPPLY_PROP_ESR_ACTUAL: + chip->esr_actual = pval->intval; + break; + case POWER_SUPPLY_PROP_ESR_NOMINAL: + chip->esr_nominal = pval->intval; + break; default: break; } @@ -1266,6 +1767,12 @@ static int qg_psy_get_property(struct power_supply *psy, if (!rc) pval->intval *= 1000; break; + case POWER_SUPPLY_PROP_RESISTANCE_NOW: + pval->intval = chip->esr_last; + break; + case POWER_SUPPLY_PROP_SOC_REPORTING_READY: + pval->intval = chip->soc_reporting_ready; + break; case POWER_SUPPLY_PROP_RESISTANCE_CAPACITIVE: pval->intval = chip->dt.rbat_conn_mohm; break; @@ -1308,6 +1815,23 @@ static int qg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CYCLE_COUNT: rc = get_cycle_count(chip->counter, &pval->intval); break; + case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: + rc = ttf_get_time_to_full(chip->ttf, &pval->intval); + break; + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: + rc = ttf_get_time_to_empty(chip->ttf, &pval->intval); + break; + case POWER_SUPPLY_PROP_ESR_ACTUAL: + pval->intval = (chip->esr_actual == -EINVAL) ? -EINVAL : + (chip->esr_actual * 1000); + break; + case POWER_SUPPLY_PROP_ESR_NOMINAL: + pval->intval = (chip->esr_nominal == -EINVAL) ? -EINVAL : + (chip->esr_nominal * 1000); + break; + case POWER_SUPPLY_PROP_SOH: + pval->intval = chip->soh; + break; default: pr_debug("Unsupported property %d\n", psp); break; @@ -1321,6 +1845,9 @@ static int qg_property_is_writeable(struct power_supply *psy, { switch (psp) { case POWER_SUPPLY_PROP_CHARGE_FULL: + case POWER_SUPPLY_PROP_ESR_ACTUAL: + case POWER_SUPPLY_PROP_ESR_NOMINAL: + case POWER_SUPPLY_PROP_SOH: return 1; default: break; @@ -1337,6 +1864,8 @@ static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_RESISTANCE, POWER_SUPPLY_PROP_RESISTANCE_ID, + POWER_SUPPLY_PROP_RESISTANCE_NOW, + POWER_SUPPLY_PROP_SOC_REPORTING_READY, POWER_SUPPLY_PROP_RESISTANCE_CAPACITIVE, POWER_SUPPLY_PROP_DEBUG_BATTERY, POWER_SUPPLY_PROP_BATTERY_TYPE, @@ -1348,6 +1877,11 @@ static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_CYCLE_COUNTS, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, + POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, + POWER_SUPPLY_PROP_ESR_ACTUAL, + POWER_SUPPLY_PROP_ESR_NOMINAL, + POWER_SUPPLY_PROP_SOH, }; static const struct power_supply_desc qg_psy_desc = { @@ -1434,6 +1968,7 @@ static int qg_parallel_status_update(struct qpnp_qg *chip) { int rc; bool parallel_enabled = is_parallel_enabled(chip); + bool update_smb = false; if (parallel_enabled == chip->parallel_enabled) return 0; @@ -1444,7 +1979,14 @@ static int qg_parallel_status_update(struct qpnp_qg *chip) mutex_lock(&chip->data_lock); - rc = process_rt_fifo_data(chip, false, true); + /* + * Parallel charger uses the same external sense, hence do not + * enable SMB sensing if PMI632 is configured for external sense. + */ + if (!chip->dt.qg_ext_sense) + update_smb = true; + + rc = process_rt_fifo_data(chip, false, update_smb); if (rc < 0) pr_err("Failed to process RT FIFO data, rc=%d\n", rc); @@ -1469,6 +2011,110 @@ static int qg_usb_status_update(struct qpnp_qg *chip) return 0; } +static int qg_handle_battery_removal(struct qpnp_qg *chip) +{ + int rc, length = QG_SDAM_MAX_OFFSET - QG_SDAM_VALID_OFFSET; + u8 *data; + + /* clear SDAM */ + data = kcalloc(length, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + rc = qg_sdam_multibyte_write(QG_SDAM_VALID_OFFSET, data, length); + if (rc < 0) + pr_err("Failed to clear SDAM rc=%d\n", rc); + + return rc; +} + +#define MAX_QG_OK_RETRIES 20 +static int qg_handle_battery_insertion(struct qpnp_qg *chip) +{ + int rc, count = 0; + u32 ocv_uv = 0, ocv_raw = 0; + u8 reg = 0; + + do { + rc = qg_read(chip, chip->qg_base + QG_STATUS1_REG, ®, 1); + if (rc < 0) { + pr_err("Failed to read STATUS1_REG rc=%d\n", rc); + return rc; + } + + if (reg & QG_OK_BIT) + break; + + msleep(200); + count++; + } while (count < MAX_QG_OK_RETRIES); + + if (count == MAX_QG_OK_RETRIES) { + qg_dbg(chip, QG_DEBUG_STATUS, "QG_OK not set!\n"); + return 0; + } + + /* read S7 PON OCV */ + rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S7_PON_OCV); + if (rc < 0) { + pr_err("Failed to read PON OCV rc=%d\n", rc); + return rc; + } + + qg_dbg(chip, QG_DEBUG_STATUS, + "S7_OCV on battery insertion = %duV\n", ocv_uv); + + chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv; + chip->kdata.param[QG_GOOD_OCV_UV].valid = true; + /* clear all the userspace data */ + chip->kdata.param[QG_CLEAR_LEARNT_DATA].data = 1; + chip->kdata.param[QG_CLEAR_LEARNT_DATA].valid = true; + + vote(chip->awake_votable, GOOD_OCV_VOTER, true, 0); + /* signal the read thread */ + chip->data_ready = true; + wake_up_interruptible(&chip->qg_wait_q); + + return 0; +} + +static int qg_battery_status_update(struct qpnp_qg *chip) +{ + int rc; + union power_supply_propval prop = {0, }; + + if (!is_batt_available(chip)) + return 0; + + mutex_lock(&chip->data_lock); + + rc = power_supply_get_property(chip->batt_psy, + POWER_SUPPLY_PROP_PRESENT, &prop); + if (rc < 0) { + pr_err("Failed to get battery-present, rc=%d\n", rc); + goto done; + } + + if (chip->battery_missing && prop.intval) { + pr_warn("Battery inserted!\n"); + rc = qg_handle_battery_insertion(chip); + if (rc < 0) + pr_err("Failed in battery-insertion rc=%d\n", rc); + } else if (!chip->battery_missing && !prop.intval) { + pr_warn("Battery removed!\n"); + rc = qg_handle_battery_removal(chip); + if (rc < 0) + pr_err("Failed in battery-removal rc=%d\n", rc); + } + + chip->battery_missing = !prop.intval; + +done: + mutex_unlock(&chip->data_lock); + return rc; +} + + static void qg_status_change_work(struct work_struct *work) { struct qpnp_qg *chip = container_of(work, @@ -1481,6 +2127,17 @@ static void qg_status_change_work(struct work_struct *work) goto out; } + rc = qg_battery_status_update(chip); + if (rc < 0) + pr_err("Failed to process battery status update rc=%d\n", rc); + + rc = power_supply_get_property(chip->batt_psy, + POWER_SUPPLY_PROP_CHARGE_TYPE, &prop); + if (rc < 0) + pr_err("Failed to get charge-type, rc=%d\n", rc); + else + chip->charge_type = prop.intval; + rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_STATUS, &prop); if (rc < 0) @@ -1527,6 +2184,8 @@ static void qg_status_change_work(struct work_struct *work) rc = qg_charge_full_update(chip); if (rc < 0) pr_err("Failed in charge_full_update, rc=%d\n", rc); + + ttf_update(chip->ttf, chip->usb_present); out: pm_relax(chip->dev); } @@ -1867,6 +2526,7 @@ static int qg_setup_battery(struct qpnp_qg *chip) qg_dbg(chip, QG_DEBUG_PROFILE, "Battery Missing!\n"); chip->battery_missing = true; chip->profile_loaded = false; + chip->soc_reporting_ready = true; } else { /* battery present */ rc = get_batt_id_ohm(chip, &chip->batt_id_ohm); @@ -1875,11 +2535,14 @@ static int qg_setup_battery(struct qpnp_qg *chip) chip->profile_loaded = false; } else { rc = qg_load_battery_profile(chip); - if (rc < 0) + if (rc < 0) { pr_err("Failed to load battery-profile rc=%d\n", rc); - else + chip->profile_loaded = false; + chip->soc_reporting_ready = true; + } else { chip->profile_loaded = true; + } } } @@ -1890,12 +2553,21 @@ static int qg_setup_battery(struct qpnp_qg *chip) return 0; } + +static struct ocv_all ocv[] = { + [S7_PON_OCV] = { 0, 0, "S7_PON_OCV"}, + [S3_GOOD_OCV] = { 0, 0, "S3_GOOD_OCV"}, + [S3_LAST_OCV] = { 0, 0, "S3_LAST_OCV"}, + [SDAM_PON_OCV] = { 0, 0, "SDAM_PON_OCV"}, +}; + +#define S7_ERROR_MARGIN_UV 20000 static int qg_determine_pon_soc(struct qpnp_qg *chip) { - int rc = 0, batt_temp = 0; + int rc = 0, batt_temp = 0, i; bool use_pon_ocv = true; unsigned long rtc_sec = 0; - u32 ocv_uv = 0, ocv_raw = 0, soc = 0, shutdown[SDAM_MAX] = {0}; + u32 ocv_uv = 0, soc = 0, shutdown[SDAM_MAX] = {0}; char ocv_type[20] = "NONE"; if (!chip->profile_loaded) { @@ -1944,33 +2616,47 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip) goto done; } - /* - * Read S3_LAST_OCV, if S3_LAST_OCV is invalid, - * read the SDAM_PON_OCV - * if SDAM is not-set, use S7_PON_OCV. - */ - strlcpy(ocv_type, "S3_LAST_SOC", 20); - rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S3_LAST_OCV); - if (rc < 0) - goto done; - - if (ocv_raw == FIFO_V_RESET_VAL) { - /* S3_LAST_OCV is invalid */ - strlcpy(ocv_type, "SDAM_PON_SOC", 20); - rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, SDAM_PON_OCV); + /* read all OCVs */ + for (i = S7_PON_OCV; i < PON_OCV_MAX; i++) { + rc = qg_read_ocv(chip, &ocv[i].ocv_uv, + &ocv[i].ocv_raw, i); if (rc < 0) - goto done; + pr_err("Failed to read %s OCV rc=%d\n", + ocv[i].ocv_type, rc); + else + qg_dbg(chip, QG_DEBUG_PON, "%s OCV=%d\n", + ocv[i].ocv_type, ocv[i].ocv_uv); + } - if (!ocv_uv) { - /* SDAM_PON_OCV is not set */ + if (ocv[S3_LAST_OCV].ocv_raw == FIFO_V_RESET_VAL) { + if (!ocv[SDAM_PON_OCV].ocv_uv) { + strlcpy(ocv_type, "S7_PON_SOC", 20); + ocv_uv = ocv[S7_PON_OCV].ocv_uv; + } else if (ocv[SDAM_PON_OCV].ocv_uv <= + ocv[S7_PON_OCV].ocv_uv) { + strlcpy(ocv_type, "S7_PON_SOC", 20); + ocv_uv = ocv[S7_PON_OCV].ocv_uv; + } else if (!shutdown[SDAM_VALID] && + ((ocv[SDAM_PON_OCV].ocv_uv - + ocv[S7_PON_OCV].ocv_uv) > + S7_ERROR_MARGIN_UV)) { strlcpy(ocv_type, "S7_PON_SOC", 20); - rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, - S7_PON_OCV); - if (rc < 0) - goto done; + ocv_uv = ocv[S7_PON_OCV].ocv_uv; + } else { + strlcpy(ocv_type, "SDAM_PON_SOC", 20); + ocv_uv = ocv[SDAM_PON_OCV].ocv_uv; + } + } else { + if (ocv[S3_LAST_OCV].ocv_uv >= ocv[S7_PON_OCV].ocv_uv) { + strlcpy(ocv_type, "S3_LAST_SOC", 20); + ocv_uv = ocv[S3_LAST_OCV].ocv_uv; + } else { + strlcpy(ocv_type, "S7_PON_SOC", 20); + ocv_uv = ocv[S7_PON_OCV].ocv_uv; } } + ocv_uv = CAP(QG_MIN_OCV_UV, QG_MAX_OCV_UV, ocv_uv); rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false); if (rc < 0) { pr_err("Failed to lookup SOC@PON rc=%d\n", rc); @@ -1996,13 +2682,16 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip) if (rc < 0) pr_err("Failed to update MSOC register rc=%d\n", rc); - rc = qg_update_sdam_params(chip); + rc = qg_store_soc_params(chip); if (rc < 0) pr_err("Failed to update sdam params rc=%d\n", rc); pr_info("using %s @ PON ocv_uv=%duV soc=%d\n", ocv_type, ocv_uv, chip->msoc); + /* SOC reporting is now ready */ + chip->soc_reporting_ready = 1; + return 0; } @@ -2025,6 +2714,7 @@ static int qg_set_wa_flags(struct qpnp_qg *chip) return 0; } +#define ADC_CONV_DLY_512MS 0xA static int qg_hw_init(struct qpnp_qg *chip) { int rc, temp; @@ -2205,6 +2895,22 @@ static int qg_hw_init(struct qpnp_qg *chip) return rc; } + /* disable S5 */ + rc = qg_masked_write(chip, chip->qg_base + + QG_S5_OCV_VALIDATE_MEAS_CTL1_REG, + ALLOW_S5_BIT, 0); + if (rc < 0) + pr_err("Failed to disable S5 rc=%d\n", rc); + + /* change PON OCV time to 512ms */ + rc = qg_masked_write(chip, chip->qg_base + + QG_S7_PON_OCV_MEAS_CTL1_REG, + ADC_CONV_DLY_MASK, + ADC_CONV_DLY_512MS); + if (rc < 0) + pr_err("Failed to reconfigure S7-delay rc=%d\n", rc); + + return 0; } @@ -2224,6 +2930,10 @@ static int qg_post_init(struct qpnp_qg *chip) QG_INIT_STATE_IRQ_DISABLE, true, 0); } + /* restore ESR data */ + if (!chip->dt.esr_disable) + qg_retrieve_esr_params(chip); + return 0; } @@ -2298,10 +3008,12 @@ static int qg_request_irqs(struct qpnp_qg *chip) return 0; } +#define QG_TTF_ITERM_DELTA_MA 1 static int qg_alg_init(struct qpnp_qg *chip) { struct cycle_counter *counter; struct cap_learning *cl; + struct ttf *ttf; struct device_node *node = chip->dev->of_node; int rc; @@ -2324,6 +3036,28 @@ static int qg_alg_init(struct qpnp_qg *chip) chip->counter = counter; + ttf = devm_kzalloc(chip->dev, sizeof(*ttf), GFP_KERNEL); + if (!ttf) + return -ENOMEM; + + ttf->get_ttf_param = qg_get_ttf_param; + ttf->awake_voter = qg_ttf_awake_voter; + ttf->iterm_delta = QG_TTF_ITERM_DELTA_MA; + ttf->data = chip; + + rc = ttf_tte_init(ttf); + if (rc < 0) { + dev_err(chip->dev, "Error in initializing ttf, rc:%d\n", + rc); + ttf->data = NULL; + counter->data = NULL; + devm_kfree(chip->dev, ttf); + devm_kfree(chip->dev, counter); + return rc; + } + + chip->ttf = ttf; + chip->dt.cl_disable = of_property_read_bool(node, "qcom,cl-disable"); @@ -2348,6 +3082,7 @@ static int qg_alg_init(struct qpnp_qg *chip) counter->data = NULL; cl->data = NULL; devm_kfree(chip->dev, counter); + devm_kfree(chip->dev, ttf); devm_kfree(chip->dev, cl); return rc; } @@ -2373,10 +3108,13 @@ static int qg_alg_init(struct qpnp_qg *chip) #define DEFAULT_CL_MAX_START_SOC 15 #define DEFAULT_CL_MIN_TEMP_DECIDEGC 150 #define DEFAULT_CL_MAX_TEMP_DECIDEGC 500 -#define DEFAULT_CL_MAX_INC_DECIPERC 5 -#define DEFAULT_CL_MAX_DEC_DECIPERC 100 -#define DEFAULT_CL_MIN_LIM_DECIPERC 0 -#define DEFAULT_CL_MAX_LIM_DECIPERC 0 +#define DEFAULT_CL_MAX_INC_DECIPERC 10 +#define DEFAULT_CL_MAX_DEC_DECIPERC 20 +#define DEFAULT_CL_MIN_LIM_DECIPERC 500 +#define DEFAULT_CL_MAX_LIM_DECIPERC 100 +#define DEFAULT_ESR_QUAL_CURRENT_UA 130000 +#define DEFAULT_ESR_QUAL_VBAT_UV 7000 +#define DEFAULT_ESR_DISABLE_SOC 1000 static int qg_parse_dt(struct qpnp_qg *chip) { int rc = 0; @@ -2570,6 +3308,33 @@ static int qg_parse_dt(struct qpnp_qg *chip) else chip->dt.rbat_conn_mohm = temp; + /* esr */ + chip->dt.esr_disable = of_property_read_bool(node, + "qcom,esr-disable"); + + chip->dt.esr_discharge_enable = of_property_read_bool(node, + "qcom,esr-discharge-enable"); + + rc = of_property_read_u32(node, "qcom,esr-qual-current-ua", &temp); + if (rc < 0) + chip->dt.esr_qual_i_ua = DEFAULT_ESR_QUAL_CURRENT_UA; + else + chip->dt.esr_qual_i_ua = temp; + + rc = of_property_read_u32(node, "qcom,esr-qual-vbatt-uv", &temp); + if (rc < 0) + chip->dt.esr_qual_v_uv = DEFAULT_ESR_QUAL_VBAT_UV; + else + chip->dt.esr_qual_v_uv = temp; + + rc = of_property_read_u32(node, "qcom,esr-disable-soc", &temp); + if (rc < 0) + chip->dt.esr_disable_soc = DEFAULT_ESR_DISABLE_SOC; + else + chip->dt.esr_disable_soc = temp * 100; + + chip->dt.qg_ext_sense = of_property_read_bool(node, "qcom,qg-ext-sns"); + /* Capacity learning params*/ if (!chip->dt.cl_disable) { chip->dt.cl_feedback_on = of_property_read_bool(node, @@ -2629,9 +3394,9 @@ static int qg_parse_dt(struct qpnp_qg *chip) chip->cl->dt.min_start_soc, chip->cl->dt.max_start_soc, chip->cl->dt.min_temp, chip->cl->dt.max_temp); } - qg_dbg(chip, QG_DEBUG_PON, "DT: vbatt_empty_mv=%dmV vbatt_low_mv=%dmV delta_soc=%d\n", + qg_dbg(chip, QG_DEBUG_PON, "DT: vbatt_empty_mv=%dmV vbatt_low_mv=%dmV delta_soc=%d ext-sns=%d\n", chip->dt.vbatt_empty_mv, chip->dt.vbatt_low_mv, - chip->dt.delta_soc); + chip->dt.delta_soc, chip->dt.qg_ext_sense); return 0; } @@ -2646,6 +3411,7 @@ static int process_suspend(struct qpnp_qg *chip) if (!chip->profile_loaded) return 0; + cancel_delayed_work_sync(&chip->ttf->ttf_work); /* disable GOOD_OCV IRQ in sleep */ vote(chip->good_ocv_irq_disable_votable, QG_INIT_STATE_IRQ_DISABLE, true, 0); @@ -2778,6 +3544,8 @@ static int process_resume(struct qpnp_qg *chip) chip->suspend_data = false; } + schedule_delayed_work(&chip->ttf->ttf_work, 0); + return rc; } @@ -2866,6 +3634,11 @@ static int qpnp_qg_probe(struct platform_device *pdev) chip->maint_soc = -EINVAL; chip->batt_soc = INT_MIN; chip->cc_soc = INT_MIN; + chip->full_soc = QG_SOC_FULL; + chip->chg_iterm_ma = INT_MIN; + chip->soh = -EINVAL; + chip->esr_actual = -EINVAL; + chip->esr_nominal = -EINVAL; rc = qg_alg_init(chip); if (rc < 0) { @@ -2931,6 +3704,7 @@ static int qpnp_qg_probe(struct platform_device *pdev) pr_err("Error in restoring cycle_count, rc=%d\n", rc); return rc; } + schedule_delayed_work(&chip->ttf->ttf_work, 10000); } rc = qg_determine_pon_soc(chip); diff --git a/include/uapi/linux/qg-profile.h b/include/uapi/linux/qg-profile.h index bffddbb038e0..0230b3227f78 100644 --- a/include/uapi/linux/qg-profile.h +++ b/include/uapi/linux/qg-profile.h @@ -55,6 +55,8 @@ struct battery_params { #define QG_MAX_FCC_MAH 16000 #define QG_MIN_SLOPE 1 #define QG_MAX_SLOPE 50000 +#define QG_ESR_SF_MIN 5000 +#define QG_ESR_SF_MAX 20000 /* IOCTLs to query battery profile data */ #define BPIOCXSOC _IOWR('B', 0x01, struct battery_params) /* SOC */ diff --git a/include/uapi/linux/qg.h b/include/uapi/linux/qg.h index 2c7b49af873d..40882a7ae8c4 100644 --- a/include/uapi/linux/qg.h +++ b/include/uapi/linux/qg.h @@ -14,12 +14,12 @@ enum qg { QG_FIFO_TIME_DELTA, QG_BATT_SOC, QG_CC_SOC, - QG_RESERVED_3, - QG_RESERVED_4, - QG_RESERVED_5, - QG_RESERVED_6, - QG_RESERVED_7, - QG_RESERVED_8, + QG_ESR_CHARGE_DELTA, + QG_ESR_DISCHARGE_DELTA, + QG_ESR_CHARGE_SF, + QG_ESR_DISCHARGE_SF, + QG_FULL_SOC, + QG_CLEAR_LEARNT_DATA, QG_RESERVED_9, QG_RESERVED_10, QG_MAX, @@ -27,6 +27,12 @@ enum qg { #define QG_BATT_SOC QG_BATT_SOC #define QG_CC_SOC QG_CC_SOC +#define QG_ESR_CHARGE_DELTA QG_ESR_CHARGE_DELTA +#define QG_ESR_DISCHARGE_DELTA QG_ESR_DISCHARGE_DELTA +#define QG_ESR_CHARGE_SF QG_ESR_CHARGE_SF +#define QG_ESR_DISCHARGE_SF QG_ESR_DISCHARGE_SF +#define QG_FULL_SOC QG_FULL_SOC +#define QG_CLEAR_LEARNT_DATA QG_CLEAR_LEARNT_DATA struct fifo_data { unsigned int v; -- GitLab From a1a3ff7d6cacab138b2f1eb6840079b5680ac4d0 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Mon, 25 Jun 2018 22:51:42 +0530 Subject: [PATCH 0951/1299] msm: ipa: Fix disabling IPA clock for ntn pipes Make a change to disable IPA clock when ntn pipes are setup to ensure clock is turned off. Change-Id: If41d78d0bd818ac9bce8dd187f86771d818194c4 Acked-by: Chaitanya Pratapa Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c index e66aeeabe7e6..9f17d892da2f 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c @@ -508,6 +508,8 @@ int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in, result = -EFAULT; goto fail_smmu_map_dl; } + + IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); IPADBG("client %d (ep: %d) connected\n", in->dl.client, ipa_ep_idx_dl); -- GitLab From d9192dd0edd936be455b711cbb16e8cdde046320 Mon Sep 17 00:00:00 2001 From: Biswajit Paul Date: Mon, 9 Feb 2015 15:21:12 -0800 Subject: [PATCH 0952/1299] kernel: Restrict permissions of /proc/iomem. The permissions of /proc/iomem currently are -r--r--r--. Everyone can see its content. As iomem contains information about the physical memory content of the device, restrict the information only to root. Change-Id: If0be35c3fac5274151bea87b738a48e6ec0ae891 CRs-Fixed: 786116 Signed-off-by: Biswajit Paul Signed-off-by: Avijit Kanti Das --- kernel/resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/resource.c b/kernel/resource.c index 7ee3dd1ad2af..fbea5afe10a8 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -172,7 +172,7 @@ static const struct file_operations proc_iomem_operations = { static int __init ioresources_init(void) { proc_create("ioports", 0, NULL, &proc_ioports_operations); - proc_create("iomem", 0, NULL, &proc_iomem_operations); + proc_create("iomem", 0400, NULL, &proc_iomem_operations); return 0; } __initcall(ioresources_init); -- GitLab From 4a5f724a818b0eeba2c50590706975fbbcc7e306 Mon Sep 17 00:00:00 2001 From: Camus Wong Date: Fri, 16 Mar 2018 12:07:06 -0400 Subject: [PATCH 0953/1299] drm/bridge: add anx7625 DSI to DP bridge driver Add anx7625 bridge driver to support DSI to DP output. Configure anx7625 chip via I2C for audio/video setup. CRs-Fixed: 2246610 Change-Id: I25c5a54fc4f6a2f2fc58c8607d81904ac82f46e3 Signed-off-by: Camus Wong Signed-off-by: Xiaowen Wu --- .../bindings/display/bridge/anx7625.txt | 40 + drivers/gpu/drm/bridge/Kconfig | 9 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix-anx7625.c | 1530 +++++++++++++++++ drivers/gpu/drm/bridge/analogix-anx7625.h | 1220 +++++++++++++ 5 files changed, 2800 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/anx7625.txt create mode 100644 drivers/gpu/drm/bridge/analogix-anx7625.c create mode 100644 drivers/gpu/drm/bridge/analogix-anx7625.h diff --git a/Documentation/devicetree/bindings/display/bridge/anx7625.txt b/Documentation/devicetree/bindings/display/bridge/anx7625.txt new file mode 100644 index 000000000000..0bebd441f082 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/anx7625.txt @@ -0,0 +1,40 @@ +Analogix ANX7625 SlimPort (Full-HD Transmitter) +----------------------------------------------- + +The ANX7625 is DSI to DisplayPort bridge. + +Required properties: + + - compatible : "analogix,anx7625" + - reg : I2C address of the device + - interrupt-parent : Should be the phandle of the interrupt controller + that services interrupts for this device + - interrupts : Should contain the INTP interrupt + - cbl_det-gpios : Which GPIO to use for cable detection + - power_en-gpios : Which GPIO to use for power enable + - reset_n-gpios : Which GPIO to use for reset + - ports : Port 0 for DSI input, should be a reference to a + valid mipi_dsi_host device + +Example: + + anx7625: anx7625@ee { + compatible = "analogix,anx7625"; + reg = <0xee>; + interrupt-parent = <&qup15>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; /* INTP */ + cbl_det-gpio = <&qup15 1 GPIO_ACTIVE_HIGH>; + power_en-gpio = <&pio 27 GPIO_ACTIVE_HIGH>; + reset_n-gpio = <&pio 49 GPIO_ACTIVE_HIGH>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + anx7625_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; + }; diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index adf9ae0e0b7c..bac60e5c3c1c 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -25,6 +25,15 @@ config DRM_ANALOGIX_ANX78XX the HDMI output of an application processor to MyDP or DisplayPort. +config DRM_ANALOGIX_ANX7625 + tristate "Analogix ANX7625 bridge" + select DRM_KMS_HELPER + ---help--- + ANX7625 is DSI to DisplayPort bridge transmitter + driver. The driver can support direct Display port + only, USB type C interface is not supported in + this driver. + config DRM_DUMB_VGA_DAC tristate "Dumb VGA DAC Bridge support" depends on OF diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 60dab87e4783..2c431adc3c41 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o obj-y += synopsys/ +obj-$(CONFIG_DRM_ANALOGIX_ANX7625) += analogix-anx7625.o diff --git a/drivers/gpu/drm/bridge/analogix-anx7625.c b/drivers/gpu/drm/bridge/analogix-anx7625.c new file mode 100644 index 000000000000..b16d6de2cabd --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix-anx7625.c @@ -0,0 +1,1530 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Copyright(c) 2016, Analogix Semiconductor. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "analogix-anx7625.h" + +#define TX_P0 0x70 +#define TX_P1 0x7A +#define TX_P2 0x72 +#define RX_P0 0x7e +#define RX_P1 0x84 +#define RX_P2 0x54 +#define TCPC_INTERFACE 0x58 + +#define ReadReg(addr, offset) ({\ + unsigned int buf;\ + reg_read(anx7625, addr, offset, &buf);\ + buf;\ +}) + +#define Read_Reg(addr, offset, buf) ({\ + reg_read(anx7625, addr, offset, buf);\ +}) + +#define ReadBlockReg(addr, offset, len, dat)\ + reg_read_block(anx7625, addr, offset, dat, len) + +#define WriteReg(addr, offset, val) ({\ + reg_write(anx7625, addr, offset, val);\ +}) + +#define WriteBlockReg(addr, offset, len, dat)\ + reg_write_block(anx7625, addr, offset, dat, len) + +#define sp_write_reg_or(address, offset, mask) \ +{ WriteReg(address, offset, ((unsigned char)ReadReg(address, offset) \ + | (mask))); } +#define sp_write_reg_and(address, offset, mask) \ +{ WriteReg(address, offset, ((unsigned char)ReadReg(address, offset) \ + &(mask))); } + +#define sp_write_reg_and_or(address, offset, and_mask, or_mask) \ +{ WriteReg(address, offset, (((unsigned char)ReadReg(address, offset)) \ + &and_mask) | (or_mask)); } +#define sp_write_reg_or_and(address, offset, or_mask, and_mask) \ +{ WriteReg(address, offset, (((unsigned char)ReadReg(address, offset)) \ + | or_mask) & (and_mask)); } + +struct anx7625_platform_data { + struct gpio_desc *gpiod_cdet; + struct gpio_desc *gpiod_p_on; + struct gpio_desc *gpiod_reset; + + int cdet_irq; + int intp_irq; +}; + +struct MIPI_Video_Format { + unsigned char timing_id; + unsigned char MIPI_video_type[32]; + unsigned char MIPI_lane_count; + unsigned long MIPI_pixel_frequency; /*Hz*/ + + unsigned long M; + unsigned long N; + unsigned char post_divider; + /* bit[7:4]: DIFF_I_RATIO, bit[3:0]: DIFF_K_RATIO; i.e. 0x84:0x1B. + * These settings affect ODFC PLL locking range. + */ + unsigned char diff_ratio; + + unsigned char compress_ratio; + unsigned char video_3D_type; + unsigned char *pps_reg; + const struct RegisterValueConfig *custom_reg0; + const struct RegisterValueConfig *custom_reg1; + + struct TimingInfor { + unsigned int MIPI_HTOTAL; + unsigned int MIPI_HActive; + unsigned int MIPI_VTOTAL; + unsigned int MIPI_VActive; + + unsigned int MIPI_H_Front_Porch; + unsigned int MIPI_H_Sync_Width; + unsigned int MIPI_H_Back_Porch; + + + unsigned int MIPI_V_Front_Porch; + unsigned int MIPI_V_Sync_Width; + unsigned int MIPI_V_Back_Porch; + } MIPI_inputl[2]; +}; + +struct anx7625 { + struct drm_dp_aux aux; + struct drm_bridge bridge; + struct i2c_client *client; + struct edid *edid; + struct drm_dp_link link; + struct anx7625_platform_data pdata; + struct mutex lock; + int mode_idx; + + u16 chipid; + + bool powered; + bool enabled; + int connected; + bool hpd_status; + u8 sys_sta_bak; + + unsigned char last_read_DevAddr; +}; + +static void Reg_Access_Conflict_Workaround(struct anx7625 *anx7625, + unsigned char DevAddr) +{ + unsigned char RegAddr; + int ret = 0, i; + + if (DevAddr != anx7625->last_read_DevAddr) { + switch (DevAddr) { + case 0x54: + case 0x72: + default: + RegAddr = 0x00; + break; + + case 0x58: + RegAddr = 0x00; + break; + + case 0x70: + RegAddr = 0xD1; + break; + + case 0x7A: + RegAddr = 0x60; + break; + + case 0x7E: + RegAddr = 0x39; + break; + + case 0x84: + RegAddr = 0x7F; + break; + } + + anx7625->client->addr = (DevAddr >> 1); + for (i = 0; i < 5; i++) { + ret = i2c_smbus_write_byte_data(anx7625->client, + RegAddr, 0x00); + if (ret >= 0) + break; + pr_err("failed to write i2c addr=%x:%x, retry %d...\n", + DevAddr, RegAddr, i); + usleep_range(1000, 1100); + } + anx7625->last_read_DevAddr = DevAddr; + } +} + +static int reg_read(struct anx7625 *anx7625, + int addr, int offset, unsigned int *buf) +{ + int ret, i; + + Reg_Access_Conflict_Workaround(anx7625, addr); + anx7625->client->addr = (addr >> 1); + for (i = 0; i < 5; i++) { + ret = i2c_smbus_read_byte_data( + anx7625->client, offset); + if (ret >= 0) + break; + pr_err("failed to read anx7625 %x:%x, retry %d...\n", + addr, offset, i); + usleep_range(1000, 1100); + } + *buf = ret; + return 0; +} + +static int reg_write(struct anx7625 *anx7625, + int addr, int offset, unsigned int val) +{ + int ret, i; + + Reg_Access_Conflict_Workaround(anx7625, addr); + anx7625->client->addr = (addr >> 1); + for (i = 0; i < 5; i++) { + ret = i2c_smbus_write_byte_data( + anx7625->client, offset, val); + if (ret >= 0) + break; + pr_err("failed to write anx7625 %x:%x, retry %d...\n", + addr, offset, i); + usleep_range(1000, 1100); + } + return 0; +} + +static int reg_read_block(struct anx7625 *anx7625, + int addr, int offset, u8 *buf, int len) +{ + int ret, i; + + Reg_Access_Conflict_Workaround(anx7625, addr); + anx7625->client->addr = (addr >> 1); + for (i = 0; i < 5; i++) { + ret = i2c_smbus_read_i2c_block_data( + anx7625->client, offset, len, buf); + if (ret >= 0) + break; + pr_err("failed to read anx7625 %x:%x, retry %d...\n", + addr, offset, i); + usleep_range(1000, 1100); + } + return 0; +} + +static int reg_write_block(struct anx7625 *anx7625, + int addr, int offset, u8 *buf, int len) +{ + int ret, i; + + Reg_Access_Conflict_Workaround(anx7625, addr); + anx7625->client->addr = (addr >> 1); + for (i = 0; i < 5; i++) { + ret = i2c_smbus_write_i2c_block_data( + anx7625->client, offset, len, buf); + if (ret >= 0) + break; + pr_err("failed to write anx7625 %x:%x, retry %d...\n", + addr, offset, i); + usleep_range(1000, 1100); + } + return 0; +} + +#define mipi_pixel_frequency(id) \ + mipi_video_timing_table[id].MIPI_pixel_frequency +#define mipi_lane_count(id) \ + mipi_video_timing_table[id].MIPI_lane_count +#define mipi_m_value(id) \ + mipi_video_timing_table[id].M +#define mipi_n_value(id) \ + mipi_video_timing_table[id].N +#define mipi_post_divider(id) \ + mipi_video_timing_table[id].post_divider +#define mipi_diff_ratio(id) \ + mipi_video_timing_table[id].diff_ratio +#define mipi_compress_ratio(id) \ + mipi_video_timing_table[id].compress_ratio + +#define mipi_original_htotal(id) \ + mipi_video_timing_table[id].MIPI_inputl[0].MIPI_HTOTAL +#define mipi_original_hactive(id) \ + mipi_video_timing_table[id].MIPI_inputl[0].MIPI_HActive +#define mipi_original_vtotal(id) \ + mipi_video_timing_table[id].MIPI_inputl[0].MIPI_VTOTAL +#define mipi_original_vactive(id) \ + mipi_video_timing_table[id].MIPI_inputl[0].MIPI_VActive +#define mipi_original_hfp(id) \ + mipi_video_timing_table[id].MIPI_inputl[0].MIPI_H_Front_Porch +#define mipi_original_hsw(id) \ + mipi_video_timing_table[id].MIPI_inputl[0].MIPI_H_Sync_Width +#define mipi_original_hbp(id) \ + mipi_video_timing_table[id].MIPI_inputl[0].MIPI_H_Back_Porch +#define mipi_original_vfp(id) \ + mipi_video_timing_table[id].MIPI_inputl[0].MIPI_V_Front_Porch +#define mipi_original_vsw(id) \ + mipi_video_timing_table[id].MIPI_inputl[0].MIPI_V_Sync_Width +#define mipi_original_vbp(id) \ + mipi_video_timing_table[id].MIPI_inputl[0].MIPI_V_Back_Porch + +#define mipi_decompressed_htotal(id) \ + mipi_video_timing_table[id].MIPI_inputl[1].MIPI_HTOTAL +#define mipi_decompressed_hactive(id) \ + mipi_video_timing_table[id].MIPI_inputl[1].MIPI_HActive +#define mipi_decompressed_vtotal(id) \ + mipi_video_timing_table[id].MIPI_inputl[1].MIPI_VTOTAL +#define mipi_decompressed_vactive(id) \ + mipi_video_timing_table[id].MIPI_inputl[1].MIPI_VActive +#define mipi_decompressed_hfp(id) \ + mipi_video_timing_table[id].MIPI_inputl[1].MIPI_H_Front_Porch +#define mipi_decompressed_hsw(id) \ + mipi_video_timing_table[id].MIPI_inputl[1].MIPI_H_Sync_Width +#define mipi_decompressed_hbp(id) \ + mipi_video_timing_table[id].MIPI_inputl[1].MIPI_H_Back_Porch +#define mipi_decompressed_vfp(id) \ + mipi_video_timing_table[id].MIPI_inputl[1].MIPI_V_Front_Porch +#define mipi_decompressed_vsw(id) \ + mipi_video_timing_table[id].MIPI_inputl[1].MIPI_V_Sync_Width +#define mipi_decompressed_vbp(id) \ + mipi_video_timing_table[id].MIPI_inputl[1].MIPI_V_Back_Porch + +#define video_3d(id) mipi_video_timing_table[id].video_3D_type + +static unsigned char PPS_4K[] = { /*VC707 (DPI+DSC)*/ + 0x11, 0x00, 0x00, 0x89, 0x10, 0x80, 0x08, 0x70, + 0x0f, 0x00, 0x00, 0x08, 0x07, 0x80, 0x07, 0x80, + 0x02, 0x00, 0x04, 0xc0, 0x00, 0x20, 0x01, 0x1e, + 0x00, 0x1a, 0x00, 0x0c, 0x0d, 0xb7, 0x03, 0x94, + 0x18, 0x00, 0x10, 0xf0, 0x03, 0x0c, 0x20, 0x00, + 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, + 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, + 0x7d, 0x7e, 0x01, 0x02, 0x01, 0x00, 0x09, 0x40, + 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8, + 0x1a, 0x38, 0x1a, 0x78, 0x1a, 0xb6, 0x2a, 0xf6, + 0x2b, 0x34, 0x2b, 0x74, 0x3b, 0x74, 0x6b, 0xf4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char PPS_AR[] = {/*1440x2560@70*/ + 0x11, 0x00, 0x00, 0x89, 0x30, 0x80, 0x0A, 0x00, + 0x05, 0xA0, 0x00, 0x10, 0x05, 0xa0, 0x05, 0xa0, + 0x02, 0x00, 0x03, 0xd0, 0x00, 0x20, 0x02, 0x33, + 0x00, 0x14, 0x00, 0x0c, 0x06, 0x67, 0x02, 0x63, + 0x18, 0x00, 0x10, 0xf0, 0x03, 0x0c, 0x20, 0x00, + 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, + 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, + 0x7d, 0x7e, 0x01, 0x02, 0x01, 0x00, 0x09, 0x40, + 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8, + 0x1a, 0x38, 0x1a, 0x78, 0x1a, 0xb6, 0x2a, 0xf6, + 0x2b, 0x34, 0x2b, 0x74, 0x3b, 0x74, 0x6b, 0xf4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char PPS_Custom[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const struct RegisterValueConfig Bit_Matrix[] = { + {TX_P2, AUDIO_CONTROL_REGISTER, 0x80}, + {TX_P2, VIDEO_BIT_MATRIX_12, 0x18}, + {TX_P2, VIDEO_BIT_MATRIX_13, 0x19}, + {TX_P2, VIDEO_BIT_MATRIX_14, 0x1a}, + {TX_P2, VIDEO_BIT_MATRIX_15, 0x1b}, + {TX_P2, VIDEO_BIT_MATRIX_16, 0x1c}, + {TX_P2, VIDEO_BIT_MATRIX_17, 0x1d}, + {TX_P2, VIDEO_BIT_MATRIX_18, 0x1e}, + {TX_P2, VIDEO_BIT_MATRIX_19, 0x1f}, + {TX_P2, VIDEO_BIT_MATRIX_20, 0x20}, + {TX_P2, VIDEO_BIT_MATRIX_21, 0x21}, + {TX_P2, VIDEO_BIT_MATRIX_22, 0x22}, + {TX_P2, VIDEO_BIT_MATRIX_23, 0x23}, + {0x00, 0x00, 0x00} +}; + +static struct MIPI_Video_Format mipi_video_timing_table[] = { + /* lane_count--pixel_clk-----M---N--div- */ + /* -diff--compr--3d--table--custom0--custom1*/ + /* original timing */ + /* total-H active-Vtotal-V active-HFP-HSW-HBP-VFP-VSW-VBP*/ + /* decompressed timing */ + /* tota-H active-Vtotal-V active-HFP-HSW-HBP-VFP-VSW-VBP*/ + { + 0, "720x480@60", 3, 27000000, 0xC00000, 0x100000, 0x0B, + 0x3B, 0, VIDEO_3D_NONE, NULL, Bit_Matrix, NULL, + { { 858, 720, 525, 480, 16, 60, 62, 10, 6, 29 } } + }, + { + 1, "1280X720P@60", 3, 74250000, 0xB00000, 0x080000, 0x07, + 0x3A, 0, VIDEO_3D_NONE, NULL, Bit_Matrix, NULL, + { { 1650, 1280, 750, 720, 110, 40, 220, 5, 5, 20 } } + }, + { + 2, "1920x1080p@30", 3, 74000000, 0x940000, 0x06C000, 0x07, + 0x3B, 0, VIDEO_3D_NONE, NULL, Bit_Matrix, NULL, + { { 2200, 1920, 1125, 1080, 88, 44, 148, 4, 5, 36 } } + }, + { + 3, "1920x1080p@60", 3, 148500000, 0xB00000, 0x080000, 0x03, + 0x37, 0, VIDEO_3D_NONE, NULL, Bit_Matrix, NULL, + { { 2200, 1920, 1125, 1080, 88, 44, 148, 4, 5, 36 } } + }, + /*MTK 4K24 DPI*/ + { + 4, "3840x2160@24", 3, 297000000, 0xB00000, 0x080000, 0x01, + 0x37, 3, VIDEO_3D_NONE, PPS_4K, Bit_Matrix, NULL, + { { 1650, 1280, 2250, 2160, 242, 30, 98, 8, 10, 72 }, + { 4950, 3840, 2250, 2160, 726, 90, 294, 8, 10, 72 } + } + }, + /*MTK 4K30 DPI*/ + { + 5, "3840x2160@30", 3, 297000000, 0xB00000, 0x080000, 0x01, + 0x37, 3, VIDEO_3D_NONE, PPS_4K, Bit_Matrix, NULL, + { { 1474, 1280, 2250, 2160, 66, 30, 98, 8, 10, 72 }, + { 4422, 3840, 2250, 2160, 198, 90, 294, 8, 10, 72 } + } + }, + + {/*DSI*/ + 6, "720x480@60", 3, 27000000, 0xC00000, 0x100000, 0x0B, + 0x3B, 0, VIDEO_3D_NONE, NULL, NULL, NULL, + { { 858, 720, 525, 480, 16, 60, 62, 10, 6, 29 } } + }, + {/*DSI*/ + 7, "1280X720P@60", 3, 74250000, 0xB00000, 0x080000, 0x07, + 0x3A, 0, VIDEO_3D_NONE, NULL, NULL, NULL, + { { 1650, 1280, 750, 720, 110, 40, 220, 5, 5, 20 } } + }, + {/*DSI*/ + 8, "1920x1080p@30", 3, 74250000, 0xB00000, 0x080000, 0x07, + 0x3B, 0, VIDEO_3D_NONE, NULL, NULL, NULL, + { { 2200, 1920, 1125, 1080, 88, 44, 148, 4, 5, 36 } } + }, + {/*DSI*/ + 9, "1920x1080p@60", 3, 148500000, 0xB00000, 0x080000, 0x03, + 0x37, 0, VIDEO_3D_NONE, NULL, NULL, NULL, + { { 2200, 1920, 1125, 1080, 88, 44, 148, 4, 5, 36 } } + }, + + /* 3840x2160p24 - MTK X30 -DSI*/ + {/*DSI*/ + 10, "3840x2160p24", 3, 268176696, 0xAA808D, 0x089544, 0x01, + 0x37, 3, VIDEO_3D_NONE, PPS_4K, NULL, NULL, + { { 1650, 1280, 2250, 2160, 242, 30, 98, 8, 10, 72 }, + { 4950, 3840, 2250, 2160, 726, 90, 294, 8, 10, 72 } + } + }, + /* 3840x2160p30 3:1 DSC - MTK X30 -DSI*/ + {/*DSI*/ + 11, "1280x2160p30", 3, 297000000, 0xA7B3AB, 0x07A120, 0x01, + 0x37, 3, VIDEO_3D_NONE, PPS_4K, NULL, NULL, + { { 1467, 1280, 2250, 2160, 66, 30, 91, 8, 10, 72 }, + { 4400, 3840, 2250, 2160, 198, 90, 272, 8, 10, 72 } + } + }, + + { + 12, "1440X2560P@70", 3, 285000000, 0xB00000, 0x080000, 0x01, + 0x37, 3, VIDEO_3D_NONE, PPS_AR, Bit_Matrix, NULL, + { {524, 480, 2576, 2560, 24, 10, 12, 6, 8, 2 }, + {1580, 1440, 2576, 2560, 80, 20, 40, 6, 8, 2} + } + }, + { + 13, "********@60", 0, 0, 0, 0, 0, + 0, 0, VIDEO_3D_NONE, NULL, NULL, NULL, + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } + }, + { + 14, "********@60", 0, 0, 0, 0, 0, + 0, 0, VIDEO_3D_NONE, NULL, NULL, NULL, + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } + }, + { + 15, "custom@DPI/DSI", 3, 297000000, 0xB00000, 0x080000, 0x01, + 0x37, 3, VIDEO_3D_NONE, PPS_Custom, Bit_Matrix, NULL, + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + } + }, +}; + +static inline struct anx7625 *bridge_to_anx7625(struct drm_bridge *bridge) +{ + return container_of(bridge, struct anx7625, bridge); +} + +#define write_dpcd_addr(addrh, addrm, addrl) \ + do { \ + unsigned int temp; \ + if (ReadReg(RX_P0, AP_AUX_ADDR_7_0) != (unchar)addrl) \ + WriteReg(RX_P0, AP_AUX_ADDR_7_0, (unchar)addrl); \ + if (ReadReg(RX_P0, AP_AUX_ADDR_15_8) != (unchar)addrm) \ + WriteReg(RX_P0, AP_AUX_ADDR_15_8, (unchar)addrm); \ + Read_Reg(RX_P0, AP_AUX_ADDR_19_16, &temp); \ + if ((unchar)(temp & 0x0F) != ((unchar)addrh & 0x0F)) \ + WriteReg(RX_P0, AP_AUX_ADDR_19_16, \ + (temp & 0xF0) | ((unchar)addrh)); \ + } while (0) + +static void wait_aux_op_finish(struct anx7625 *anx7625, unchar *err_flag) +{ + unchar cnt; + uint c; + + *err_flag = 0; + cnt = 150; + while (ReadReg(RX_P0, AP_AUX_CTRL_STATUS) & AP_AUX_CTRL_OP_EN) { + usleep_range(2000, 2100); + if ((cnt--) == 0) { + TRACE("aux operate failed!\n"); + *err_flag = 1; + break; + } + } + + Read_Reg(RX_P0, AP_AUX_CTRL_STATUS, &c); + if (c & 0x0F) { + TRACE1("wait aux operation status %02x\n", (uint)c); + *err_flag = 1; + } +} + +unchar sp_tx_aux_dpcdread_bytes(struct anx7625 *anx7625, + unchar addrh, unchar addrm, unchar addrl, + unchar cCount, unchar *pBuf) +{ + uint c, i; + unchar bOK; + + /*command and length*/ + c = ((cCount - 1) << 4) | 0x09; + WriteReg(RX_P0, AP_AUX_COMMAND, c); + /*address*/ + write_dpcd_addr(addrh, addrm, addrl); + /*aux en*/ + sp_write_reg_or(RX_P0, AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN); + usleep_range(2000, 2100); + /* TRACE3("auxch addr = 0x%02x%02x%02x\n", addrh,addrm,addrl);*/ + wait_aux_op_finish(anx7625, &bOK); + if (bOK == AUX_ERR) { + TRACE("aux read failed\n"); + return AUX_ERR; + } + + for (i = 0; i < cCount; i++) { + Read_Reg(RX_P0, AP_AUX_BUFF_START + i, &c); + *(pBuf + i) = c; + /*TRACE2("Buf[%d] = 0x%02x\n", (uint)i, *(pBuf + i));*/ + if (i >= MAX_BUF_CNT) + break; + } + + return AUX_OK; +} + +unchar sp_tx_aux_dpcdwrite_bytes(struct anx7625 *anx7625, + unchar addrh, unchar addrm, unchar addrl, + unchar cCount, unchar *pBuf) +{ + unchar c, i, ret; + + /*command and length*/ + c = ((cCount - 1) << 4) | 0x08; + WriteReg(RX_P0, AP_AUX_COMMAND, c); + /*address*/ + write_dpcd_addr(addrh, addrm, addrl); + /*data*/ + for (i = 0; i < cCount; i++) { + c = *pBuf; + pBuf++; + WriteReg(RX_P0, AP_AUX_BUFF_START + i, c); + + if (i >= 15) + break; + } + /*aux en*/ + sp_write_reg_or(RX_P0, AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN); + wait_aux_op_finish(anx7625, &ret); + TRACE("aux write done\n"); + return ret; +} + +static unchar sp_tx_aux_wr(struct anx7625 *anx7625, unchar offset) +{ + unchar c; + + WriteReg(RX_P0, AP_AUX_BUFF_START, offset); + WriteReg(RX_P0, AP_AUX_COMMAND, 0x04); + sp_write_reg_or(RX_P0, AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN); + wait_aux_op_finish(anx7625, &c); + + return c; +} + +static unchar sp_tx_aux_rd(struct anx7625 *anx7625, unchar len_cmd) +{ + unchar c; + + WriteReg(RX_P0, AP_AUX_COMMAND, len_cmd); + sp_write_reg_or(RX_P0, AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN); + wait_aux_op_finish(anx7625, &c); + + return c; +} + +static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) +{ + struct anx7625 *anx7625 = container_of(aux, struct anx7625, aux); + u8 *buffer = msg->buffer; + int err = 0; + + if (!buffer || !msg->size) + return 0; + + if ((msg->request & DP_AUX_NATIVE_READ) == DP_AUX_NATIVE_READ) { + err = sp_tx_aux_dpcdread_bytes(anx7625, + (msg->address >> 16) & 0xff, + (msg->address >> 8) & 0xff, + (msg->address) & 0xff, + msg->size, + buffer); + } else if ((msg->request & DP_AUX_NATIVE_WRITE) == + DP_AUX_NATIVE_WRITE) { + err = sp_tx_aux_dpcdwrite_bytes(anx7625, + (msg->address >> 16) & 0xff, + (msg->address >> 8) & 0xff, + (msg->address) & 0xff, + msg->size, + buffer); + } else if ((msg->request & DP_AUX_I2C_READ) == DP_AUX_I2C_READ) { + err = sp_tx_aux_rd(anx7625, ((msg->size - 1) << 4) | 0x01); + if (!err) { + ReadBlockReg(RX_P0, AP_AUX_BUFF_START, + msg->size, buffer); + } + } else if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE) { + WriteReg(RX_P0, AP_AUX_ADDR_7_0, (msg->address) & 0xff); + WriteReg(RX_P0, AP_AUX_ADDR_15_8, 0); + sp_write_reg_and(RX_P0, AP_AUX_ADDR_19_16, 0xf0); + err = sp_tx_aux_wr(anx7625, buffer[0]); + } + + msg->reply = DP_AUX_I2C_REPLY_ACK; + + if (err) + pr_err("anx7625 aux transfer failed %d\n", err); + + return msg->size; +} + +static int anx7625_enable_interrupts(struct anx7625 *anx7625) +{ + /* enable all interrupts */ + WriteReg(RX_P0, INTERFACE_INTR_MASK, 0x7f); + + return 0; +} + +static int anx7625_disable_interrupts(struct anx7625 *anx7625) +{ + /* disable all interrupts */ + WriteReg(RX_P0, INTERFACE_INTR_MASK, 0xff); + + return 0; +} + +static int anx7625_poweroff(struct anx7625 *anx7625) +{ + struct anx7625_platform_data *pdata = &anx7625->pdata; + + if (!anx7625->powered) + return 0; + + anx7625_disable_interrupts(anx7625); + + gpiod_set_value_cansleep(pdata->gpiod_reset, 0); + usleep_range(1000, 2000); + + gpiod_set_value_cansleep(pdata->gpiod_p_on, 0); + usleep_range(1000, 2000); + + anx7625->powered = false; + return 0; +} + +static int anx7625_poweron(struct anx7625 *anx7625) +{ + struct anx7625_platform_data *pdata = &anx7625->pdata; + + if (anx7625->powered) + return 0; + + gpiod_set_value_cansleep(pdata->gpiod_p_on, 1); + usleep_range(10000, 11000); + + gpiod_set_value_cansleep(pdata->gpiod_reset, 1); + usleep_range(10000, 11000); + + /* setup clock */ + WriteReg(RX_P0, XTAL_FRQ_SEL, XTAL_FRQ_27M); + + /*First, reset main ocm*/ + WriteReg(RX_P0, 0x88, 0x40); + + /* disable PD */ + WriteReg(RX_P0, AP_AV_STATUS, AP_DISABLE_PD); + + /*after configuration, start main ocm running.*/ + WriteReg(RX_P0, 0x88, 0x00); + + /* enable interrupt */ + anx7625_enable_interrupts(anx7625); + + anx7625->powered = true; + return 0; +} + +static void DSI_Video_Timing_Configuration(struct anx7625 *anx7625) +{ + int table_id = anx7625->mode_idx; + + /*configure clock*/ + WriteReg(RX_P0, PIXEL_CLOCK_L, + (mipi_pixel_frequency(table_id) / 1000000) & 0xFF); + WriteReg(RX_P0, PIXEL_CLOCK_H, + (mipi_pixel_frequency(table_id) / 1000000) >> 8); + /*lane count*/ + sp_write_reg_and(RX_P1, MIPI_LANE_CTRL_0, 0xfc); + sp_write_reg_or(RX_P1, MIPI_LANE_CTRL_0, + mipi_lane_count(table_id)); + /*Htotal*/ + WriteReg(RX_P2, HORIZONTAL_TOTAL_PIXELS_L, + mipi_original_htotal(table_id) & 0xFF); + WriteReg(RX_P2, HORIZONTAL_TOTAL_PIXELS_H, + mipi_original_htotal(table_id) >> 8); + /*Hactive*/ + WriteReg(RX_P2, HORIZONTAL_ACTIVE_PIXELS_L, + mipi_original_hactive(table_id) & 0xFF); + WriteReg(RX_P2, HORIZONTAL_ACTIVE_PIXELS_H, + mipi_original_hactive(table_id) >> 8); + /*HFP*/ + WriteReg(RX_P2, HORIZONTAL_FRONT_PORCH_L, + mipi_original_hfp(table_id) & 0xFF); + WriteReg(RX_P2, HORIZONTAL_FRONT_PORCH_H, + mipi_original_hfp(table_id) >> 8); + /*HWS*/ + WriteReg(RX_P2, HORIZONTAL_SYNC_WIDTH_L, + mipi_original_hsw(table_id) & 0xFF); + WriteReg(RX_P2, HORIZONTAL_SYNC_WIDTH_H, + mipi_original_hsw(table_id) >> 8); + /*HBP*/ + WriteReg(RX_P2, HORIZONTAL_BACK_PORCH_L, + mipi_original_hbp(table_id) & 0xFF); + WriteReg(RX_P2, HORIZONTAL_BACK_PORCH_H, + mipi_original_hbp(table_id) >> 8); + /*Vactive*/ + WriteReg(RX_P2, ACTIVE_LINES_L, + mipi_original_vactive(table_id) & 0xFF); + WriteReg(RX_P2, ACTIVE_LINES_H, + mipi_original_vactive(table_id) >> 8); + /*VFP*/ + WriteReg(RX_P2, VERTICAL_FRONT_PORCH, + mipi_original_vfp(table_id)); + /*VWS*/ + WriteReg(RX_P2, VERTICAL_SYNC_WIDTH, + mipi_original_vsw(table_id)); + /*VBP*/ + WriteReg(RX_P2, VERTICAL_BACK_PORCH, + mipi_original_vbp(table_id)); + /*M value*/ + WriteReg(RX_P1, MIPI_PLL_M_NUM_23_16, + (mipi_m_value(table_id) >> 16) & 0xff); + WriteReg(RX_P1, MIPI_PLL_M_NUM_15_8, + (mipi_m_value(table_id) >> 8) & 0xff); + WriteReg(RX_P1, MIPI_PLL_M_NUM_7_0, + mipi_m_value(table_id) & 0xff); + /*N value*/ + WriteReg(RX_P1, MIPI_PLL_N_NUM_23_16, + (mipi_n_value(table_id) >> 16) & 0xff); + WriteReg(RX_P1, MIPI_PLL_N_NUM_15_8, + (mipi_n_value(table_id) >> 8) & 0xff); + WriteReg(RX_P1, MIPI_PLL_N_NUM_7_0, + mipi_n_value(table_id) & 0xff); + /*diff*/ + WriteReg(RX_P1, MIPI_DIGITAL_ADJ_1, + mipi_diff_ratio(table_id)); +} + +static void API_ODFC_Configuration(struct anx7625 *anx7625) +{ + int table_id = anx7625->mode_idx; + + /*config input reference clock frequency 27MHz/19.2MHz*/ + sp_write_reg_and(RX_P1, MIPI_DIGITAL_PLL_16, + ~(REF_CLK_27000kHz << MIPI_FREF_D_IND)); + sp_write_reg_or(RX_P1, MIPI_DIGITAL_PLL_16, + (((XTAL_FRQ >= 26000000UL) && (XTAL_FRQ <= 27000000UL)) ? + (REF_CLK_27000kHz << MIPI_FREF_D_IND) + : (REF_CLK_19200kHz << MIPI_FREF_D_IND))); + /*post divider*/ + sp_write_reg_and(RX_P1, MIPI_DIGITAL_PLL_8, 0x0f); + sp_write_reg_or(RX_P1, MIPI_DIGITAL_PLL_8, + mipi_post_divider(table_id) << 4); + + /*add patch for MIS2-125 (5pcs ANX7625 fail ATE MBIST test)*/ + sp_write_reg_and(RX_P1, MIPI_DIGITAL_PLL_7, + ~MIPI_PLL_VCO_TUNE_REG_VAL); + + /*reset ODFC PLL*/ + sp_write_reg_and(RX_P1, MIPI_DIGITAL_PLL_7, + ~MIPI_PLL_RESET_N); + sp_write_reg_or(RX_P1, MIPI_DIGITAL_PLL_7, + MIPI_PLL_RESET_N); + /*force PLL lock*/ + //WriteReg(TX_P0, DP_CONFIG_24, 0x0c); +} + +static void DSC_Video_Timing_Configuration(struct anx7625 *anx7625, + unsigned char table_id) +{ + unchar i; + + /*config uncompressed video format*/ + /*Htotal*/ + WriteReg(TX_P2, HORIZONTAL_TOTAL_PIXELS_L, + (mipi_original_htotal(table_id) * mipi_compress_ratio(table_id)) + & 0xFF); + WriteReg(TX_P2, HORIZONTAL_TOTAL_PIXELS_H, + (mipi_original_htotal(table_id) * mipi_compress_ratio(table_id)) + >> 8); + /*Hactive*/ + WriteReg(TX_P2, HORIZONTAL_ACTIVE_PIXELS_L, + (mipi_original_hactive(table_id) + * mipi_compress_ratio(table_id)) & 0xFF); + WriteReg(TX_P2, HORIZONTAL_ACTIVE_PIXELS_H, + (mipi_original_hactive(table_id) + * mipi_compress_ratio(table_id)) >> 8); + /*HFP*/ + WriteReg(TX_P2, HORIZONTAL_FRONT_PORCH_L, + (mipi_original_hfp(table_id) * mipi_compress_ratio(table_id)) + & 0xFF); + WriteReg(TX_P2, HORIZONTAL_FRONT_PORCH_H, + (mipi_original_hfp(table_id) * mipi_compress_ratio(table_id)) + >> 8); + /*HWS*/ + WriteReg(TX_P2, HORIZONTAL_SYNC_WIDTH_L, + (mipi_original_hsw(table_id) * mipi_compress_ratio(table_id)) + & 0xFF); + WriteReg(TX_P2, HORIZONTAL_SYNC_WIDTH_H, + (mipi_original_hsw(table_id) * mipi_compress_ratio(table_id)) + >> 8); + /*HBP*/ + WriteReg(TX_P2, HORIZONTAL_BACK_PORCH_L, + (mipi_original_hbp(table_id) * mipi_compress_ratio(table_id)) + & 0xFF); + WriteReg(TX_P2, HORIZONTAL_BACK_PORCH_H, + (mipi_original_hbp(table_id) * mipi_compress_ratio(table_id)) + >> 8); + /*Vtotal*/ + WriteReg(TX_P2, TOTAL_LINES_L, + mipi_original_vtotal(table_id) & 0xFF); + WriteReg(TX_P2, TOTAL_LINES_H, + mipi_original_vtotal(table_id) >> 8); + /*Vactive*/ + WriteReg(TX_P2, ACTIVE_LINES_L, + mipi_original_vactive(table_id) & 0xFF); + WriteReg(TX_P2, ACTIVE_LINES_H, + mipi_original_vactive(table_id) >> 8); + /*VFP*/ + WriteReg(TX_P2, VERTICAL_FRONT_PORCH, + mipi_original_vfp(table_id)); + /*VWS*/ + WriteReg(TX_P2, VERTICAL_SYNC_WIDTH, + mipi_original_vsw(table_id)); + /*VBP*/ + WriteReg(TX_P2, VERTICAL_BACK_PORCH, + mipi_original_vbp(table_id)); + + /*config uncompressed video format to woraround */ + /* downstream compatibility issues*/ + /*Htotal*/ + WriteReg(RX_P0, TOTAL_PIXEL_L_7E, + mipi_decompressed_htotal(table_id) & 0xFF); + WriteReg(RX_P0, TOTAL_PIXEL_H_7E, + mipi_decompressed_htotal(table_id) >> 8); + /*Hactive*/ + WriteReg(RX_P0, ACTIVE_PIXEL_L_7E, + mipi_decompressed_hactive(table_id) & 0xFF); + WriteReg(RX_P0, ACTIVE_PIXEL_H_7E, + mipi_decompressed_hactive(table_id) >> 8); + /*HFP*/ + WriteReg(RX_P0, HORIZON_FRONT_PORCH_L_7E, + mipi_decompressed_hfp(table_id) & 0xFF); + WriteReg(RX_P0, HORIZON_FRONT_PORCH_H_7E, + mipi_decompressed_hfp(table_id) >> 8); + /*HWS*/ + WriteReg(RX_P0, HORIZON_SYNC_WIDTH_L_7E, + mipi_decompressed_hsw(table_id) & 0xFF); + WriteReg(RX_P0, HORIZON_SYNC_WIDTH_H_7E, + mipi_decompressed_hsw(table_id) >> 8); + /*HBP*/ + WriteReg(RX_P0, HORIZON_BACK_PORCH_L_7E, + mipi_decompressed_hbp(table_id) & 0xFF); + WriteReg(RX_P0, HORIZON_BACK_PORCH_H_7E, + mipi_decompressed_hbp(table_id) >> 8); + + /*config DSC decoder internal blank timing for decoder to start*/ + WriteReg(RX_P1, H_BLANK_L, ((mipi_original_htotal(table_id) + - mipi_original_hactive(table_id))) & 0xFF); + WriteReg(RX_P1, H_BLANK_H, ((mipi_original_htotal(table_id) + - mipi_original_hactive(table_id))) >> 8); + + /*compress ratio RATIO [7:6] 3:div2; 0,1,2:div3*/ + sp_write_reg_and(RX_P0, R_I2C_1, 0x3f); + sp_write_reg_or(RX_P0, R_I2C_1, + (5 - mipi_compress_ratio(table_id)) << 6); + + /*PPS table*/ + if (mipi_video_timing_table[table_id].pps_reg != NULL) { + for (i = 0; i < 0x80; i += 0x10) + WriteBlockReg(RX_P2, R_PPS_REG_0 + i, 0x10, + (unsigned char *)mipi_video_timing_table + [table_id].pps_reg + i); + } +} + +static void API_Custom_Register0_Configuration(struct anx7625 *anx7625, + unsigned char table_id) +{ + unchar i = 0; + /*custom specific register*/ + if (mipi_video_timing_table[table_id].custom_reg0 != NULL) { + while (mipi_video_timing_table[table_id].custom_reg0[i] + .slave_addr) { + WriteReg(mipi_video_timing_table[table_id] + .custom_reg0[i].slave_addr, + mipi_video_timing_table[table_id] + .custom_reg0[i].reg, + mipi_video_timing_table[table_id] + .custom_reg0[i].val); + i++; + } + } +} + +static void API_Custom_Register1_Configuration(struct anx7625 *anx7625, + unsigned char table_id) +{ + unchar i = 0; + /*custom specific register*/ + if (mipi_video_timing_table[table_id].custom_reg1 != NULL) { + while (mipi_video_timing_table[table_id].custom_reg1[i] + .slave_addr) { + WriteReg(mipi_video_timing_table[table_id] + .custom_reg1[i].slave_addr, + mipi_video_timing_table[table_id] + .custom_reg1[i].reg, + mipi_video_timing_table[table_id] + .custom_reg1[i].val); + i++; + } + } +} + +static void swap_DSI_lane3(struct anx7625 *anx7625) +{ + unsigned char RegValue; + /* swap MIPI-DSI data lane 3 P and N */ + RegValue = ReadReg(RX_P1, MIPI_SWAP); + RegValue |= (1 << MIPI_SWAP_CH3); + WriteReg(RX_P1, MIPI_SWAP, RegValue); +} + +static void API_DSI_Configuration(struct anx7625 *anx7625, + unsigned char table_id) +{ + unsigned char RegValue; + + /* swap MIPI-DSI data lane 3 P and N */ + swap_DSI_lane3(anx7625); + + /* DSI clock settings */ + RegValue = (0 << MIPI_HS_PWD_CLK) | + (0 << MIPI_HS_RT_CLK) | + (0 << MIPI_PD_CLK) | + (1 << MIPI_CLK_RT_MANUAL_PD_EN) | + (1 << MIPI_CLK_HS_MANUAL_PD_EN) | + (0 << MIPI_CLK_DET_DET_BYPASS) | + (0 << MIPI_CLK_MISS_CTRL) | + (0 << MIPI_PD_LPTX_CH_MANUAL_PD_EN); + WriteReg(RX_P1, MIPI_PHY_CONTROL_3, RegValue); + + /* Decreased HS prepare timing delay from 160ns to 80ns work with + * a) Dragon board 810 series (Qualcomm Technologies, Inc AP) + * b) Moving DSI source (PG3A pattern generator + + * P332 D-PHY Probe) default D-PHY timing + */ + WriteReg(RX_P1, MIPI_TIME_HS_PRPR, 0x10); /* 5ns/step */ + + sp_write_reg_or(RX_P1, MIPI_DIGITAL_PLL_18, + SELECT_DSI<mode_idx < 10) + DSI_Configuration(anx7625, anx7625->mode_idx); + else + DSI_DSC_Configuration(anx7625, anx7625->mode_idx); + + return 0; +} + +static int anx7625_stop(struct anx7625 *anx7625) +{ + /*set mute flag*/ + sp_write_reg_or(RX_P0, AP_AV_STATUS, AP_MIPI_MUTE); + + /*clear mipi RX en*/ + sp_write_reg_and(RX_P0, AP_AV_STATUS, ~AP_MIPI_RX_EN); + + return 0; +} + +#define STS_HPD_CHANGE \ +(((sys_status&HPD_STATUS) != (anx7625->sys_sta_bak&HPD_STATUS)) ?\ + HPD_STATUS_CHANGE:0) + +static void handle_intr_vector(struct anx7625 *anx7625) +{ + unsigned char sys_status; + u8 intr_vector = ReadReg(RX_P0, INTERFACE_CHANGE_INT); + + WriteReg(RX_P0, INTERFACE_CHANGE_INT, + intr_vector & (~intr_vector)); + + sys_status = ReadReg(RX_P0, SYSTEM_STSTUS); + + if ((~INTR_MASK_SETTING) & + ((intr_vector & HPD_STATUS_CHANGE) | STS_HPD_CHANGE)) { + if (!(sys_status & HPD_STATUS)) { + anx7625->hpd_status = 0; + TRACE1("HPD low\n"); + if (anx7625->enabled) + anx7625_stop(anx7625); + } else { + anx7625->hpd_status = 1; + TRACE1("HPD high\n"); + if (anx7625->enabled) + anx7625_start(anx7625); + } + } + + anx7625->sys_sta_bak = sys_status; +} + +static int anx7625_init_pdata(struct anx7625 *anx7625) +{ + struct anx7625_platform_data *pdata = &anx7625->pdata; + struct device *dev = &anx7625->client->dev; + + /* GPIO for HPD */ + pdata->gpiod_cdet = devm_gpiod_get(dev, "cbl_det", GPIOD_IN); + if (IS_ERR(pdata->gpiod_cdet)) + return PTR_ERR(pdata->gpiod_cdet); + + /* GPIO for chip power enable */ + pdata->gpiod_p_on = devm_gpiod_get(dev, "power_en", GPIOD_OUT_LOW); + if (IS_ERR(pdata->gpiod_p_on)) + return PTR_ERR(pdata->gpiod_p_on); + + /* GPIO for chip reset */ + pdata->gpiod_reset = devm_gpiod_get(dev, "reset_n", GPIOD_OUT_LOW); + + return PTR_ERR_OR_ZERO(pdata->gpiod_reset); +} + +static int anx7625_get_mode_idx(const struct drm_display_mode *mode) +{ + struct MIPI_Video_Format *fmt; + int mode_idx = -1, categoly = 0, i; + + if (mode->htotal >= 3840) + categoly = 1; + + for (i = 6; i < sizeof(mipi_video_timing_table) / + sizeof(mipi_video_timing_table[0]); i++) { + fmt = &mipi_video_timing_table[i]; + if (fmt->MIPI_pixel_frequency == mode->clock * 1000 && + fmt->MIPI_inputl[categoly].MIPI_HTOTAL == + mode->htotal && + fmt->MIPI_inputl[categoly].MIPI_VTOTAL == + mode->vtotal && + fmt->MIPI_inputl[categoly].MIPI_HActive == + mode->hdisplay && + fmt->MIPI_inputl[categoly].MIPI_VActive == + mode->vdisplay && + fmt->MIPI_inputl[categoly].MIPI_H_Front_Porch == + mode->hsync_start - mode->hdisplay && + fmt->MIPI_inputl[categoly].MIPI_H_Sync_Width == + mode->hsync_end - mode->hsync_start && + fmt->MIPI_inputl[categoly].MIPI_H_Back_Porch == + mode->htotal - mode->hsync_end && + fmt->MIPI_inputl[categoly].MIPI_V_Front_Porch == + mode->vsync_start - mode->vdisplay && + fmt->MIPI_inputl[categoly].MIPI_V_Sync_Width == + mode->vsync_end - mode->vsync_start && + fmt->MIPI_inputl[categoly].MIPI_V_Back_Porch == + mode->vtotal - mode->vsync_end) { + mode_idx = i; + break; + } + } + + return mode_idx; +} + +static int anx7625_bridge_attach(struct drm_bridge *bridge) +{ + struct anx7625 *anx7625 = bridge_to_anx7625(bridge); + int err; + + if (!bridge->encoder) { + DRM_ERROR("Parent encoder object not found"); + return -ENODEV; + } + + /* Register aux channel */ + anx7625->aux.name = "DP-AUX"; + anx7625->aux.dev = &anx7625->client->dev; + anx7625->aux.transfer = anx7625_aux_transfer; + + err = drm_dp_aux_register(&anx7625->aux); + if (err < 0) { + DRM_ERROR("Failed to register aux channel: %d\n", err); + return err; + } + + return 0; +} + +static enum drm_mode_status +anx7625_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_mode *mode) +{ + if (anx7625_get_mode_idx(mode) < 0) { + pr_err("failed to find valid index\n"); + return MODE_NOMODE; + } + + return MODE_OK; +} + +static void anx7625_bridge_disable(struct drm_bridge *bridge) +{ + struct anx7625 *anx7625 = bridge_to_anx7625(bridge); + + mutex_lock(&anx7625->lock); + + anx7625_stop(anx7625); + + anx7625->enabled = false; + + mutex_unlock(&anx7625->lock); + + TRACE("anx7625 disabled\n"); +} + +static void anx7625_bridge_mode_set(struct drm_bridge *bridge, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct anx7625 *anx7625 = bridge_to_anx7625(bridge); + int mode_idx; + + mode_idx = anx7625_get_mode_idx(adjusted_mode); + + mutex_lock(&anx7625->lock); + + if (mode_idx >= 0) + anx7625->mode_idx = mode_idx; + else + DRM_ERROR("Failed to find pre-defined mode for %s\n", + mode->name); + + mutex_unlock(&anx7625->lock); +} + +static void anx7625_bridge_enable(struct drm_bridge *bridge) +{ + struct anx7625 *anx7625 = bridge_to_anx7625(bridge); + int err; + + mutex_lock(&anx7625->lock); + + anx7625->enabled = true; + + if (!anx7625->connected) + DRM_ERROR("cable is not connected\n"); + + if (!anx7625->hpd_status) + DRM_ERROR("hpd is not set\n"); + + err = anx7625_start(anx7625); + if (err) + DRM_ERROR("Failed to start: %d\n", err); + + mutex_unlock(&anx7625->lock); + + TRACE("anx7625 enabled\n"); +} + +static const struct drm_bridge_funcs anx7625_bridge_funcs = { + .attach = anx7625_bridge_attach, + .mode_valid = anx7625_bridge_mode_valid, + .disable = anx7625_bridge_disable, + .mode_set = anx7625_bridge_mode_set, + .enable = anx7625_bridge_enable, +}; + +static irqreturn_t anx7625_cdet_threaded_handler(int irq, void *data) +{ + struct anx7625 *anx7625 = data; + int connected; + + mutex_lock(&anx7625->lock); + + connected = gpiod_get_value_cansleep(anx7625->pdata.gpiod_cdet); + + if (anx7625->connected != connected) { + anx7625->connected = connected; + TRACE("cable status %d\n", connected); + } + + mutex_unlock(&anx7625->lock); + + return IRQ_HANDLED; +} + +static irqreturn_t anx7625_intp_threaded_handler(int unused, void *data) +{ + struct anx7625 *anx7625 = data; + unsigned char c; + + mutex_lock(&anx7625->lock); + + c = ReadReg(TCPC_INTERFACE, INTR_ALERT_1); + + if (c & INTR_SOFTWARE_INT) + handle_intr_vector(anx7625); + + while (ReadReg(RX_P0, + INTERFACE_CHANGE_INT) != 0) + handle_intr_vector(anx7625); + + if (c) + WriteReg(TCPC_INTERFACE, INTR_ALERT_1, 0xFF); + + mutex_unlock(&anx7625->lock); + + return IRQ_HANDLED; +} + +static const u16 anx7625_chipid_list[] = { + 0x7625, +}; + +static int anx7625_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct anx7625 *anx7625; + struct anx7625_platform_data *pdata; + unsigned int i, idl, idh, version[2]; + bool found = false; + int err; + + anx7625 = devm_kzalloc(&client->dev, sizeof(*anx7625), GFP_KERNEL); + if (!anx7625) + return -ENOMEM; + + pdata = &anx7625->pdata; + + mutex_init(&anx7625->lock); + + anx7625->client = client; + i2c_set_clientdata(client, anx7625); + + err = anx7625_init_pdata(anx7625); + if (err) { + DRM_ERROR("Failed to initialize pdata: %d\n", err); + return err; + } + + pdata->cdet_irq = gpiod_to_irq(pdata->gpiod_cdet); + if (pdata->cdet_irq < 0) { + DRM_ERROR("Failed to get CDET IRQ: %d\n", pdata->cdet_irq); + return -ENODEV; + } + + pdata->intp_irq = client->irq; + if (!pdata->intp_irq) { + DRM_ERROR("Failed to get INTP IRQ\n"); + return -ENODEV; + } + + /* Power on chip */ + err = anx7625_poweron(anx7625); + if (err) + goto err_poweroff; + + /* Look for supported chip ID */ + err = Read_Reg(TCPC_INTERFACE, PRODUCT_ID_L, &idl); + if (err) + goto err_poweroff; + + err = Read_Reg(TCPC_INTERFACE, PRODUCT_ID_H, &idh); + if (err) + goto err_poweroff; + + err = Read_Reg(RX_P0, OCM_FW_VERSION, &version[0]); + if (err) + goto err_poweroff; + + err = Read_Reg(RX_P0, OCM_FW_REVERSION, &version[1]); + if (err) + goto err_poweroff; + + anx7625->chipid = (u8)idl | ((u8)idh << 8); + + for (i = 0; i < ARRAY_SIZE(anx7625_chipid_list); i++) { + if (anx7625->chipid == anx7625_chipid_list[i]) { + DRM_INFO("Found ANX%x (ver. %x%x) Transmitter\n", + anx7625->chipid, version[0], version[1]); + found = true; + break; + } + } + + if (!found) { + DRM_ERROR("ANX%x (ver. %x%x) not supported by this driver\n", + anx7625->chipid, version[0], version[1]); + err = -ENODEV; + goto err_poweroff; + } + + err = devm_request_threaded_irq(&client->dev, pdata->cdet_irq, NULL, + anx7625_cdet_threaded_handler, + IRQF_TRIGGER_RISING + | IRQF_TRIGGER_RISING + | IRQF_ONESHOT, + "anx7625-hpd", anx7625); + if (err) { + DRM_ERROR("Failed to request CABLE_DET threaded IRQ: %d\n", + err); + goto err_poweroff; + } + + err = devm_request_threaded_irq(&client->dev, pdata->intp_irq, NULL, + anx7625_intp_threaded_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "anx7625-intp", anx7625); + if (err) { + DRM_ERROR("Failed to request INTP threaded IRQ: %d\n", err); + goto err_poweroff; + } + +#if IS_ENABLED(CONFIG_OF) + anx7625->bridge.of_node = client->dev.of_node; +#endif + + anx7625->bridge.funcs = &anx7625_bridge_funcs; + + drm_bridge_add(&anx7625->bridge); + + /* init connected status */ + anx7625->connected = + gpiod_get_value_cansleep(anx7625->pdata.gpiod_cdet); + + /* init hpd status */ + anx7625->sys_sta_bak = ReadReg(RX_P0, SYSTEM_STSTUS); + anx7625->hpd_status = (anx7625->sys_sta_bak & HPD_STATUS) ? + true : false; + + return 0; + +err_poweroff: + anx7625_poweroff(anx7625); + DRM_ERROR("Failed to load anx7625 driver: %d\n", err); + return err; +} + +static int anx7625_i2c_remove(struct i2c_client *client) +{ + struct anx7625 *anx7625 = i2c_get_clientdata(client); + + anx7625_poweroff(anx7625); + + drm_bridge_remove(&anx7625->bridge); + + kfree(anx7625->edid); + + return 0; +} + +static const struct i2c_device_id anx7625_id[] = { + { "anx7625", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, anx7625_id); + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id anx7625_id_match_table[] = { + { .compatible = "analogix,anx7625", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, anx7625_id_match_table); +#endif + +static struct i2c_driver anx7625_driver = { + .driver = { + .name = "anx7625", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = anx7625_id_match_table, +#endif + }, + .probe = anx7625_i2c_probe, + .remove = anx7625_i2c_remove, + .id_table = anx7625_id, +}; + +module_i2c_driver(anx7625_driver); +MODULE_DESCRIPTION("anx7625 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/bridge/analogix-anx7625.h b/drivers/gpu/drm/bridge/analogix-anx7625.h new file mode 100644 index 000000000000..2d78a133ed18 --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix-anx7625.h @@ -0,0 +1,1220 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Copyright(c) 2016, Analogix Semiconductor. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __MI2_REG_H__ +#define __MI2_REG_H__ + +#define DEBUG_LOG_OUTPUT + +#define _BIT0 0x01 +#define _BIT1 0x02 +#define _BIT2 0x04 +#define _BIT3 0x08 +#define _BIT4 0x10 +#define _BIT5 0x20 +#define _BIT6 0x40 +#define _BIT7 0x80 + +/***************************************************************/ +/*Register definition of device address 0x58*/ + +#define PRODUCT_ID_L 0x02 +#define PRODUCT_ID_H 0x03 + +#define TCPC_ROLE_CONTROL 0x1a +#define TCPC_COMMAND 0x23 + +#define ANALOG_CTRL_0 0xA0 +#define DFP_OR_UFP _BIT6 + +#define INTR_ALERT_1 0xCC +#define INTR_SOFTWARE_INT _BIT3 +#define INTR_RECEIVED_MSG _BIT5 + +#define TCPC_CONTROL 0x19 +/* bit positions */ +#define DEBUG_ACCESSORY_CONTROL 4 +#define BIST_TEST_MODE 1 +#define PLUG_ORIENTATION 0 + +#define POWER_CONTROL 0x1C +/* bit positions */ +#define DISABLE_VBUS_VOLTAGE_MONITOR 6 +#define DISABLE_VOLTAGE_ALARMS 5 +#define VCONN_POWER_SUPPORTED_CONTROL 1 +#define ENABLE_VCONN 0 + + + +#define ANALOG_CTRL_1 0xA1 + + +#define ANALOG_CTRL_9 0xA9 +/* bit positions */ +#define SAFE_MODE 7 +#define TEST_USB_PD_EN 6 +#define TEST_EN_MI 5 +#define BMC_MODE1_SEL_VL 3 +#define BMC_MODE1_CAP 0 + +#define TCPC_SWITCH_0 0xB4 +/* bit positions */ +#define SWAP_AUX_R 7 +#define SWAP_AUX_T 6 +#define SW_SEL1_5 5 +#define SW_SEL1_4 4 +#define SW_SEL1_3 3 +#define SW_SEL1_2 2 +#define SW_SEL1_1 1 +#define SW_SEL1_0 0 + +#define TCPC_SWITCH_1 0xB5 +/* bit positions */ +#define SW_SEL2_5 5 +#define SW_SEL2_4 4 +#define SW_SEL2_3 3 +#define SW_SEL2_2 2 +#define SW_SEL2_1 1 +#define SW_SEL2_0 0 + +#define CHIP_POWER_CTRL 0xB6 +/* bit positions */ +#define PD_V10_ODFC 5 +#define PD_V10_DPTX 4 +#define PU_DPTX 3 +#define PU_HDMIRX 2 +#define ISO_EN_N_T 1 +#define PU_PART_DIG 0 + +#define HPD_CTRL 0xBD +/* bit positions */ +#define HPD_OUT 5 +#define R_HPD_UNPLUG 4 +#define R_HPD_PLUGIN 3 +#define R_HPD_IRQ 2 +#define R_HPD_MODE 1 +#define R_HPD_OUT 0 + + + + + +/*================ END of I2C Address 0x58 ========================*/ + + + +/***************************************************************/ +/*Register definition of device address 0x70*/ +#define I2C_ADDR_70_DPTX 0x70 + +#define SYSTEM 0x80 +/* bit positions */ +#define CHIP_AUTH_RESET 7 +#define BYPASS_CHIP_AUTH 6 +#define HDCP_VERSION 5 +#define HDCP2_FW_EN 4 +#define HDCP2_HPD 3 +#define DET_STA 2 +#define FORCE_DET 1 +#define DET_CTRL 0 + +#define DP_CONFIG_3 0x84 +/* bit positions */ +/* bit[7:5] are bpc - bits per channel */ +#define BPC 5 +/* 011: 12 bit */ +/* 010: 10 bit */ +/* 001: 8 bit */ +/* 000: 6 bit */ +/* other: reserved */ +#define YC_COEFF 4 /* ITU-R BT.601 or BT.709 */ +#define D_RANGE 3 +/* color space and chroma format: */ +/* 00: RGB, 01: YCbCr422, */ +/* 10: YCbCr444, */ +/* 11: reserved */ +/* dynamic range: video or graphics */ +#define COLOR_F 1 +#define SYNC_MODE 0 + +#define SP_TX_LINK_BW_SET_REG 0xA0 +#define SP_TX_LANE_COUNT_SET_REG 0xA1 + +#define BUF_DATA_COUNT 0xE4 + +#define AUX_CTRL 0xE5 +#define AUX_ADDR_7_0 0xE6 +#define AUX_ADDR_15_8 0xE7 +#define AUX_ADDR_19_16 0xE8 + +#define SP_TX_INT_STATUS1 0xF7/*DISPLAYPORT_INTERRUPT*/ +#define POLLING_ERR 0x10 + +#define DP_CONFIG_24 0xB0 +#define POLLING_EN 0x02 + +#define DP_CONFIG_20 0xB8 +/* bit positions */ +/* bit[7:6] are reserved */ +#define M_VID_DEBUG 5 +#define NEW_PRBS7 4 +#define DIS_FIFO_RST 3 +#define DISABLE_AUTO_RESET_ENCODER 2 +#define INSERT_ER 1 +#define PRBS31_EN 0 +#define M_VID_0 0xC0 + +#define M_VID_1 0xC1 + +#define M_VID_2 0xC2 + +#define N_VID_0 0xC3 + +#define N_VID_1 0xC4 + +#define N_VID_2 0xC5 + + +#define BUF_DATA_0 0xF0 +#define SP_TX_AUX_STATUS 0xE0 + +#define AUX_CTRL2 0xE9 +#define ADDR_ONLY_BIT 0x02 +#define AUX_OP_EN 0x01 +/***************************************************************/ +/*Register definition of device address 0x72*/ +#define AUX_RST 0x04 +#define RST_CTRL2 0x07 + +#define SP_TX_TOTAL_LINE_STA_L 0x24 +#define SP_TX_TOTAL_LINE_STA_H 0x25 +#define SP_TX_ACT_LINE_STA_L 0x26 +#define SP_TX_ACT_LINE_STA_H 0x27 +#define SP_TX_V_F_PORCH_STA 0x28 +#define SP_TX_V_SYNC_STA 0x29 +#define SP_TX_V_B_PORCH_STA 0x2A +#define SP_TX_TOTAL_PIXEL_STA_L 0x2B +#define SP_TX_TOTAL_PIXEL_STA_H 0x2C +#define SP_TX_ACT_PIXEL_STA_L 0x2D +#define SP_TX_ACT_PIXEL_STA_H 0x2E +#define SP_TX_H_F_PORCH_STA_L 0x2F +#define SP_TX_H_F_PORCH_STA_H 0x30 +#define SP_TX_H_SYNC_STA_L 0x31 +#define SP_TX_H_SYNC_STA_H 0x32 +#define SP_TX_H_B_PORCH_STA_L 0x33 +#define SP_TX_H_B_PORCH_STA_H 0x34 +#define SP_TX_VID_CTRL 0x84 + +#define VIDEO_BIT_MATRIX_12 0x4c +#define VIDEO_BIT_MATRIX_13 0x4d +#define VIDEO_BIT_MATRIX_14 0x4e +#define VIDEO_BIT_MATRIX_15 0x4f +#define VIDEO_BIT_MATRIX_16 0x50 +#define VIDEO_BIT_MATRIX_17 0x51 +#define VIDEO_BIT_MATRIX_18 0x52 +#define VIDEO_BIT_MATRIX_19 0x53 +#define VIDEO_BIT_MATRIX_20 0x54 +#define VIDEO_BIT_MATRIX_21 0x55 +#define VIDEO_BIT_MATRIX_22 0x56 +#define VIDEO_BIT_MATRIX_23 0x57 + +#define AUDIO_CHANNEL_STATUS_1 0xd0 +#define AUDIO_CHANNEL_STATUS_2 0xd1 +#define AUDIO_CHANNEL_STATUS_3 0xd2 +#define AUDIO_CHANNEL_STATUS_4 0xd3 +#define AUDIO_CHANNEL_STATUS_5 0xd4 +#define AUDIO_CHANNEL_STATUS_6 0xd5 +#define TDM_SLAVE_MODE 0x10 +#define I2S_SLAVE_MODE 0x08 + +#define AUDIO_CONTROL_REGISTER 0xe6 +#define TDM_TIMING_MODE 0x08 + +#define I2C_ADDR_72_DPTX 0x72 + + +#define POWER_CONTROL_0 0x05 +/* bit positions */ +#define PD_REG 7 +#define PD_HDCP2 6 +#define PD_HDCP 5 +#define PD_AUDIO 4 +#define PD_VIDEO 3 +#define PD_LINK 2 +#define PD_TOTAL 1 +/* bit[0] is reserved */ + +#define RESET_CONTROL_0 0x06 +/* bit positions */ +#define MISC_RST 7 +#define VID_CAP_RST 6 +#define VID_FIFO_RST 5 +#define AUD_FIFO_RST 4 +#define AUD_RST 3 +#define HDCP_RST 2 +#define SW_RST 1 +#define HW_RST 0 + +#define VIDEO_CONTROL_0 0x08 +/* bit positions */ +#define VIDEO_EN 7 +/* bit[6] is reserved */ +/* DE re-generation mode: 1=enabled, 0=disabled */ +#define DE_GEN 5 +/* De YC-MUX: 1=enabled, 0=disabled */ +#define DEMUX 4 +/* bit[3] is reserved in MI-2 */ +#define HALF_FREQUENCY_MODE 3 +/* alwaysa set bit[2] to 1 in MI-2 */ +#define DDR_MODE 2 +#define DDR_CTRL 1 +#define NEGEDGE_LATCH 0 + + +#define VIDEO_CONTROL_2 0x0A +/* bit positions */ + /* YCbCr cofficients of input video: 1=ITU709, 0=ITU601 */ +#define IN_YC_COEFFI 7 + /* reserved in MI-2 */ +#define HDMI_HPD 6 +/* dalay one of DE: 1=enabled, 0=disabled */ +#define DE_DELAY 5 +/* update enable control of video format parameter in capture block: */ +/* 1=enabled, 0=disabled */ +#define VID_CHK_UPDATE_EN 4 +#define VIDEO_COLOR_SWAP 1 /* bit[3:1]: reserved in MI-2 */ +#define VIDEO_BIT_SWAP 0 /* reserved in MI-2 */ + +#define VIDEO_CONTROL_4 0x0C +/* bit positions */ +#define CSC_STD_SEL 7 +#define XVYCC_RNG_LMT 6 +#define RANGE_Y2R 5 /* reserved in MI-2 */ +#define CSPACE_Y2R 4 /* reserved in MI-2 */ +#define RGB_RNG_LMT 3 +#define YC_RNG_LMT 2 +#define RANGE_R2Y 1 +#define CSPACE_R2Y 0 + +#define VIDEO_CONTROL_5 0x0D +/* bit positions */ +#define TEST_PATTERN_EN 7 /* video BIST: 1=enabled, 0=disabled */ +#define VIDEO_PROCESS_EN 6 +#define IN_PIXEL_REPEAT 4 /* bit[5:4]: reserved in MI-2 */ +/* up sampling mode: 1=FIR filter, 0=copy sample */ +#define VID_US_MODE 3 +/* down sampling mode: 1=FIR filter, 0=skip sample */ +#define VID_DS_MODE 2 +/* reserved in MI-2 */ +#define UP_SAMPLE 1 +/* 4:4:4 to 4:2:2 down sampling: 1=enabled, 0=disabled */ +#define DOWN_SAMPLE 0 + + + +#define VIDEO_CONTROL_7 0x0F +/* bit positions */ +#define VID_HRES_TH 4 +#define VID_VRES_TH 0 + + +#define TOTAL_LINE_CFG_L 0x12 +#define TOTAL_LINE_CFG_H 0x13 /* note: bit[7:6] are reserved */ +#define ACTIVE_LINES_L 0x14 +#define ACTIVE_LINES_H 0x15 /* note: bit[7:6] are reserved */ +#define VERTICAL_FRONT_PORCH 0x16 +#define VERTICAL_SYNC_WIDTH 0x17 +#define VERTICAL_BACK_PORCH 0x18 + +#define HORIZONTAL_TOTAL_PIXELS_L 0x19 +#define HORIZONTAL_TOTAL_PIXELS_H 0x1A /* note: bit[7:6] are reserved */ +#define HORIZONTAL_ACTIVE_PIXELS_L 0x1B +#define HORIZONTAL_ACTIVE_PIXELS_H 0x1C /* note: bit[7:6] are reserved */ +#define HORIZONTAL_FRONT_PORCH_L 0x1D +#define HORIZONTAL_FRONT_PORCH_H 0x1E /* note: bit[7:4] are reserved */ +#define HORIZONTAL_SYNC_WIDTH_L 0x1F +#define HORIZONTAL_SYNC_WIDTH_H 0x20 /* note: bit[7:4] are reserved */ +#define HORIZONTAL_BACK_PORCH_L 0x21 +#define HORIZONTAL_BACK_PORCH_H 0x22 /* note: bit[7:4] are reserved */ + + + + +#define NFCU_02 0xC8 +#define NFCU_03 0xC9 +#define NFCU_04 0xCA +#define NFCU_05 0xCB + +/*======================= END of I2C Address 0x72 ===============*/ +/***************************************************************/ +/*Register definition of device address 0x7A*/ +#define DPPLL_REG4 0xF9 +/* bit positions */ +/* DPPLL_REG4[7:4] is not used */ +#define atest_enable 3 /* DPPLL_REG4[3] is analog signal test enable */ +/* 0: disable test analog signal + * 1: enable test analog signal + */ +#define dtest_enable 2 /* DPPLL_REG4[2] is digital signal test enable */ +/* 0: disable test digital signal + * 1: enable test digital signal + */ +#define test_sig_sel 0 /* DPPLL_REG4[1:0] is test signal selection */ +/* when atest_enable = 1, + * 00: vreg_1p45 + 01: duty_meas (decided by duty_outputen and duty_sel<1:0>) + 10: avdd10 + 11: vcox + */ +/* when dtest_enable = 1, + * 00: refbx (\wr 7e 42 f; \wr 7e 81 e1; \wr 7a f9 4 + ==> Now on WS pin, you'd see a 27 MHz clock.) + 01: ckfbx (\wr 7e 42 f; \wr 7e 81 e1; \wr 7a f9 5 + ==> Now on WS pin, you'd see a 27 MHz signal. + However, this signal is neither square wave nor sine wave, + it should be narrow pulses.) + 10: ck_vco + 11: avss10 + */ + + + + +/*================= END of I2C Address 0x7A =====================*/ + +/***************************************************************/ +/*Register definition of device address 0x7e*/ + +#define I2C_ADDR_7E_FLASH_CONTROLLER 0x7E + +#define R_BOOT_RETRY 0x00 +/* bit positions */ +#define SRAM_CS 4 +#define FUSE_WRITE 3 +#define FUSE_STATUS 2 +#define BOOT_RETRY_NUM 0 + +#define R_RAM_CTRL 0x05 +/* bit positions */ +#define FLASH_DONE 7 +#define BOOT_LOAD_DONE 6 +#define CRC_OK 5 +#define LOAD_DONE 4 +#define O_RW_DONE 3 +#define FUSE_BUSY 2 +#define DECRYPT_EN 1 +#define LOAD_START 0 + + +#define FUSE_DATA_IN7_0 0x0A +#define FUSE_DATA_IN15_8 0x0B +#define FUSE_DATA_IN23_16 0x0C + + +/* note: The actual implementation doesn't match register spec v0.5 */ +/* - High byte and low byte are reversed. */ +#define FLASH_ADDR_H 0x0F +#define FLASH_ADDR_L 0x10 + +/* note: The actual implementation doesn't match register spec v0.5 */ +/* - High byte and low byte are reversed. */ +#define EEPROM_ADDR_H 0x0F +#define EEPROM_ADDR_L 0x10 + + +#define FLASH_WRITE_BUF_BASE_ADDR 0x11 +#define FLASH_WRITE_MAX_LENGTH 0x20 + +#define EEPROM_WRITE_BUF_BASE_ADDR 0x11 +#define EEPROM_WRITE_MAX_LENGTH 0x10 + +#define AUTO_PD_MODE 0x2f/*0x6e*/ +#define AUTO_PD_ENABLE 0x02 +#define MAX_VOLTAGE_SETTING 0x29/*0xd0*/ +#define MAX_POWER_SETTING 0x2A/*0xd1*/ +#define MIN_POWER_SETTING 0x2B/*0xd2*/ +#define RDO_MAX_VOLTAGE 0x2C /* 0x7E:0x2C // 0xD3*/ +#define RDO_MAX_POWER 0x2D /* 0x7E:0x2D // 0xD4*/ +#define RDO_MAX_CURRENT 0x2E /* 0x7E:0x2E // 0xD5*/ + +/* note: 0 means 1 byte, x means (x+1) bytes; max x=31 */ +/* note: The actual implementation doesn't match register spec v0.5 */ +/* - High byte and low byte are reversed. */ +#define FLASH_LEN_H 0x31 +#define FLASH_LEN_L 0x32 + +/* note: The actual implementation doesn't match register spec v0.5 */ +/* - High byte and low byte are reversed. */ +#define EEPROM_LEN_H 0x31 +#define EEPROM_LEN_L 0x32 + +#define OCM_FW_VERSION 0x31 +#define OCM_FW_REVERSION 0x32 + +#define R_FLASH_RW_CTRL 0x33 +/* bit positions */ +#define READ_DELAY_SELECT 7 +#define GENERAL_INSTRUCTION_EN 6 +#define FLASH_ERASE_EN 5 +#define RDID_READ_EN 4 +#define REMS_READ_EN 3 +#define WRITE_STATUS_EN 2 +#define FLASH_READ 1 +#define FLASH_WRITE 0 + +/* the value to be written into Flash status register */ +#define STATUS_REGISTER_IN 0x34 +/* Flash REMS READ DATA (depend on Flash vendor definition) */ +#define REMS_READ_ADDR 0x35 + + + +/* This register is for single-byte commands only, i.e. */ +/* in Table 2 in GD25D10B datasheet, all the cells */ +/* following "Byte 1" in the row are blank. */ +/* For all other multi-byte commands, hardware has a wrapper, */ +/* and software shouldn't write the commands in this register directly. */ +#define GENERAL_INSTRUCTION_TYPE 0x36 +/* Flash operation commands - refer to Table 2 in GD25D10B/05B datasheet */ +#define WRITE_ENABLE 0x06 +#define WRITE_DISABLE 0x04 +#define DEEP_POWER_DOWN 0xB9 +#define DEEP_PD_REL 0xAB /* Release from Deep Power-Down */ +#define CHIP_ERASE_A 0xC7 +#define CHIP_ERASE_B 0x60 + +#define FLASH_ERASE_TYPE 0x37 +#define SECTOR_ERASE 0x20 +#define BLOCK_ERASE_32K 0x52 +#define BLOCK_ERASE_64K 0xD8 + +#define STATUS_REGISTER 0x38 /* Flash status register readback value */ +/* bit positions */ +/* Status Register Protect bit, operates in conjunction with */ +/* the Write Protect (WP#) signal */ +/* The SRP bit and WP signal set the device to the Hardware Protected mode.*/ +/* When the SRP = 1, and WP# signal is Low, the non-volatile bits */ +/* of the Status Register (SRP, BP2, BP1, BP0) */ +/* become read-only and the Write Status Register (WRSR) */ +/* instruction is not executed. */ +/* The default value of SRP bit is 0. */ +#define SRP0 7 + +/* Block Protect bits */ +/* These bits are non-volatile. They define the size of the area */ +/* to be software protected against Program and Erase commands. */ +/* These bits are written with the Write Status Register (WRSR) command. */ +/* When the (BP4, BP3, BP2, BP1, BP0) bits are set to 1, */ +/* the relevant memory area becomes protected against Page Program (PP), */ +/* Sector Erase (SE), and Block Erase (BE) commands. */ +/* Refer to Table 1.0 in GD25D10B/05B datasheet for details. */ +/* The (BP4, BP3, BP2, BP1, BP0) bits can be written provided that */ +/* the Hardware Protected mode has not been set. */ +#define BP4 6 +#define BP3 5 +#define BP2 4 +#define BP1 3 +#define BP0 2 + +/* Write Enable Latch bit, indicates the status of */ +/* the internal Write Enable Latch. */ +/* When WEL bit is 1, the internal Write Enable Latch is set. */ +/* When WEL bit is 0, the internal Write Enable Latch is reset, */ +/* and Write Status Register, Program or */ +/* Erase commands are NOT accepted. */ +/* The default value of WEL bit is 0. */ +#define WEL 1 + +/* Write In Progress bit, indicates whether the memory is busy */ +/* in program/erase/write status register progress. */ +/* When WIP bit is 1, it means the device is busy in */ +/* program/erase/write status register progress. */ +/* When WIP bit is 0, it means the device is not in */ +/* program/erase/write status register progress. */ +/* The default value of WIP bit is 0. */ +#define WIP 0 + +#define MANUFACTURE_ID 0x39 +#define DEVICE_ID 0x3A +#define MEM_TYPE 0x3B +#define CAPACITY 0x3C + + + +#define XTAL_FRQ_SEL 0x3F +/* bit field positions */ +#define XTAL_FRQ_SEL_POS 5 +/* bit field values */ +#define XTAL_FRQ_19M2 (0 << XTAL_FRQ_SEL_POS) +#define XTAL_FRQ_27M (4 << XTAL_FRQ_SEL_POS) + +#define R_DSC_CTRL_0 0x40 +/* bit positions */ +#define READ_STATUS_EN 7 +#define CLK_1MEG_RB 6 /* 1MHz clock reset; 0=reset, 0=reset release */ +#define DSC_BIST_DONE 1 /* bit[5:1]: 1=DSC MBIST pass */ +#define DSC_EN 0x01 /* 1=DSC enabled, 0=DSC disabled */ + +#define INTERFACE_INTR_MASK 0x43 +#define RECEIVED_MSG_MASK 1 +#define RECEIVED_ACK_MASK 2 +#define VCONN_CHANGE_MASK 4 +#define VBUS_CHANGE_MASK 8 +#define CC_STATUS_CHANGE_MASK 16 +#define DATA_ROLE_CHANGE_MASK 32 + +#define INTERFACE_CHANGE_INT 0x44 +#define RECEIVED_MSG 0x01 +#define RECEIVED_ACK 0x02 +#define VCONN_CHANGE 0x04 +#define VBUS_CHANGE 0x08 +#define CC_STATUS_CHANGE 0x10 +#define DATA_ROLE_CHANGE 0x20 +#define PR_CONSUMER_GOT_POWER 0x40 +#define HPD_STATUS_CHANGE 0x80 + +#define SYSTEM_STSTUS 0x45 +/*0: VCONN off; 1: VCONN on*/ +#define VCONN_STATUS 0x04 +/*0: vbus off; 1: vbus on*/ +#define VBUS_STATUS 0x08 +/*0: host; 1:device*/ +#define DATA_ROLE 0x20 + +#define HPD_STATUS 0x80 +#define NEW_CC_STATUS 0x46 + +#define GPIO_CTRL_0 0x47 +/* bit positions */ +#define GPIO_3_DATA 7 +#define GPIO_3_OEN 6 +#define GPIO_2_DATA 5 +#define GPIO_2_OEN 4 +#define GPIO_1_DATA 3 +#define GPIO_1_OEN 2 +#define GPIO_0_DATA 1 +#define GPIO_0_OEN 0 + +#define GPIO_CTRL_1 0x48 +/* bit positions */ +/* bit[7:4] are reserved */ +/* When bonding with Flash, this register will control the flash WP pin */ +#define FLASH_WP 3 +/* 0 = write protect, 1 = no write protect*/ +#define WRITE_UNPROTECTED 1 +#define WRITE_PROTECTED 0 +/* bit[2:0] are reserved */ + + +#define GPIO_CTRL_2 0x49 +/* bit positions */ +#define HPD_SOURCE 6 +#define GPIO_10_DATA 5 +#define GPIO_10_OEN 4 +#define GPIO_9_DATA 3 +#define GPIO_9_OEN 2 +#define GPIO_8_DATA 1 +#define GPIO_8_OEN 0 +#define GPIO_STATUS_1 0x4B +/* bit positions */ +#define OCM_RESET 2 +#define INTERRUPT_POLARITY 1 +#define INTERRUPT_OPEN_DRAIN 0 +#define TOTAL_PIXEL_L_7E 0x50 +#define TOTAL_PIXEL_H_7E 0x51 /* note: bit[7:6] are reserved */ + +#define ACTIVE_PIXEL_L_7E 0x52 +#define ACTIVE_PIXEL_H_7E 0x53 /* note: bit[7:6] are reserved */ + +#define HORIZON_FRONT_PORCH_L_7E 0x54 +/* note: bit[7:4] are EEPROM Key 0, which is not used in MI-2 */ +#define HORIZON_FRONT_PORCH_H_7E 0x55 + +#define HORIZON_SYNC_WIDTH_L_7E 0x56 +#define HORIZON_SYNC_WIDTH_H_7E 0x57 + +#define HORIZON_BACK_PORCH_L_7E 0x58 +#define HORIZON_BACK_PORCH_H_7E 0x59 + +#define FLASH_READ_BUF_BASE_ADDR 0x60 +#define FLASH_READ_MAX_LENGTH 0x20 + +#define EEPROM_READ_BUF_BASE_ADDR 0x60 +#define EEPROM_READ_MAX_LENGTH 0x10 + +#define DSC_REG_ADDR_H_F_PORCH_H 0x55 +/* bit positions */ +#define KEY_0 4 +#define HORIZON_FRONT_PORCH_H 0 + +#define DSC_REG_ADDR_H_SYNC_CFG_H 0x57 +/* bit positions */ +#define KEY_1 4 +#define HORIZON_SYNC_WIDTH_H 0 + +#define DSC_REG_ADDR_H_PORCH_CFG_H 0x59 +/* bit positions */ +#define KEY_2 4 +#define HORIZON_BACK_PORCH_H 0 +#define R_I2C_0 0x80 +/* bit positions */ +#define COL_CORE_RESET 7 +#define I2C_ASSERT_DELAY 0 + +#define R_I2C_1 0x81 +/* bit positions */ +#define RATIO 6 +#define DEBUG_OE 5 +#define ADDR_80H_SEL 4 +#define WRITE_DELAY_COUNTER 0 + +#define OCM_DEBUG_REG_8 0x88 +/* bit positions */ +#define STOP_MAIN_OCM 6 +#define AP_AUX_ADDR_7_0 0x11 +#define AP_AUX_ADDR_15_8 0x12 +#define AP_AUX_ADDR_19_16 0x13 + +/* note: bit[0:3] AUX status, bit 4 op_en, bit 5 address only */ +#define AP_AUX_CTRL_STATUS 0x14 +#define AP_AUX_CTRL_OP_EN 0x10 +#define AP_AUX_CTRL_ADDRONLY 0x20 + +#define AP_AUX_BUFF_START 0x15 +#define PIXEL_CLOCK_L 0x25 +#define PIXEL_CLOCK_H 0x26 + +#define AP_AUX_COMMAND 0x27 /*com+len*/ +/*bit 0&1: 3D video structure */ +/* 0x01: frame packing, 0x02:Line alternative, 0x03:Side-by-side(full)*/ +#define AP_AV_STATUS 0x28 +#define AP_VIDEO_CHG _BIT2 +#define AP_AUDIO_CHG _BIT3 +#define AP_MIPI_MUTE _BIT4 /* 1:MIPI input mute, 0: ummute*/ +#define AP_MIPI_RX_EN _BIT5 /* 1: MIPI RX input in 0: no RX in*/ +#define AP_DISABLE_PD _BIT6 +#define AP_DISABLE_DISPLAY _BIT7 +/***************************************************************/ +/*Register definition of device address 0x54*/ +#define TOTAL_LINES_L 0x12 +#define TOTAL_LINES_H 0x13 +#define ACTIVE_LINES_L 0x14 +#define ACTIVE_LINES_H 0x15 /* note: bit[7:6] are reserved */ +#define VERTICAL_FRONT_PORCH 0x16 +#define VERTICAL_SYNC_WIDTH 0x17 +#define VERTICAL_BACK_PORCH 0x18 + +#define HORIZONTAL_TOTAL_PIXELS_L 0x19 +#define HORIZONTAL_TOTAL_PIXELS_H 0x1A /* note: bit[7:6] are reserved */ +#define HORIZONTAL_ACTIVE_PIXELS_L 0x1B +#define HORIZONTAL_ACTIVE_PIXELS_H 0x1C /* note: bit[7:6] are reserved */ +#define HORIZONTAL_FRONT_PORCH_L 0x1D +#define HORIZONTAL_FRONT_PORCH_H 0x1E /* note: bit[7:4] are reserved */ +#define HORIZONTAL_SYNC_WIDTH_L 0x1F +#define HORIZONTAL_SYNC_WIDTH_H 0x20 /* note: bit[7:4] are reserved */ +#define HORIZONTAL_BACK_PORCH_L 0x21 +#define HORIZONTAL_BACK_PORCH_H 0x22 /* note: bit[7:5] are reserved */ + +#define R_PPS_REG_0 0x80 +/***************************************************************/ +/*Register definition of device address 0x84*/ +#define MIPI_PHY_CONTROL_1 0x01 +/* bit positions */ +#define MIPI_PD_LPCD_3 7 +#define MIPI_PD_LPCD_2 6 +#define MIPI_PD_LPCD_1 5 +#define MIPI_PD_LPCD_0 4 +#define MIPI_PD_3 3 +#define MIPI_PD_2 2 +#define MIPI_PD_1 1 +#define MIPI_PD_0 0 + + +#define MIPI_PHY_CONTROL_3 0x03 +/* bit positions */ +#define MIPI_HS_PWD_CLK 7 +#define MIPI_HS_RT_CLK 6 +#define MIPI_PD_CLK 5 +#define MIPI_CLK_RT_MANUAL_PD_EN 4 +#define MIPI_CLK_HS_MANUAL_PD_EN 3 +#define MIPI_CLK_DET_DET_BYPASS 2 +#define MIPI_CLK_MISS_CTRL 1 +#define MIPI_PD_LPTX_CH_MANUAL_PD_EN 0 + + +#define MIPI_LANE_CTRL_0 0x05 +/* bit positions */ +#define MIPI_DATA_REVERSE 7 +#define MIPI_SYNC_LEAD_REVERSE 6 +#define MIPI_FORCE_TIME_LPX 5 +#define MIPI_BYPASS_WAKE_UP 4 +#define MIPI_DESKEW_EN 3 +#define MIPI_EOTP_EN 2 +#define MIPI_ACTIVE_LANE 0 +/* bit[1:0] - 00: 1 lane, 01: 2 lanes, 10: 3 lanes, 11: 4 lanes */ +#define MIPI_TIME_HS_PRPR 0x08 + +/* After MIPI RX protocol layer received this many video frames, */ +/* protocol layer starts to reconstruct video stream from PHY */ +#define MIPI_VIDEO_STABLE_CNT 0x0A + + +#define MIPI_LANE_CTRL_10 0x0F +/* bit positions */ +#define MIPI_SW_RESET_N 7 +#define MIPI_ERROR_REPORT_EN 6 +#define MIPI_LANE_SWAP 4 +/* bit[5:4] - Debug mode to swap MIPI data lanes */ +#define MIPI_POWER_DOWN 3 +#define MIPI_ECC_ERR_CLR 2 +#define MIPI_PD_LPRX_CLK 1 +#define MIPI_9B8B_EN 0 + +#define MIPI_RX_REG0 0x10 +#define MIPI_RX_REG1 0x11 +#define MIPI_RX_REG2 0x12 +#define MIPI_RX_REG3 0x13 +#define MIPI_RX_REG4 0x14 +/* bit positions */ +#define hsrx_rterm 4 +/* MIPI_RX_REGx[7:4] is hsrx_rterm[3:0], */ +/* x=0~4; x=0~3 are for data lanes 0~3, x=4 is for clock */ + +/* defines the HS RX termination impedance: */ +/* 0000: 125 Ohm */ +/* 0110: 100 Ohm (default) */ +/* 1111: 75 Ohm */ +#define sel_hs_dly 1 +/* MIPI_RX_REGx[3:1] is sel_hs_dly[2:0],*/ +/* x=0~4; x=0~3 are for data lanes 0~3, x=4 is for clock */ +/* defines the hsrx data delay; adjust the data/clock edge timing*/ +/* 000: no timing adjust*/ +/* 001: add 80ps delay */ +/* ... */ +/* 100: add 4*80ps delay (default)*/ +/* ... */ +/* 111: add 7*80ps delay */ +/* For every step, the adjust delay is about 80ps @TT, 130ps@SS, 54ps@FF */ +/* note: The descriptions above come from an internal documentation */ +/* mi2-analog_pinlist_v1.4.xlsx. */ +/* Test shows the actual delay is around 110ps per step for TT chips.*/ +/* MIPI_RX_REGx[0] is reserved. */ + +#define MIPI_RX_REG5 0x15 +/* bit positions */ +#define ref_sel_lpcd 6 /* MIPI_RX_REG5[7:6] is ref_sel_lpcd[1:0] */ +/* define the lpcd reference voltage */ +/* 00: 250 mV */ +/* 01: 300 mV (default) */ +/* 10: 350 mV */ +/* 11: 400 mV */ +#define ref_sel_lprx 4 /* MIPI_RX_REG5[5:4] is ref_sel_lprx[1:0] */ +/* define the lprx reference voltage */ +/* 00: 650 mV */ +/* 01: 700 mV (default) */ +/* 10: 750 mV */ +/* 11: 800 mV */ +/* MIPI_RX_REG5[3] is reserved. */ +#define sel_lptx_term 0 /* MIPI_RX_REG5[2:0] is sel_lptx_term[2:0] */ +/* define the lptx termination (thermal code) */ +/* 111: 120 Ohm */ +/* 011: 150 Ohm */ +/* 001: 200 Ohm (default) */ +/* 000: 310 Ohm */ + +#define MIPI_RX_REG7 0x17 +/* bit positions */ +#define dpi_ck_delay 5 /* MIPI_RX_REG7[7:5] is dpi ck delay config */ +/* 0xx no delay */ +/* 100 120 ps */ +/* 101 120*2 ps (default) */ +/* 110 120*3 ps */ +/* 111 120*4 ps */ +/* MIPI_RX_REG7[4] is test enable: 1: enable, 0: disable */ +#define test_enable 4 +/* MIPI_RX_REG7[3:0] is test signal selection */ +#define test_signal_sel 0 +/* dtesto / atesto */ +/* 0000 pd_rt_ch2 / vref_lprx */ +/* 0001 pd_lpcd_ch2 / vref_lpcd */ +/* 0010 pd_lprx_ch2 / vgate_lp */ +/* 0011 pd_lptx_ch2 / avss */ +/* 0100 swap_ch2 */ +/* 0101 pd_rx */ +/* 0110 pd_ch2 */ +/* 0111 pd_hsrx_ch2 */ +/* 1000 lp_outn_ch2 */ +/* 1001 lp_outp_ch2 */ +/* 1010 lpcd_outn_ch2 */ +/* 1011 lpcd_outp_ch2 */ +/* 1100 data_ch2<2> */ +/* 1101 data_ch2<1> */ +/* 1110 data_ch2<0> */ +/* 1111 ck_byte_r */ + +#define MIPI_DIGITAL_ADJ_1 0x1B +/* bit positions */ +/* bit[7:4]: Integral part ratio of the adjust loop */ +#define DIFF_I_RATIO 4 +/* 0~7: 1/(2^(n+3)) */ +/* >= 8: reserved */ +/* bit[3:0]: The total adjust loop ratio to the feedback block */ +#define DIFF_K_RATIO 0 +/* 0~0xF: 1/(2^n) */ + +#define MIPI_PLL_M_NUM_23_16 0x1E +#define MIPI_PLL_M_NUM_15_8 0x1F +#define MIPI_PLL_M_NUM_7_0 0x20 +#define MIPI_PLL_N_NUM_23_16 0x21 +#define MIPI_PLL_N_NUM_15_8 0x22 +#define MIPI_PLL_N_NUM_7_0 0x23 + +#define MIPI_DIGITAL_PLL_6 0x2A +/* bit positions */ +/* bit[7:6]: VCO band control, only effective */ +/* when MIPI_PLL_FORCE_BAND_EN (0x84:0x2B[6]) is 1 */ +#define MIPI_PLL_BAND_REG 6 +/* f_vco frequency: */ +/* band 0: 1 ~ 1.15 GHz */ +/* band 1: 1.15 ~ 1.3 GHz */ +/* band 2: 1.3 ~ 1.5 GHz */ +/* band 3: 1.5 ~ 2.0 GHz */ + +/* band 3 is usable but not recommended, as using band 3: */ +/* a) The power consumption is higher. */ +/* b) For SS corner chips, VCO may not work at 2GHz. */ +/* bit 5 is reserved */ +#define MIPI_M_NUM_READY 0x10 +#define MIPI_N_NUM_READY 0x08 +#define STABLE_INTEGER_CNT_EN 0x04 +#define MIPI_PLL_TEST_BIT 0 +/* bit[1:0]: test point output select - */ +/* 00: VCO power, 01: dvdd_pdt, 10: dvdd, 11: vcox */ + +#define MIPI_DIGITAL_PLL_7 0x2B +/* bit positions */ +#define MIPI_PLL_FORCE_N_EN 7 +#define MIPI_PLL_FORCE_BAND_EN 6 + +#define MIPI_PLL_VCO_TUNE_REG 4 +/* bit[5:4]: VCO metal capacitance - */ +/* 00: +20% fast, 01: +10% fast (default), 10: typical, 11: -10% slow */ +#define MIPI_PLL_VCO_TUNE_REG_VAL 0x30 +/* bit[5:4]: VCO metal capacitance */ + +#define MIPI_PLL_PLL_LDO_BIT 2 +/* bit[3:2]: vco_v2i power - */ +/* 00: 1.40V, 01: 1.45V (default), 10: 1.50V, 11: 1.55V */ +#define MIPI_PLL_RESET_N 0x02 +#define MIPI_FRQ_FORCE_NDET 0 + + + +#define MIPI_ALERT_CLR_0 0x2D +/* bit positions */ +#define HS_link_error_clear 7 +/* This bit itself is S/C, and it clears 0x84:0x31[7] */ + + +#define MIPI_ALERT_OUT_0 0x31 +/* bit positions */ +#define check_sum_err_hs_sync 7 +/* This bit is cleared by 0x84:0x2D[7] */ + +#define MIPI_DIGITAL_PLL_8 0x33 +/* bit positions */ +#define MIPI_POST_DIV_VAL 4 +/* n means divided by (n+1), n = 0~15 */ +#define MIPI_EN_LOCK_FRZ 3 +#define MIPI_FRQ_COUNTER_RST 2 +#define MIPI_FRQ_SET_REG_8 1 +/* bit 0 is reserved */ + +#define MIPI_DIGITAL_PLL_9 0x34 + +#define MIPI_DIGITAL_PLL_16 0x3B +/* bit positions */ +#define MIPI_FRQ_FREEZE_NDET 7 +#define MIPI_FRQ_REG_SET_ENABLE 6 +#define MIPI_REG_FORCE_SEL_EN 5 +#define MIPI_REG_SEL_DIV_REG 4 +#define MIPI_REG_FORCE_PRE_DIV_EN 3 +/* bit 2 is reserved */ +#define MIPI_FREF_D_IND 1 +#define REF_CLK_27000kHz 1 +#define REF_CLK_19200kHz 0 +#define MIPI_REG_PLL_PLL_TEST_ENABLE 0 + +#define MIPI_DIGITAL_PLL_18 0x3D +/* bit positions */ +#define FRQ_COUNT_RB_SEL 7 +#define REG_FORCE_POST_DIV_EN 6 +#define MIPI_DPI_SELECT 5 +#define SELECT_DSI 1 +#define SELECT_DPI 0 +#define REG_BAUD_DIV_RATIO 0 + +#define H_BLANK_L 0x3E +/* for DSC only */ + +#define H_BLANK_H 0x3F +/* for DSC only; note: bit[7:6] are reserved */ + +#define MIPI_SWAP 0x4A +/* bit positions */ +#define MIPI_SWAP_CH0 7 +#define MIPI_SWAP_CH1 6 +#define MIPI_SWAP_CH2 5 +#define MIPI_SWAP_CH3 4 +#define MIPI_SWAP_CLK 3 +/* bit[2:0] are reserved */ + +#define MIPI_HS_FIRST_PACKET_HEADER 0x67 +#define MIPI_HS_FIRST_PACKET_WIDTH_L 0x68 +#define MIPI_HS_FIRST_PACKET_WIDTH_H 0x69 +#define MIPI_HS_FIRST_PACKET 0x6A + + + +/*========================= END of I2C Address 0x84 ================*/ + + +/* DEV_ADDR = 0x7A or 0x7B , MIPI Rx Registers*/ +/* DEV_ADDR = 0x7A or 0x7B , MIPI Rx Registers*/ +#define MIPI_ANALOG_PWD_CTRL0 0x00 +#define MIPI_ANALOG_PWD_CTRL1 0x01 +#define MIPI_ANALOG_PWD_CTRL2 0x02 + + + +/*DPCD regs*/ +#define DPCD_DPCD_REV 0x00 +#define DPCD_MAX_LINK_RATE 0x01 +#define DPCD_MAX_LANE_COUNT 0x02 + + +/***************************************************************/ + +/*Comands status*/ +enum interface_status { + CMD_SUCCESS, + CMD_REJECT, + CMD_FAIL, + CMD_BUSY, + CMD_STATUS +}; + +enum PD_MSG_TYPE { + TYPE_PWR_SRC_CAP = 0x00, + TYPE_PWR_SNK_CAP = 0x01, + TYPE_DP_SNK_IDENTITY = 0x02, + TYPE_SVID = 0x03, + TYPE_GET_DP_SNK_CAP = 0x04, + TYPE_ACCEPT = 0x05, + TYPE_REJECT = 0x06, + TYPE_PSWAP_REQ = 0x10, + TYPE_DSWAP_REQ = 0x11, + TYPE_GOTO_MIN_REQ = 0x12, + TYPE_VCONN_SWAP_REQ = 0x13, + TYPE_VDM = 0x14, + TYPE_DP_SNK_CFG = 0x15, + TYPE_PWR_OBJ_REQ = 0x16, + TYPE_PD_STATUS_REQ = 0x17, + TYPE_DP_ALT_ENTER = 0x19, + TYPE_DP_ALT_EXIT = 0x1A, + TYPE_GET_SNK_CAP = 0x1B, + TYPE_SOP_PRIME = 0x1C, + TYPE_SOP_DOUBLE_PRIME = 0x1D, + TYPE_RESPONSE_TO_REQ = 0xF0, + TYPE_SOFT_RST = 0xF1, + TYPE_HARD_RST = 0xF2, + TYPE_RESTART = 0xF3, + TYPE_EXT_SRC_CAP = 0xA1, /* Source_Capabilities_Extended*/ + TYPE_EXT_SRC_STS = 0xA2, /* Source_Status*/ + TYPE_EXT_GET_BATT_CAP = 0xA3, /* Get_Battery_Cap*/ + TYPE_EXT_GET_BATT_STS = 0xA4, /* Get_Battery_ Status*/ + TYPE_EXT_BATT_CAP = 0xA5, /* Battery_Capabilities*/ + TYPE_EXT_GET_MFR_INFO = 0xA6, /* Get_Manufacturer_Info*/ + TYPE_EXT_MFR_INFO = 0xA7, /* Manufacturer_Info*/ + TYPE_EXT_PDFU_REQUEST = 0xA8, /* FW update Request*/ + TYPE_EXT_PDFU_RESPONSE = 0xA9, /* FW update Response*/ + TYPE_EXT_BATT_STS = 0xAA, /* PD_DATA_BATTERY_STATUS*/ + TYPE_EXT_ALERT = 0xAB, /* PD_DATA_ALERT*/ + TYPE_EXT_NOT_SUPPORTED = 0xAC, /* PD_CTRL_NOT_SUPPORTED*/ + TYPE_EXT_GET_SRC_CAP = 0xAD, /* PD_CTRL_GET_SOURCE_CAP_EXTENDED*/ + TYPE_EXT_GET_SRC_STS = 0xAE, /* PD_CTRL_GET_STATUS*/ + TYPE_EXT_FR_SWAP = 0xAF, /* PD_CTRL_FR_SWAP*/ + TYPE_FR_SWAP_SIGNAL = 0xB0, /* Fast Role Swap signal*/ +}; + +/* PDO : Power Data Object + * 1. The vSafe5V Fixed Supply Object shall always be the first object. + * 2. The remaining Fixed Supply Objects, + * if present, shall be sent in voltage order; lowest to highest. + * 3. The Battery Supply Objects, + * if present shall be sent in Minimum Voltage order; lowest to highest. + * 4. The Variable Supply (non battery) Objects, + * if present, shall be sent in Minimum Voltage order; lowest to highest. + */ +#define PDO_TYPE_FIXED ((u32)0 << 30) +#define PDO_TYPE_BATTERY ((u32)1 << 30) +#define PDO_TYPE_VARIABLE ((u32)2 << 30) +#define PDO_TYPE_MASK ((u32)3 << 30) +#define PDO_FIXED_DUAL_ROLE ((u32)1 << 29) /* Dual role device */ +#define PDO_FIXED_SUSPEND ((u32)1 << 28) /* USB Suspend supported */ +#define PDO_FIXED_EXTERNAL ((u32)1 << 27) /* Externally powered */ +#define PDO_FIXED_COMM_CAP ((u32)1 << 26) /* USB Communications Capable */ +#define PDO_FIXED_DATA_SWAP ((u32)1 << 25) /* Data role swap command */ +#define PDO_FIXED_PEAK_CURR ((u32)1 << 20) /* [21..20] Peak current */ +/* Voltage in 50mV units */ +#define PDO_FIXED_VOLT(mv) (u32)((((u32)mv)/50) << 10) +/* Max current in 10mA units */ +#define PDO_FIXED_CURR(ma) (u32)((((u32)ma)/10)) + +/*build a fixed PDO packet*/ +#define PDO_FIXED(mv, ma, flags) \ + (PDO_FIXED_VOLT(mv)\ + | PDO_FIXED_CURR(ma)\ + | (flags)) + +/*Pos in Data Object, the first index number begin from 0 */ +#define PDO_INDEX(n, dat) (dat << (n * PD_ONE_DATA_OBJECT_SIZE*sizeof(u8))) +#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20) +#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10) +#define PDO_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 0) + +#define PDO_VAR(min_mv, max_mv, op_ma) \ + (PDO_VAR_MIN_VOLT(min_mv) | PDO_VAR_MAX_VOLT(max_mv) | \ + PDO_VAR_OP_CURR(op_ma) | PDO_TYPE_VARIABLE) +#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20) +#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10) +#define PDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 0) +#define PDO_BATT(min_mv, max_mv, op_mw) \ + (PDO_BATT_MIN_VOLT(min_mv)\ + | PDO_BATT_MAX_VOLT(max_mv)\ + | PDO_BATT_OP_POWER(op_mw)\ + | PDO_TYPE_BATTERY) + +#define GET_PDO_TYPE(PDO) ((PDO & PDO_TYPE_MASK) >> 30) +#define GET_PDO_FIXED_DUAL_ROLE(PDO) ((PDO & PDO_FIXED_DUAL_ROLE) >> 29) +#define GET_PDO_FIXED_SUSPEND(PDO) ((PDO & PDO_FIXED_SUSPEND) >> 28) +#define GET_PDO_FIXED_EXTERNAL(PDO) ((PDO & PDO_FIXED_EXTERNAL) >> 27) +#define GET_PDO_FIXED_COMM_CAP(PDO) ((PDO & PDO_FIXED_COMM_CAP) >> 26) +#define GET_PDO_FIXED_DATA_SWAP(PDO) ((PDO & PDO_FIXED_DATA_SWAP) >> 25) +#define GET_PDO_FIXED_PEAK_CURR(PDO) ((PDO >> 20) & 0x03) + +#define GET_PDO_FIXED_VOLT(PDO) (((PDO >> 10) & 0x3FF) * 50) +#define GET_PDO_FIXED_CURR(PDO) ((PDO & 0x3FF) * 10) +#define GET_VAR_MAX_VOLT(PDO) (((PDO >> 20) & 0x3FF) * 50) +#define GET_VAR_MIN_VOLT(PDO) (((PDO >> 10) & 0x3FF) * 50) +#define GET_VAR_MAX_CURR(PDO) ((PDO & 0x3FF) * 10) +#define GET_BATT_MAX_VOLT(PDO) (((PDO >> 20) & 0x3FF) * 50) +#define GET_BATT_MIN_VOLT(PDO) (((PDO >> 10) & 0x3FF) * 50) +#define GET_BATT_OP_POWER(PDO) (((PDO) & 0x3FF) * 250) + +#define INTERFACE_TIMEOUT 30 +#define InterfaceSendBuf_Addr 0xc0 +#define InterfaceRecvBuf_Addr 0xe0 +#define YES 1 +#define NO 0 +#define ERR_CABLE_UNPLUG -1 +#define PD_ONE_DATA_OBJECT_SIZE 4 +#define PD_MAX_DATA_OBJECT_NUM 7 +#define VDO_SIZE (PD_ONE_DATA_OBJECT_SIZE * PD_MAX_DATA_OBJECT_NUM) +#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP) + +/*5000mv voltage*/ +#define PD_VOLTAGE_5V 5000 + +#define PD_MAX_VOLTAGE_20V 20000 +#define PD_MAX_VOLTAGE_21V 21000 + +/*0.9A current */ +#define PD_CURRENT_900MA 900 +#define PD_CURRENT_1500MA 1500 + +#define PD_CURRENT_3A 3000 + +#define PD_POWER_15W 15000 + +#define PD_POWER_60W 60000 + +/* RDO : Request Data Object */ +#define RDO_OBJ_POS(n) (((u32)(n) & 0x7) << 28) +#define RDO_POS(rdo) ((((32)rdo) >> 28) & 0x7) +#define RDO_GIVE_BACK ((u32)1 << 27) +#define RDO_CAP_MISMATCH ((u32)1 << 26) +#define RDO_COMM_CAP ((u32)1 << 25) +#define RDO_NO_SUSPEND ((u32)1 << 24) +#define RDO_FIXED_VAR_OP_CURR(ma) (((((u32)ma) / 10) & 0x3FF) << 10) +#define RDO_FIXED_VAR_MAX_CURR(ma) (((((u32)ma) / 10) & 0x3FF) << 0) + +#define RDO_BATT_OP_POWER(mw) (((((u32)mw) / 250) & 0x3FF) << 10) +#define RDO_BATT_MAX_POWER(mw) (((((u32)mw) / 250) & 0x3FF) << 10) + +#define RDO_FIXED(n, op_ma, max_ma, flags) \ + (RDO_OBJ_POS(n) | (flags) | \ + RDO_FIXED_VAR_OP_CURR(op_ma) | \ + RDO_FIXED_VAR_MAX_CURR(max_ma)) + +#ifdef DEBUG_LOG_OUTPUT +#define TRACE pr_info +#define TRACE1 pr_info +#define TRACE2 pr_info +#define TRACE3 pr_info +#else +#define TRACE(fmt, arg...) +#define TRACE1(fmt, arg...) +#define TRACE2(fmt, arg...) +#define TRACE3(fmt, arg...) +#endif + +#define BYTE unsigned char +#define unchar unsigned char +#define uint unsigned int +#define ulong unsigned long + +enum { + VIDEO_3D_NONE = 0x00, + VIDEO_3D_FRAME_PACKING = 0x01, + VIDEO_3D_TOP_AND_BOTTOM = 0x02, + VIDEO_3D_SIDE_BY_SIDE = 0x03, +}; + +struct RegisterValueConfig { + unsigned char slave_addr; + unsigned char reg; + unsigned char val; +}; + +#define AUX_ERR 1 +#define AUX_OK 0 + +#define MAX_BUF_CNT 6 +#define INTR_MASK_SETTING 0x0 + +enum HDCP_CAP_TYPE { + NO_HDCP_SUPPORT = 0x00, + HDCP14_SUPPORT = 0x01, + HDCP22_SUPPORT = 0x02, + HDCP_ALL_SUPPORT = 0x03 +}; + +#define XTAL_FRQ 27000000UL /* MI-2 clock frequency in Hz: 27 MHz*/ + +#define FLASH_LOAD_STA 0x05 +#define FLASH_LOAD_STA_CHK (1<<7) + +#endif /* __MI2_REG_H__ */ -- GitLab From eb61a9d94dc6aeeee61bc300e71d5fe6e7b4c2fe Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Fri, 15 Jun 2018 09:34:34 -0700 Subject: [PATCH 0954/1299] sched/walt: improve the scheduler This change is for general scheduler improvement. Change-Id: I01e6610bba2e8c66a628d6289eeed4e854264fdd Signed-off-by: Satya Durga Srinivasu Prabhala Signed-off-by: Abhijeet Dharmapurikar --- include/linux/sched/sysctl.h | 1 + kernel/sched/fair.c | 9 ++++++++- kernel/sched/sched.h | 11 +++++++++++ kernel/sysctl.c | 9 +++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index 2df98acfeb5a..2dd27ce2840d 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -40,6 +40,7 @@ extern unsigned int sysctl_sched_boost; extern unsigned int sysctl_sched_group_upmigrate_pct; extern unsigned int sysctl_sched_group_downmigrate_pct; extern unsigned int sysctl_sched_walt_rotate_big_tasks; +extern unsigned int sysctl_sched_min_task_util_for_boost_colocation; extern int walt_proc_update_handler(struct ctl_table *table, int write, diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 5061b32a652a..f9230854ecef 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -196,6 +196,11 @@ unsigned int sched_capacity_margin_up[NR_CPUS] = { unsigned int sched_capacity_margin_down[NR_CPUS] = { [0 ... NR_CPUS-1] = 1205}; /* ~15% margin */ +#ifdef CONFIG_SCHED_WALT +/* 1ms default for 20ms window size scaled to 1024 */ +unsigned int sysctl_sched_min_task_util_for_boost_colocation = 51; +#endif + static inline void update_load_add(struct load_weight *lw, unsigned long inc) { lw->weight += inc; @@ -7625,7 +7630,9 @@ static inline struct cpumask *find_rtg_target(struct task_struct *p) rcu_read_lock(); grp = task_related_thread_group(p); - if (grp && grp->preferred_cluster) { + if (grp && grp->preferred_cluster && + (task_util(p) > + sysctl_sched_min_task_util_for_boost_colocation)) { rtg_target = &grp->preferred_cluster->cpus; if (!task_fits_max(p, cpumask_first(rtg_target))) rtg_target = NULL; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index da6fc108c256..4939b5a345f0 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2906,6 +2906,17 @@ static inline bool task_boost_on_big_eligible(struct task_struct *p) bool boost_on_big = task_sched_boost(p) && sched_boost_policy() == SCHED_BOOST_ON_BIG; + if (boost_on_big) { + /* + * Filter out tasks less than min task util threshold + * under conservative boost. + */ + if (sysctl_sched_boost == CONSERVATIVE_BOOST && + task_util(p) <= + sysctl_sched_min_task_util_for_boost_colocation) + boost_on_big = false; + } + return boost_on_big; } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index daa2c9024ed0..311692d1ba25 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -373,6 +373,15 @@ static struct ctl_table kern_table[] = { .extra1 = &zero, .extra2 = &one, }, + { + .procname = "sched_min_task_util_for_boost_colocation", + .data = &sysctl_sched_min_task_util_for_boost_colocation, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one_thousand, + }, #endif { .procname = "sched_upmigrate", -- GitLab From f079246bdda1e030da44055d4fbbaa59866949f9 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Fri, 29 Jun 2018 16:41:33 +0530 Subject: [PATCH 0955/1299] sched/fair: start_cpu() fix for rtg_target case It is possible that an offlined cpu be returned while adjusting the start_cpu to the preferred cluster. The dereferencing of sched domain via an offlined cpu will end up accessing stale pointers. To fix it, check the preferred cpu mask against online mask. Moreover since a cpu always fits its preferred cluster, move the check before task_fits_max based ones. Note that task_fits_max based start_cpu checks do not suffer from returning an offline cpu because the {min/mid/max}_cap_orig_cpu are updated in hotplug path such that they always point to an online cpu. Change-Id: Ib3b03b5eac2c555a84e3e5719afce33e7be8abb2 Signed-off-by: Pavankumar Kondeti --- kernel/sched/fair.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 5061b32a652a..6de5ac24e66a 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7053,6 +7053,15 @@ static int start_cpu(struct task_struct *p, bool boosted, if (boosted) return rd->max_cap_orig_cpu; + /* A task always fits on its rtg_target */ + if (rtg_target) { + int rtg_target_cpu = cpumask_first_and(rtg_target, + cpu_online_mask); + + if (rtg_target_cpu < nr_cpu_ids) + return rtg_target_cpu; + } + /* Where the task should land based on its demand */ if (rd->min_cap_orig_cpu != -1 && task_fits_max(p, rd->min_cap_orig_cpu)) @@ -7063,20 +7072,6 @@ static int start_cpu(struct task_struct *p, bool boosted, else start_cpu = rd->max_cap_orig_cpu; - /* - * start it up to its preferred cluster if the preferred clusteris - * higher capacity - */ - if (start_cpu != -1 && rtg_target && - !cpumask_test_cpu(start_cpu, rtg_target)) { - int rtg_target_cpu = cpumask_first(rtg_target); - - if (capacity_orig_of(start_cpu) < - capacity_orig_of(rtg_target_cpu)) { - start_cpu = rtg_target_cpu; - } - } - return start_cpu; } -- GitLab From ad8d704206bc0b5a19ec6ea35789fd2b34969c60 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Wed, 11 May 2016 10:38:12 +0530 Subject: [PATCH 0956/1299] sched/walt: don't account CPU idle exit time to task demand Discount the CPU idle exit time from the first task picked up to run on an idle CPU. Change-Id: Iaca5f7c022fbffeaa288ed09928fe34ac8bf5b9f Signed-off-by: Pavankumar Kondeti [satyap@codeaurora.org: trivial merge conflict resolution] Signed-off-by: Satya Durga Srinivasu Prabhala --- kernel/sched/walt.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c index 3efbef67e0b8..9d949aa316ff 100644 --- a/kernel/sched/walt.c +++ b/kernel/sched/walt.c @@ -1609,6 +1609,13 @@ account_busy_for_task_demand(struct rq *rq, struct task_struct *p, int event) (event == PICK_NEXT_TASK || event == TASK_MIGRATE))) return 0; + /* + * The idle exit time is not accounted for the first task _picked_ up to + * run on the idle CPU. + */ + if (event == PICK_NEXT_TASK && rq->curr == rq->idle) + return 0; + /* * TASK_UPDATE can be called on sleeping task, when its moved between * related groups -- GitLab From 397cbe4b64529f26ce624a00b091351d70fc3f2e Mon Sep 17 00:00:00 2001 From: Dennis Cagle Date: Tue, 10 Apr 2018 10:47:20 -0700 Subject: [PATCH 0957/1299] sound: rawmidi: Move spinlock under realloc_mutex A merge conflict resolution of commit e57f781805f0 ("ANDROID: sound: rawmidi: Hold lock around realloc") placed a realloc_mutex lock inside of a runtime->lock irq spinlock. The mutex lock has to encompass the spinlock to avoid attempts to sleep in an invalid context. Change-Id: I9333a01615c54fea3788f32955f40ae4b7a812a0 Signed-off-by: Dennis Cagle --- sound/core/rawmidi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 4b44386d5d22..1583dce54865 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -976,9 +976,9 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, struct snd_rawmidi_runtime *runtime = substream->runtime; unsigned long appl_ptr; - spin_lock_irqsave(&runtime->lock, flags); if (userbuf) mutex_lock(&runtime->realloc_mutex); + spin_lock_irqsave(&runtime->lock, flags); while (count > 0 && runtime->avail) { count1 = runtime->buffer_size - runtime->appl_ptr; if (count1 > count) -- GitLab From b751af340d5572034b8ba69e4d55862487e82649 Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Fri, 29 Jun 2018 12:07:49 -0700 Subject: [PATCH 0958/1299] iommu: arm-smmu: Print page-table entry (PTE) info on cb fault During context fault, if the software ATOS succeeds, print the PTE along with other debug info. This would help give more info such as descriptor attributes, memory region attributes etc. Also, mention the nature of access i.e. Read/Write. Change-Id: Ic0d6a6e6c43ede2857725e6e8fd8d474ba992e0a Signed-off-by: Sudarshan Rajagopalan --- drivers/iommu/arm-smmu.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 6727f9e99868..73c925a6e16f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1270,6 +1270,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) void __iomem *gr1_base; bool fatal_asf = smmu->options & ARM_SMMU_OPT_FATAL_ASF; phys_addr_t phys_soft; + uint64_t pte; bool non_fatal_fault = !!(smmu_domain->attributes & (1 << DOMAIN_ATTR_NON_FATAL_FAULTS)); @@ -1331,15 +1332,18 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) dev_err(smmu->dev, "FAR = %016lx\n", (unsigned long)iova); dev_err(smmu->dev, - "FSR = %08x [%s%s%s%s%s%s%s%s%s]\n", + "FSR = %08x [%s%s%s%s%s%s%s%s%s%s]\n", fsr, - (fsr & 0x02) ? "TF " : "", + (fsr & 0x02) ? (fsynr0 & 0x10 ? + "TF W " : "TF R ") : "", (fsr & 0x04) ? "AFF " : "", - (fsr & 0x08) ? "PF " : "", + (fsr & 0x08) ? (fsynr0 & 0x10 ? + "PF W " : "PF R ") : "", (fsr & 0x10) ? "EF " : "", (fsr & 0x20) ? "TLBMCF " : "", (fsr & 0x40) ? "TLBLKF " : "", (fsr & 0x80) ? "MHF " : "", + (fsr & 0x100) ? "UUT " : "", (fsr & 0x40000000) ? "SS " : "", (fsr & 0x80000000) ? "MULTI " : ""); dev_err(smmu->dev, @@ -1348,6 +1352,10 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) dev_err(smmu->dev, "SOFTWARE TABLE WALK FAILED! Looks like %s accessed an unmapped address!\n", dev_name(smmu->dev)); + else { + pte = arm_smmu_iova_to_pte(domain, iova); + dev_err(smmu->dev, "PTE = %016llx\n", pte); + } if (phys_atos) dev_err(smmu->dev, "hard iova-to-phys (ATOS)=%pa\n", &phys_atos); @@ -5053,8 +5061,8 @@ static phys_addr_t qsmmuv500_iova_to_phys( val = readq_relaxed(tbu->base + DEBUG_PAR_REG); fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR); if (fsr & FSR_FAULT) { - dev_err(tbu->dev, "ECATS generated a fault interrupt! FSR = %llx\n", - fsr); + dev_err(tbu->dev, "ECATS generated a fault interrupt! FSR = %llx, SID=0x%x\n", + fsr, sid); /* Clear pending interrupts */ writel_relaxed(fsr, cb_base + ARM_SMMU_CB_FSR); -- GitLab From 92350113c6fa765a790b14e66c42490d2acffd6f Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Thu, 28 Jun 2018 14:32:59 -0400 Subject: [PATCH 0959/1299] msm: npu: Fix iommu detaching issue during unloading driver arm_iommu_detach_device should be called before arm_iommu_release_mapping. CRs-Fixed: 2270158 Change-Id: I3d778858146ad102a5bb4680306918f328dfcc01 Signed-off-by: Jilai Wang --- drivers/media/platform/msm/npu/npu_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/npu/npu_dev.c b/drivers/media/platform/msm/npu/npu_dev.c index e422ea49c9e2..ce4e5e6b90e0 100644 --- a/drivers/media/platform/msm/npu/npu_dev.c +++ b/drivers/media/platform/msm/npu/npu_dev.c @@ -1426,8 +1426,8 @@ static int npu_remove(struct platform_device *pdev) thermal_cooling_device_unregister(npu_dev->tcdev); npu_debugfs_deinit(npu_dev); npu_host_deinit(npu_dev); - arm_iommu_release_mapping(npu_dev->smmu_ctx.mmu_mapping); arm_iommu_detach_device(&(npu_dev->pdev->dev)); + arm_iommu_release_mapping(npu_dev->smmu_ctx.mmu_mapping); sysfs_remove_group(&npu_dev->device->kobj, &npu_fs_attr_group); cdev_del(&npu_dev->cdev); device_destroy(npu_dev->class, npu_dev->dev_num); -- GitLab From e1de99912f7d2589a0a689f0adf5ac7e16c5ad1c Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Mon, 25 Jun 2018 13:50:28 -0700 Subject: [PATCH 0960/1299] rmnet: flow control optimization Reduce unnecessary DFC flow control operations. Correctly handle FC messages when bearer_id is 0xFF. Change-Id: Iba353d4be39b57167dbdab5df4cf9d348285464b Acked-by: Weiyi Chen Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/soc/qcom/dfc_qmi.c | 153 ++++++++++++++------------------- drivers/soc/qcom/qmi_rmnet_i.h | 1 - 2 files changed, 66 insertions(+), 88 deletions(-) diff --git a/drivers/soc/qcom/dfc_qmi.c b/drivers/soc/qcom/dfc_qmi.c index 05ab56cd2e65..4b2fb8c297ef 100644 --- a/drivers/soc/qcom/dfc_qmi.c +++ b/drivers/soc/qcom/dfc_qmi.c @@ -23,11 +23,6 @@ #define DFC_MAX_QOS_ID_V01 2 #define DEFAULT_FLOW_ID 0 -/* bearer list update result */ -#define NO_BEARER 0 -#define NO_CHANGE 1 -#define UPDATED 2 - struct dfc_qmi_data { void *rmnet_port; struct workqueue_struct *dfc_wq; @@ -519,91 +514,89 @@ static int dfc_init_service(struct dfc_qmi_data *data, struct qmi_info *qmi) return dfc_indication_register_req(&data->handle, &data->ssctl, 1); } -static int dfc_disable_bearer_flows(struct net_device *dev, u8 bearer_id) +static int dfc_bearer_flow_ctl(struct net_device *dev, struct qos_info *qos, + u8 bearer_id, int enable) { - struct qos_info *qos = (struct qos_info *)rmnet_get_qos_pt(dev); struct list_head *p; struct rmnet_flow_map *itm; int rc = 0; - if (!qos) - return 0; - list_for_each(p, &qos->flow_head) { itm = list_entry(p, struct rmnet_flow_map, list); if (unlikely(!itm)) - return 0; + continue; if (itm->bearer_id == bearer_id) { - tc_qdisc_flow_control(dev, itm->tcm_handle, 0); + tc_qdisc_flow_control(dev, itm->tcm_handle, enable); rc++; } } return rc; } -static int dfc_update_fc_map(struct qos_info *qos, u8 ack_req, - struct dfc_flow_status_info_type_v01 *fc_info) +static int dfc_all_bearer_flow_ctl(struct net_device *dev, + struct qos_info *qos, u8 ack_req, + struct dfc_flow_status_info_type_v01 *fc_info) { - struct rmnet_bearer_map *itm = NULL; - int rc = NO_BEARER; + struct list_head *p; + struct rmnet_flow_map *flow_itm; + struct rmnet_bearer_map *bearer_itm; + int enable; + int rc = 0; - itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id); - if (itm) { - if ((itm->grant_size == fc_info->num_bytes) && - (itm->counter > 0)) { - /*flow is enabled and grant_size is the same*/ - rc = NO_CHANGE; - } else { - itm->grant_size = fc_info->num_bytes; - itm->seq = fc_info->seq_num; - itm->ack_req = ack_req; - rc = UPDATED; - } - itm->counter = 0; + list_for_each(p, &qos->bearer_head) { + bearer_itm = list_entry(p, struct rmnet_bearer_map, list); + + if (unlikely(!bearer_itm)) + continue; + + bearer_itm->grant_size = fc_info->num_bytes; + bearer_itm->seq = fc_info->seq_num; + bearer_itm->ack_req = ack_req; } - return rc; -} -static int dfc_do_fc(struct net_device *dev, u32 flow_id, - int ip_type, int enable) -{ - struct qos_info *qos = (struct qos_info *)rmnet_get_qos_pt(dev); - struct rmnet_flow_map *itm = NULL; - int len = 0; + enable = fc_info->num_bytes > 0 ? 1 : 0; - if (!qos) - return 0; + list_for_each(p, &qos->flow_head) { + flow_itm = list_entry(p, struct rmnet_flow_map, list); - itm = qmi_rmnet_get_flow_map(qos, flow_id, ip_type); - if (itm) { - len = tc_qdisc_flow_control(dev, itm->tcm_handle, enable); + if (unlikely(!flow_itm)) + continue; + + tc_qdisc_flow_control(dev, flow_itm->tcm_handle, enable); + rc++; } - return len; + return rc; } -static void dfc_do_flow_controls(struct net_device *dev, - struct dfc_flow_status_info_type_v01 *flow) +static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, + u8 ack_req, + struct dfc_flow_status_info_type_v01 *fc_info) { - int i; - int enable = (flow->num_bytes > 0) ? 1 : 0; - int qdisc_len; - - for (i = 0; i < flow->qos_ids_len; i++) { - /* do flow control per specified flow */ - if (flow->qos_ids[i].ip_type == DFC_IPV4_TYPE_V01) { - qdisc_len = dfc_do_fc(dev, flow->qos_ids[i].qos_id, - AF_INET, enable); - pr_debug("%s() qdisc_len=%d\n", __func__, qdisc_len); - } else if (flow->qos_ids[i].ip_type == DFC_IPV6_TYPE_V01) { - qdisc_len = dfc_do_fc(dev, flow->qos_ids[i].qos_id, - AF_INET6, enable); - } else { - pr_err("%s() ip type[%d] not supported\n", - __func__, flow->qos_ids[i].ip_type); - } + struct rmnet_bearer_map *itm = NULL; + int rc = 0; + int action = -1; + + itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id); + if (itm) { + if (itm->grant_size == 0 && fc_info->num_bytes > 0) + action = 1; + else if (itm->grant_size > 0 && fc_info->num_bytes == 0) + action = 0; + + itm->grant_size = fc_info->num_bytes; + itm->seq = fc_info->seq_num; + itm->ack_req = ack_req; + + if (action != -1) + rc = dfc_bearer_flow_ctl( + dev, qos, fc_info->bearer_id, action); + } else { + pr_debug("grant %u before flow activate", fc_info->num_bytes); + qos->default_grant = fc_info->num_bytes; } + return rc; } static void dfc_do_burst_flow_control(struct work_struct *work) @@ -645,22 +638,11 @@ static void dfc_do_burst_flow_control(struct work_struct *work) if (!qos) continue; - rc = dfc_update_fc_map(qos, ack_req, flow_status); - if (rc == NO_BEARER) { - pr_debug("%s: num_bytes[%u]\n", - __func__, flow_status->num_bytes); - qos->default_grant = flow_status->num_bytes; - continue; - } else if (rc == NO_CHANGE) { - continue; - } else { - if ((flow_status->num_bytes > 0) || - (flow_status->bearer_id != 0xFF)) - dfc_do_flow_controls(dev, flow_status); - else - netif_stop_queue(dev); - - } + if (unlikely(flow_status->bearer_id == 0xFF)) + rc = dfc_all_bearer_flow_ctl( + dev, qos, ack_req, flow_status); + else + rc = dfc_update_fc_map(dev, qos, ack_req, flow_status); } clean_out: @@ -862,18 +844,15 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, return; } - bearer->counter += skb->len; - if (bearer->counter >= bearer->grant_size) { - bearer->counter = 0; - - dfc_disable_bearer_flows(dev, bearer->bearer_id); - rtnl_unlock(); + if (skb->len >= bearer->grant_size) { + bearer->grant_size = 0; + dfc_bearer_flow_ctl(dev, qos, bearer->bearer_id, 0); } else { - rtnl_unlock(); + bearer->grant_size -= skb->len; } - } else { - rtnl_unlock(); } + + rtnl_unlock(); } void dfc_reset_port_pt(void *dfc_data) diff --git a/drivers/soc/qcom/qmi_rmnet_i.h b/drivers/soc/qcom/qmi_rmnet_i.h index e87778d98eb5..7c6eda527ad1 100644 --- a/drivers/soc/qcom/qmi_rmnet_i.h +++ b/drivers/soc/qcom/qmi_rmnet_i.h @@ -35,7 +35,6 @@ struct rmnet_bearer_map { u8 bearer_id; int flow_ref; u32 grant_size; - u32 counter; u16 seq; u8 ack_req; }; -- GitLab From 033cba8a4a8f7bd34e2260c517d0d02e441f28e8 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Mon, 25 Jun 2018 18:20:12 -0600 Subject: [PATCH 0961/1299] net: rmnet: Add trace subsystem Add a trace template function for rmnet and use it for profiling. Change-Id: I7ef86611d31a4b7ce464d53b3968cec5c799604d Acked-by: Ning Cai Signed-off-by: Subash Abhinov Kasiviswanathan --- .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 3 + drivers/soc/qcom/dfc_qmi.c | 65 +++--- drivers/soc/qcom/qmi_rmnet.c | 8 +- drivers/soc/qcom/qmi_rmnet_i.h | 2 +- include/trace/events/dfc.h | 185 ++++++++++++++++++ include/trace/events/rmnet.h | 43 ++++ 6 files changed, 279 insertions(+), 27 deletions(-) create mode 100644 include/trace/events/dfc.h create mode 100644 include/trace/events/rmnet.h diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c index c46534fc5f74..37cd96d2a7ff 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c @@ -24,6 +24,8 @@ #include "rmnet_vnd.h" #include +#define CREATE_TRACE_POINTS +#include /* RX/TX Fixup */ @@ -62,6 +64,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, priv = netdev_priv(dev); if (priv->real_dev) { + trace_rmnet_xmit_skb(skb); qmi_rmnet_burst_fc_check(dev, skb); rmnet_egress_handler(skb); } else { diff --git a/drivers/soc/qcom/dfc_qmi.c b/drivers/soc/qcom/dfc_qmi.c index 4b2fb8c297ef..920f2e5ee925 100644 --- a/drivers/soc/qcom/dfc_qmi.c +++ b/drivers/soc/qcom/dfc_qmi.c @@ -18,6 +18,8 @@ #include #include "qmi_rmnet_i.h" +#define CREATE_TRACE_POINTS +#include #define DFC_MAX_BEARERS_V01 16 #define DFC_MAX_QOS_ID_V01 2 @@ -29,7 +31,7 @@ struct dfc_qmi_data { struct work_struct svc_arrive; struct qmi_handle handle; struct sockaddr_qrtr ssctl; - int modem; + int index; }; struct dfc_svc_ind { @@ -507,7 +509,7 @@ static int dfc_init_service(struct dfc_qmi_data *data, struct qmi_info *qmi) int rc; rc = dfc_bind_client_req(&data->handle, &data->ssctl, - &qmi->fc_info[data->modem].svc); + &qmi->fc_info[data->index].svc); if (rc < 0) return rc; @@ -515,20 +517,21 @@ static int dfc_init_service(struct dfc_qmi_data *data, struct qmi_info *qmi) } static int dfc_bearer_flow_ctl(struct net_device *dev, struct qos_info *qos, - u8 bearer_id, int enable) + u8 bearer_id, u32 grant_size, int enable) { struct list_head *p; struct rmnet_flow_map *itm; - int rc = 0; + int rc = 0, qlen; list_for_each(p, &qos->flow_head) { itm = list_entry(p, struct rmnet_flow_map, list); - if (unlikely(!itm)) - continue; - if (itm->bearer_id == bearer_id) { - tc_qdisc_flow_control(dev, itm->tcm_handle, enable); + qlen = tc_qdisc_flow_control(dev, itm->tcm_handle, + enable); + trace_dfc_qmi_tc(itm->bearer_id, itm->flow_id, + grant_size, qlen, itm->tcm_handle, + enable); rc++; } } @@ -543,14 +546,11 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, struct rmnet_flow_map *flow_itm; struct rmnet_bearer_map *bearer_itm; int enable; - int rc = 0; + int rc = 0, len; list_for_each(p, &qos->bearer_head) { bearer_itm = list_entry(p, struct rmnet_bearer_map, list); - if (unlikely(!bearer_itm)) - continue; - bearer_itm->grant_size = fc_info->num_bytes; bearer_itm->seq = fc_info->seq_num; bearer_itm->ack_req = ack_req; @@ -561,10 +561,10 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, list_for_each(p, &qos->flow_head) { flow_itm = list_entry(p, struct rmnet_flow_map, list); - if (unlikely(!flow_itm)) - continue; - - tc_qdisc_flow_control(dev, flow_itm->tcm_handle, enable); + len = tc_qdisc_flow_control(dev, flow_itm->tcm_handle, enable); + trace_dfc_qmi_tc(flow_itm->bearer_id, flow_itm->flow_id, + fc_info->num_bytes, len, + flow_itm->tcm_handle, enable); rc++; } return rc; @@ -590,8 +590,8 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, itm->ack_req = ack_req; if (action != -1) - rc = dfc_bearer_flow_ctl( - dev, qos, fc_info->bearer_id, action); + rc = dfc_bearer_flow_ctl(dev, qos, fc_info->bearer_id, + itm->grant_size, action); } else { pr_debug("grant %u before flow activate", fc_info->num_bytes); qos->default_grant = fc_info->num_bytes; @@ -629,6 +629,12 @@ static void dfc_do_burst_flow_control(struct work_struct *work) for (i = 0; i < ind->flow_status_len; i++) { flow_status = &ind->flow_status[i]; + trace_dfc_flow_ind(svc_ind->data->index, + i, flow_status->mux_id, + flow_status->bearer_id, + flow_status->num_bytes, + flow_status->seq_num, + ack_req); dev = rmnet_get_rmnet_dev(svc_ind->data->rmnet_port, flow_status->mux_id); if (!dev) @@ -711,7 +717,11 @@ static void dfc_svc_init(struct work_struct *work) return; } - qmi->fc_info[data->modem].dfc_client = (void *)data; + qmi->fc_info[data->index].dfc_client = (void *)data; + trace_dfc_client_state_up(data->index, + qmi->fc_info[data->index].svc.instance, + qmi->fc_info[data->index].svc.ep_type, + qmi->fc_info[data->index].svc.iface_id); } static int dfc_svc_arrive(struct qmi_handle *qmi, struct qmi_service *svc) @@ -735,9 +745,10 @@ static void dfc_svc_exit(struct qmi_handle *qmi, struct qmi_service *svc) struct qmi_info *qmi_pt; int client; + trace_dfc_client_state_down(data->index, 1); qmi_pt = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (qmi_pt) { - for (client = 0; client < 2; client++) { + for (client = 0; client < MAX_CLIENT_NUM; client++) { if (qmi_pt->fc_info[client].dfc_client == (void *)data) qmi_pt->fc_info[client].dfc_client = NULL; break; @@ -763,7 +774,7 @@ static struct qmi_msg_handler qmi_indication_handler[] = { {}, }; -int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) +int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) { struct dfc_qmi_data *data; int rc = -ENOMEM; @@ -773,7 +784,7 @@ int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) return -ENOMEM; data->rmnet_port = port; - data->modem = modem; + data->index = index; data->dfc_wq = create_singlethread_workqueue("dfc_wq"); if (!data->dfc_wq) { @@ -792,7 +803,7 @@ int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) rc = qmi_add_lookup(&data->handle, DFC_SERVICE_ID_V01, DFC_SERVICE_VERS_V01, - qmi->fc_info[modem].svc.instance); + qmi->fc_info[index].svc.instance); if (rc < 0) { pr_err("%s: failed qmi_add_lookup - rc[%d]\n", __func__, rc); goto err2; @@ -816,7 +827,7 @@ void dfc_qmi_client_exit(void *dfc_data) /* Skip this call for now due to error in qmi layer * qmi_handle_release(&data->handle); */ - + trace_dfc_client_state_down(data->index, 0); drain_workqueue(data->dfc_wq); destroy_workqueue(data->dfc_wq); kfree(data); @@ -844,9 +855,13 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, return; } + trace_dfc_flow_check(bearer->bearer_id, + skb->len, bearer->grant_size); + if (skb->len >= bearer->grant_size) { bearer->grant_size = 0; - dfc_bearer_flow_ctl(dev, qos, bearer->bearer_id, 0); + dfc_bearer_flow_ctl(dev, qos, bearer->bearer_id, + bearer->grant_size, 0); } else { bearer->grant_size -= skb->len; } diff --git a/drivers/soc/qcom/qmi_rmnet.c b/drivers/soc/qcom/qmi_rmnet.c index 601ac1f8a48a..0d7e86e3a6b5 100644 --- a/drivers/soc/qcom/qmi_rmnet.c +++ b/drivers/soc/qcom/qmi_rmnet.c @@ -17,6 +17,7 @@ #include #include #include "qmi_rmnet_i.h" +#include #define NLMSG_FLOW_ACTIVATE 1 #define NLMSG_FLOW_DEACTIVATE 2 @@ -148,6 +149,8 @@ static int qmi_rmnet_add_flow(struct net_device *dev, struct tcmsg *tcm) new_map.flow_id = tcm->tcm_parent; new_map.ip_type = tcm->tcm_ifindex; new_map.tcm_handle = tcm->tcm_handle; + trace_dfc_flow_info(new_map.bearer_id, new_map.flow_id, + new_map.ip_type, new_map.tcm_handle, 1); itm = qmi_rmnet_get_flow_map(qos_info, new_map.flow_id, new_map.ip_type); @@ -202,8 +205,11 @@ qmi_rmnet_del_flow(struct net_device *dev, struct tcmsg *tcm) new_map.ip_type = tcm->tcm_ifindex; itm = qmi_rmnet_get_flow_map(qos_info, new_map.flow_id, new_map.ip_type); - if (itm) + if (itm) { + trace_dfc_flow_info(new_map.bearer_id, new_map.flow_id, + new_map.ip_type, itm->tcm_handle, 0); list_del(&itm->list); + } /*clear bearer map*/ bearer = qmi_rmnet_get_bearer_map(qos_info, new_map.bearer_id); diff --git a/drivers/soc/qcom/qmi_rmnet_i.h b/drivers/soc/qcom/qmi_rmnet_i.h index 7c6eda527ad1..151b8345bc60 100644 --- a/drivers/soc/qcom/qmi_rmnet_i.h +++ b/drivers/soc/qcom/qmi_rmnet_i.h @@ -90,7 +90,7 @@ qmi_rmnet_get_flow_map(struct qos_info *qos_info, struct rmnet_bearer_map * qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id); -int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi); +int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi); void dfc_qmi_client_exit(void *dfc_data); diff --git a/include/trace/events/dfc.h b/include/trace/events/dfc.h new file mode 100644 index 000000000000..dc8dd5ae23b9 --- /dev/null +++ b/include/trace/events/dfc.h @@ -0,0 +1,185 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM dfc + +#if !defined(_TRACE_DFC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_DFC_H + +#include + +TRACE_EVENT(dfc_qmi_tc, + + TP_PROTO(u8 bearer_id, u32 flow_id, u32 grant, int qlen, + u32 tcm_handle, int enable), + + TP_ARGS(bearer_id, flow_id, grant, qlen, tcm_handle, enable), + + TP_STRUCT__entry( + __field(u8, bid) + __field(u32, fid) + __field(u32, grant) + __field(int, qlen) + __field(u32, tcm_handle) + __field(int, enable) + ), + + TP_fast_assign( + __entry->bid = bearer_id; + __entry->fid = flow_id; + __entry->grant = grant; + __entry->qlen = qlen; + __entry->tcm_handle = tcm_handle; + __entry->enable = enable; + ), + + TP_printk("bearer_id=%u grant=%u qdisc_len=%d flow_id=%u " + "tcm_handle=0x%x %s", + __entry->bid, __entry->grant, __entry->qlen, __entry->fid, + __entry->tcm_handle, + __entry->enable ? "enable" : "disable") +); + +TRACE_EVENT(dfc_flow_ind, + + TP_PROTO(int src, int idx, u8 mux_id, u8 bearer_id, u32 grant, + u16 seq_num, u8 ack_req), + + TP_ARGS(src, idx, mux_id, bearer_id, grant, seq_num, ack_req), + + TP_STRUCT__entry( + __field(int, src) + __field(int, idx) + __field(u8, mid) + __field(u8, bid) + __field(u32, grant) + __field(u16, seq) + __field(u8, ack_req) + ), + + TP_fast_assign( + __entry->src = src; + __entry->idx = idx; + __entry->mid = mux_id; + __entry->bid = bearer_id; + __entry->grant = grant; + __entry->seq = seq_num; + __entry->ack_req = ack_req; + ), + + TP_printk("src=%d idx[%d]: mux_id=%u bearer_id=%u grant=%u " + "seq_num=%u ack_req=%u", + __entry->src, __entry->idx, __entry->mid, __entry->bid, + __entry->grant, __entry->seq, __entry->ack_req) +); + +TRACE_EVENT(dfc_flow_check, + + TP_PROTO(u8 bearer_id, unsigned int len, u32 grant), + + TP_ARGS(bearer_id, len, grant), + + TP_STRUCT__entry( + __field(u8, bearer_id) + __field(unsigned int, len) + __field(u32, grant) + ), + + TP_fast_assign( + __entry->bearer_id = bearer_id; + __entry->len = len; + __entry->grant = grant; + ), + + TP_printk("bearer_id=%u skb_len=%u current_grant=%u", + __entry->bearer_id, __entry->len, __entry->grant) +); + +TRACE_EVENT(dfc_flow_info, + + TP_PROTO(u8 bearer_id, u32 flow_id, int ip_type, u32 handle, int add), + + TP_ARGS(bearer_id, flow_id, ip_type, handle, add), + + TP_STRUCT__entry( + __field(u8, bid) + __field(u32, fid) + __field(int, ip) + __field(u32, handle) + __field(int, action) + ), + + TP_fast_assign( + __entry->bid = bearer_id; + __entry->fid = flow_id; + __entry->ip = ip_type; + __entry->handle = handle; + __entry->action = add; + ), + + TP_printk("%s: bearer_id=%u flow_id=%u ip_type=%d tcm_handle=0x%x", + __entry->action ? "add flow" : "delete flow", + __entry->bid, __entry->fid, __entry->ip, __entry->handle) +); + +TRACE_EVENT(dfc_client_state_up, + + TP_PROTO(int idx, u32 instance, u32 ep_type, u32 iface), + + TP_ARGS(idx, instance, ep_type, iface), + + TP_STRUCT__entry( + __field(int, idx) + __field(u32, instance) + __field(u32, ep_type) + __field(u32, iface) + ), + + TP_fast_assign( + __entry->idx = idx; + __entry->instance = instance; + __entry->ep_type = ep_type; + __entry->iface = iface; + ), + + TP_printk("Client[%d]: Connection established with DFC Service " + "instance=%u ep_type=%u iface_id=%u", + __entry->idx, __entry->instance, + __entry->ep_type, __entry->iface) +); + +TRACE_EVENT(dfc_client_state_down, + + TP_PROTO(int idx, int from_cb), + + TP_ARGS(idx, from_cb), + + TP_STRUCT__entry( + __field(int, idx) + __field(int, from_cb) + ), + + TP_fast_assign( + __entry->idx = idx; + __entry->from_cb = from_cb; + ), + + TP_printk("Client[%d]: Connection with DFC service lost. " + "Exit by callback %d", + __entry->idx, __entry->from_cb) +); + +#endif /* _TRACE_DFC_H */ + +/* This part must be outside protection */ +#include diff --git a/include/trace/events/rmnet.h b/include/trace/events/rmnet.h new file mode 100644 index 000000000000..5904792c9fff --- /dev/null +++ b/include/trace/events/rmnet.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM rmnet + +#if !defined(_TRACE_RMNET_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_RMNET_H + +#include +#include + +TRACE_EVENT(rmnet_xmit_skb, + + TP_PROTO(struct sk_buff *skb), + + TP_ARGS(skb), + + TP_STRUCT__entry( + __string(dev_name, skb->dev->name) + __field(unsigned int, len) + ), + + TP_fast_assign( + __assign_str(dev_name, skb->dev->name); + __entry->len = skb->len; + ), + + TP_printk("dev_name=%s len=%u", __get_str(dev_name), __entry->len) +); + +#endif /* _TRACE_RMNET_H */ + +#include -- GitLab From da62aa4bc0ffccc04452bbfbaaa8488387845b95 Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Thu, 28 Jun 2018 20:22:56 -0400 Subject: [PATCH 0962/1299] drm/msm/sde: register power domain before smmu init Register power domain before smmu init to trigger extra probe attempt for any device that depends on mdp power domain registeration. This fixed the issue that sde_rotator is not probed during boot. CRs-Fixed: 2270743 Change-Id: Ia802ee3bf069b8084fc61db3fcbc62dc5934d021 Signed-off-by: Xiaowen Wu --- drivers/gpu/drm/msm/sde/sde_kms.c | 52 +++++++++++++++---------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index c43977cec65b..d4051c917df6 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -3020,6 +3020,32 @@ static int sde_kms_hw_init(struct msm_kms *kms) sde_kms->splash_data.resource_handoff_pending = true; + /* initialize power domain if defined */ + if (of_find_property(dev->dev->of_node, "#power-domain-cells", NULL)) { + sde_kms->genpd.name = dev->unique; + sde_kms->genpd.power_off = sde_kms_pd_disable; + sde_kms->genpd.power_on = sde_kms_pd_enable; + + rc = pm_genpd_init(&sde_kms->genpd, NULL, true); + if (rc < 0) { + SDE_ERROR("failed to init genpd provider %s: %d\n", + sde_kms->genpd.name, rc); + goto genpd_err; + } + + rc = of_genpd_add_provider_simple(dev->dev->of_node, + &sde_kms->genpd); + if (rc < 0) { + SDE_ERROR("failed to add genpd provider %s: %d\n", + sde_kms->genpd.name, rc); + pm_genpd_remove(&sde_kms->genpd); + goto genpd_err; + } + + sde_kms->genpd_init = true; + SDE_DEBUG("added genpd provider %s\n", sde_kms->genpd.name); + } + rc = _sde_kms_mmu_init(sde_kms); if (rc) { SDE_ERROR("sde_kms_mmu_init failed: %d\n", rc); @@ -3128,32 +3154,6 @@ static int sde_kms_hw_init(struct msm_kms *kms) SDE_POWER_EVENT_PRE_DISABLE, sde_kms_handle_power_event, sde_kms, "kms"); - /* initialize power domain if defined */ - if (of_find_property(dev->dev->of_node, "#power-domain-cells", NULL)) { - sde_kms->genpd.name = dev->unique; - sde_kms->genpd.power_off = sde_kms_pd_disable; - sde_kms->genpd.power_on = sde_kms_pd_enable; - - rc = pm_genpd_init(&sde_kms->genpd, NULL, true); - if (rc < 0) { - SDE_ERROR("failed to init genpd provider %s: %d\n", - sde_kms->genpd.name, rc); - goto genpd_err; - } - - rc = of_genpd_add_provider_simple(dev->dev->of_node, - &sde_kms->genpd); - if (rc < 0) { - SDE_ERROR("failed to add genpd provider %s: %d\n", - sde_kms->genpd.name, rc); - pm_genpd_remove(&sde_kms->genpd); - goto genpd_err; - } - - sde_kms->genpd_init = true; - SDE_DEBUG("added genpd provider %s\n", sde_kms->genpd.name); - } - if (sde_kms->splash_data.cont_splash_en) { SDE_DEBUG("Skipping MDP Resources disable\n"); } else { -- GitLab From 239b188cdf4a0d39ab054618078e6d65b4eb43a5 Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Wed, 20 Jun 2018 18:02:58 -0700 Subject: [PATCH 0963/1299] sched: use cuml demand for idle selection Currently we choose a idle cpu if its in a shallower c state than the previous one. But if it comes across a idle cpu with the same cstate, it skips it. Instead of skipping it, check if it has a lower cuml demand and if so prefer that cpu over the previous one. But prefer previous cpu over a cpu with lower cuml demand. Change-Id: I94b74b1b1c91d1cc7d4b5f40fb4f79558271e992 Signed-off-by: Abhijeet Dharmapurikar --- kernel/sched/fair.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 6de5ac24e66a..33d00c25e857 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7086,6 +7086,7 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, unsigned long target_util = ULONG_MAX; unsigned long best_active_util = ULONG_MAX; unsigned long best_active_cuml_util = ULONG_MAX; + unsigned long best_idle_cuml_util = ULONG_MAX; int best_idle_cstate = INT_MAX; struct sched_domain *sd; struct sched_group *sg; @@ -7096,6 +7097,7 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, long spare_cap, most_spare_cap = 0; int most_spare_cap_cpu = -1; unsigned int active_cpus_count = 0; + int prev_cpu = task_cpu(p); *backup_cpu = -1; @@ -7292,12 +7294,19 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, * shallow idle big CPU. */ if (sysctl_sched_cstate_aware && - best_idle_cstate <= idle_idx) + best_idle_cstate < idle_idx) + continue; + + if (best_idle_cstate == idle_idx && + (best_idle_cpu == prev_cpu || + (i != prev_cpu && + new_util_cuml > best_idle_cuml_util))) continue; /* Keep track of best idle CPU */ target_capacity = capacity_orig; best_idle_cstate = idle_idx; + best_idle_cuml_util = new_util_cuml; best_idle_cpu = i; continue; } -- GitLab From 10f7dc075b87361d42d0145b74bfd75f28cc4545 Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Tue, 26 Jun 2018 14:24:37 -0700 Subject: [PATCH 0964/1299] sched/fair: dont run energy calculation unless necessary The placement code calls find_best_target() to find the next cpu, and if possible a backup cpu. After that it does an energy evaluation between next, backup and prev cpu. When find_best_target() finds the next or backup the same as prev, we unnecessarily account for the same cpu twice in energy evaluation. So, drop the backup if its same as prev. If the next cpu is same as the prev, make backup the next candidate. Change-Id: Ia2dc0c1b059ad515d99e7d66556795b24d30629c Signed-off-by: Abhijeet Dharmapurikar --- kernel/sched/fair.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 33d00c25e857..5b3dcbff4c7f 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7420,6 +7420,19 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu, if (*backup_cpu == target_cpu) *backup_cpu = -1; + /* + * The next step of energy evaluation includes + * prev_cpu. Drop target or backup if it is + * same as prev_cpu + */ + if (*backup_cpu == prev_cpu) + *backup_cpu = -1; + + if (target_cpu == prev_cpu) { + target_cpu = *backup_cpu; + *backup_cpu = -1; + } + return target_cpu; } -- GitLab From 3bd38496a4d441f62a251e3847f4a8cdf658e3de Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Thu, 21 Jun 2018 11:12:59 -0700 Subject: [PATCH 0965/1299] soc: qcom: smp2p: Add restart ack feature Add support for subsystem restart detection. When this feature bit is set, the remote processor will tell us when it is reinitialized. All clients registered for falling edge interrupts will be notified when the smp2p entries are cleared for ssr. Change-Id: Id82f8b93e83dcd8ad3ed92fdea36f111014ff1e9 Signed-off-by: Chris Lew --- drivers/soc/qcom/smp2p.c | 133 ++++++++++++++++++++++++++++++--------- 1 file changed, 104 insertions(+), 29 deletions(-) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index ac5979cf56d9..a75c9a531eef 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -47,8 +47,12 @@ #define SMP2P_MAX_ENTRY_NAME 16 #define SMP2P_FEATURE_SSR_ACK 0x1 +#define SMP2P_FLAGS_RESTART_DONE_BIT 0 +#define SMP2P_FLAGS_RESTART_ACK_BIT 1 #define SMP2P_MAGIC 0x504d5324 +#define SMP2P_VERSION 1 +#define SMP2P_FEATURES SMP2P_FEATURE_SSR_ACK /** * struct smp2p_smem_item - in memory communication structure @@ -140,6 +144,10 @@ struct qcom_smp2p { unsigned valid_entries; + bool ssr_ack_enabled; + bool ssr_ack; + bool open; + unsigned local_pid; unsigned remote_pid; @@ -159,42 +167,64 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p) regmap_write(smp2p->ipc_regmap, smp2p->ipc_offset, BIT(smp2p->ipc_bit)); } -/** - * qcom_smp2p_intr() - interrupt handler for incoming notifications - * @irq: unused - * @data: smp2p driver context - * - * Handle notifications from the remote side to handle newly allocated entries - * or any changes to the state bits of existing entries. - */ -static irqreturn_t qcom_smp2p_intr(int irq, void *data) +static bool qcom_smp2p_check_ssr(struct qcom_smp2p *smp2p) { - struct smp2p_smem_item *in; + struct smp2p_smem_item *in = smp2p->in; + bool restart; + + if (!smp2p->ssr_ack_enabled) + return false; + + restart = in->flags & BIT(SMP2P_FLAGS_RESTART_DONE_BIT); + if (restart == smp2p->ssr_ack) + return false; + + return true; +} + +static void qcom_smp2p_do_ssr_ack(struct qcom_smp2p *smp2p) +{ + struct smp2p_smem_item *out = smp2p->out; + u32 ack; + u32 val; + + smp2p->ssr_ack = ack = !smp2p->ssr_ack; + ack = ack << SMP2P_FLAGS_RESTART_ACK_BIT; + + val = out->flags & ~BIT(SMP2P_FLAGS_RESTART_ACK_BIT); + val |= ack; + out->flags = val; + + qcom_smp2p_kick(smp2p); +} + +static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p) +{ + struct smp2p_smem_item *out = smp2p->out; + struct smp2p_smem_item *in = smp2p->in; + u32 features; + + if (in->version == out->version) { + features = in->features & out->features; + out->features = features; + + if (features & SMP2P_FEATURE_SSR_ACK) + smp2p->ssr_ack_enabled = true; + + smp2p->open = true; + } +} + +static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p) +{ + struct smp2p_smem_item *in = smp2p->in; struct smp2p_entry *entry; - struct qcom_smp2p *smp2p = data; unsigned long status; - unsigned smem_id = smp2p->smem_items[SMP2P_INBOUND]; - unsigned pid = smp2p->remote_pid; - size_t size; int irq_pin; char buf[SMP2P_MAX_ENTRY_NAME]; u32 val; int i; - in = smp2p->in; - - /* Acquire smem item, if not already found */ - if (!in) { - in = qcom_smem_get(pid, smem_id, &size); - if (IS_ERR(in)) { - dev_err(smp2p->dev, - "Unable to acquire remote smp2p item\n"); - return IRQ_HANDLED; - } - - smp2p->in = in; - } - /* Match newly created entries */ for (i = smp2p->valid_entries; i < in->valid_entries; i++) { list_for_each_entry(entry, &smp2p->inbound, node) { @@ -236,6 +266,50 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data) } } } +} + +/** + * qcom_smp2p_intr() - interrupt handler for incoming notifications + * @irq: unused + * @data: smp2p driver context + * + * Handle notifications from the remote side to handle newly allocated entries + * or any changes to the state bits of existing entries. + */ +static irqreturn_t qcom_smp2p_intr(int irq, void *data) +{ + struct smp2p_smem_item *in; + struct qcom_smp2p *smp2p = data; + unsigned int smem_id = smp2p->smem_items[SMP2P_INBOUND]; + unsigned int pid = smp2p->remote_pid; + size_t size; + + in = smp2p->in; + + /* Acquire smem item, if not already found */ + if (!in) { + in = qcom_smem_get(pid, smem_id, &size); + if (IS_ERR(in)) { + dev_err(smp2p->dev, + "Unable to acquire remote smp2p item\n"); + return IRQ_HANDLED; + } + + smp2p->in = in; + } + + if (!smp2p->open) + qcom_smp2p_negotiate(smp2p); + + if (smp2p->open) { + bool do_restart; + + do_restart = qcom_smp2p_check_ssr(smp2p); + qcom_smp2p_notify_in(smp2p); + + if (do_restart) + qcom_smp2p_do_ssr_ack(smp2p); + } return IRQ_HANDLED; } @@ -393,13 +467,14 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p) out->remote_pid = smp2p->remote_pid; out->total_entries = SMP2P_MAX_ENTRY; out->valid_entries = 0; + out->features = SMP2P_FEATURES; /* * Make sure the rest of the header is written before we validate the * item by writing a valid version number. */ wmb(); - out->version = 1; + out->version = SMP2P_VERSION; qcom_smp2p_kick(smp2p); -- GitLab From 0480b82634b6247a00490ac34c232e3c8acdfc14 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Wed, 20 Jun 2018 17:49:13 -0700 Subject: [PATCH 0966/1299] soc: qcom: smp2p: Add IPC logging support Add IPC logs to track bit state entries. These logs will help detect issues in remote processor bootup. Change-Id: I31a549532122e0ad7e4c9da454ee65c7b48fdd1d Signed-off-by: Chris Lew --- drivers/soc/qcom/smp2p.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index a75c9a531eef..e6cb274083a5 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -26,6 +26,8 @@ #include #include +#include + /* * The Shared Memory Point to Point (SMP2P) protocol facilitates communication * of a single 32-bit value between two processors. Each value has a single @@ -160,6 +162,14 @@ struct qcom_smp2p { struct list_head outbound; }; +static void *ilc; +#define SMP2P_LOG_PAGE_CNT 2 +#define SMP2P_INFO(x, ...) \ +do { \ + if (ilc) \ + ipc_log_string(ilc, "[%s]: "x, __func__, ##__VA_ARGS__); \ +} while (0) + static void qcom_smp2p_kick(struct qcom_smp2p *smp2p) { /* Make sure any updated data is written before the kick */ @@ -179,6 +189,7 @@ static bool qcom_smp2p_check_ssr(struct qcom_smp2p *smp2p) if (restart == smp2p->ssr_ack) return false; + SMP2P_INFO("%d: SSR DETECTED\n", smp2p->remote_pid); return true; } @@ -212,6 +223,8 @@ static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p) smp2p->ssr_ack_enabled = true; smp2p->open = true; + SMP2P_INFO("%d: state=open ssr_ack=%d\n", smp2p->remote_pid, + smp2p->ssr_ack_enabled); } } @@ -253,6 +266,9 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p) if (!status) continue; + SMP2P_INFO("%d: %s: status:%0x val:%0x\n", + smp2p->remote_pid, entry->name, status, val); + for_each_set_bit(i, &status, 32) { if ((val & BIT(i) && test_bit(i, entry->irq_rising)) || (!(val & BIT(i)) && test_bit(i, entry->irq_falling))) { @@ -524,6 +540,9 @@ static int qcom_smp2p_probe(struct platform_device *pdev) const char *key; int ret; + if (!ilc) + ilc = ipc_log_context_create(SMP2P_LOG_PAGE_CNT, "smp2p", 0); + smp2p = devm_kzalloc(&pdev->dev, sizeof(*smp2p), GFP_KERNEL); if (!smp2p) return -ENOMEM; -- GitLab From 9de18caa8e7d40afc3585822bdec785c0ae32e33 Mon Sep 17 00:00:00 2001 From: Vijay Viswanath Date: Fri, 11 May 2018 18:21:16 +0530 Subject: [PATCH 0967/1299] mmc: core: rescan for card if deferred resume fails SD card can be removed when system is under suspend and mmc driver will not get cd-gpio irq. And because of deferred_resume feature, we will do nothing during system resume and hence cannot detect card removal event. So when we do deferred_resume (when a request is issued to mmc driver), schedule a rescan if: - Deferred_resume fails AND - Card is removable and polling is not enabled Change-Id: I8048027ad3900c1be72b65dfb4ec535780351488 Signed-off-by: Vijay Viswanath --- drivers/mmc/core/core.c | 17 ++++++++++++++++- drivers/mmc/core/sd.c | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 44746757111a..91b50be61ac2 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -3249,7 +3249,22 @@ int mmc_resume_bus(struct mmc_host *host) if (host->bus_ops && !host->bus_dead && host->card) { mmc_power_up(host, host->card->ocr); BUG_ON(!host->bus_ops->resume); - host->bus_ops->resume(host); + err = host->bus_ops->resume(host); + if (err) { + pr_err("%s: %s: resume failed: %d\n", + mmc_hostname(host), __func__, err); + /* + * If we have cd-gpio based detection mechanism and + * deferred resume is supported, we will not detect + * card removal event when system is suspended. So if + * resume fails after a system suspend/resume, + * schedule the work to detect card presence. + */ + if (mmc_card_is_removable(host) && + !(host->caps & MMC_CAP_NEEDS_POLL)) { + mmc_detect_change(host, 0); + } + } if (mmc_card_cmdq(host->card)) { err = mmc_cmdq_halt(host, false); if (err) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 0630c0caa1a4..5924f5977359 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1303,6 +1303,8 @@ static int _mmc_sd_resume(struct mmc_host *host) mmc_hostname(host), __func__, err); mmc_card_set_removed(host->card); mmc_detect_change(host, msecs_to_jiffies(200)); + } else if (err) { + goto out; } mmc_card_clr_suspended(host->card); -- GitLab From 52863b4704af6ac7c6860d8aad7d1271f6f5e51d Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Sat, 30 Jun 2018 06:11:08 +0530 Subject: [PATCH 0968/1299] msm: ADSPRPC: Use right DMA APIs to flush userspace buffers Remove the use of dmac_flush_range for userspace buffers and use DMA buffer begin and end CPU access APIs for cleaning and invalidating the cache. Change-Id: Ice73eafac840bd1cabee0a2bfc8a641832a7d0c8 Acked-by: Thyagarajan Venkatanarayanan Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 60 +++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 5449a9148bba..06a25625271a 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1464,9 +1464,17 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) if (map && (map->attr & FASTRPC_ATTR_COHERENT)) continue; - if (rpra[i].buf.len && ctx->overps[oix]->mstart) - dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv), - uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len)); + if (rpra && rpra[i].buf.len && ctx->overps[oix]->mstart) { + if (map && map->handle) { + dma_buf_begin_cpu_access(map->buf, + DMA_BIDIRECTIONAL); + dma_buf_end_cpu_access(map->buf, + DMA_BIDIRECTIONAL); + } else + dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv), + uint64_to_ptr(rpra[i].buf.pv + + rpra[i].buf.len)); + } } PERF_END); for (i = bufs; rpra && i < bufs + handles; i++) { @@ -1475,11 +1483,6 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) rpra[i].dma.offset = (uint32_t)(uintptr_t)lpra[i].buf.pv; } - if (!ctx->fl->sctx->smmu.coherent) { - PERF(ctx->fl->profile, GET_COUNTER(perf_counter, PERF_FLUSH), - dmac_flush_range((char *)rpra, (char *)rpra + ctx->used); - PERF_END); - } bail: return err; } @@ -1565,14 +1568,31 @@ static void inv_args_pre(struct smq_invoke_ctx *ctx) if (buf_page_start(ptr_to_uint64((void *)rpra)) == buf_page_start(rpra[i].buf.pv)) continue; - if (!IS_CACHE_ALIGNED((uintptr_t)uint64_to_ptr(rpra[i].buf.pv))) - dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv), - (char *)(uint64_to_ptr(rpra[i].buf.pv + 1))); + if (!IS_CACHE_ALIGNED((uintptr_t) + uint64_to_ptr(rpra[i].buf.pv))) { + if (map && map->handle) { + dma_buf_begin_cpu_access(map->buf, + DMA_BIDIRECTIONAL); + dma_buf_end_cpu_access(map->buf, + DMA_BIDIRECTIONAL); + } else + dmac_flush_range( + uint64_to_ptr(rpra[i].buf.pv), (char *) + uint64_to_ptr(rpra[i].buf.pv + 1)); + } + end = (uintptr_t)uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len); - if (!IS_CACHE_ALIGNED(end)) - dmac_flush_range((char *)end, - (char *)end + 1); + if (!IS_CACHE_ALIGNED(end)) { + if (map && map->handle) { + dma_buf_begin_cpu_access(map->buf, + DMA_BIDIRECTIONAL); + dma_buf_end_cpu_access(map->buf, + DMA_BIDIRECTIONAL); + } else + dmac_flush_range((char *)end, + (char *)end + 1); + } } } @@ -1581,7 +1601,6 @@ static void inv_args(struct smq_invoke_ctx *ctx) int i, inbufs, outbufs; uint32_t sc = ctx->sc; remote_arg64_t *rpra = ctx->rpra; - int used = ctx->used; inbufs = REMOTE_SCALARS_INBUFS(sc); outbufs = REMOTE_SCALARS_OUTBUFS(sc); @@ -1603,17 +1622,16 @@ static void inv_args(struct smq_invoke_ctx *ctx) continue; } if (map && map->buf) { - dma_buf_begin_cpu_access(map->buf, DMA_BIDIRECTIONAL); - dma_buf_end_cpu_access(map->buf, DMA_BIDIRECTIONAL); - } - else + dma_buf_begin_cpu_access(map->buf, + DMA_BIDIRECTIONAL); + dma_buf_end_cpu_access(map->buf, + DMA_BIDIRECTIONAL); + } else dmac_inv_range((char *)uint64_to_ptr(rpra[i].buf.pv), (char *)uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len)); } - if (rpra) - dmac_inv_range(rpra, (char *)rpra + used); } static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, -- GitLab From 743155eae54091877a92a708b88e55184d40e1af Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Fri, 22 Jun 2018 15:42:58 -0700 Subject: [PATCH 0969/1299] ARM: dts: msm: Change QMP interrupt register for SM8150 Current IPC interrupts to NPU are not configured correctly. Switch to a spare control register and update the mask values needed to trigger and interrupt to NPU. Change-Id: Ia1ca29e874f8dfb85ec7d73ace7be0566b55f5cf Signed-off-by: Chris Lew --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index c5529cfd06d3..b3da334553e1 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -2802,9 +2802,9 @@ qmp_npu0: qcom,qmp-npu-low@9818000 { compatible = "qcom,qmp-mbox"; - reg = <0x9818000 0x8000>, <0x17c00010 0x4>; + reg = <0x9818000 0x8000>, <0x9901008 0x4>; reg-names = "msgram", "irq-reg-base"; - qcom,irq-mask = <0x20>; + qcom,irq-mask = <0x12>; interrupts = ; label = "npu_qmp_low"; @@ -2813,11 +2813,11 @@ #mbox-cells = <1>; }; - qmp_npu1: qcom,qmp-npu-high@981a000 { + qmp_npu1: qcom,qmp-npu-high@9818000 { compatible = "qcom,qmp-mbox"; - reg = <0x9818000 0x8000>, <0x17c00010 0x4>; + reg = <0x9818000 0x8000>, <0x9901008 0x4>; reg-names = "msgram", "irq-reg-base"; - qcom,irq-mask = <0x40>; + qcom,irq-mask = <0x14>; interrupts = ; label = "npu_qmp_high"; -- GitLab From a88aefea65f45969df3a1f1d08d0d3d71a0b9fc1 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Mon, 18 Sep 2017 12:20:20 -0700 Subject: [PATCH 0970/1299] msm: Add CLD80211_ATTR_META_DATA vendor attribute Add CLD80211_ATTR_META_DATA vendor attribute, which will be used by userspace RTT application to send meta data to wlan driver allowing it to peek into RTT request message without opening up complete definition of RTT message. Change-Id: If2f8253b59c6860fbaecab05f1b76f11da1ddb6f CRs-Fixed: 2114181 Signed-off-by: Naveen Rawat --- drivers/net/wireless/cnss_genl/cnss_nl.c | 2 ++ include/net/cnss_nl.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/cnss_genl/cnss_nl.c b/drivers/net/wireless/cnss_genl/cnss_nl.c index 464a0361f473..d49691548596 100644 --- a/drivers/net/wireless/cnss_genl/cnss_nl.c +++ b/drivers/net/wireless/cnss_genl/cnss_nl.c @@ -64,6 +64,8 @@ static const struct nla_policy cld80211_policy[CLD80211_ATTR_MAX + 1] = { [CLD80211_ATTR_VENDOR_DATA] = { .type = NLA_NESTED }, [CLD80211_ATTR_DATA] = { .type = NLA_BINARY, .len = CLD80211_MAX_NL_DATA }, + [CLD80211_ATTR_META_DATA] = { .type = NLA_BINARY, + .len = CLD80211_MAX_NL_DATA }, }; static int cld80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, diff --git a/include/net/cnss_nl.h b/include/net/cnss_nl.h index 128cb3d0c6f3..3bafdd59eee0 100644 --- a/include/net/cnss_nl.h +++ b/include/net/cnss_nl.h @@ -23,12 +23,16 @@ * @CLD80211_ATTR_VENDOR_DATA: Embed all other attributes in this nested * attribute. * @CLD80211_ATTR_DATA: Embed complete data in this attribute + * @CLD80211_ATTR_META_DATA: Embed meta data for above data. This will help + * wlan driver to peek into request message packet without opening up definition + * of complete request message. * * Any new message in future can be added as another attribute */ enum cld80211_attr { CLD80211_ATTR_VENDOR_DATA = 1, CLD80211_ATTR_DATA, + CLD80211_ATTR_META_DATA, /* add new attributes above here */ __CLD80211_ATTR_AFTER_LAST, -- GitLab From 0e46b7a351ad75fd18c324318627cb5a94b4e49b Mon Sep 17 00:00:00 2001 From: Ramprasad Katkam Date: Thu, 28 Jun 2018 21:55:38 +0530 Subject: [PATCH 0971/1299] ARM: dts: msm: Fix clock node name Fix name of clock parameter in qcs405 external codec variant. Change-Id: I45b557cb2d3ee4c5422e51e01302f975f3325fcc Signed-off-by: Ramprasad Katkam --- arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi b/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi index fa2f21d561bc..e4f4d840cd9c 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-tasha.dtsi @@ -29,7 +29,7 @@ pinctrl-0 = <&tasha_mclk_default>; pinctrl-1 = <&tasha_mclk_default>; #clock-names = "osr_clk"; - #clocks = <&pms405_clkdiv>; + clocks = <&pms405_clkdiv>; #clock-cells = <1>; }; -- GitLab From eedee6225fbefa2dd31bec0ec30a40b71b5658ee Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Thu, 12 Apr 2018 16:00:27 +0530 Subject: [PATCH 0972/1299] usb: dwc3: Change to simulate VBUS without extcon/PMI On targets that does not have any mechanism for VBUS and ID notifications, simulate a VBUS connect to put the core in peripheral mode by default. Signed-off-by: Sriharsha Allenki Change-Id: I951af6d98820bc2ee1bd8f7d3affa3832b4695f9 --- drivers/usb/dwc3/dwc3-msm.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 40adca7ac959..6d899aec43d9 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -2907,9 +2907,17 @@ static int dwc3_msm_extcon_register(struct dwc3_msm *mdwc) struct extcon_dev *edev; int idx, extcon_cnt, ret = 0; bool check_vbus_state, check_id_state, phandle_found = false; + struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); - if (!of_property_read_bool(node, "extcon")) + if (!of_property_read_bool(node, "extcon") && + (dwc->dr_mode == USB_DR_MODE_OTG)) { + dev_dbg(mdwc->dev, "%s: no extcon, simulate vbus connect\n", + __func__); + mdwc->vbus_active = true; + dwc->vbus_active = true; + queue_work(mdwc->dwc3_wq, &mdwc->resume_work); return 0; + } extcon_cnt = of_count_phandle_with_args(node, "extcon", NULL); if (extcon_cnt < 0) { -- GitLab From 98159c5dd9e928839177ec4bab4eaea58f9c9faa Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Sat, 30 Jun 2018 18:26:15 +0530 Subject: [PATCH 0973/1299] ARM: dts: msm: Remove extcon for USB2.0 on QCS405 On QCS405, all the platforms does not have SMB charger present, so remove the extcon property for USB2.0 on the default dt file for QCS405. Change-Id: I4df0e55939da1add1ef13b28921d10acfd88ec7c Signed-off-by: Sriharsha Allenki --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index ee07feb6e9aa..4a63b9fbd638 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -1029,7 +1029,3 @@ &usb3_vbus_boost_default>; }; }; - -&usb2s { - extcon = <&smb1351_otg_supply>; -}; -- GitLab From a2a8d561c35eca3940dd2830acbafd5185e2b3d4 Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Sun, 1 Jul 2018 10:16:10 +0300 Subject: [PATCH 0974/1299] wil6210: force EDMG channel through debugfs Force EDMG (Enhanced Directional Multi-Gigabit) channel through debugfs for debugging channel bonding feature. Usage: echo > force_edmg_channel When force_edmg_channel is set, it will be used in connect and PCP start commands. Change-Id: Ia1e12cb8cf730dbb448fae47b40dfa11053567d0 Signed-off-by: Alexei Avshalom Lazar Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/cfg80211.c | 90 +++++++++++++++++++++ drivers/net/wireless/ath/wil6210/debugfs.c | 1 + drivers/net/wireless/ath/wil6210/wil6210.h | 4 + drivers/net/wireless/ath/wil6210/wmi.c | 25 +++++- drivers/net/wireless/ath/wil6210/wmi.h | 33 +++++++- 5 files changed, 147 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 0c98459f01d6..bf31d676002c 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -338,6 +338,86 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type) return -EOPNOTSUPP; } +int wil_spec2wmi_ch(u8 spec_ch, u8 *wmi_ch) +{ + switch (spec_ch) { + case 1: + *wmi_ch = WMI_CHANNEL_1; + break; + case 2: + *wmi_ch = WMI_CHANNEL_2; + break; + case 3: + *wmi_ch = WMI_CHANNEL_3; + break; + case 4: + *wmi_ch = WMI_CHANNEL_4; + break; + case 5: + *wmi_ch = WMI_CHANNEL_5; + break; + case 6: + *wmi_ch = WMI_CHANNEL_6; + break; + case 9: + *wmi_ch = WMI_CHANNEL_9; + break; + case 10: + *wmi_ch = WMI_CHANNEL_10; + break; + case 11: + *wmi_ch = WMI_CHANNEL_11; + break; + case 12: + *wmi_ch = WMI_CHANNEL_12; + break; + default: + return -EINVAL; + } + + return 0; +} + +int wil_wmi2spec_ch(u8 wmi_ch, u8 *spec_ch) +{ + switch (wmi_ch) { + case WMI_CHANNEL_1: + *spec_ch = 1; + break; + case WMI_CHANNEL_2: + *spec_ch = 2; + break; + case WMI_CHANNEL_3: + *spec_ch = 3; + break; + case WMI_CHANNEL_4: + *spec_ch = 4; + break; + case WMI_CHANNEL_5: + *spec_ch = 5; + break; + case WMI_CHANNEL_6: + *spec_ch = 6; + break; + case WMI_CHANNEL_9: + *spec_ch = 9; + break; + case WMI_CHANNEL_10: + *spec_ch = 10; + break; + case WMI_CHANNEL_11: + *spec_ch = 11; + break; + case WMI_CHANNEL_12: + *spec_ch = 12; + break; + default: + return -EINVAL; + } + + return 0; +} + int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, struct station_info *sinfo) { @@ -1084,6 +1164,16 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, } conn.channel = ch - 1; + if (test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities)) + if (wil->force_edmg_channel) { + rc = wil_spec2wmi_ch(wil->force_edmg_channel, + &conn.edmg_channel); + if (rc) + wil_err(wil, + "wmi channel for channel %d not found", + wil->force_edmg_channel); + } + ether_addr_copy(conn.bssid, bss->bssid); ether_addr_copy(conn.dst_mac, bss->bssid); diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 15ed905792ea..4c1a9dad0564 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -2167,6 +2167,7 @@ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(ring_idle_trsh, 0644, doff_u32), WIL_FIELD(num_rx_status_rings, 0644, doff_u8), WIL_FIELD(amsdu_en, 0644, doff_u8), + WIL_FIELD(force_edmg_channel, 0644, doff_u8), {}, }; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 6ecfeb1fbe30..2a2f7771f3f7 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -948,6 +948,7 @@ struct wil6210_priv { u8 wakeup_trigger; struct wil_suspend_stats suspend_stats; struct wil_debugfs_data dbg_data; + u8 force_edmg_channel; void *platform_handle; struct wil_platform_ops platform_ops; @@ -1355,6 +1356,9 @@ int wmi_start_sched_scan(struct wil6210_priv *wil, int wmi_stop_sched_scan(struct wil6210_priv *wil); int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len); +int wil_wmi2spec_ch(u8 wmi_ch, u8 *spec_ch); +int wil_spec2wmi_ch(u8 spec_ch, u8 *wmi_ch); + int reverse_memcmp(const void *cs, const void *ct, size_t count); /* WMI for enhanced DMA */ diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 9d82c37ece6f..3b544b4b7c9c 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -908,7 +908,8 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len) struct net_device *ndev = vif_to_ndev(vif); struct wireless_dev *wdev = vif_to_wdev(vif); struct wmi_connect_event *evt = d; - int ch; /* channel number */ + int ch; /* channel number (primary) */ + u8 spec_ch = 0; /* spec channel number */ struct station_info sinfo; u8 *assoc_req_ie, *assoc_resp_ie; size_t assoc_req_ielen, assoc_resp_ielen; @@ -936,8 +937,16 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len) } ch = evt->channel + 1; - wil_info(wil, "Connect %pM channel [%d] cid %d aid %d\n", - evt->bssid, ch, evt->cid, evt->aid); + if (evt->edmg_channel && + test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities)) + wil_wmi2spec_ch(evt->edmg_channel, &spec_ch); + if (spec_ch) + wil_info(wil, "Connect %pM EDMG channel [%d] primary channel [%d] cid %d aid %d\n", + evt->bssid, spec_ch, ch, evt->cid, evt->aid); + else + wil_info(wil, "Connect %pM channel [%d] cid %d aid %d\n", + evt->bssid, ch, evt->cid, evt->aid); + wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, evt->assoc_info, len - sizeof(*evt), true); @@ -1683,6 +1692,16 @@ int wmi_pcp_start(struct wil6210_vif *vif, .evt = {.status = WMI_FW_STATUS_FAILURE}, }; + if (test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities)) + if (wil->force_edmg_channel) { + rc = wil_spec2wmi_ch(wil->force_edmg_channel, + &cmd.edmg_channel); + if (rc) + wil_err(wil, + "wmi channel for channel %d not found", + wil->force_edmg_channel); + } + if (!vif->privacy) cmd.disable_sec = 1; diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index b2de674ecce2..7a7ccccf900f 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -85,6 +85,7 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_LO_POWER_CALIB_FROM_OTP = 14, WMI_FW_CAPABILITY_PNO = 15, WMI_FW_CAPABILITY_CONNECT_SNR_THR = 16, + WMI_FW_CAPABILITY_CHANNEL_BONDING = 17, WMI_FW_CAPABILITY_REF_CLOCK_CONTROL = 18, WMI_FW_CAPABILITY_AP_SME_OFFLOAD_NONE = 19, WMI_FW_CAPABILITY_AMSDU = 23, @@ -314,6 +315,19 @@ enum wmi_connect_ctrl_flag_bits { #define WMI_MAX_SSID_LEN (32) +enum wmi_channel { + WMI_CHANNEL_1 = 0x00, + WMI_CHANNEL_2 = 0x01, + WMI_CHANNEL_3 = 0x02, + WMI_CHANNEL_4 = 0x03, + WMI_CHANNEL_5 = 0x04, + WMI_CHANNEL_6 = 0x05, + WMI_CHANNEL_9 = 0x06, + WMI_CHANNEL_10 = 0x07, + WMI_CHANNEL_11 = 0x08, + WMI_CHANNEL_12 = 0x09, +}; + /* WMI_CONNECT_CMDID */ struct wmi_connect_cmd { u8 network_type; @@ -325,8 +339,12 @@ struct wmi_connect_cmd { u8 group_crypto_len; u8 ssid_len; u8 ssid[WMI_MAX_SSID_LEN]; + /* enum wmi_channel WMI_CHANNEL_1..WMI_CHANNEL_6; for EDMG this is + * the primary channel number + */ u8 channel; - u8 reserved0; + /* enum wmi_channel WMI_CHANNEL_9..WMI_CHANNEL_12 */ + u8 edmg_channel; u8 bssid[WMI_MAC_LEN]; __le32 ctrl_flags; u8 dst_mac[WMI_MAC_LEN]; @@ -644,12 +662,17 @@ struct wmi_pcp_start_cmd { u8 pcp_max_assoc_sta; u8 hidden_ssid; u8 is_go; - u8 reserved0[5]; + /* enum wmi_channel WMI_CHANNEL_9..WMI_CHANNEL_12 */ + u8 edmg_channel; + u8 reserved[4]; /* A-BFT length override if non-0 */ u8 abft_len; /* enum wmi_ap_sme_offload_mode_e */ u8 ap_sme_offload_mode; u8 network_type; + /* enum wmi_channel WMI_CHANNEL_1..WMI_CHANNEL_6; for EDMG this is + * the primary channel number + */ u8 channel; u8 disable_sec_offload; u8 disable_sec; @@ -1899,8 +1922,12 @@ struct wmi_notify_req_done_event { /* WMI_CONNECT_EVENTID */ struct wmi_connect_event { + /* enum wmi_channel WMI_CHANNEL_1..WMI_CHANNEL_6; for EDMG this is + * the primary channel number + */ u8 channel; - u8 reserved0; + /* enum wmi_channel WMI_CHANNEL_9..WMI_CHANNEL_12 */ + u8 edmg_channel; u8 bssid[WMI_MAC_LEN]; __le16 listen_interval; __le16 beacon_interval; -- GitLab From 00633b8d12adbeac94f0026c6a10a2ad631c394b Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Sun, 1 Jul 2018 14:47:31 +0530 Subject: [PATCH 0975/1299] defconfig: Enable USB gadget uevents on QCS405 On QCS405 enable USB gadget events for the android_usb class creation and the userspace can receive the USB gadget uevents. Change-Id: I6db4acd892710500a140465dd24839a0b1ade2f2 Signed-off-by: Sriharsha Allenki --- arch/arm/configs/vendor/qcs405_defconfig | 1 + arch/arm64/configs/vendor/qcs405_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index a08933b0bccf..8ecd73be3ba3 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -352,6 +352,7 @@ CONFIG_USB_GADGET_DEBUG_FS=y CONFIG_USB_GADGET_VBUS_DRAW=900 CONFIG_USB_CONFIGFS=y CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_UEVENT=y CONFIG_USB_CONFIGFS_F_DIAG=y CONFIG_MMC=y CONFIG_MMC_PERF_PROFILING=y diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index 9e34c16fb8af..d7238873e369 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -354,6 +354,7 @@ CONFIG_USB_GADGET_DEBUG_FS=y CONFIG_USB_GADGET_VBUS_DRAW=900 CONFIG_USB_CONFIGFS=y CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_UEVENT=y CONFIG_USB_CONFIGFS_F_DIAG=y CONFIG_MMC=y CONFIG_MMC_PERF_PROFILING=y -- GitLab From a92462efa5ae6ebd6a61bc16d2ae302758511f10 Mon Sep 17 00:00:00 2001 From: Sayali Lokhande Date: Sat, 30 Jun 2018 15:48:43 +0530 Subject: [PATCH 0976/1299] ARM: dts: msm: Add sdhc rclk pin setting for QCS405 Add sdc1_rclk_on and rclk_off pin control setting to support eMMC in hs400 enhanced strobe mode. Change-Id: If2804df87f9045065e722b04e3d0c2b1de3aeec4 Signed-off-by: Sayali Lokhande --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 927b205c6929..b6937b159d0a 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -916,8 +916,10 @@ qcom,vdd-io-current-level = <0 325000>; pinctrl-names = "active", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; + pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on + &sdc1_rclk_on>; + pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off + &sdc1_rclk_off>; status = "ok"; }; -- GitLab From 7c1cd10a7179087f263d90bb2fc8299533ac6fc1 Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Thu, 16 Nov 2017 15:14:36 +0530 Subject: [PATCH 0977/1299] iommu: arm-smmu: enable clocks and regulators in smmu detach During smmu detach, arm_smmu_domain_remove_master function is called which clears SMR, S2CR registers and performs tlb_flush operation. Enable the required clocks and regulators for the access. Change-Id: I8317b8bfe95b3b76cd2878d4090dd7b647094f7a Signed-off-by: Vijayanand Jitta Signed-off-by: Charan Teja Reddy --- drivers/iommu/arm-smmu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 25037f3c6bee..e9211a1c64cc 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -2346,13 +2346,13 @@ static void arm_smmu_detach_dev(struct iommu_domain *domain, return; } - arm_smmu_domain_remove_master(smmu_domain, fwspec); + if (atomic_domain) + arm_smmu_power_on_atomic(smmu->pwr); + else + arm_smmu_power_on(smmu->pwr); - /* Remove additional vote for atomic power */ - if (atomic_domain) { - WARN_ON(arm_smmu_power_on_atomic(smmu->pwr)); - arm_smmu_power_off(smmu->pwr); - } + arm_smmu_domain_remove_master(smmu_domain, fwspec); + arm_smmu_power_off(smmu->pwr); } static int arm_smmu_assign_table(struct arm_smmu_domain *smmu_domain) -- GitLab From 8f73b2784b032a437fc8367b424c8c2dd2d0eb33 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Sun, 1 Jul 2018 21:27:39 +0530 Subject: [PATCH 0978/1299] ARM: dts: msm: correct interrupt lines of gfx smmu on qcs405 Correct the interrupt lines of context banks of graphics SMMU on QCS405. These are used by a context bank to report any error to CPU. Change-Id: I6158ef9b72af5177c6584ce16a5a3bec26bd48e9 Signed-off-by: Charan Teja Reddy --- arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi index 7a7beda8f149..2338738e7c55 100644 --- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-qcs405.dtsi @@ -28,10 +28,10 @@ #size-cells = <1>; #address-cells = <1>; ranges; - interrupts = , - , - , - ; + interrupts = , + , + , + ; clocks = <&clock_gcc GCC_SMMU_CFG_CLK>, <&clock_gcc GCC_GFX_TCU_CLK>; clock-names = "iface_clk", "core_clk"; -- GitLab From 8d0ec5e1ed1c66ea918f44578c6d70c22bbc585c Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Wed, 16 May 2018 18:26:38 -0700 Subject: [PATCH 0979/1299] ARM: dts: msm: Add DSI/DP/WB support for ADP Star Add DSI/DP/WB display nodes in device tree to support display on ADP Star. CRs-Fixed: 2266258 Change-Id: I781d2cef01212bbe072eec5a2a4c90584289e22a Signed-off-by: Xiaowen Wu --- .../dts/qcom/dsi-panel-ext-bridge-1080p.dtsi | 53 ++++ arch/arm64/boot/dts/qcom/sa8155.dtsi | 288 ++++++++++++++++++ 2 files changed, 341 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/dsi-panel-ext-bridge-1080p.dtsi diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-ext-bridge-1080p.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-ext-bridge-1080p.dtsi new file mode 100644 index 000000000000..0d518a6901eb --- /dev/null +++ b/arch/arm64/boot/dts/qcom/dsi-panel-ext-bridge-1080p.dtsi @@ -0,0 +1,53 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_ext_bridge_1080p: qcom,mdss_dsi_ext_bridge_1080p { + qcom,mdss-dsi-panel-name = "ext video mode dsi bridge"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-traffic-mode = "non_burst_sync_pulse"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-t-clk-post = <0x03>; + qcom,mdss-dsi-t-clk-pre = <0x24>; + qcom,mdss-dsi-force-clock-lane-hs; + qcom,mdss-dsi-ext-bridge-mode; + + qcom,mdss-dsi-display-timings { + timing@0{ + qcom,mdss-dsi-panel-width = <1920>; + qcom,mdss-dsi-panel-height = <1080>; + qcom,mdss-dsi-h-front-porch = <88>; + qcom,mdss-dsi-h-back-porch = <148>; + qcom,mdss-dsi-h-pulse-width = <44>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <36>; + qcom,mdss-dsi-v-front-porch = <4>; + qcom,mdss-dsi-v-pulse-width = <5>; + qcom,mdss-dsi-h-sync-pulse = <0>; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,display-topology = <1 0 1>; + qcom,default-topology-index = <0>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8155.dtsi b/arch/arm64/boot/dts/qcom/sa8155.dtsi index c404b40d1823..dc4df2a85882 100644 --- a/arch/arm64/boot/dts/qcom/sa8155.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155.dtsi @@ -314,3 +314,291 @@ }; }; }; + +&tlmm { + ioexp_intr_active: ioexp_intr_active { + mux { + pins = "gpio48"; + function = "gpio"; + }; + config { + pins = "gpio48"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + ioexp_reset_active: ioexp_reset_active { + mux { + pins = "gpio30"; + function = "gpio"; + }; + config { + pins = "gpio30"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&sde_dp { + qcom,ext-disp = <&ext_disp>; + qcom,dp-hpd-gpio = <&ioexp 8 0>; + + pinctrl-names = "mdss_dp_active", "mdss_dp_sleep"; + pinctrl-0 = <&dp_hpd_cfg_pins>; + pinctrl-1 = <&dp_hpd_cfg_pins>; + + qcom,core-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + qcom,core-supply-entry@0 { + reg = <0>; + qcom,supply-name = "refgen"; + qcom,supply-min-voltage = <0>; + qcom,supply-max-voltage = <0>; + qcom,supply-enable-load = <0>; + qcom,supply-disable-load = <0>; + }; + }; +}; + +&qupv3_se15_i2c { + status = "ok"; + + pinctrl-0 = <&qupv3_se15_i2c_active + &ioexp_intr_active + &ioexp_reset_active>; + + ioexp: gpio@3e { + #gpio-cells = <2>; + #interrupt-cells = <2>; + compatible = "semtech,sx1509q"; + reg = <0x3e>; + interrupt-parent = <&tlmm>; + interrupts = <48 0>; + gpio-controller; + interrupt-controller; + semtech,probe-reset; + + pinctrl-names = "default"; + pinctrl-0 = <&dsi1_hpd_cfg_pins + &dsi1_cdet_cfg_pins + &dsi2_hpd_cfg_pins + &dsi2_cdet_cfg_pins>; + + dsi1_hpd_cfg_pins: gpio0-cfg { + pins = "gpio0"; + bias-pull-up; + }; + + dsi1_cdet_cfg_pins: gpio1-cfg { + pins = "gpio1"; + bias-pull-down; + }; + + dsi2_hpd_cfg_pins: gpio2-cfg { + pins = "gpio2"; + bias-pull-up; + }; + + dsi2_cdet_cfg_pins: gpio3-cfg { + pins = "gpio3"; + bias-pull-down; + }; + + dp_hpd_cfg_pins: gpio8-cfg { + pins = "gpio8"; + bias-pull-down; + }; + }; + + i2c-mux@77 { + compatible = "nxp,pca9542"; + reg = <0x77>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + anx_7625_1: anx7625@2c { + compatible = "analogix,anx7625"; + reg = <0x2c>; + interrupt-parent = <&ioexp>; + interrupts = <0 0>; + cbl_det-gpio = <&ioexp 1 0>; + power_en-gpio = <&tlmm 47 0>; + reset_n-gpio = <&tlmm 49 0>; + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + anx_7625_2: anx7625@2c { + compatible = "analogix,anx7625"; + reg = <0x2c>; + interrupt-parent = <&ioexp>; + interrupts = <2 0>; + cbl_det-gpio = <&ioexp 3 0>; + power_en-gpio = <&tlmm 87 0>; + reset_n-gpio = <&tlmm 29 0>; + }; + }; + }; +}; + +&anx_7625_1 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + anx_7625_1_in: endpoint { + remote-endpoint = <&dsi_anx_7625_1_out>; + }; + }; + }; +}; + +&anx_7625_2 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + anx_7625_2_in: endpoint { + remote-endpoint = <&dsi_anx_7625_2_out>; + }; + }; + }; +}; + +#include "dsi-panel-ext-bridge-1080p.dtsi" + +&soc { + dsi_anx_7625_1: qcom,dsi-display@17 { + label = "dsi_anx_7625_1"; + qcom,dsi-display-active; + qcom,display-type = "primary"; + + qcom,dsi-ctrl-num = <0>; + qcom,dsi-phy-num = <0>; + qcom,dsi-select-clocks = "src_byte_clk0", "src_pixel_clk0"; + + qcom,dsi-panel = <&dsi_ext_bridge_1080p>; + }; + + dsi_anx_7625_2: qcom,dsi-display@18 { + label = "dsi_anx_7625_2"; + qcom,dsi-display-active; + qcom,display-type = "secondary"; + + qcom,dsi-ctrl-num = <1>; + qcom,dsi-phy-num = <1>; + qcom,dsi-select-clocks = "src_byte_clk1", "src_pixel_clk1"; + + qcom,dsi-panel = <&dsi_ext_bridge_1080p>; + }; + + dsi_dp1: qcom,dsi-display@1 { + compatible = "qcom,dsi-display"; + label = "primary"; + + qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>; + qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>; + + clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>, + <&mdss_dsi0_pll PCLK_MUX_0_CLK>, + <&mdss_dsi1_pll BYTECLK_MUX_1_CLK>, + <&mdss_dsi1_pll PCLK_MUX_1_CLK>; + clock-names = "src_byte_clk0", "src_pixel_clk0", + "src_byte_clk1", "src_pixel_clk1"; + + qcom,dsi-display-list = + <&dsi_anx_7625_1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi_anx_7625_1_out: endpoint { + remote-endpoint = <&anx_7625_1_in>; + }; + }; + }; + }; + + dsi_dp2: qcom,dsi-display@2 { + compatible = "qcom,dsi-display"; + label = "secondary"; + + qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>; + qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>; + + clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>, + <&mdss_dsi0_pll PCLK_MUX_0_CLK>, + <&mdss_dsi1_pll BYTECLK_MUX_1_CLK>, + <&mdss_dsi1_pll PCLK_MUX_1_CLK>; + clock-names = "src_byte_clk0", "src_pixel_clk0", + "src_byte_clk1", "src_pixel_clk1"; + + qcom,dsi-display-list = + <&dsi_anx_7625_2>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi_anx_7625_2_out: endpoint { + remote-endpoint = <&anx_7625_2_in>; + }; + }; + }; + }; + + refgen: refgen-regulator@88e7000 { + compatible = "qcom,refgen-regulator"; + reg = <0x88e7000 0x60>; + regulator-name = "refgen"; + regulator-enable-ramp-delay = <5>; + }; + + sde_wb: qcom,wb-display@0 { + compatible = "qcom,wb-display"; + cell-index = <0>; + label = "wb_display"; + }; + + ext_disp: qcom,msm-ext-disp { + compatible = "qcom,msm-ext-disp"; + + ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx { + compatible = "qcom,msm-ext-disp-audio-codec-rx"; + }; + }; +}; + +&mdss_dsi_phy0 { + qcom,panel-force-clock-lane-hs; +}; + +&mdss_dsi_phy1 { + qcom,panel-force-clock-lane-hs; +}; + +&mdss_mdp { + connectors = <&dsi_dp1 &dsi_dp2 &sde_dp &sde_wb>; +}; -- GitLab From fa4321e2d484b86e9b21357659781e437f11970c Mon Sep 17 00:00:00 2001 From: Xiaowen Wu Date: Wed, 20 Jun 2018 19:26:24 -0400 Subject: [PATCH 0980/1299] ARM: add display card drivers to auto platform add display card drivers to auto defconfig CRs-Fixed: 2266264 Change-Id: I15f9d53fea1f3d77d46ff6b244081c09351f6fc6 Signed-off-by: Xiaowen Wu --- arch/arm64/configs/vendor/sm8150-auto_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-auto_defconfig b/arch/arm64/configs/vendor/sm8150-auto_defconfig index af8898cbc26a..eb0060ebee4b 100644 --- a/arch/arm64/configs/vendor/sm8150-auto_defconfig +++ b/arch/arm64/configs/vendor/sm8150-auto_defconfig @@ -328,6 +328,7 @@ CONFIG_DIAG_CHAR=y CONFIG_MSM_FASTCVPD=y CONFIG_MSM_ADSPRPC=y CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX_PCA954x=y CONFIG_I2C_QCOM_GENI=y CONFIG_SPI=y CONFIG_SPI_QCOM_GENI=y @@ -338,6 +339,7 @@ CONFIG_PM8150_PMIC_SIMULATOR=y CONFIG_PM8150B_PMIC_SIMULATOR=y CONFIG_PM8150L_PMIC_SIMULATOR=y CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_PINCTRL_SX150X=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y CONFIG_PINCTRL_SM8150=y CONFIG_GPIO_SYSFS=y @@ -389,6 +391,7 @@ CONFIG_DRM=y CONFIG_DRM_MSM_REGISTER_LOGGING=y CONFIG_DRM_SDE_EVTLOG_DEBUG=y CONFIG_DRM_SDE_RSC=y +CONFIG_DRM_ANALOGIX_ANX7625=y CONFIG_FB_VIRTUAL=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_BACKLIGHT_CLASS_DEVICE=y -- GitLab From 491af6396f75124f1a45233307a138038028376a Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Sun, 1 Jul 2018 16:03:58 +0530 Subject: [PATCH 0981/1299] msm: ADSPRPC: Fix array out of bounds issue Array is being accessed out of bounds. Fix this. Change-Id: I2e108099bc7ac262050f76375169c37e2b663e21 Signed-off-by: Shiraz Hashim --- drivers/char/adsprpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 06a25625271a..c39d1b888064 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2154,7 +2154,7 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, if (map->flags == ADSP_MMAP_HEAP_ADDR) { struct fastrpc_ioctl_invoke_crc ioctl; struct scm_desc desc = {0}; - remote_arg_t ra[1]; + remote_arg_t ra[2]; int err = 0; struct { uint8_t skey; -- GitLab From e8244a97d182df4b7bf039861844253e9372aee9 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Thu, 21 Jun 2018 12:45:43 +0530 Subject: [PATCH 0982/1299] defconfig: Enable cnss_genl driver compilation cnss_genl driver creates a netlink family and multicast groups to facilitate communication between WLAN driver and userspace. Define flag CONFIG_CNSS_GENL and set to 'y'(yes) to enable compilation of the cnss_genl driver inorder to use the same Change-Id: I9d81f933e4fe3c9383f213c777d335e1fe51bdd2 Signed-off-by: Srinivas Dasari CRs-Fixed: 1117130 --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index d9f91b7ccfd8..8382ace603bc 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -294,6 +294,7 @@ CONFIG_USB_USBNET=y CONFIG_WIL6210=m CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CLD_LL_CORE=y +CONFIG_CNSS_GENL=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 9b1c7c3b11d1..9e49055d493a 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -305,6 +305,7 @@ CONFIG_PPP_SYNC_TTY=y CONFIG_WIL6210=m CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CLD_LL_CORE=y +CONFIG_CNSS_GENL=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set -- GitLab From 42e002176ffa24b7f623f6639d1a70b55a85b5d1 Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Mon, 2 Jul 2018 23:15:45 +0530 Subject: [PATCH 0983/1299] ARM: dts: msm: Add two wire UART support and correct irq mapping Correct interrupt mapping as per intc and also add two wire UART support on blsp1 uart2 instance for wifi use case. Change-Id: Ide67df9031ffa04c2e2280cb282a78a21f22d00e Signed-off-by: Mukesh Kumar Savaliya --- arch/arm64/boot/dts/qcom/qcs405-blsp.dtsi | 20 ++++++++++---------- arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi | 12 ++++-------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-blsp.dtsi b/arch/arm64/boot/dts/qcom/qcs405-blsp.dtsi index 224ec15a22cb..f58fc527b934 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-blsp.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-blsp.dtsi @@ -348,8 +348,8 @@ interrupts = <0 1 2>; #interrupt-cells = <1>; interrupt-map-mask = <0xffffffff>; - interrupt-map = <0 &intc 0 0 107 0 - 1 &intc 0 0 238 0 + interrupt-map = <0 &intc 0 107 0 + 1 &intc 0 238 0 2 &tlmm 31 0>; qcom,inject-rx-on-wakeup; @@ -385,8 +385,8 @@ interrupts = <0 1 2>; #interrupt-cells = <1>; interrupt-map-mask = <0xffffffff>; - interrupt-map = <0 &intc 0 0 108 0 - 1 &intc 0 0 238 0 + interrupt-map = <0 &intc 0 108 0 + 1 &intc 0 238 0 2 &tlmm 23 0>; qcom,inject-rx-on-wakeup; @@ -422,8 +422,8 @@ interrupts = <0 1 2>; #interrupt-cells = <1>; interrupt-map-mask = <0xffffffff>; - interrupt-map = <0 &intc 0 0 118 0 - 1 &intc 0 0 238 0 + interrupt-map = <0 &intc 0 118 0 + 1 &intc 0 238 0 2 &tlmm 18 0>; qcom,inject-rx-on-wakeup; @@ -459,8 +459,8 @@ interrupts = <0 1 2>; #interrupt-cells = <1>; interrupt-map-mask = <0xffffffff>; - interrupt-map = <0 &intc 0 0 119 0 - 1 &intc 0 0 238 0 + interrupt-map = <0 &intc 0 119 0 + 1 &intc 0 238 0 2 &tlmm 83 0>; qcom,inject-rx-on-wakeup; @@ -498,8 +498,8 @@ interrupts = <0 1 2>; #interrupt-cells = <1>; interrupt-map-mask = <0xffffffff>; - interrupt-map = <0 &intc 0 0 297 0 - 1 &intc 0 0 239 0 + interrupt-map = <0 &intc 0 297 0 + 1 &intc 0 239 0 2 &tlmm 27 0>; qcom,inject-rx-on-wakeup; diff --git a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi index 9b51a14b26b2..8f9fe8eaa2d4 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi @@ -85,14 +85,12 @@ blsp1_uart2 { blsp1_uart2_active: blsp1_uart2_active { mux { - pins = "gpio22", "gpio23", - "gpio24", "gpio25"; + pins = "gpio22", "gpio23"; function = "blsp_uart1"; }; config { - pins = "gpio22", "gpio23", - "gpio24", "gpio25"; + pins = "gpio22", "gpio23"; drive-strength = <2>; bias-disable; }; @@ -100,14 +98,12 @@ blsp1_uart2_sleep: blsp1_uart2_sleep { mux { - pins = "gpio22", "gpio23", - "gpio24", "gpio25"; + pins = "gpio22", "gpio23"; function = "gpio"; }; config { - pins = "gpio22", "gpio23", - "gpio24", "gpio25"; + pins = "gpio22", "gpio23"; drive-strength = <2>; bias-disable; }; -- GitLab From 6e0f03f6b8ec19b8fb7f30bc3aa0dc722d60c69f Mon Sep 17 00:00:00 2001 From: Sandeep Panda Date: Fri, 2 Feb 2018 11:17:04 +0530 Subject: [PATCH 0984/1299] drm/msm/dsi-staging: fix ulps during suspend for video mode Currently DSI driver is only considering command mode panel for getting the number of data lanes enabled, while waiting for lanes to be idle. So in video mode the wait is failing because of mismatch in number of data lanes. Also when coming out of ulps in suspend we should not configure the DSI controller twice, which may put DSI HW in bad state. This change fixes the same for ulps during suspend feature. Change-Id: I090e7d726759a8317dee7941c1067207c986b98b Signed-off-by: Shashank Babu Chinta Venkata Signed-off-by: Sandeep Panda --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 32 ++++++++++++++--- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h | 4 +++ drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 34 ++++++++++++++----- drivers/gpu/drm/msm/dsi-staging/dsi_phy.c | 6 ++-- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 0cdca09fac88..7f925f701566 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -1442,8 +1442,7 @@ static int dsi_enable_ulps(struct dsi_ctrl *dsi_ctrl) u32 lanes = 0; u32 ulps_lanes; - if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) - lanes = dsi_ctrl->host_config.common_config.data_lanes; + lanes = dsi_ctrl->host_config.common_config.data_lanes; rc = dsi_ctrl->hw.ops.wait_for_lane_idle(&dsi_ctrl->hw, lanes); if (rc) { @@ -1484,9 +1483,7 @@ static int dsi_disable_ulps(struct dsi_ctrl *dsi_ctrl) return 0; } - if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) - lanes = dsi_ctrl->host_config.common_config.data_lanes; - + lanes = dsi_ctrl->host_config.common_config.data_lanes; lanes |= DSI_CLOCK_LANE; ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw); @@ -2462,6 +2459,31 @@ int dsi_ctrl_host_timing_update(struct dsi_ctrl *dsi_ctrl) return 0; } +/** + * dsi_ctrl_update_host_init_state() - Update the host initialization state. + * @dsi_ctrl: DSI controller handle. + * @enable: boolean signifying host state. + * + * Update the host initialization status only while exiting from ulps during + * suspend state. + * + * Return: error code. + */ +int dsi_ctrl_update_host_init_state(struct dsi_ctrl *dsi_ctrl, bool enable) +{ + int rc = 0; + u32 state = enable ? 0x1 : 0x0; + + rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, state); + if (rc) { + pr_err("[DSI_%d] Controller state check failed, rc=%d\n", + dsi_ctrl->cell_index, rc); + return rc; + } + dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, state); + return rc; +} + /** * dsi_ctrl_host_init() - Initialize DSI host hardware. * @dsi_ctrl: DSI controller handle. diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h index edb1b31f3238..81bbbc7786a9 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h @@ -753,5 +753,9 @@ int dsi_ctrl_get_host_engine_init_state(struct dsi_ctrl *dsi_ctrl, * @dsi_ctrl: DSI controller handle. */ int dsi_ctrl_wait_for_cmd_mode_mdp_idle(struct dsi_ctrl *dsi_ctrl); +/** + * dsi_ctrl_update_host_init_state() - Set the host initialization state + */ +int dsi_ctrl_update_host_init_state(struct dsi_ctrl *dsi_ctrl, bool en); #endif /* _DSI_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 6ba07171a196..acefbc1a82cb 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -2225,18 +2225,34 @@ static int dsi_display_ctrl_init(struct dsi_display *display) int i; struct dsi_display_ctrl *ctrl; - for (i = 0 ; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - rc = dsi_ctrl_host_init(ctrl->ctrl, - display->is_cont_splash_enabled); - if (rc) { - pr_err("[%s] failed to init host_%d, rc=%d\n", - display->name, i, rc); - goto error_host_deinit; + /* when ULPS suspend feature is enabled, we will keep the lanes in + * ULPS during suspend state and clamp DSI phy. Hence while resuming + * we will programe DSI controller as part of core clock enable. + * After that we should not re-configure DSI controller again here for + * usecases where we are resuming from ulps suspend as it might put + * the HW in bad state. + */ + if (!display->panel->ulps_suspend_enabled || !display->ulps_enabled) { + for (i = 0 ; i < display->ctrl_count; i++) { + ctrl = &display->ctrl[i]; + rc = dsi_ctrl_host_init(ctrl->ctrl, + display->is_cont_splash_enabled); + if (rc) { + pr_err("[%s] failed to init host_%d, rc=%d\n", + display->name, i, rc); + goto error_host_deinit; + } + } + } else { + for (i = 0 ; i < display->ctrl_count; i++) { + ctrl = &display->ctrl[i]; + rc = dsi_ctrl_update_host_init_state(ctrl->ctrl, true); + if (rc) + pr_debug("host init update failed rc=%d\n", rc); } } - return 0; + return rc; error_host_deinit: for (i = i - 1; i >= 0; i--) { ctrl = &display->ctrl[i]; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c index caf554a55d07..285329c5e6cc 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c @@ -708,8 +708,7 @@ static int dsi_phy_enable_ulps(struct msm_dsi_phy *phy, u32 lanes = 0; u32 ulps_lanes; - if (config->panel_mode == DSI_OP_CMD_MODE) - lanes = config->common_config.data_lanes; + lanes = config->common_config.data_lanes; lanes |= DSI_CLOCK_LANE; /* @@ -744,8 +743,7 @@ static int dsi_phy_disable_ulps(struct msm_dsi_phy *phy, { u32 ulps_lanes, lanes = 0; - if (config->panel_mode == DSI_OP_CMD_MODE) - lanes = config->common_config.data_lanes; + lanes = config->common_config.data_lanes; lanes |= DSI_CLOCK_LANE; ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw); -- GitLab From 5e23ea87135bea2aff4c7bea983989d7159f7c02 Mon Sep 17 00:00:00 2001 From: Sandeep Panda Date: Thu, 29 Mar 2018 09:00:10 +0530 Subject: [PATCH 0985/1299] drm/msm/dsi-staging: fix multiple reg read in ESD In the current implementation when ESD check needs to send multiple read commands then the last command flag is only set for first read command. So the transfer of rest of the read commands will fail. This changes fixes all the issues related to multiple reg read feature. Change-Id: If783c9e7bc15630358d2cb1f6cd5a6b3320fbf6d Signed-off-by: Sandeep Panda Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 10 ++++++++++ drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 10 +++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 7f925f701566..cbdb7572d94a 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -1338,6 +1338,9 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, u32 dlen, diff, rlen = msg->rx_len; unsigned char *buff; char cmd; + struct dsi_cmd_desc *of_cmd; + + of_cmd = container_of(msg, struct dsi_cmd_desc, msg); if (msg->rx_len <= 2) { short_resp = true; @@ -1371,6 +1374,13 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, pr_err("Message transmission failed, rc=%d\n", rc); goto error; } + /* + * wait before reading rdbk_data register, if any delay is + * required after sending the read command. + */ + if (of_cmd && of_cmd->post_wait_ms) + usleep_range(of_cmd->post_wait_ms * 1000, + ((of_cmd->post_wait_ms * 1000) + 10)); dlen = dsi_ctrl->hw.ops.get_cmd_read_data(&dsi_ctrl->hw, buff, total_bytes_read, diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index acefbc1a82cb..98500645a664 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -564,14 +564,14 @@ static int dsi_display_read_status(struct dsi_display_ctrl *ctrl, lenp = config->status_valid_params ?: config->status_cmds_rlen; count = config->status_cmd.count; cmds = config->status_cmd.cmds; - if (cmds->last_command) { - cmds->msg.flags |= MIPI_DSI_MSG_LASTCOMMAND; - flags |= DSI_CTRL_CMD_LAST_COMMAND; - } flags |= (DSI_CTRL_CMD_FETCH_MEMORY | DSI_CTRL_CMD_READ); for (i = 0; i < count; ++i) { memset(config->status_buf, 0x0, SZ_4K); + if (cmds[i].last_command) { + cmds[i].msg.flags |= MIPI_DSI_MSG_LASTCOMMAND; + flags |= DSI_CTRL_CMD_LAST_COMMAND; + } cmds[i].msg.rx_buf = config->status_buf; cmds[i].msg.rx_len = config->status_cmds_rlen[i]; rc = dsi_ctrl_cmd_transfer(ctrl->ctrl, &cmds[i].msg, flags); @@ -655,7 +655,7 @@ static int dsi_display_status_reg_read(struct dsi_display *display) rc = dsi_display_validate_status(ctrl, display->panel); if (rc <= 0) { - pr_err("[%s] read status failed on master,rc=%d\n", + pr_err("[%s] read status failed on slave,rc=%d\n", display->name, rc); goto exit; } -- GitLab From 51ca09b5ffe14f4ad5321683b141ba70158f534d Mon Sep 17 00:00:00 2001 From: Vara Reddy Date: Wed, 7 Feb 2018 11:37:37 -0800 Subject: [PATCH 0986/1299] drm/msm/dsi-staging: check esd reg readback value correctly Fix issue around checking esd register read back value with the expected value from the dtsi entries. Change-Id: I8aeccc3acb61f10c3141e42a15eb6c674af251e6 CRs-Fixed: 2183397 Signed-off-by: Vara Reddy Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 98500645a664..a240ebf96d7e 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -484,7 +484,6 @@ static bool dsi_display_validate_reg_read(struct dsi_panel *panel) int i, j = 0; int len = 0, *lenp; int group = 0, count = 0; - struct dsi_display_mode *mode; struct drm_panel_esd_config *config; if (!panel) @@ -493,8 +492,7 @@ static bool dsi_display_validate_reg_read(struct dsi_panel *panel) config = &(panel->esd_config); lenp = config->status_valid_params ?: config->status_cmds_rlen; - mode = panel->cur_mode; - count = mode->priv_info->cmd_sets[DSI_CMD_SET_PANEL_STATUS].count; + count = config->status_cmd.count; for (i = 0; i < count; i++) len += lenp[i]; -- GitLab From 13968be6b04dbad87354edd0ba24355c9ec4d0e8 Mon Sep 17 00:00:00 2001 From: Vara Reddy Date: Thu, 25 Jan 2018 15:47:38 -0800 Subject: [PATCH 0987/1299] drm/msm/dsi-staging: remove unnecesary locks from commit path Frame drops are observed when crtc_commit thread tries to hold panel lock for updating the frame, while backlight service thread is pushing the backlight commands holding panel_lock. Remove holding panel lock from commit thread. CRs-Fixed: 2179313 Change-Id: I7d6e5044db570102b7c2c7edb1c5c4b24847ed3f Signed-off-by: Vara Reddy Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 3 --- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 8 -------- 2 files changed, 11 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index cbdb7572d94a..f34e1c604580 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -2747,9 +2747,6 @@ int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl, return -EINVAL; } - mutex_lock(&dsi_ctrl->ctrl_lock); - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index d90c553ff47d..3a0b9cf3b5d1 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -3074,11 +3074,7 @@ int dsi_panel_get_phy_props(struct dsi_panel *panel, return -EINVAL; } - mutex_lock(&panel->panel_lock); - memcpy(phy_props, &panel->phy_props, sizeof(*phy_props)); - - mutex_unlock(&panel->panel_lock); return rc; } @@ -3092,11 +3088,7 @@ int dsi_panel_get_dfps_caps(struct dsi_panel *panel, return -EINVAL; } - mutex_lock(&panel->panel_lock); - memcpy(dfps_caps, &panel->dfps_caps, sizeof(*dfps_caps)); - - mutex_unlock(&panel->panel_lock); return rc; } -- GitLab From 60b169cb11fd4b1cdc66fbea354a18fd98dae480 Mon Sep 17 00:00:00 2001 From: Vara Reddy Date: Tue, 30 Jan 2018 14:23:36 -0800 Subject: [PATCH 0988/1299] drm/msm/dsi-staging: send roi commands during resolution switch Send 2a/2b roi commands when display resolution is changed. This is fixing panel corruption issue if resolution switch command list doesn't have the new roi region updated. Change-Id: I5244424e5dff2d07b88d52290365f3ad600eeb13 CRs-Fixed: 2166948 Signed-off-by: Vara Reddy Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 6 +++++- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index f34e1c604580..47f487486154 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -2136,11 +2136,14 @@ int dsi_ctrl_set_roi(struct dsi_ctrl *dsi_ctrl, struct dsi_rect *roi, } mutex_lock(&dsi_ctrl->ctrl_lock); - if (!dsi_rect_is_equal(&dsi_ctrl->roi, roi)) { + if ((!dsi_rect_is_equal(&dsi_ctrl->roi, roi)) || + dsi_ctrl->modeupdated) { *changed = true; memcpy(&dsi_ctrl->roi, roi, sizeof(dsi_ctrl->roi)); + dsi_ctrl->modeupdated = false; } else *changed = false; + mutex_unlock(&dsi_ctrl->ctrl_lock); return rc; } @@ -2721,6 +2724,7 @@ int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl, ctrl->mode_bounds.w = ctrl->host_config.video_timing.h_active; ctrl->mode_bounds.h = ctrl->host_config.video_timing.v_active; memcpy(&ctrl->roi, &ctrl->mode_bounds, sizeof(ctrl->mode_bounds)); + ctrl->modeupdated = true; ctrl->roi.x = 0; error: mutex_unlock(&ctrl->ctrl_lock); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h index 81bbbc7786a9..7bfa45d5bc85 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h @@ -211,6 +211,7 @@ struct dsi_ctrl_interrupts { * dsi controller and run only dsi controller. * @null_insertion_enabled: A boolean property to allow dsi controller to * insert null packet. + * @modeupdated: Boolean to send new roi if mode is updated. */ struct dsi_ctrl { struct platform_device *pdev; @@ -258,6 +259,7 @@ struct dsi_ctrl { bool phy_isolation_enabled; bool null_insertion_enabled; + bool modeupdated; }; /** -- GitLab From f3c26e8551db5db0fd9f6952224ad9450bb0de5c Mon Sep 17 00:00:00 2001 From: Vara Reddy Date: Thu, 5 Apr 2018 04:56:39 -0700 Subject: [PATCH 0989/1299] drm/msm/dsi-staging: correct return value of dsi_host_transfer Fix the dsi_host_transfer API to accurately return the error code in case of failures. CRs-Fixed: 2191069 Change-Id: I54503ca2f2fc02bf2374abae5147b8c1f13eff02 Signed-off-by: Vara Reddy Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index a240ebf96d7e..7b07fac9f6ca 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -2609,7 +2609,7 @@ static ssize_t dsi_host_transfer(struct mipi_dsi_host *host, const struct mipi_dsi_msg *msg) { struct dsi_display *display = to_dsi_display(host); - int rc = 0; + int rc = 0, ret = 0; if (!host || !msg) { pr_err("Invalid params\n"); @@ -2667,13 +2667,17 @@ static ssize_t dsi_host_transfer(struct mipi_dsi_host *host, } error_disable_cmd_engine: - (void)dsi_display_cmd_engine_disable(display); + ret = dsi_display_cmd_engine_disable(display); + if (ret) { + pr_err("[%s]failed to disable DSI cmd engine, rc=%d\n", + display->name, ret); + } error_disable_clks: - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, + ret = dsi_display_clk_ctrl(display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_OFF); - if (rc) { + if (ret) { pr_err("[%s] failed to disable all DSI clocks, rc=%d\n", - display->name, rc); + display->name, ret); } error: return rc; -- GitLab From 43dfa3a4218beb6f91a05105e56d127cdccd818f Mon Sep 17 00:00:00 2001 From: Vara Reddy Date: Thu, 5 Apr 2018 04:01:34 -0700 Subject: [PATCH 0990/1299] drm/msm/dsi-staging: enable debug logs during dsi state checks During state checks in dsi control, enable state machine error logs by default to catch rarely reproducible issues. CRs-Fixed: 2170957 Change-Id: I1dd3afeba8bb023e427a4ed15b40d3758b53e885 Signed-off-by: Vara Reddy Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 47f487486154..c7e82767065b 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -280,12 +280,12 @@ static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl, switch (op) { case DSI_CTRL_OP_POWER_STATE_CHANGE: if (state->power_state == op_state) { - pr_debug("[%d] No change in state, pwr_state=%d\n", + pr_err("[%d] No change in state, pwr_state=%d\n", dsi_ctrl->cell_index, op_state); rc = -EINVAL; } else if (state->power_state == DSI_CTRL_POWER_VREG_ON) { if (state->vid_engine_state == DSI_CTRL_ENGINE_ON) { - pr_debug("[%d]State error: op=%d: %d\n", + pr_err("[%d]State error: op=%d: %d\n", dsi_ctrl->cell_index, op_state, state->vid_engine_state); @@ -295,12 +295,12 @@ static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl, break; case DSI_CTRL_OP_CMD_ENGINE: if (state->cmd_engine_state == op_state) { - pr_debug("[%d] No change in state, cmd_state=%d\n", + pr_err("[%d] No change in state, cmd_state=%d\n", dsi_ctrl->cell_index, op_state); rc = -EINVAL; } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) || (state->controller_state != DSI_CTRL_ENGINE_ON)) { - pr_debug("[%d]State error: op=%d: %d, %d\n", + pr_err("[%d]State error: op=%d: %d, %d\n", dsi_ctrl->cell_index, op, state->power_state, @@ -310,12 +310,12 @@ static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl, break; case DSI_CTRL_OP_VID_ENGINE: if (state->vid_engine_state == op_state) { - pr_debug("[%d] No change in state, cmd_state=%d\n", + pr_err("[%d] No change in state, cmd_state=%d\n", dsi_ctrl->cell_index, op_state); rc = -EINVAL; } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) || (state->controller_state != DSI_CTRL_ENGINE_ON)) { - pr_debug("[%d]State error: op=%d: %d, %d\n", + pr_err("[%d]State error: op=%d: %d, %d\n", dsi_ctrl->cell_index, op, state->power_state, @@ -325,11 +325,11 @@ static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl, break; case DSI_CTRL_OP_HOST_ENGINE: if (state->controller_state == op_state) { - pr_debug("[%d] No change in state, ctrl_state=%d\n", + pr_err("[%d] No change in state, ctrl_state=%d\n", dsi_ctrl->cell_index, op_state); rc = -EINVAL; } else if (state->power_state != DSI_CTRL_POWER_VREG_ON) { - pr_debug("[%d]State error (link is off): op=%d:, %d\n", + pr_err("[%d]State error (link is off): op=%d:, %d\n", dsi_ctrl->cell_index, op_state, state->power_state); @@ -337,7 +337,7 @@ static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl, } else if ((op_state == DSI_CTRL_ENGINE_OFF) && ((state->cmd_engine_state != DSI_CTRL_ENGINE_OFF) || (state->vid_engine_state != DSI_CTRL_ENGINE_OFF))) { - pr_debug("[%d]State error (eng on): op=%d: %d, %d\n", + pr_err("[%d]State error (eng on): op=%d: %d, %d\n", dsi_ctrl->cell_index, op_state, state->cmd_engine_state, @@ -349,7 +349,7 @@ static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl, if ((state->power_state != DSI_CTRL_POWER_VREG_ON) || (state->host_initialized != true) || (state->cmd_engine_state != DSI_CTRL_ENGINE_ON)) { - pr_debug("[%d]State error: op=%d: %d, %d, %d\n", + pr_err("[%d]State error: op=%d: %d, %d, %d\n", dsi_ctrl->cell_index, op, state->power_state, @@ -360,23 +360,23 @@ static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl, break; case DSI_CTRL_OP_HOST_INIT: if (state->host_initialized == op_state) { - pr_debug("[%d] No change in state, host_init=%d\n", + pr_err("[%d] No change in state, host_init=%d\n", dsi_ctrl->cell_index, op_state); rc = -EINVAL; } else if (state->power_state != DSI_CTRL_POWER_VREG_ON) { - pr_debug("[%d]State error: op=%d: %d\n", + pr_err("[%d]State error: op=%d: %d\n", dsi_ctrl->cell_index, op, state->power_state); rc = -EINVAL; } break; case DSI_CTRL_OP_TPG: if (state->tpg_enabled == op_state) { - pr_debug("[%d] No change in state, tpg_enabled=%d\n", + pr_err("[%d] No change in state, tpg_enabled=%d\n", dsi_ctrl->cell_index, op_state); rc = -EINVAL; } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) || (state->controller_state != DSI_CTRL_ENGINE_ON)) { - pr_debug("[%d]State error: op=%d: %d, %d\n", + pr_err("[%d]State error: op=%d: %d, %d\n", dsi_ctrl->cell_index, op, state->power_state, @@ -386,7 +386,7 @@ static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl, break; case DSI_CTRL_OP_PHY_SW_RESET: if (state->power_state != DSI_CTRL_POWER_VREG_ON) { - pr_debug("[%d]State error: op=%d: %d\n", + pr_err("[%d]State error: op=%d: %d\n", dsi_ctrl->cell_index, op, state->power_state); rc = -EINVAL; } -- GitLab From 1c1e23d98a9df2d2b82e653d589abaaeced3ea79 Mon Sep 17 00:00:00 2001 From: Vara Reddy Date: Tue, 10 Apr 2018 08:58:32 -0700 Subject: [PATCH 0991/1299] drm/msm/dsi-staging: parse dsc version parameters Parse dsc version and dsc scr version supported by panel and send the pps command accordingly. CRs-Fixed: 2202007 Change-Id: I680cc50cb5ae6817f600a8b3eb37f60aab741b4b Signed-off-by: Vara Reddy Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 33 +++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index 3a0b9cf3b5d1..05761f2a2e8e 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -2030,9 +2030,8 @@ int dsi_dsc_populate_static_param(struct msm_display_dsc_info *dsc) int final_value, final_scale; int ratio_index; - dsc->version = 0x11; - dsc->scr_rev = 0; dsc->rc_model_size = 8192; + if (dsc->version == 0x11 && dsc->scr_rev == 0x1) dsc->first_line_bpg_offset = 15; else @@ -2225,6 +2224,36 @@ static int dsi_panel_parse_dsc_params(struct dsi_display_mode *mode, return 0; } + rc = utils->read_u32(utils->data, "qcom,mdss-dsc-version", &data); + if (rc) { + priv_info->dsc.version = 0x11; + rc = 0; + } else { + priv_info->dsc.version = data & 0xff; + /* only support DSC 1.1 rev */ + if (priv_info->dsc.version != 0x11) { + pr_err("%s: DSC version:%d not supported\n", __func__, + priv_info->dsc.version); + rc = -EINVAL; + goto error; + } + } + + rc = utils->read_u32(utils->data, "qcom,mdss-dsc-scr-version", &data); + if (rc) { + priv_info->dsc.scr_rev = 0x0; + rc = 0; + } else { + priv_info->dsc.scr_rev = data & 0xff; + /* only one scr rev supported */ + if (priv_info->dsc.scr_rev > 0x1) { + pr_err("%s: DSC scr version:%d not supported\n", + __func__, priv_info->dsc.scr_rev); + rc = -EINVAL; + goto error; + } + } + rc = utils->read_u32(utils->data, "qcom,mdss-dsc-slice-height", &data); if (rc) { pr_err("failed to parse qcom,mdss-dsc-slice-height\n"); -- GitLab From afb54903dade886f26de4ae33962bbb0de26d5d9 Mon Sep 17 00:00:00 2001 From: Sandeep Panda Date: Tue, 13 Feb 2018 17:58:05 +0530 Subject: [PATCH 0992/1299] drm/msm/sde: add recovery mechanism if TE signal not received There can be scenarios where display panel might not send TE signal at a regular intervals. It may take more time than what kms driver can wait for and will be fatal. In those use cases add recovery mechanism to reset the panel and display subsystem. Change-Id: I8c28f6212b7fc68073d84b274cef92e670e0352e Signed-off-by: Sandeep Panda Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 15 +++-- drivers/gpu/drm/msm/dsi-staging/dsi_display.h | 4 +- drivers/gpu/drm/msm/sde/sde_connector.c | 64 +++++++++++++++---- drivers/gpu/drm/msm/sde/sde_connector.h | 10 ++- .../gpu/drm/msm/sde/sde_encoder_phys_cmd.c | 9 ++- 5 files changed, 80 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 7b07fac9f6ca..916377359afe 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -688,7 +688,7 @@ static int dsi_display_status_check_te(struct dsi_display *display) reinit_completion(&display->esd_te_gate); if (!wait_for_completion_timeout(&display->esd_te_gate, esd_te_timeout)) { - pr_err("ESD check failed\n"); + pr_err("TE check failed\n"); rc = -EINVAL; } @@ -697,7 +697,8 @@ static int dsi_display_status_check_te(struct dsi_display *display) return rc; } -int dsi_display_check_status(struct drm_connector *connector, void *display) +int dsi_display_check_status(struct drm_connector *connector, void *display, + bool te_check_override) { struct dsi_display *dsi_display = display; struct dsi_panel *panel; @@ -707,18 +708,20 @@ int dsi_display_check_status(struct drm_connector *connector, void *display) if (dsi_display == NULL) return -EINVAL; - panel = dsi_display->panel; - - status_mode = panel->esd_config.status_mode; - mutex_lock(&dsi_display->display_lock); + panel = dsi_display->panel; if (!panel->panel_initialized) { pr_debug("Panel not initialized\n"); mutex_unlock(&dsi_display->display_lock); return rc; } + if (te_check_override && gpio_is_valid(dsi_display->disp_te_gpio)) + status_mode = ESD_MODE_PANEL_TE; + else + status_mode = panel->esd_config.status_mode; + dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_ON); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h index da4969425a4a..74652df844a5 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h @@ -581,8 +581,10 @@ int dsi_display_set_backlight(struct drm_connector *connector, * dsi_display_check_status() - check if panel is dead or alive * @connector: Pointer to drm connector structure * @display: Handle to display. + * @te_check_override: Whether check for TE from panel or default check */ -int dsi_display_check_status(struct drm_connector *connector, void *display); +int dsi_display_check_status(struct drm_connector *connector, void *display, + bool te_check_override); /** * dsi_display_cmd_transfer() - transfer command to the panel diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 802b8d4fec3b..3f4b0663deaf 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -1749,12 +1749,60 @@ static int sde_connector_atomic_check(struct drm_connector *connector, return 0; } +static void _sde_connector_report_panel_dead(struct sde_connector *conn) +{ + struct drm_event event; + bool panel_dead = true; + + if (!conn) + return; + + event.type = DRM_EVENT_PANEL_DEAD; + event.length = sizeof(bool); + msm_mode_object_event_notify(&conn->base.base, + conn->base.dev, &event, (u8 *)&panel_dead); + sde_encoder_display_failure_notification(conn->encoder); + SDE_EVT32(SDE_EVTLOG_ERROR); + SDE_ERROR("esd check failed report PANEL_DEAD conn_id: %d enc_id: %d\n", + conn->base.base.id, conn->encoder->base.id); +} + +int sde_connector_esd_status(struct drm_connector *conn) +{ + struct sde_connector *sde_conn = NULL; + int ret = 0; + + if (!conn) + return ret; + + sde_conn = to_sde_connector(conn); + if (!sde_conn || !sde_conn->ops.check_status) + return ret; + + /* protect this call with ESD status check call */ + mutex_lock(&sde_conn->lock); + ret = sde_conn->ops.check_status(&sde_conn->base, sde_conn->display, + true); + mutex_unlock(&sde_conn->lock); + + if (ret <= 0) { + /* cancel if any pending esd work */ + sde_connector_schedule_status_work(conn, false); + _sde_connector_report_panel_dead(sde_conn); + ret = -ETIMEDOUT; + } else { + SDE_DEBUG("Successfully received TE from panel\n"); + ret = 0; + } + SDE_EVT32(ret); + + return ret; +} + static void sde_connector_check_status_work(struct work_struct *work) { struct sde_connector *conn; - struct drm_event event; int rc = 0; - bool panel_dead = false; conn = container_of(to_delayed_work(work), struct sde_connector, status_work); @@ -1771,7 +1819,7 @@ static void sde_connector_check_status_work(struct work_struct *work) return; } - rc = conn->ops.check_status(&conn->base, conn->display); + rc = conn->ops.check_status(&conn->base, conn->display, false); mutex_unlock(&conn->lock); if (conn->force_panel_dead) { @@ -1795,15 +1843,7 @@ static void sde_connector_check_status_work(struct work_struct *work) } status_dead: - SDE_EVT32(rc, SDE_EVTLOG_ERROR); - SDE_ERROR("esd check failed report PANEL_DEAD conn_id: %d enc_id: %d\n", - conn->base.base.id, conn->encoder->base.id); - panel_dead = true; - event.type = DRM_EVENT_PANEL_DEAD; - event.length = sizeof(bool); - msm_mode_object_event_notify(&conn->base.base, - conn->base.dev, &event, (u8 *)&panel_dead); - sde_encoder_display_failure_notification(conn->encoder); + _sde_connector_report_panel_dead(conn); } static const struct drm_connector_helper_funcs sde_connector_helper_ops = { diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h index a4d66620f860..f803fb5c73f4 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.h +++ b/drivers/gpu/drm/msm/sde/sde_connector.h @@ -236,9 +236,11 @@ struct sde_connector_ops { * check_status - check status of connected display panel * @connector: Pointer to drm connector structure * @display: Pointer to private display handle + * @te_check_override: Whether check TE from panel or default check * Returns: positive value for success, negetive or zero for failure */ - int (*check_status)(struct drm_connector *connector, void *display); + int (*check_status)(struct drm_connector *connector, void *display, + bool te_check_override); /** * cmd_transfer - Transfer command to the connected display panel @@ -847,4 +849,10 @@ int sde_connector_event_notify(struct drm_connector *connector, uint32_t type, */ int sde_connector_get_panel_vfp(struct drm_connector *connector, struct drm_display_mode *mode); +/** + * sde_connector_esd_status - helper function to check te status + * @connector: Pointer to DRM connector object + */ +int sde_connector_esd_status(struct drm_connector *connector); + #endif /* _SDE_CONNECTOR_H_ */ diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c index b72e5f2b17bb..1cdfc6e9fe5b 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c @@ -522,6 +522,10 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( atomic_read(&phys_enc->pending_kickoff_cnt), frame_event); + /* check if panel is still sending TE signal or not */ + if (sde_connector_esd_status(phys_enc->connector)) + goto exit; + /* to avoid flooding, only log first time, and "dead" time */ if (cmd_enc->pp_timeout_report_cnt == 1) { SDE_ERROR_CMDENC(cmd_enc, @@ -549,11 +553,12 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( SDE_DBG_DUMP("panic"); } - atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); - /* request a ctl reset before the next kickoff */ phys_enc->enable_state = SDE_ENC_ERR_NEEDS_HW_RESET; +exit: + atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); + if (phys_enc->parent_ops.handle_frame_done) phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, frame_event); -- GitLab From a087e2b7b345eb658468dede5804e56c526380ca Mon Sep 17 00:00:00 2001 From: Sandeep Panda Date: Wed, 25 Apr 2018 11:25:42 +0530 Subject: [PATCH 0993/1299] drm/msm/sde: enable backlight in ESD recovery case In case of ESD recovery display disable/enable happens without the knowledge of backlight framework. So backlight does not change during this period. This causes issues where panel used DCS backlight update method where backlight is lost during ESD trigger and it is not set again after recovery is complete. This change fixes the issue by calling backlight update API during ESD recovery display enable/disable case. Change-Id: I157120688603dd0558b773bbf41996b6d7373d94 Signed-off-by: Sandeep Panda Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_drm.c | 7 +++++- drivers/gpu/drm/msm/sde/sde_connector.c | 30 +++++++++++++++++++++-- drivers/gpu/drm/msm/sde/sde_connector.h | 9 ++++++- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c index 3f4134867ff2..04b91e0b0496 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c @@ -198,6 +198,7 @@ static void dsi_bridge_enable(struct drm_bridge *bridge) { int rc = 0; struct dsi_bridge *c_bridge = to_dsi_bridge(bridge); + struct dsi_display *display; if (!bridge) { pr_err("Invalid params\n"); @@ -209,11 +210,15 @@ static void dsi_bridge_enable(struct drm_bridge *bridge) pr_debug("[%d] seamless enable\n", c_bridge->id); return; } + display = c_bridge->display; - rc = dsi_display_post_enable(c_bridge->display); + rc = dsi_display_post_enable(display); if (rc) pr_err("[%d] DSI display post enabled failed, rc=%d\n", c_bridge->id, rc); + + if (display && display->drm_conn) + sde_connector_helper_bridge_enable(display->drm_conn); } static void dsi_bridge_disable(struct drm_bridge *bridge) diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 3f4b0663deaf..e71726daf450 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -643,6 +643,7 @@ int sde_connector_pre_kickoff(struct drm_connector *connector) void sde_connector_helper_bridge_disable(struct drm_connector *connector) { int rc; + struct sde_connector *c_conn = NULL; if (!connector) return; @@ -653,6 +654,31 @@ void sde_connector_helper_bridge_disable(struct drm_connector *connector) connector->base.id, rc); SDE_EVT32(connector->base.id, SDE_EVTLOG_ERROR); } + + c_conn = to_sde_connector(connector); + if (c_conn->panel_dead) { + c_conn->bl_device->props.power = FB_BLANK_POWERDOWN; + c_conn->bl_device->props.state |= BL_CORE_FBBLANK; + backlight_update_status(c_conn->bl_device); + } +} + +void sde_connector_helper_bridge_enable(struct drm_connector *connector) +{ + struct sde_connector *c_conn = NULL; + + if (!connector) + return; + + c_conn = to_sde_connector(connector); + + /* Special handling for ESD recovery case */ + if (c_conn->panel_dead) { + c_conn->bl_device->props.power = FB_BLANK_UNBLANK; + c_conn->bl_device->props.state &= ~BL_CORE_FBBLANK; + backlight_update_status(c_conn->bl_device); + c_conn->panel_dead = false; + } } int sde_connector_clk_ctrl(struct drm_connector *connector, bool enable) @@ -1752,15 +1778,15 @@ static int sde_connector_atomic_check(struct drm_connector *connector, static void _sde_connector_report_panel_dead(struct sde_connector *conn) { struct drm_event event; - bool panel_dead = true; if (!conn) return; + conn->panel_dead = true; event.type = DRM_EVENT_PANEL_DEAD; event.length = sizeof(bool); msm_mode_object_event_notify(&conn->base.base, - conn->base.dev, &event, (u8 *)&panel_dead); + conn->base.dev, &event, (u8 *)&conn->panel_dead); sde_encoder_display_failure_notification(conn->encoder); SDE_EVT32(SDE_EVTLOG_ERROR); SDE_ERROR("esd check failed report PANEL_DEAD conn_id: %d enc_id: %d\n", diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h index f803fb5c73f4..6436b45843f6 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.h +++ b/drivers/gpu/drm/msm/sde/sde_connector.h @@ -369,6 +369,8 @@ struct sde_connector_evt { * @status_work: work object to perform status checks * @force_panel_dead: variable to trigger forced ESD recovery * @esd_status_interval: variable to change ESD check interval in millisec + * @panel_dead: Flag to indicate if panel has gone bad + * @esd_status_check: Flag to indicate if ESD thread is scheduled or not * @bl_scale_dirty: Flag to indicate PP BL scale value(s) is changed * @bl_scale: BL scale value for ABA feature * @bl_scale_ad: BL scale value for AD feature @@ -414,7 +416,7 @@ struct sde_connector { struct delayed_work status_work; u32 force_panel_dead; u32 esd_status_interval; - + bool panel_dead; bool esd_status_check; bool bl_scale_dirty; @@ -839,6 +841,11 @@ void sde_connector_destroy(struct drm_connector *connector); */ int sde_connector_event_notify(struct drm_connector *connector, uint32_t type, uint32_t len, uint32_t val); +/** + * sde_connector_helper_bridge_enable - helper function for drm bridge enable + * @connector: Pointer to DRM connector object + */ +void sde_connector_helper_bridge_enable(struct drm_connector *connector); /** * sde_connector_get_panel_vfp - helper to get panel vfp -- GitLab From 0e138412af2f78725fbc90a2795cb5ad556af4cf Mon Sep 17 00:00:00 2001 From: Jayant Shekhar Date: Mon, 4 Jun 2018 12:15:23 +0530 Subject: [PATCH 0994/1299] drm/msm/sde: queue display failure work to event thread There are possibilities of deadlock if esd trigger work is queued to display thread. There is a corner case where during bridge disable, display thread is waiting for esd trigger work to complete to cancel esd thread, while esd trigger work is blocked on display thread. To fix this queue esd trigger work to event thread. Below is the call stack of both threads: ESD thread ---------- __switch_to+0xb8/0xec kthread_flush_work+0xdc/0x150 sde_encoder_display_failure_notification+0xc0/0x1e8 _sde_connector_report_panel_dead.part.8+0x6c/0xd4 sde_connector_check_status_work+0x10c/0x1d4 process_one_work+0x168/0x468 worker_thread+0x140/0x460 kthread+0xf4/0x108 ret_from_fork+0x10/0x50 0xffffffffffffffff Commit thread ------------- __switch_to+0xb8/0xec flush_work+0x44/0x68 __cancel_work_timer+0x138/0x1e0 cancel_delayed_work_sync+0x24/0x30 sde_connector_schedule_status_work.part.16+0xc0/0x114 _sde_connector_update_power_locked+0x1c4/0x224 _sde_connector_update_dirty_properties+0x80/0x100 sde_connector_helper_bridge_disable+0x24/0x100 dsi_bridge_disable+0x30/0x98 drm_bridge_disable+0x128/0x144 msm_atomic_helper_commit_modeset_disables+0x148/0x578 complete_commit+0x74/0x668 _msm_drm_commit_work_cb+0x4c/0x1c4 kthread_worker_fn+0xc0/0x1e4 kthread+0xf4/0x108 ret_from_fork+0x10/0x50 0xffffffffffffffff Change-Id: Ifd95664113857fd5c06098a3a2f87f28c1975513 Signed-off-by: Jayant Shekhar --- drivers/gpu/drm/msm/sde/sde_connector.c | 8 ++++++++ drivers/gpu/drm/msm/sde/sde_encoder.c | 11 ++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index e71726daf450..69654e762906 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -1782,6 +1782,14 @@ static void _sde_connector_report_panel_dead(struct sde_connector *conn) if (!conn) return; + /* Panel dead notification can come: + * 1) ESD thread + * 2) Commit thread (if TE stops coming) + * So such case, avoid failure notification twice. + */ + if (conn->panel_dead) + return; + conn->panel_dead = true; event.type = DRM_EVENT_PANEL_DEAD; event.length = sizeof(bool); diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 0dde5d784910..1c262d40e86b 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -5251,7 +5251,7 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder) int sde_encoder_display_failure_notification(struct drm_encoder *enc) { - struct msm_drm_thread *disp_thread = NULL; + struct msm_drm_thread *event_thread = NULL; struct msm_drm_private *priv = NULL; struct sde_encoder_virt *sde_enc = NULL; @@ -5263,7 +5263,7 @@ int sde_encoder_display_failure_notification(struct drm_encoder *enc) priv = enc->dev->dev_private; sde_enc = to_sde_encoder_virt(enc); if (!sde_enc->crtc || (sde_enc->crtc->index - >= ARRAY_SIZE(priv->disp_thread))) { + >= ARRAY_SIZE(priv->event_thread))) { SDE_DEBUG_ENC(sde_enc, "invalid cached CRTC: %d or crtc index: %d\n", sde_enc->crtc == NULL, @@ -5273,11 +5273,12 @@ int sde_encoder_display_failure_notification(struct drm_encoder *enc) SDE_EVT32_VERBOSE(DRMID(enc)); - disp_thread = &priv->disp_thread[sde_enc->crtc->index]; + event_thread = &priv->event_thread[sde_enc->crtc->index]; - kthread_queue_work(&disp_thread->worker, - &sde_enc->esd_trigger_work); + kthread_queue_work(&event_thread->worker, + &sde_enc->esd_trigger_work); kthread_flush_work(&sde_enc->esd_trigger_work); + /** * panel may stop generating te signal (vsync) during esd failure. rsc * hardware may hang without vsync. Avoid rsc hang by generating the -- GitLab From 8a660b69f1b27b67e6f3f0eced78a28f56f80f67 Mon Sep 17 00:00:00 2001 From: Sandeep Panda Date: Fri, 4 May 2018 10:56:59 +0530 Subject: [PATCH 0995/1299] drm/msm/dsi-staging: update ESD thread disable sequence Currently to synchronize ESD check and DSI disable, ESD thread acquires display mutex before the check starts. But this is causing performance issues when atomic check also tries to acquire the display mutex and blocks on ESD thread if the later has already acquired it. Fix this race condition by removing display mutex lock from ESD thread and instead synchronize ESD check and DSI disable by always ensuring that ESD check has been stopped before DSI disable sequence kicks in. Change-Id: I5a0b44a7cbf01648303eb85c7a08a6a62c1ef94e Signed-off-by: Sandeep Panda Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 19 +++++++------------ drivers/gpu/drm/msm/sde/sde_connector.c | 3 +++ drivers/gpu/drm/msm/sde/sde_encoder.c | 5 ----- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 916377359afe..80aed687b99a 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -555,9 +555,6 @@ static int dsi_display_read_status(struct dsi_display_ctrl *ctrl, if (dsi_ctrl_validate_host_state(ctrl->ctrl)) return 1; - /* acquire panel_lock to make sure no commands are in progress */ - dsi_panel_acquire_panel_lock(panel); - config = &(panel->esd_config); lenp = config->status_valid_params ?: config->status_cmds_rlen; count = config->status_cmd.count; @@ -575,7 +572,7 @@ static int dsi_display_read_status(struct dsi_display_ctrl *ctrl, rc = dsi_ctrl_cmd_transfer(ctrl->ctrl, &cmds[i].msg, flags); if (rc <= 0) { pr_err("rx cmd transfer failed rc=%d\n", rc); - goto error; + return rc; } memcpy(config->return_buf + start, @@ -583,9 +580,6 @@ static int dsi_display_read_status(struct dsi_display_ctrl *ctrl, start += lenp[i]; } -error: - /* release panel_lock */ - dsi_panel_release_panel_lock(panel); return rc; } @@ -705,15 +699,16 @@ int dsi_display_check_status(struct drm_connector *connector, void *display, u32 status_mode; int rc = 0x1; - if (dsi_display == NULL) + if (!dsi_display || !dsi_display->panel) return -EINVAL; - mutex_lock(&dsi_display->display_lock); - panel = dsi_display->panel; + + dsi_panel_acquire_panel_lock(panel); + if (!panel->panel_initialized) { pr_debug("Panel not initialized\n"); - mutex_unlock(&dsi_display->display_lock); + dsi_panel_release_panel_lock(panel); return rc; } @@ -738,7 +733,7 @@ int dsi_display_check_status(struct drm_connector *connector, void *display, dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_OFF); - mutex_unlock(&dsi_display->display_lock); + dsi_panel_release_panel_lock(panel); return rc; } diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 69654e762906..7433aedac66c 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -655,6 +655,9 @@ void sde_connector_helper_bridge_disable(struct drm_connector *connector) SDE_EVT32(connector->base.id, SDE_EVTLOG_ERROR); } + /* Disable ESD thread */ + sde_connector_schedule_status_work(connector, false); + c_conn = to_sde_connector(connector); if (c_conn->panel_dead) { c_conn->bl_device->props.power = FB_BLANK_POWERDOWN; diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 1c262d40e86b..22301ec30fff 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -3002,7 +3002,6 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) struct sde_encoder_virt *sde_enc = NULL; struct msm_drm_private *priv; struct sde_kms *sde_kms; - struct drm_connector *drm_conn = NULL; enum sde_intf_mode intf_mode; int i = 0; @@ -3031,10 +3030,6 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) SDE_EVT32(DRMID(drm_enc)); - /* Disable ESD thread */ - drm_conn = sde_enc->cur_master->connector; - sde_connector_schedule_status_work(drm_conn, false); - /* wait for idle */ sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); -- GitLab From c4429baaa0f774c3f6d1ff3091b841320ac65eda Mon Sep 17 00:00:00 2001 From: Sandeep Panda Date: Wed, 9 May 2018 15:39:39 +0530 Subject: [PATCH 0996/1299] drm/msm/dsi-staging: add support to wait post dsi command rx Some display panel have the requirement of waiting for certain duration before dsi host can read back the response from panel, to a DCS read command. This change adds the support to store the delay required in dsi message structure it self. Change-Id: I82f53d811f82195eb900e4594b01c6e0f23fed53 Signed-off-by: Sandeep Panda Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 9 +++------ drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 2 +- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 4 +++- include/drm/drm_mipi_dsi.h | 2 ++ 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index c7e82767065b..9abc69cd0327 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -1338,9 +1338,6 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, u32 dlen, diff, rlen = msg->rx_len; unsigned char *buff; char cmd; - struct dsi_cmd_desc *of_cmd; - - of_cmd = container_of(msg, struct dsi_cmd_desc, msg); if (msg->rx_len <= 2) { short_resp = true; @@ -1378,9 +1375,9 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, * wait before reading rdbk_data register, if any delay is * required after sending the read command. */ - if (of_cmd && of_cmd->post_wait_ms) - usleep_range(of_cmd->post_wait_ms * 1000, - ((of_cmd->post_wait_ms * 1000) + 10)); + if (msg->wait_ms) + usleep_range(msg->wait_ms * 1000, + ((msg->wait_ms * 1000) + 10)); dlen = dsi_ctrl->hw.ops.get_cmd_read_data(&dsi_ctrl->hw, buff, total_bytes_read, diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 80aed687b99a..2225513a796a 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -749,7 +749,7 @@ static int dsi_display_cmd_prepare(const char *cmd_buf, u32 cmd_buf_len, cmd->msg.channel = cmd_buf[2]; cmd->msg.flags = cmd_buf[3]; cmd->msg.ctrl = 0; - cmd->post_wait_ms = cmd_buf[4]; + cmd->post_wait_ms = cmd->msg.wait_ms = cmd_buf[4]; cmd->msg.tx_len = ((cmd_buf[5] << 8) | (cmd_buf[6])); if (cmd->msg.tx_len > payload_len) { diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index 05761f2a2e8e..4fbc7d8b9b56 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -1490,7 +1490,7 @@ static int dsi_panel_create_cmd_packets(const char *data, cmd[i].msg.channel = data[2]; cmd[i].msg.flags |= (data[3] == 1 ? MIPI_DSI_MSG_REQ_ACK : 0); cmd[i].msg.ctrl = 0; - cmd[i].post_wait_ms = data[4]; + cmd[i].post_wait_ms = cmd[i].msg.wait_ms = data[4]; cmd[i].msg.tx_len = ((data[5] << 8) | (data[6])); size = cmd[i].msg.tx_len * sizeof(u8); @@ -3471,6 +3471,7 @@ static int dsi_panel_roi_prepare_dcs_cmds(struct dsi_panel_cmd_set *set, set->cmds[0].msg.tx_buf = caset; set->cmds[0].msg.rx_len = 0; set->cmds[0].msg.rx_buf = 0; + set->cmds[0].msg.wait_ms = 0; set->cmds[0].last_command = 0; set->cmds[0].post_wait_ms = 0; @@ -3482,6 +3483,7 @@ static int dsi_panel_roi_prepare_dcs_cmds(struct dsi_panel_cmd_set *set, set->cmds[1].msg.tx_buf = paset; set->cmds[1].msg.rx_len = 0; set->cmds[1].msg.rx_buf = 0; + set->cmds[1].msg.wait_ms = 0; set->cmds[1].last_command = 1; set->cmds[1].post_wait_ms = 0; diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 3c2024d8e6f5..328f232f33ee 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -32,6 +32,7 @@ struct mipi_dsi_device; * @type: payload data type * @flags: flags controlling this message transmission * @ctrl: ctrl index to transmit on + * @wait_ms: duration in ms to wait after message transmission * @tx_len: length of @tx_buf * @tx_buf: data to be written * @rx_len: length of @rx_buf @@ -42,6 +43,7 @@ struct mipi_dsi_msg { u8 type; u16 flags; u32 ctrl; + u32 wait_ms; size_t tx_len; const void *tx_buf; -- GitLab From e6066e2c838a9390cd47ab17d8f1919fca222055 Mon Sep 17 00:00:00 2001 From: Shashank Babu Chinta Venkata Date: Tue, 12 Jun 2018 18:31:46 -0700 Subject: [PATCH 0997/1299] drm/msm/dsi-staging: avoid sending panel off commands During ESD recovery, we cannot ensure health of DSI PHY link. Thus, sending ESD panel off commands may subject to fail. Avoid sending panel off commands when ESD recovery is underway. Change-Id: I443c8b1044ad68ae3fc6e4b2a904134970ec8c18 Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 6 +++++- drivers/gpu/drm/msm/dsi-staging/dsi_drm.c | 6 +++++- drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 13 ++++++++----- drivers/gpu/drm/msm/dsi-staging/dsi_panel.h | 1 + 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 2225513a796a..87c583d2c464 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -654,9 +654,13 @@ static int dsi_display_status_reg_read(struct dsi_display *display) } exit: /* mask only error interrupts */ - if (rc <= 0) + if (rc <= 0) { dsi_display_mask_ctrl_error_interrupts(display); + /* Handle Panel failures during display disable sequence */ + display->panel->esd_recovery_pending = true; + } + dsi_display_cmd_engine_disable(display); done: return rc; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c index 04b91e0b0496..e79f200e6bc8 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c @@ -151,8 +151,12 @@ static void dsi_bridge_pre_enable(struct drm_bridge *bridge) return; } - if (!c_bridge || !c_bridge->display) + if (!c_bridge || !c_bridge->display || !c_bridge->display->panel) { pr_err("Incorrect bridge details\n"); + return; + } + + c_bridge->display->panel->esd_recovery_pending = false; /* By this point mode should have been validated through mode_fixup */ rc = dsi_display_set_mode(c_bridge->display, diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index 4fbc7d8b9b56..45cf593f9198 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -3697,11 +3697,14 @@ int dsi_panel_disable(struct dsi_panel *panel) mutex_lock(&panel->panel_lock); - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_OFF); - if (rc) { - pr_err("[%s] failed to send DSI_CMD_SET_OFF cmds, rc=%d\n", - panel->name, rc); - goto error; + /* Avoid sending panel off commands when ESD recovery is underway */ + if (!panel->esd_recovery_pending) { + rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_OFF); + if (rc) { + pr_err("[%s] failed to send DSI_CMD_SET_OFF cmds, rc=%d\n", + panel->name, rc); + goto error; + } } panel->panel_initialized = false; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h index 07a141caaacd..1ae2288e2649 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h @@ -176,6 +176,7 @@ struct dsi_panel { bool ulps_enabled; bool ulps_suspend_enabled; bool allow_phy_power_off; + bool esd_recovery_pending; bool panel_initialized; bool te_using_watchdog_timer; -- GitLab From 1db854ff556468f23cc21284e54e171cc1b4764e Mon Sep 17 00:00:00 2001 From: Shashank Babu Chinta Venkata Date: Fri, 22 Jun 2018 15:50:04 -0700 Subject: [PATCH 0998/1299] drm/msm/dsi-staging: disable FIFO error interrupts in ESD In ESD recovery sequence, there is high likelihood of encountering DSI FIFO overflow/underflow errors which might put controller in bad state. This change disables FIFO error interrupts prior to attempting panel status read. Change-Id: Ib4245241789f74b51ef06778df63cbae572f60e0 Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 26 ++++++++-- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h | 7 ++- .../gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c | 15 +++--- drivers/gpu/drm/msm/dsi-staging/dsi_defs.h | 1 + drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 49 +++++++++++++++---- 5 files changed, 76 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 9abc69cd0327..1813ad497840 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -1232,7 +1232,7 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, } } - if (dsi_hw_ops.mask_error_intr) + if (dsi_hw_ops.mask_error_intr && !dsi_ctrl->esd_check_underway) dsi_hw_ops.mask_error_intr(&dsi_ctrl->hw, BIT(DSI_FIFO_OVERFLOW), false); dsi_hw_ops.reset_cmd_fifo(&dsi_ctrl->hw); @@ -2867,7 +2867,8 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags) dsi_ctrl->cell_index); } } - if (dsi_ctrl->hw.ops.mask_error_intr) + if (dsi_ctrl->hw.ops.mask_error_intr && + !dsi_ctrl->esd_check_underway) dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw, BIT(DSI_FIFO_OVERFLOW), false); @@ -3362,7 +3363,8 @@ u32 dsi_ctrl_collect_misr(struct dsi_ctrl *dsi_ctrl) return misr; } -void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl) +void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl, u32 idx, + bool mask_enable) { if (!dsi_ctrl || !dsi_ctrl->hw.ops.error_intr_ctrl || !dsi_ctrl->hw.ops.clear_error_status) { @@ -3375,9 +3377,23 @@ void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl) * register */ mutex_lock(&dsi_ctrl->ctrl_lock); - dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, false); - dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw, + if (idx & BIT(DSI_ERR_INTR_ALL)) { + /* + * The behavior of mask_enable is different in ctrl register + * and mask register and hence mask_enable is manipulated for + * selective error interrupt masking vs total error interrupt + * masking. + */ + + dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, !mask_enable); + dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw, DSI_ERROR_INTERRUPT_COUNT); + } else { + dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw, idx, + mask_enable); + dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw, + DSI_ERROR_INTERRUPT_COUNT); + } mutex_unlock(&dsi_ctrl->ctrl_lock); } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h index 7bfa45d5bc85..f196efcc6451 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h @@ -204,6 +204,7 @@ struct dsi_ctrl_interrupts { * @cmd_buffer_size: Size of command buffer. * @vaddr: CPU virtual address of cmd buffer. * @secure_mode: Indicates if secure-session is in progress + * @esd_check_underway: Indicates if esd status check is in progress * @debugfs_root: Root for debugfs entries. * @misr_enable: Frame MISR enable/disable * @misr_cache: Cached Frame MISR value @@ -249,6 +250,7 @@ struct dsi_ctrl { u32 cmd_len; void *vaddr; bool secure_mode; + bool esd_check_underway; /* Debug Information */ struct dentry *debugfs_root; @@ -732,8 +734,11 @@ void dsi_ctrl_isr_configure(struct dsi_ctrl *dsi_ctrl, bool enable); * dsi_ctrl_mask_error_status_interrupts() - API to mask dsi ctrl error status * interrupts * @dsi_ctrl: DSI controller handle. + * @idx: id indicating which interrupts to enable/disable. + * @mask_enable: boolean to enable/disable masking. */ -void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl); +void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl, u32 idx, + bool mask_enable); /** * dsi_ctrl_irq_update() - Put a irq vote to process DSI error diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c index a82e8558669a..fd799e6a1001 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c @@ -1423,17 +1423,20 @@ void dsi_ctrl_hw_cmn_mask_error_intr(struct dsi_ctrl_hw *ctrl, u32 idx, bool en) reg = DSI_R32(ctrl, 0x10c); if (idx & BIT(DSI_FIFO_OVERFLOW)) { - if (en) - reg |= (0xf << 16); - else - reg &= ~(0xf << 16); + if (en) { + reg |= (0x1f << 16); + reg |= BIT(9); + } else { + reg &= ~(0x1f << 16); + reg &= ~BIT(9); + } } if (idx & BIT(DSI_FIFO_UNDERFLOW)) { if (en) - reg |= (0xf << 26); + reg |= (0x1b << 26); else - reg &= ~(0xf << 26); + reg &= ~(0x1b << 26); } if (idx & BIT(DSI_LP_Rx_TIMEOUT)) { diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h index fc4497f9c878..d287184e8016 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h @@ -602,6 +602,7 @@ enum dsi_error_status { DSI_FIFO_OVERFLOW = 1, DSI_FIFO_UNDERFLOW, DSI_LP_Rx_TIMEOUT, + DSI_ERR_INTR_ALL, }; #endif /* _DSI_DEFS_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 87c583d2c464..85254d74671f 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -53,7 +53,8 @@ static const struct of_device_id dsi_display_dt_match[] = { {} }; -static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display) +static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display, + u32 mask, bool enable) { int i; struct dsi_display_ctrl *ctrl; @@ -66,7 +67,25 @@ static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display) ctrl = &display->ctrl[i]; if (!ctrl) continue; - dsi_ctrl_mask_error_status_interrupts(ctrl->ctrl); + dsi_ctrl_mask_error_status_interrupts(ctrl->ctrl, mask, enable); + } +} + +static void dsi_display_set_ctrl_esd_check_flag(struct dsi_display *display, + bool enable) +{ + int i; + struct dsi_display_ctrl *ctrl; + + if (!display) + return; + + for (i = 0; (i < display->ctrl_count) && + (i < MAX_DSI_CTRLS_PER_DISPLAY); i++) { + ctrl = &display->ctrl[i]; + if (!ctrl) + continue; + ctrl->ctrl->esd_check_underway = enable; } } @@ -653,14 +672,6 @@ static int dsi_display_status_reg_read(struct dsi_display *display) } } exit: - /* mask only error interrupts */ - if (rc <= 0) { - dsi_display_mask_ctrl_error_interrupts(display); - - /* Handle Panel failures during display disable sequence */ - display->panel->esd_recovery_pending = true; - } - dsi_display_cmd_engine_disable(display); done: return rc; @@ -702,6 +713,7 @@ int dsi_display_check_status(struct drm_connector *connector, void *display, struct dsi_panel *panel; u32 status_mode; int rc = 0x1; + u32 mask; if (!dsi_display || !dsi_display->panel) return -EINVAL; @@ -724,6 +736,11 @@ int dsi_display_check_status(struct drm_connector *connector, void *display, dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_ON); + /* Mask error interrupts before attempting ESD read */ + mask = BIT(DSI_FIFO_OVERFLOW) | BIT(DSI_FIFO_UNDERFLOW); + dsi_display_set_ctrl_esd_check_flag(dsi_display, true); + dsi_display_mask_ctrl_error_interrupts(dsi_display, mask, true); + if (status_mode == ESD_MODE_REG_READ) { rc = dsi_display_status_reg_read(dsi_display); } else if (status_mode == ESD_MODE_SW_BTA) { @@ -735,6 +752,16 @@ int dsi_display_check_status(struct drm_connector *connector, void *display, panel->esd_config.esd_enabled = false; } + /* Unmask error interrupts */ + if (rc > 0) { + dsi_display_set_ctrl_esd_check_flag(dsi_display, false); + dsi_display_mask_ctrl_error_interrupts(dsi_display, mask, + false); + } else { + /* Handle Panel failures during display disable sequence */ + panel->esd_recovery_pending = true; + } + dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_OFF); dsi_panel_release_panel_lock(panel); @@ -5948,6 +5975,8 @@ int dsi_display_prepare(struct dsi_display *display) mode = display->panel->cur_mode; + dsi_display_set_ctrl_esd_check_flag(display, false); + if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) { if (display->is_cont_splash_enabled) { pr_err("DMS is not supposed to be set on first frame\n"); -- GitLab From 045b32a6e3e001f9ea1009d19d9cd9907774e79a Mon Sep 17 00:00:00 2001 From: Shashank Babu Chinta Venkata Date: Wed, 13 Jun 2018 17:36:01 -0700 Subject: [PATCH 0999/1299] drm/msm/dsi-staging: set correct state for status check command In the current implementation dsi driver is always sending the status check command in HS mode. This change fixes the issue by setting the proper state based on panel device tree entry, before sending the status check command from dsi host. Change-Id: I9e8ed8616295de2a2f1d5fa2a8a83b706c70f033 Signed-off-by: Sandeep Panda Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 85254d74671f..bfd89ade14bd 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -586,6 +586,8 @@ static int dsi_display_read_status(struct dsi_display_ctrl *ctrl, cmds[i].msg.flags |= MIPI_DSI_MSG_LASTCOMMAND; flags |= DSI_CTRL_CMD_LAST_COMMAND; } + if (config->status_cmd.state == DSI_CMD_SET_STATE_LP) + cmds[i].msg.flags |= MIPI_DSI_MSG_USE_LPM; cmds[i].msg.rx_buf = config->status_buf; cmds[i].msg.rx_len = config->status_cmds_rlen[i]; rc = dsi_ctrl_cmd_transfer(ctrl->ctrl, &cmds[i].msg, flags); -- GitLab From c6e8cab44d2a6c886e399042e33228906d889091 Mon Sep 17 00:00:00 2001 From: Shashank Babu Chinta Venkata Date: Wed, 13 Jun 2018 14:49:39 -0700 Subject: [PATCH 1000/1299] drm/msm/dsi-staging: handle spurious error interrupts DSI controller can trigger spurious error interrupts during ESD attack scenarios. Add a check for such spurious interrupts during error handling. Change-Id: Iab86e34a7d94991de5c2ad1c62404f1dee1c81b6 Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 42 ++++++++++++++++++++++ drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h | 4 +++ 2 files changed, 46 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 1813ad497840..2fbf7b9f24e4 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -2166,6 +2166,35 @@ int dsi_ctrl_phy_reset_config(struct dsi_ctrl *dsi_ctrl, bool enable) return 0; } +static bool dsi_ctrl_check_for_spurious_error_interrupts( + struct dsi_ctrl *dsi_ctrl) +{ + const unsigned long intr_check_interval = msecs_to_jiffies(1000); + const unsigned int interrupt_threshold = 15; + unsigned long jiffies_now = jiffies; + + if (!dsi_ctrl) { + pr_err("Invalid DSI controller structure\n"); + return false; + } + + if (dsi_ctrl->jiffies_start == 0) + dsi_ctrl->jiffies_start = jiffies; + + dsi_ctrl->error_interrupt_count++; + + if ((jiffies_now - dsi_ctrl->jiffies_start) < intr_check_interval) { + if (dsi_ctrl->error_interrupt_count > interrupt_threshold) { + pr_warn("Detected spurious interrupts on dsi ctrl\n"); + return true; + } + } else { + dsi_ctrl->jiffies_start = jiffies; + dsi_ctrl->error_interrupt_count = 1; + } + return false; +} + static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl, unsigned long int error) { @@ -2237,6 +2266,19 @@ static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl, if (error & 0xF) pr_err("ack error: 0x%lx\n", error); + /* + * DSI Phy can go into bad state during ESD influence. This can + * manifest as various types of spurious error interrupts on + * DSI controller. This check will allow us to handle afore mentioned + * case and prevent us from re enabling interrupts until a full ESD + * recovery is completed. + */ + if (dsi_ctrl_check_for_spurious_error_interrupts(dsi_ctrl) && + dsi_ctrl->esd_check_underway) { + dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw); + return; + } + /* enable back DSI interrupts */ if (dsi_ctrl->hw.ops.error_intr_ctrl) dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, true); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h index f196efcc6451..751c3e118824 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h @@ -259,6 +259,10 @@ struct dsi_ctrl { bool misr_enable; u32 misr_cache; + /* Check for spurious interrupts */ + unsigned long jiffies_start; + unsigned int error_interrupt_count; + bool phy_isolation_enabled; bool null_insertion_enabled; bool modeupdated; -- GitLab From 3b6c82ac443ae15bb70d3343c87248de5963657d Mon Sep 17 00:00:00 2001 From: Shashank Babu Chinta Venkata Date: Thu, 28 Jun 2018 12:14:50 -0700 Subject: [PATCH 1001/1299] drm/msm/dsi-staging: avoid TE status check during ESD recovery When ESD recovery is underway, there is high likelihood of a ping pong timeout which might trigger a TE check on panel. Avoid this check as panel is already in bad state. Change-Id: I14aa6b70df928cc986b907ad98838ade000a89e3 Signed-off-by: Shashank Babu Chinta Venkata --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index bfd89ade14bd..069bc9882f68 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -730,6 +730,12 @@ int dsi_display_check_status(struct drm_connector *connector, void *display, return rc; } + /* Prevent another ESD check,when ESD recovery is underway */ + if (panel->esd_recovery_pending) { + dsi_panel_release_panel_lock(panel); + return rc; + } + if (te_check_override && gpio_is_valid(dsi_display->disp_te_gpio)) status_mode = ESD_MODE_PANEL_TE; else -- GitLab From 3a87a8d6004d92d63ac9c758e78318ea18940979 Mon Sep 17 00:00:00 2001 From: Sandeep Panda Date: Wed, 2 Aug 2017 14:29:48 +0530 Subject: [PATCH 1002/1299] ARM: dts: msm: remove sync broadcast property for nt35597 panel Remove sync broadcast property for nt35597 truly panel as the panel does not behave properly for slave controller if ESD is enabled. Change-Id: I51c7aae2727880e8b3fbe734fa83ee9202e9055e Signed-off-by: Sandeep Panda --- .../dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi index 0d0e7f7f8316..c83fd8735604 100644 --- a/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi +++ b/arch/arm64/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi @@ -29,7 +29,6 @@ qcom,mdss-dsi-lane-1-state; qcom,mdss-dsi-lane-2-state; qcom,mdss-dsi-lane-3-state; - qcom,cmd-sync-wait-broadcast; qcom,mdss-dsi-dma-trigger = "trigger_sw"; qcom,mdss-dsi-mdp-trigger = "none"; qcom,mdss-dsi-reset-sequence = <1 20>, <0 20>, <1 50>; -- GitLab From c1e180e5dc7579f863dba8cf9c7dc4f2d8053f60 Mon Sep 17 00:00:00 2001 From: Shashank Babu Chinta Venkata Date: Sat, 16 Jun 2018 14:43:17 -0700 Subject: [PATCH 1003/1299] ARM: dts: msm: alter esd panel check value for 4k cmd mode for SM8150 Alter ESD panel status check value per specification for 4k Sharp panel in command mode for SM8150. Change-Id: I40094a193a8127ad8a9ba0d6607b5d90272783b0 Signed-off-by: Shashank Babu Chinta Venkata --- arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi index c45aa33b115a..a06f8816e42a 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi @@ -502,8 +502,8 @@ qcom,mdss-dsi-panel-status-check-mode = "reg_read"; qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0c]; qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode"; - qcom,mdss-dsi-panel-status-value = <0x7>; - qcom,mdss-dsi-panel-on-check-value = <0x7>; + qcom,mdss-dsi-panel-status-value = <0x77>; + qcom,mdss-dsi-panel-on-check-value = <0x77>; qcom,mdss-dsi-panel-status-read-length = <1>; qcom,mdss-dsi-display-timings { timing@0{ -- GitLab From d9863148a228460d29c4d7cf15f7ab5ddf9c65a9 Mon Sep 17 00:00:00 2001 From: Shashank Babu Chinta Venkata Date: Wed, 13 Jun 2018 17:22:05 -0700 Subject: [PATCH 1004/1299] ARM: dts: msm: enable esd check for various displays on SM8150 Enable ESD detection mechanism for Sharp 4k video mode, 4k command mode, Truly 2k dsc video mode and Truly 2k dual DSI video mode. Change-Id: Iab80aa5ec3455480f47cb4cd4eff7a3e9dfc899f Signed-off-by: Shashank Babu Chinta Venkata --- .../boot/dts/qcom/sm8150-sde-display.dtsi | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi index a06f8816e42a..b863f2de64df 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde-display.dtsi @@ -430,6 +430,13 @@ qcom,mdss-dsi-max-refresh-rate = <60>; qcom,mdss-dsi-pan-enable-dynamic-fps; qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp"; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-check-mode = "reg_read"; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a]; + qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-panel-status-value = <0x9c>; + qcom,mdss-dsi-panel-on-check-value = <0x9c>; + qcom,mdss-dsi-panel-status-read-length = <1>; qcom,mdss-dsi-display-timings { timing@0{ qcom,mdss-dsi-panel-phy-timings = [00 1c 08 07 23 22 07 @@ -461,6 +468,13 @@ }; &dsi_nt35597_truly_dsc_cmd { + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-check-mode = "reg_read"; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a]; + qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-panel-status-value = <0x9c>; + qcom,mdss-dsi-panel-on-check-value = <0x9c>; + qcom,mdss-dsi-panel-status-read-length = <1>; qcom,mdss-dsi-display-timings { timing@0{ qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05 @@ -474,6 +488,13 @@ }; &dsi_nt35597_truly_dsc_video { + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-check-mode = "reg_read"; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a]; + qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-panel-status-value = <0x9c>; + qcom,mdss-dsi-panel-on-check-value = <0x9c>; + qcom,mdss-dsi-panel-status-read-length = <1>; qcom,mdss-dsi-display-timings { timing@0{ qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05 @@ -487,6 +508,13 @@ }; &dsi_sharp_4k_dsc_video { + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-check-mode = "reg_read"; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0c]; + qcom,mdss-dsi-panel-status-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-value = <0x77>; + qcom,mdss-dsi-panel-on-check-value = <0x77>; + qcom,mdss-dsi-panel-status-read-length = <1>; qcom,mdss-dsi-display-timings { timing@0{ qcom,mdss-dsi-panel-phy-timings = [00 1e 08 07 24 22 08 -- GitLab From 4212774e66d46c2fc88add79097026fac25b23c3 Mon Sep 17 00:00:00 2001 From: Hardik Arya Date: Fri, 6 Apr 2018 15:10:36 +0530 Subject: [PATCH 1005/1299] diag: Validate query dci event and log mask size properly Currently there is possibility of out-of-bound read due to incorrect validation of received dci event and log mask for query. The patch update the validation for the same. Change-Id: I4266eb0f69fdbfa48c5aacc17744dec83995e9e6 Signed-off-by: Hardik Arya --- drivers/char/diag/diag_dci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index e25653a2c81f..8c77d88245c5 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -690,7 +690,7 @@ int diag_dci_query_log_mask(struct diag_dci_client_tbl *entry, byte_mask = 0x01 << (item_num % 8); offset = equip_id * 514; - if (offset + byte_index > DCI_LOG_MASK_SIZE) { + if (offset + byte_index >= DCI_LOG_MASK_SIZE) { pr_err("diag: In %s, invalid offset: %d, log_code: %d, byte_index: %d\n", __func__, offset, log_code, byte_index); return 0; @@ -717,7 +717,7 @@ int diag_dci_query_event_mask(struct diag_dci_client_tbl *entry, bit_index = event_id % 8; byte_mask = 0x1 << bit_index; - if (byte_index > DCI_EVENT_MASK_SIZE) { + if (byte_index >= DCI_EVENT_MASK_SIZE) { pr_err("diag: In %s, invalid, event_id: %d, byte_index: %d\n", __func__, event_id, byte_index); return 0; -- GitLab From 3990d6251ad68b008bc5b2869e03639a346fde3e Mon Sep 17 00:00:00 2001 From: Vijaykumar Badiger Date: Sat, 30 Jun 2018 14:46:01 -0700 Subject: [PATCH 1006/1299] ARM: dts: msm: disable ufs low power mode for sa8155 Disable low power mode for UFS till system wide LPM is enabled for automotive platform. Change-Id: Ic692b77284b69ff929313077b286327c8ca62358 Signed-off-by: Vijaykumar Badiger --- arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi b/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi index df8fb4d394b6..07744a9b4d31 100644 --- a/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi @@ -153,6 +153,7 @@ qcom,vddp-ref-clk-supply = <&pm8150_2_l5>; qcom,vddp-ref-clk-max-microamp = <100>; + qcom,disable-lpm; status = "ok"; }; -- GitLab From 7e3a6c13ac23aef2356c60d5ffc0bf244722c761 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Wed, 12 Jul 2017 14:51:08 -0600 Subject: [PATCH 1007/1299] nf: IDLETIMER: Fix possible use before initialization in idletimer_resume idletimer_resume() assumes that the PM_SUSPEND_PREPARE notifier is sent before PM_POST_SUSPEND so that timer->last_suspend_time is initialized. However, it is possible for PM_POST_SUSPEND to be sent first if there is an error returned from another driver's PM_SUSPEND_PREPARE notifier. Add a flag indicating whether the current value of timer->last_suspend is valid. Detected with CONFIG_SLUB_DEBUG & CONFIG_DEBUG_SPINLOCK in arm64. The timestamp lock is held for more than a minute while set_normalized_timespec() proceses the poisoned timer->last_suspend_time argument. CRs-Fixed: 2271709 Change-Id: I95328b0ac85dba819ff9cef751c3d07300c232f1 Signed-off-by: Subash Abhinov Kasiviswanathan --- net/netfilter/xt_IDLETIMER.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c index 18cd4a5a7a98..91639f559e9b 100644 --- a/net/netfilter/xt_IDLETIMER.c +++ b/net/netfilter/xt_IDLETIMER.c @@ -76,6 +76,7 @@ struct idletimer_tg { bool send_nl_msg; bool active; uid_t uid; + bool suspend_time_valid; }; static LIST_HEAD(idletimer_tg_list); @@ -245,8 +246,13 @@ static int idletimer_resume(struct notifier_block *notifier, switch (pm_event) { case PM_SUSPEND_PREPARE: get_monotonic_boottime(&timer->last_suspend_time); + timer->suspend_time_valid = true; break; case PM_POST_SUSPEND: + if (!timer->suspend_time_valid) + break; + timer->suspend_time_valid = false; + spin_lock_bh(×tamp_lock); if (!timer->active) { spin_unlock_bh(×tamp_lock); @@ -281,7 +287,7 @@ static int idletimer_tg_create(struct idletimer_tg_info *info) { int ret; - info->timer = kmalloc(sizeof(*info->timer), GFP_KERNEL); + info->timer = kzalloc(sizeof(*info->timer), GFP_KERNEL); if (!info->timer) { ret = -ENOMEM; goto out; -- GitLab From fd55b8055aa4d1b9889a66eb83374a9578badde0 Mon Sep 17 00:00:00 2001 From: Dinesh K Garg Date: Tue, 26 Sep 2017 13:39:25 -0700 Subject: [PATCH 1008/1299] msm: mink: Add support for local objects Currently, SMCInvoke does not support requests initiated by TZ to get data from Linux OS. Adding support so that TZ can call Linux OS. This includes support of memory objects which are owned by Linux OS. Change-Id: Ib97fe13954865a1ae908aa4da2e0439dbc26b38a Signed-off-by: Dinesh K Garg --- .../bindings/smcinvoke/smcinvoke.txt | 11 + drivers/soc/qcom/smcinvoke.c | 1608 +++++++++++++++-- drivers/soc/qcom/smcinvoke_object.h | 86 +- include/uapi/linux/smcinvoke.h | 68 +- 4 files changed, 1543 insertions(+), 230 deletions(-) create mode 100644 Documentation/devicetree/bindings/smcinvoke/smcinvoke.txt diff --git a/Documentation/devicetree/bindings/smcinvoke/smcinvoke.txt b/Documentation/devicetree/bindings/smcinvoke/smcinvoke.txt new file mode 100644 index 000000000000..a0e201c83bf4 --- /dev/null +++ b/Documentation/devicetree/bindings/smcinvoke/smcinvoke.txt @@ -0,0 +1,11 @@ +* SMCInvoke driver to provide transport between TZ and Linux + +Required properties: +- compatible : Should be "qcom,smcinvoke" +- reg : should contain memory region address reserved for loading secure apps. + +Example: + qcom_smcinvoke: smcinvoke@87900000 { + compatible = "qcom,smcinvoke"; + reg = <0x87900000 0x2200000>; + }; diff --git a/drivers/soc/qcom/smcinvoke.c b/drivers/soc/qcom/smcinvoke.c index 28bb85bd3870..c54b9a8e507b 100644 --- a/drivers/soc/qcom/smcinvoke.c +++ b/drivers/soc/qcom/smcinvoke.c @@ -15,13 +15,17 @@ #include #include +#include #include #include #include #include +#include #include #include #include +#include +#include #include #include @@ -30,25 +34,117 @@ #include "smcinvoke_object.h" #include "../../misc/qseecom_kernel.h" -#define SMCINVOKE_DEV "smcinvoke" -#define SMCINVOKE_TZ_PARAM_ID 0x224 -#define SMCINVOKE_TZ_CMD 0x32000600 -#define SMCINVOKE_TZ_ROOT_OBJ 1 -#define SMCINVOKE_TZ_MIN_BUF_SIZE 4096 -#define SMCINVOKE_ARGS_ALIGN_SIZE (sizeof(uint64_t)) -#define SMCINVOKE_TZ_OBJ_NULL 0 - -#define FOR_ARGS(ndxvar, counts, section) \ - for (ndxvar = object_counts_index_##section(counts); \ - ndxvar < (object_counts_index_##section(counts) \ - + object_counts_num_##section(counts)); \ +#define SMCINVOKE_DEV "smcinvoke" +#define SMCINVOKE_TZ_ROOT_OBJ 1 +#define SMCINVOKE_TZ_OBJ_NULL 0 +#define SMCINVOKE_TZ_MIN_BUF_SIZE 4096 +#define SMCINVOKE_ARGS_ALIGN_SIZE (sizeof(uint64_t)) +#define SMCINVOKE_NEXT_AVAILABLE_TXN 0 +#define SMCINVOKE_REQ_PLACED 1 +#define SMCINVOKE_REQ_PROCESSING 2 +#define SMCINVOKE_REQ_PROCESSED 3 +#define SMCINVOKE_INCREMENT 1 +#define SMCINVOKE_DECREMENT 0 +#define SMCINVOKE_OBJ_TYPE_TZ_OBJ 0 +#define SMCINVOKE_OBJ_TYPE_SERVER 1 +#define SMCINVOKE_MEM_MAP_OBJ 0 +#define SMCINVOKE_MEM_RGN_OBJ 1 +#define SMCINVOKE_MEM_PERM_RW 6 + +/* TZ defined values - Start */ +#define SMCINVOKE_INVOKE_PARAM_ID 0x224 +#define SMCINVOKE_CB_RSP_PARAM_ID 0x22 +#define SMCINVOKE_INVOKE_CMD 0x32000600 +#define SMCINVOKE_CB_RSP_CMD 0x32000601 +#define SMCINVOKE_RESULT_INBOUND_REQ_NEEDED 3 +/* TZ defined values - End */ + +/* + * This is the state when server FD has been closed but + * TZ still has refs of CBOBjs served by this server + */ +#define SMCINVOKE_SERVER_STATE_DEFUNCT 1 + +#define FOR_ARGS(ndxvar, counts, section) \ + for (ndxvar = OBJECT_COUNTS_INDEX_##section(counts); \ + ndxvar < (OBJECT_COUNTS_INDEX_##section(counts) \ + + OBJECT_COUNTS_NUM_##section(counts)); \ ++ndxvar) +#define TZCB_BUF_OFFSET(tzcb_req) (sizeof(tzcb_req->result) + \ + sizeof(struct smcinvoke_msg_hdr) + \ + sizeof(union smcinvoke_tz_args) * \ + OBJECT_COUNTS_TOTAL(tzcb_req->hdr.counts)) + +/* + * +ve uhandle : either remote obj or mem obj, decided by f_ops + * -ve uhandle : either Obj NULL or CBObj + * - -1: OBJ NULL + * - < -1: CBObj + */ +#define UHANDLE_IS_FD(h) ((h) >= 0) +#define UHANDLE_IS_NULL(h) ((h) == SMCINVOKE_USERSPACE_OBJ_NULL) +#define UHANDLE_IS_CB_OBJ(h) (h < SMCINVOKE_USERSPACE_OBJ_NULL) +#define UHANDLE_NULL (SMCINVOKE_USERSPACE_OBJ_NULL) +/* + * MAKE => create handle for other domain i.e. TZ or userspace + * GET => retrieve obj from incoming handle + */ +#define UHANDLE_GET_CB_OBJ(h) (-2-(h)) +#define UHANDLE_MAKE_CB_OBJ(o) (-2-(o)) +#define UHANDLE_GET_FD(h) (h) + +/* + * +ve tzhandle : remote object i.e. owned by TZ + * -ve tzhandle : local object i.e. owned by linux + * -------------------------------------------------- + *| 1 (1 bit) | Obj Id (15 bits) | srvr id (16 bits) | + * --------------------------------------------------- + * Server ids are defined below for various local objects + * server id 0 : Kernel Obj + * server id 1 : Memory region Obj + * server id 2 : Memory map Obj + * server id 3-15: Reserverd + * server id 16 & up: Callback Objs + */ +#define KRNL_SRVR_ID 0 +#define MEM_RGN_SRVR_ID 1 +#define MEM_MAP_SRVR_ID 2 +#define CBOBJ_SERVER_ID_START 0x10 +/* CBOBJs will be served by server id 0x10 onwards */ +#define TZHANDLE_GET_SERVER(h) ((uint16_t)((h) & 0xFFFF)) +#define TZHANDLE_GET_OBJID(h) (((h) >> 16) & 0x7FFF) +#define TZHANDLE_MAKE_LOCAL(s, o) (((0x8000 | (o)) << 16) | s) + +#define TZHANDLE_IS_NULL(h) ((h) == SMCINVOKE_TZ_OBJ_NULL) +#define TZHANDLE_IS_LOCAL(h) ((h) & 0x80000000) +#define TZHANDLE_IS_REMOTE(h) (!TZHANDLE_IS_NULL(h) && !TZHANDLE_IS_LOCAL(h)) + +#define TZHANDLE_IS_KERNEL_OBJ(h) (TZHANDLE_IS_LOCAL(h) && \ + TZHANDLE_GET_SERVER(h) == KRNL_SRVR_ID) +#define TZHANDLE_IS_MEM_RGN_OBJ(h) (TZHANDLE_IS_LOCAL(h) && \ + TZHANDLE_GET_SERVER(h) == MEM_RGN_SRVR_ID) +#define TZHANDLE_IS_MEM_MAP_OBJ(h) (TZHANDLE_IS_LOCAL(h) && \ + TZHANDLE_GET_SERVER(h) == MEM_MAP_SRVR_ID) +#define TZHANDLE_IS_MEM_OBJ(h) (TZHANDLE_IS_MEM_RGN_OBJ(h) || \ + TZHANDLE_IS_MEM_MAP_OBJ(h)) +#define TZHANDLE_IS_CB_OBJ(h) (TZHANDLE_IS_LOCAL(h) && \ + TZHANDLE_GET_SERVER(h) >= CBOBJ_SERVER_ID_START) + +#define FILE_IS_REMOTE_OBJ(f) ((f)->f_op && (f)->f_op == &g_smcinvoke_fops) + +static DEFINE_MUTEX(g_smcinvoke_lock); +static DEFINE_HASHTABLE(g_cb_servers, 8); +static LIST_HEAD(g_mem_objs); +static uint16_t g_last_cb_server_id = CBOBJ_SERVER_ID_START; +static uint16_t g_last_mem_rgn_id, g_last_mem_map_obj_id; +static size_t g_max_cb_buf_size = SMCINVOKE_TZ_MIN_BUF_SIZE; + static long smcinvoke_ioctl(struct file *, unsigned int, unsigned long); static int smcinvoke_open(struct inode *, struct file *); static int smcinvoke_release(struct inode *, struct file *); -static const struct file_operations smcinvoke_fops = { +static const struct file_operations g_smcinvoke_fops = { .owner = THIS_MODULE, .unlocked_ioctl = smcinvoke_ioctl, .compat_ioctl = smcinvoke_ioctl, @@ -56,6 +152,12 @@ static const struct file_operations smcinvoke_fops = { .release = smcinvoke_release, }; +static dev_t smcinvoke_device_no; +static struct cdev smcinvoke_cdev; +static struct class *driver_class; +static struct device *class_dev; +static struct platform_device *smcinvoke_pdev; + struct smcinvoke_buf_hdr { uint32_t offset; uint32_t size; @@ -63,22 +165,320 @@ struct smcinvoke_buf_hdr { union smcinvoke_tz_args { struct smcinvoke_buf_hdr b; - uint32_t tzhandle; + int32_t handle; }; + struct smcinvoke_msg_hdr { - uint32_t tzhandle; - uint32_t op; - uint32_t counts; + uint32_t tzhandle; + uint32_t op; + uint32_t counts; }; -struct smcinvoke_tzobj_context { - uint32_t tzhandle; +/* Inbound reqs from TZ */ +struct smcinvoke_tzcb_req { + int32_t result; + struct smcinvoke_msg_hdr hdr; + union smcinvoke_tz_args args[0]; }; -static dev_t smcinvoke_device_no; -struct cdev smcinvoke_cdev; -struct class *driver_class; -struct device *class_dev; +struct smcinvoke_file_data { + uint32_t context_type; + union { + uint32_t tzhandle; + uint16_t server_id; + }; +}; + +struct smcinvoke_piggyback_msg { + uint32_t version; + uint32_t op; + uint32_t counts; + int32_t objs[0]; +}; + +/* Data structure to hold request coming from TZ */ +struct smcinvoke_cb_txn { + uint32_t txn_id; + int32_t state; + struct smcinvoke_tzcb_req *cb_req; + size_t cb_req_bytes; + struct file **filp_to_release; + struct hlist_node hash; +}; + +struct smcinvoke_server_info { + uint16_t server_id; + uint16_t state; + uint32_t txn_id; + wait_queue_head_t req_wait_q; + wait_queue_head_t rsp_wait_q; + size_t cb_buf_size; + DECLARE_HASHTABLE(reqs_table, 4); + DECLARE_HASHTABLE(responses_table, 4); + struct hlist_node hash; + struct list_head pending_cbobjs; +}; + +struct smcinvoke_cbobj { + uint16_t cbobj_id; + struct kref ref_cnt; + struct smcinvoke_server_info *server; + struct list_head list; +}; + +/* + * We require couple of objects, one for mem region & another + * for mapped mem_obj once mem region has been mapped. It is + * possible that TZ can release either independent of other. + */ +struct smcinvoke_mem_obj { + /* these ids are objid part of tzhandle */ + uint16_t mem_region_id; + uint16_t mem_map_obj_id; + struct dma_buf *dma_buf; + struct dma_buf_attachment *buf_attach; + struct sg_table *sgt; + struct kref mem_regn_ref_cnt; + struct kref mem_map_obj_ref_cnt; + uint64_t p_addr; + size_t p_addr_len; + struct list_head list; +}; + +static struct smcinvoke_server_info *find_cb_server_locked(uint16_t server_id) +{ + struct smcinvoke_server_info *data = NULL; + + hash_for_each_possible(g_cb_servers, data, hash, server_id) { + if (data->server_id == server_id) + return data; + } + return NULL; +} + +static uint16_t next_cb_server_id_locked(void) +{ + while (find_cb_server_locked(++g_last_cb_server_id)); + + return g_last_cb_server_id; +} + +static inline void release_filp(struct file **filp_to_release, size_t arr_len) +{ + size_t i = 0; + + for (i = 0; i < arr_len; i++) { + if (filp_to_release[i]) { + fput(filp_to_release[i]); + filp_to_release[i] = NULL; + } + } +} + +static struct smcinvoke_mem_obj *find_mem_obj_locked(uint16_t mem_obj_id, + bool is_mem_rgn_obj) +{ + struct smcinvoke_mem_obj *mem_obj = NULL; + + if (list_empty(&g_mem_objs)) { + pr_err("%s: mem obj %d not found\n", __func__, mem_obj_id); + return NULL; + } + + list_for_each_entry(mem_obj, &g_mem_objs, list) { + if ((is_mem_rgn_obj && + (mem_obj->mem_region_id == mem_obj_id)) || + (!is_mem_rgn_obj && + (mem_obj->mem_map_obj_id == mem_obj_id))) + return mem_obj; + } + return NULL; +} + +static uint32_t next_mem_region_obj_id_locked(void) +{ + while (find_mem_obj_locked(++g_last_mem_rgn_id, SMCINVOKE_MEM_RGN_OBJ)); + + return g_last_mem_rgn_id; +} + +static uint32_t next_mem_map_obj_id_locked(void) +{ + while (find_mem_obj_locked(++g_last_mem_map_obj_id, + SMCINVOKE_MEM_MAP_OBJ)); + + return g_last_mem_map_obj_id; +} + +static inline void free_mem_obj_locked(struct smcinvoke_mem_obj *mem_obj) +{ + list_del(&mem_obj->list); + dma_buf_put(mem_obj->dma_buf); + kfree(mem_obj); +} + +static void del_mem_regn_obj_locked(struct kref *kref) +{ + struct smcinvoke_mem_obj *mem_obj = container_of(kref, + struct smcinvoke_mem_obj, mem_regn_ref_cnt); + + /* + * mem_regn obj and mem_map obj are held into mem_obj structure which + * can't be released until both kinds of objs have been released. + * So check whether mem_map iobj has ref 0 and only then release mem_obj + */ + if (kref_read(&mem_obj->mem_map_obj_ref_cnt) == 0) + free_mem_obj_locked(mem_obj); +} + +static void del_mem_map_obj_locked(struct kref *kref) +{ + struct smcinvoke_mem_obj *mem_obj = container_of(kref, + struct smcinvoke_mem_obj, mem_map_obj_ref_cnt); + + mem_obj->p_addr_len = 0; + mem_obj->p_addr = 0; + if (mem_obj->sgt) + dma_buf_unmap_attachment(mem_obj->buf_attach, + mem_obj->sgt, DMA_BIDIRECTIONAL); + if (mem_obj->buf_attach) + dma_buf_detach(mem_obj->dma_buf, mem_obj->buf_attach); + + /* + * mem_regn obj and mem_map obj are held into mem_obj structure which + * can't be released until both kinds of objs have been released. + * So check if mem_regn obj has ref 0 and only then release mem_obj + */ + if (kref_read(&mem_obj->mem_regn_ref_cnt) == 0) + free_mem_obj_locked(mem_obj); +} + +static int release_mem_obj_locked(int32_t tzhandle) +{ + int is_mem_regn_obj = TZHANDLE_IS_MEM_RGN_OBJ(tzhandle); + struct smcinvoke_mem_obj *mem_obj = find_mem_obj_locked( + TZHANDLE_GET_OBJID(tzhandle), is_mem_regn_obj); + + if (!mem_obj) + return OBJECT_ERROR_BADOBJ; + + if (is_mem_regn_obj) + kref_put(&mem_obj->mem_regn_ref_cnt, del_mem_regn_obj_locked); + else + kref_put(&mem_obj->mem_map_obj_ref_cnt, del_mem_map_obj_locked); + + return OBJECT_OK; +} + +static void free_pending_cbobj_locked(struct kref *kref) +{ + struct smcinvoke_server_info *server = NULL; + struct smcinvoke_cbobj *obj = container_of(kref, + struct smcinvoke_cbobj, ref_cnt); + list_del(&obj->list); + server = obj->server; + kfree(obj); + if ((server->state == SMCINVOKE_SERVER_STATE_DEFUNCT) && + list_empty(&server->pending_cbobjs)) + kfree(server); +} + +static int get_pending_cbobj_locked(uint16_t srvr_id, int16_t obj_id) +{ + struct smcinvoke_server_info *server = find_cb_server_locked(srvr_id); + struct list_head *head = NULL; + struct smcinvoke_cbobj *cbobj = NULL; + struct smcinvoke_cbobj *obj = NULL; + + if (!server) + return OBJECT_ERROR_BADOBJ; + + head = &server->pending_cbobjs; + list_for_each_entry(cbobj, head, list) + if (cbobj->cbobj_id == obj_id) { + kref_get(&cbobj->ref_cnt); + return 0; + } + + obj = kzalloc(sizeof(*obj), GFP_KERNEL); + if (!obj) + return OBJECT_ERROR_KMEM; + + obj->cbobj_id = obj_id; + kref_init(&obj->ref_cnt); + obj->server = server; + list_add_tail(&obj->list, head); + + return 0; +} + +static int put_pending_cbobj_locked(uint16_t srvr_id, int16_t obj_id) +{ + struct smcinvoke_server_info *srvr_info = + find_cb_server_locked(srvr_id); + struct list_head *head = NULL; + struct smcinvoke_cbobj *cbobj = NULL; + + if (!srvr_info) + return -EINVAL; + + head = &srvr_info->pending_cbobjs; + list_for_each_entry(cbobj, head, list) + if (cbobj->cbobj_id == obj_id) { + kref_put(&cbobj->ref_cnt, free_pending_cbobj_locked); + return 0; + } + return -EINVAL; +} + +static int release_tzhandle_locked(int32_t tzhandle) +{ + if (TZHANDLE_IS_MEM_OBJ(tzhandle)) + return release_mem_obj_locked(tzhandle); + else if (TZHANDLE_IS_CB_OBJ(tzhandle)) + return put_pending_cbobj_locked(TZHANDLE_GET_SERVER(tzhandle), + TZHANDLE_GET_OBJID(tzhandle)); + return OBJECT_ERROR; +} + +static void release_tzhandles(const int32_t *tzhandles, size_t len) +{ + size_t i; + + mutex_lock(&g_smcinvoke_lock); + for (i = 0; i < len; i++) + release_tzhandle_locked(tzhandles[i]); + mutex_unlock(&g_smcinvoke_lock); +} + +static struct smcinvoke_cb_txn *find_cbtxn_locked( + struct smcinvoke_server_info *server, + uint32_t txn_id, int32_t state) +{ + int i = 0; + struct smcinvoke_cb_txn *cb_txn = NULL; + + /* + * Since HASH_BITS() does not work on pointers, we can't select hash + * table using state and loop over it. + */ + if (state == SMCINVOKE_REQ_PLACED) { + /* pick up 1st req */ + hash_for_each(server->reqs_table, i, cb_txn, hash) { + hash_del(&cb_txn->hash); + return cb_txn; + } + } else if (state == SMCINVOKE_REQ_PROCESSING) { + hash_for_each_possible( + server->responses_table, cb_txn, hash, txn_id) { + if (cb_txn->txn_id == txn_id) { + hash_del(&cb_txn->hash); + return cb_txn; + } + } + } + return NULL; +} /* * size_add saturates at SIZE_MAX. If integer overflow is detected, @@ -107,75 +507,158 @@ static inline size_t size_align(size_t a, size_t b) return size_add(a, pad_size(a, b)); } +static uint16_t get_server_id(int cb_server_fd) +{ + uint16_t server_id = 0; + struct smcinvoke_file_data *svr_cxt = NULL; + struct file *tmp_filp = fget(cb_server_fd); + + if (!tmp_filp) + return server_id; + + svr_cxt = tmp_filp->private_data; + if (svr_cxt && svr_cxt->context_type == SMCINVOKE_OBJ_TYPE_SERVER) + server_id = svr_cxt->server_id; + + if (tmp_filp) + fput(tmp_filp); + + return server_id; +} + +static bool is_dma_fd(int32_t uhandle, struct dma_buf **dma_buf) +{ + *dma_buf = dma_buf_get(uhandle); + return IS_ERR_OR_NULL(*dma_buf) ? false : true; +} + +static bool is_remote_obj(int32_t uhandle, struct smcinvoke_file_data **tzobj, + struct file **filp) +{ + bool ret = false; + struct file *tmp_filp = fget(uhandle); + + if (!tmp_filp) + return ret; + + if (FILE_IS_REMOTE_OBJ(tmp_filp)) { + *tzobj = tmp_filp->private_data; + if ((*tzobj)->context_type == SMCINVOKE_OBJ_TYPE_TZ_OBJ) { + *filp = tmp_filp; + tmp_filp = NULL; + ret = true; + } + } + + if (tmp_filp) + fput(tmp_filp); + return ret; +} + +static int create_mem_obj(struct dma_buf *dma_buf, int32_t *mem_obj) +{ + struct smcinvoke_mem_obj *t_mem_obj = + kzalloc(sizeof(*t_mem_obj), GFP_KERNEL); + + if (!t_mem_obj) { + dma_buf_put(dma_buf); + return -ENOMEM; + } + + kref_init(&t_mem_obj->mem_regn_ref_cnt); + t_mem_obj->dma_buf = dma_buf; + mutex_lock(&g_smcinvoke_lock); + t_mem_obj->mem_region_id = next_mem_region_obj_id_locked(); + list_add_tail(&t_mem_obj->list, &g_mem_objs); + mutex_unlock(&g_smcinvoke_lock); + *mem_obj = TZHANDLE_MAKE_LOCAL(MEM_RGN_SRVR_ID, + t_mem_obj->mem_region_id); + return 0; +} + /* * This function retrieves file pointer corresponding to FD provided. It stores * retrived file pointer until IOCTL call is concluded. Once call is completed, * all stored file pointers are released. file pointers are stored to prevent * other threads from releasing that FD while IOCTL is in progress. */ -static int get_tzhandle_from_fd(int64_t fd, struct file **filp, - uint32_t *tzhandle) +static int get_tzhandle_from_uhandle(int32_t uhandle, int32_t server_fd, + struct file **filp, uint32_t *tzhandle) { int ret = -EBADF; - struct file *tmp_filp = NULL; - struct smcinvoke_tzobj_context *tzobj = NULL; + uint16_t server_id = 0; - if (fd == SMCINVOKE_USERSPACE_OBJ_NULL) { + if (UHANDLE_IS_NULL(uhandle)) { *tzhandle = SMCINVOKE_TZ_OBJ_NULL; ret = 0; - goto out; - } else if (fd < SMCINVOKE_USERSPACE_OBJ_NULL) { - goto out; - } - - tmp_filp = fget(fd); - if (!tmp_filp) - goto out; + } else if (UHANDLE_IS_CB_OBJ(uhandle)) { + server_id = get_server_id(server_fd); + if (server_id < CBOBJ_SERVER_ID_START) + goto out; - /* Verify if filp is smcinvoke device's file pointer */ - if (!tmp_filp->f_op || !tmp_filp->private_data || - (tmp_filp->f_op != &smcinvoke_fops)) { - fput(tmp_filp); - goto out; + mutex_lock(&g_smcinvoke_lock); + ret = get_pending_cbobj_locked(server_id, + UHANDLE_GET_CB_OBJ(uhandle)); + mutex_unlock(&g_smcinvoke_lock); + if (ret) + goto out; + *tzhandle = TZHANDLE_MAKE_LOCAL(server_id, + UHANDLE_GET_CB_OBJ(uhandle)); + ret = 0; + } else if (UHANDLE_IS_FD(uhandle)) { + struct dma_buf *dma_buf = NULL; + struct smcinvoke_file_data *tzobj = NULL; + + if (is_dma_fd(UHANDLE_GET_FD(uhandle), &dma_buf)) { + ret = create_mem_obj(dma_buf, tzhandle); + } else if (is_remote_obj(UHANDLE_GET_FD(uhandle), + &tzobj, filp)) { + *tzhandle = tzobj->tzhandle; + ret = 0; + } } - - tzobj = tmp_filp->private_data; - *tzhandle = tzobj->tzhandle; - *filp = tmp_filp; - ret = 0; out: + if (ret && *filp) { + fput(*filp); + *filp = NULL; + } return ret; } -static int get_fd_from_tzhandle(uint32_t tzhandle, int64_t *fd) +static int get_fd_for_obj(uint32_t obj_type, uint32_t obj, int64_t *fd) { - int unused_fd = -1, ret = -1; + int unused_fd = -1, ret = -EINVAL; struct file *f = NULL; - struct smcinvoke_tzobj_context *cxt = NULL; - - if (tzhandle == SMCINVOKE_TZ_OBJ_NULL) { - *fd = SMCINVOKE_USERSPACE_OBJ_NULL; - ret = 0; - goto out; - } + struct smcinvoke_file_data *cxt = NULL; cxt = kzalloc(sizeof(*cxt), GFP_KERNEL); if (!cxt) { ret = -ENOMEM; goto out; } + if (obj_type == SMCINVOKE_OBJ_TYPE_TZ_OBJ) { + cxt->context_type = SMCINVOKE_OBJ_TYPE_TZ_OBJ; + cxt->tzhandle = obj; + } else if (obj_type == SMCINVOKE_OBJ_TYPE_SERVER) { + cxt->context_type = SMCINVOKE_OBJ_TYPE_SERVER; + cxt->server_id = obj; + } else { + goto out; + } + unused_fd = get_unused_fd_flags(O_RDWR); if (unused_fd < 0) goto out; - f = anon_inode_getfile(SMCINVOKE_DEV, &smcinvoke_fops, cxt, O_RDWR); + if (fd == NULL) + goto out; + + f = anon_inode_getfile(SMCINVOKE_DEV, &g_smcinvoke_fops, cxt, O_RDWR); if (IS_ERR(f)) goto out; *fd = unused_fd; fd_install(*fd, f); - ((struct smcinvoke_tzobj_context *) - (f->private_data))->tzhandle = tzhandle; return 0; out: if (unused_fd >= 0) @@ -185,50 +668,237 @@ static int get_fd_from_tzhandle(uint32_t tzhandle, int64_t *fd) return ret; } -static int prepare_send_scm_msg(const uint8_t *in_buf, size_t in_buf_len, - const uint8_t *out_buf, size_t out_buf_len, - int32_t *smcinvoke_result) +static int get_uhandle_from_tzhandle(int32_t tzhandle, int32_t srvr_id, + int64_t *uhandle) { - int ret = 0; - struct scm_desc desc = {0}; - size_t inbuf_flush_size = (1UL << get_order(in_buf_len)) * PAGE_SIZE; - size_t outbuf_flush_size = (1UL << get_order(out_buf_len)) * PAGE_SIZE; + int ret = -1; - desc.arginfo = SMCINVOKE_TZ_PARAM_ID; - desc.args[0] = (uint64_t)virt_to_phys(in_buf); - desc.args[1] = inbuf_flush_size; - desc.args[2] = (uint64_t)virt_to_phys(out_buf); - desc.args[3] = outbuf_flush_size; + if (TZHANDLE_IS_NULL(tzhandle)) { + *uhandle = UHANDLE_NULL; + ret = 0; + } else if (TZHANDLE_IS_CB_OBJ(tzhandle)) { + if (srvr_id != TZHANDLE_GET_SERVER(tzhandle)) + goto out; + *uhandle = UHANDLE_MAKE_CB_OBJ(TZHANDLE_GET_OBJID(tzhandle)); + mutex_lock(&g_smcinvoke_lock); + ret = get_pending_cbobj_locked(srvr_id, + TZHANDLE_GET_OBJID(tzhandle)); + mutex_unlock(&g_smcinvoke_lock); + } else if (TZHANDLE_IS_MEM_RGN_OBJ(tzhandle)) { + struct smcinvoke_mem_obj *mem_obj = NULL; + + mutex_lock(&g_smcinvoke_lock); + mem_obj = find_mem_obj_locked(TZHANDLE_GET_OBJID(tzhandle), + SMCINVOKE_MEM_RGN_OBJ); + + if (mem_obj != NULL) { + unsigned long flags = 0; + int fd; + + if (dma_buf_get_flags(mem_obj->dma_buf, &flags)) + goto exit_lock; + fd = dma_buf_fd(mem_obj->dma_buf, flags); + + if (fd < 0) + goto exit_lock; + *uhandle = fd; + ret = 0; + } +exit_lock: + mutex_unlock(&g_smcinvoke_lock); + } else if (TZHANDLE_IS_REMOTE(tzhandle)) { + /* if execution comes here => tzhandle is an unsigned int */ + ret = get_fd_for_obj(SMCINVOKE_OBJ_TYPE_TZ_OBJ, + (uint32_t)tzhandle, uhandle); + } +out: + return ret; +} - dmac_flush_range(in_buf, in_buf + inbuf_flush_size); - dmac_flush_range(out_buf, out_buf + outbuf_flush_size); +static int32_t smcinvoke_release_mem_obj_locked(void *buf, size_t buf_len) +{ + struct smcinvoke_tzcb_req *msg = buf; - ret = scm_call2(SMCINVOKE_TZ_CMD, &desc); + if (msg->hdr.counts != OBJECT_COUNTS_PACK(0, 0, 0, 0)) + return OBJECT_ERROR_INVALID; - /* process listener request */ - if (!ret && (desc.ret[0] == QSEOS_RESULT_INCOMPLETE || - desc.ret[0] == QSEOS_RESULT_BLOCKED_ON_LISTENER)) - ret = qseecom_process_listener_from_smcinvoke(&desc); + return release_tzhandle_locked(msg->hdr.tzhandle); +} - *smcinvoke_result = (int32_t)desc.ret[1]; - if (ret || desc.ret[1] || desc.ret[2] || desc.ret[0]) - pr_err("SCM call failed with ret val = %d %d %d %d\n", - ret, (int)desc.ret[0], - (int)desc.ret[1], (int)desc.ret[2]); +static int32_t smcinvoke_map_mem_region(void *buf, size_t buf_len) +{ + int ret = OBJECT_OK; + struct smcinvoke_tzcb_req *msg = buf; + struct { + uint64_t p_addr; + uint64_t len; + uint32_t perms; + } *ob = NULL; + int32_t *oo = NULL; + struct smcinvoke_mem_obj *mem_obj = NULL; + struct dma_buf_attachment *buf_attach = NULL; + struct sg_table *sgt = NULL; + + if (msg->hdr.counts != OBJECT_COUNTS_PACK(0, 1, 1, 1) || + (buf_len - msg->args[0].b.offset < msg->args[0].b.size)) + return OBJECT_ERROR_INVALID; + + /* args[0] = BO, args[1] = OI, args[2] = OO */ + ob = buf + msg->args[0].b.offset; + oo = &msg->args[2].handle; + + mutex_lock(&g_smcinvoke_lock); + mem_obj = find_mem_obj_locked(TZHANDLE_GET_OBJID(msg->args[1].handle), + SMCINVOKE_MEM_RGN_OBJ); + if (!mem_obj) { + mutex_unlock(&g_smcinvoke_lock); + return OBJECT_ERROR_BADOBJ; + } - dmac_inv_range(in_buf, in_buf + inbuf_flush_size); - dmac_inv_range(out_buf, out_buf + outbuf_flush_size); + if (!mem_obj->p_addr) { + kref_init(&mem_obj->mem_map_obj_ref_cnt); + buf_attach = dma_buf_attach(mem_obj->dma_buf, + &smcinvoke_pdev->dev); + if (IS_ERR(buf_attach)) { + ret = OBJECT_ERROR_KMEM; + goto out; + } + mem_obj->buf_attach = buf_attach; + + sgt = dma_buf_map_attachment(buf_attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + ret = OBJECT_ERROR_KMEM; + goto out; + } + mem_obj->sgt = sgt; + + /* contiguous only => nents=1 */ + if (sgt->nents != 1) { + ret = OBJECT_ERROR_INVALID; + goto out; + } + mem_obj->p_addr = sg_dma_address(sgt->sgl); + mem_obj->p_addr_len = sgt->sgl->length; + if (!mem_obj->p_addr) { + ret = OBJECT_ERROR_INVALID; + goto out; + } + mem_obj->mem_map_obj_id = next_mem_map_obj_id_locked(); + } else { + kref_get(&mem_obj->mem_map_obj_ref_cnt); + } + ob->p_addr = mem_obj->p_addr; + ob->len = mem_obj->p_addr_len; + ob->perms = SMCINVOKE_MEM_PERM_RW; + *oo = mem_obj->mem_map_obj_id; +out: + if (ret != OBJECT_OK) + kref_put(&mem_obj->mem_map_obj_ref_cnt, del_mem_map_obj_locked); + mutex_unlock(&g_smcinvoke_lock); return ret; } -static int marshal_out(void *buf, uint32_t buf_size, +static void process_kernel_obj(void *buf, size_t buf_len) +{ + struct smcinvoke_tzcb_req *cb_req = buf; + + cb_req->result = (cb_req->hdr.op == OBJECT_OP_MAP_REGION) ? + smcinvoke_map_mem_region(buf, buf_len) : + OBJECT_ERROR_INVALID; +} + +static void process_mem_obj(void *buf, size_t buf_len) +{ + struct smcinvoke_tzcb_req *cb_req = buf; + + mutex_lock(&g_smcinvoke_lock); + cb_req->result = (cb_req->hdr.op == OBJECT_OP_RELEASE) ? + smcinvoke_release_mem_obj_locked(buf, buf_len) : + OBJECT_ERROR_INVALID; + mutex_unlock(&g_smcinvoke_lock); +} + +/* + * Buf should be aligned to struct smcinvoke_tzcb_req + */ +static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp) +{ + /* ret is going to TZ. Provide values from OBJECT_ERROR_<> */ + int ret = OBJECT_ERROR_DEFUNCT; + struct smcinvoke_cb_txn *cb_txn = NULL; + struct smcinvoke_tzcb_req *cb_req = NULL; + struct smcinvoke_server_info *srvr_info = NULL; + + if (buf_len < sizeof(struct smcinvoke_tzcb_req)) + return; + + cb_req = buf; + /* check whether it is to be served by kernel or userspace */ + if (TZHANDLE_IS_KERNEL_OBJ(cb_req->hdr.tzhandle)) { + return process_kernel_obj(buf, buf_len); + } else if (TZHANDLE_IS_MEM_OBJ(cb_req->hdr.tzhandle)) { + return process_mem_obj(buf, buf_len); + } else if (!TZHANDLE_IS_CB_OBJ(cb_req->hdr.tzhandle)) { + cb_req->result = OBJECT_ERROR_INVALID; + return; + } + + cb_txn = kzalloc(sizeof(*cb_txn), GFP_KERNEL); + if (!cb_txn) { + ret = OBJECT_ERROR_KMEM; + goto out; + } + + cb_txn->state = SMCINVOKE_REQ_PLACED; + cb_txn->cb_req = cb_req; + cb_txn->cb_req_bytes = buf_len; + cb_txn->filp_to_release = arr_filp; + + mutex_lock(&g_smcinvoke_lock); + srvr_info = find_cb_server_locked( + TZHANDLE_GET_SERVER(cb_req->hdr.tzhandle)); + if (!srvr_info || srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT) { + mutex_unlock(&g_smcinvoke_lock); + goto out; + } + + cb_txn->txn_id = ++srvr_info->txn_id; + hash_add(srvr_info->reqs_table, &cb_txn->hash, cb_txn->txn_id); + mutex_unlock(&g_smcinvoke_lock); + wake_up_interruptible(&srvr_info->req_wait_q); + wait_event(srvr_info->rsp_wait_q, + (cb_txn->state == SMCINVOKE_REQ_PROCESSED) || + (srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT)); +out: + /* + * If we are here, either req is processed or not + * if processed, result would have been set by txn processor + * if not processed, we should set result with ret which should have + * correct value that TZ/TA can understand + */ + if (!cb_txn || (cb_txn->state != SMCINVOKE_REQ_PROCESSED)) { + cb_req->result = ret; + if (srvr_info && + srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT && + OBJECT_OP_METHODID(cb_req->hdr.op) == OBJECT_OP_RELEASE) { + mutex_lock(&g_smcinvoke_lock); + put_pending_cbobj_locked( + TZHANDLE_GET_SERVER(cb_req->hdr.tzhandle), + TZHANDLE_GET_OBJID(cb_req->hdr.tzhandle)); + mutex_unlock(&g_smcinvoke_lock); + } + } + kfree(cb_txn); +} + +static int marshal_out_invoke_req(const uint8_t *buf, uint32_t buf_size, struct smcinvoke_cmd_req *req, union smcinvoke_arg *args_buf) { int ret = -EINVAL, i = 0; union smcinvoke_tz_args *tz_args = NULL; size_t offset = sizeof(struct smcinvoke_msg_hdr) + - object_counts_total(req->counts) * + OBJECT_COUNTS_TOTAL(req->counts) * sizeof(union smcinvoke_tz_args); if (offset > buf_size) @@ -237,7 +907,10 @@ static int marshal_out(void *buf, uint32_t buf_size, tz_args = (union smcinvoke_tz_args *) (buf + sizeof(struct smcinvoke_msg_hdr)); - tz_args += object_counts_num_BI(req->counts); + tz_args += OBJECT_COUNTS_NUM_BI(req->counts); + + if (args_buf == NULL) + return 0; FOR_ARGS(i, req->counts, BO) { args_buf[i].b.size = tz_args->b.size; @@ -254,15 +927,17 @@ static int marshal_out(void *buf, uint32_t buf_size, } tz_args++; } - tz_args += object_counts_num_OI(req->counts); + tz_args += OBJECT_COUNTS_NUM_OI(req->counts); FOR_ARGS(i, req->counts, OO) { /* - * create a new FD and assign to output object's - * context + * create a new FD and assign to output object's context. + * We are passing cb_server_fd from output param in case OO + * is a CBObj. For CBObj, we have to ensure that it is sent + * to server who serves it and that info comes from USpace. */ - ret = get_fd_from_tzhandle(tz_args->tzhandle, - &(args_buf[i].o.fd)); + ret = get_uhandle_from_tzhandle(tz_args->handle, + args_buf[i].o.cb_server_fd, &(args_buf[i].o.fd)); if (ret) goto out; tz_args++; @@ -272,6 +947,93 @@ static int marshal_out(void *buf, uint32_t buf_size, return ret; } +static bool is_inbound_req(int val) +{ + return (val == SMCINVOKE_RESULT_INBOUND_REQ_NEEDED || + val == QSEOS_RESULT_INCOMPLETE || + val == QSEOS_RESULT_BLOCKED_ON_LISTENER); +} + +static int prepare_send_scm_msg(const uint8_t *in_buf, size_t in_buf_len, + uint8_t *out_buf, size_t out_buf_len, + struct smcinvoke_cmd_req *req, + union smcinvoke_arg *args_buf, + bool *tz_acked) +{ + int ret = 0, cmd; + struct scm_desc desc = {0}; + struct file *arr_filp[OBJECT_COUNTS_MAX_OO] = {NULL}; + + *tz_acked = false; + /* buf size should be page aligned */ + if ((in_buf_len % PAGE_SIZE) != 0 || (out_buf_len % PAGE_SIZE) != 0) + return -EINVAL; + + desc.arginfo = SMCINVOKE_INVOKE_PARAM_ID; + desc.args[0] = (uint64_t)virt_to_phys(in_buf); + desc.args[1] = in_buf_len; + desc.args[2] = (uint64_t)virt_to_phys(out_buf); + desc.args[3] = out_buf_len; + cmd = SMCINVOKE_INVOKE_CMD; + dmac_flush_range(in_buf, in_buf + in_buf_len); + dmac_flush_range(out_buf, out_buf + out_buf_len); + /* + * purpose of lock here is to ensure that any CB obj that may be going + * to user as OO is not released by piggyback message on another invoke + * request. We should not move this lock to process_invoke_req() because + * that will either cause deadlock or prevent any other invoke request + * to come in. We release this lock when either + * a) TZ requires HLOS action to complete ongoing invoke operation + * b) Final response to invoke has been marshalled out + */ + while (1) { + mutex_lock(&g_smcinvoke_lock); + ret = scm_call2(cmd, &desc); + if (!ret && !is_inbound_req(desc.ret[0])) { + req->result = (int32_t)desc.ret[1]; + /* dont marshal if Obj returns an error */ + if (!req->result) { + dmac_inv_range(in_buf, in_buf + in_buf_len); + if (args_buf != NULL) + ret = marshal_out_invoke_req(in_buf, + in_buf_len, req, args_buf); + } + *tz_acked = true; + } + mutex_unlock(&g_smcinvoke_lock); + + if (cmd == SMCINVOKE_CB_RSP_CMD) + release_filp(arr_filp, OBJECT_COUNTS_MAX_OO); + + if (ret || !is_inbound_req(desc.ret[0])) + break; + + /* process listener request */ + if (desc.ret[0] == QSEOS_RESULT_INCOMPLETE || + desc.ret[0] == QSEOS_RESULT_BLOCKED_ON_LISTENER) + ret = qseecom_process_listener_from_smcinvoke(&desc); + + /* + * qseecom does not understand smcinvoke's callback object && + * erringly sets ret value as -EINVAL :( We need to handle it. + */ + if (ret && desc.ret[0] != SMCINVOKE_RESULT_INBOUND_REQ_NEEDED) + break; + + dmac_inv_range(out_buf, out_buf + out_buf_len); + + if (desc.ret[0] == SMCINVOKE_RESULT_INBOUND_REQ_NEEDED) { + process_tzcb_req(out_buf, out_buf_len, arr_filp); + memset(&desc, 0, sizeof(struct scm_desc)); + desc.arginfo = SMCINVOKE_CB_RSP_PARAM_ID; + desc.args[0] = (uint64_t)virt_to_phys(out_buf); + desc.args[1] = out_buf_len; + cmd = SMCINVOKE_CB_RSP_CMD; + dmac_flush_range(out_buf, out_buf + out_buf_len); + } + } + return ret; +} /* * SMC expects arguments in following format * --------------------------------------------------------------------------- @@ -287,38 +1049,42 @@ static size_t compute_in_msg_size(const struct smcinvoke_cmd_req *req, uint32_t i = 0; size_t total_size = sizeof(struct smcinvoke_msg_hdr) + - object_counts_total(req->counts) * + OBJECT_COUNTS_TOTAL(req->counts) * sizeof(union smcinvoke_tz_args); /* Computed total_size should be 8 bytes aligned from start of buf */ total_size = ALIGN(total_size, SMCINVOKE_ARGS_ALIGN_SIZE); /* each buffer has to be 8 bytes aligned */ - while (i < object_counts_num_buffers(req->counts)) + while (i < OBJECT_COUNTS_NUM_buffers(req->counts)) total_size = size_add(total_size, size_align(args_buf[i++].b.size, SMCINVOKE_ARGS_ALIGN_SIZE)); - /* Since we're using get_free_pages, no need for explicit PAGE align */ - return total_size; + return PAGE_ALIGN(total_size); } -static int marshal_in(const struct smcinvoke_cmd_req *req, +static int marshal_in_invoke_req(const struct smcinvoke_cmd_req *req, const union smcinvoke_arg *args_buf, uint32_t tzhandle, - uint8_t *buf, size_t buf_size, struct file **arr_filp) + uint8_t *buf, size_t buf_size, struct file **arr_filp, + int32_t *tzhandles_to_release) { - int ret = -EINVAL, i = 0; - union smcinvoke_tz_args *tz_args = NULL; - struct smcinvoke_msg_hdr msg_hdr = {tzhandle, req->op, req->counts}; + int ret = -EINVAL, i = 0, j = 0, k = 0; + const struct smcinvoke_msg_hdr msg_hdr = { + tzhandle, req->op, req->counts}; uint32_t offset = sizeof(struct smcinvoke_msg_hdr) + sizeof(union smcinvoke_tz_args) * - object_counts_total(req->counts); + OBJECT_COUNTS_TOTAL(req->counts); + union smcinvoke_tz_args *tz_args = NULL; if (buf_size < offset) goto out; *(struct smcinvoke_msg_hdr *)buf = msg_hdr; - tz_args = (union smcinvoke_tz_args *) - (buf + sizeof(struct smcinvoke_msg_hdr)); + tz_args = (union smcinvoke_tz_args *)(buf + + sizeof(struct smcinvoke_msg_hdr)); + + if (args_buf == NULL) + return 0; FOR_ARGS(i, req->counts, BI) { offset = size_align(offset, SMCINVOKE_ARGS_ALIGN_SIZE); @@ -326,11 +1092,10 @@ static int marshal_in(const struct smcinvoke_cmd_req *req, (args_buf[i].b.size > (buf_size - offset))) goto out; - tz_args->b.offset = offset; - tz_args->b.size = args_buf[i].b.size; - tz_args++; + tz_args[i].b.offset = offset; + tz_args[i].b.size = args_buf[i].b.size; - if (copy_from_user(buf+offset, + if (copy_from_user(buf + offset, (void __user *)(uintptr_t)(args_buf[i].b.addr), args_buf[i].b.size)) goto out; @@ -343,167 +1108,590 @@ static int marshal_in(const struct smcinvoke_cmd_req *req, (args_buf[i].b.size > (buf_size - offset))) goto out; - tz_args->b.offset = offset; - tz_args->b.size = args_buf[i].b.size; - tz_args++; - + tz_args[i].b.offset = offset; + tz_args[i].b.size = args_buf[i].b.size; offset += args_buf[i].b.size; } FOR_ARGS(i, req->counts, OI) { - if (get_tzhandle_from_fd(args_buf[i].o.fd, - &arr_filp[i], &(tz_args->tzhandle))) + ret = get_tzhandle_from_uhandle(args_buf[i].o.fd, + args_buf[i].o.cb_server_fd, &arr_filp[j++], + &(tz_args[i].handle)); + if (ret) goto out; - tz_args++; + tzhandles_to_release[k++] = tz_args[i].handle; } ret = 0; out: return ret; } -long smcinvoke_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +static int marshal_in_tzcb_req(const struct smcinvoke_cb_txn *cb_txn, + struct smcinvoke_accept *user_req, int srvr_id) { - int ret = -1, i = 0, nr_args = 0; - struct smcinvoke_cmd_req req = {0}; - void *in_msg = NULL; - size_t inmsg_size = 0; - void *out_msg = NULL; - union smcinvoke_arg *args_buf = NULL; - struct file *filp_to_release[object_counts_max_OO] = {NULL}; - struct smcinvoke_tzobj_context *tzobj = filp->private_data; + int ret = 0, i = 0; + union smcinvoke_arg tmp_arg; + struct smcinvoke_tzcb_req *tzcb_req = cb_txn->cb_req; + union smcinvoke_tz_args *tz_args = tzcb_req->args; + size_t tzcb_req_len = cb_txn->cb_req_bytes; + size_t tz_buf_offset = TZCB_BUF_OFFSET(tzcb_req); + size_t user_req_buf_offset = sizeof(union smcinvoke_arg) * + OBJECT_COUNTS_TOTAL(tzcb_req->hdr.counts); + + if (tz_buf_offset > tzcb_req_len) { + ret = -EINVAL; + goto out; + } - switch (cmd) { - case SMCINVOKE_IOCTL_INVOKE_REQ: - if (_IOC_SIZE(cmd) != sizeof(req)) { - ret = -EINVAL; + user_req->txn_id = cb_txn->txn_id; + if (get_uhandle_from_tzhandle(tzcb_req->hdr.tzhandle, srvr_id, + (int64_t *)&user_req->cbobj_id)) { + ret = -EINVAL; + goto out; + } + user_req->op = tzcb_req->hdr.op; + user_req->counts = tzcb_req->hdr.counts; + user_req->argsize = sizeof(union smcinvoke_arg); + + FOR_ARGS(i, tzcb_req->hdr.counts, BI) { + user_req_buf_offset = size_align(user_req_buf_offset, + SMCINVOKE_ARGS_ALIGN_SIZE); + tmp_arg.b.size = tz_args[i].b.size; + if ((tz_args[i].b.offset > tzcb_req_len) || + (tz_args[i].b.size > tzcb_req_len - tz_args[i].b.offset) || + (user_req_buf_offset > user_req->buf_len) || + (tmp_arg.b.size > + user_req->buf_len - user_req_buf_offset)) { + ret = -EINVAL; + pr_err("%s: buffer overflow detected\n", __func__); + goto out; + } + tmp_arg.b.addr = user_req->buf_addr + user_req_buf_offset; + + if (copy_to_user(u64_to_user_ptr + (user_req->buf_addr + i * sizeof(tmp_arg)), + &tmp_arg, sizeof(tmp_arg)) || + copy_to_user(u64_to_user_ptr(tmp_arg.b.addr), + (uint8_t *)(tzcb_req) + tz_args[i].b.offset, + tz_args[i].b.size)) { + ret = -EFAULT; goto out; } - ret = copy_from_user(&req, (void __user *)arg, sizeof(req)); + user_req_buf_offset += tmp_arg.b.size; + } + FOR_ARGS(i, tzcb_req->hdr.counts, BO) { + user_req_buf_offset = size_align(user_req_buf_offset, + SMCINVOKE_ARGS_ALIGN_SIZE); + + tmp_arg.b.size = tz_args[i].b.size; + if ((user_req_buf_offset > user_req->buf_len) || + (tmp_arg.b.size > + user_req->buf_len - user_req_buf_offset)) { + ret = -EINVAL; + pr_err("%s: buffer overflow detected\n", __func__); + goto out; + } + tmp_arg.b.addr = user_req->buf_addr + user_req_buf_offset; + + if (copy_to_user(u64_to_user_ptr + (user_req->buf_addr + i * sizeof(tmp_arg)), + &tmp_arg, sizeof(tmp_arg))) { + ret = -EFAULT; + goto out; + } + user_req_buf_offset += tmp_arg.b.size; + } + FOR_ARGS(i, tzcb_req->hdr.counts, OI) { + /* + * create a new FD and assign to output object's + * context + */ + ret = get_uhandle_from_tzhandle(tz_args[i].handle, srvr_id, + &(tmp_arg.o.fd)); if (ret) { - ret = -EFAULT; + ret = -EINVAL; + goto out; + } + if (copy_to_user(u64_to_user_ptr + (user_req->buf_addr + i * sizeof(tmp_arg)), + &tmp_arg, sizeof(tmp_arg))) { + ret = -EFAULT; + goto out; + } + } +out: + return ret; +} + +static int marshal_out_tzcb_req(const struct smcinvoke_accept *user_req, + struct smcinvoke_cb_txn *cb_txn, + struct file **arr_filp) +{ + int ret = -EINVAL, i = 0; + int32_t tzhandles_to_release[OBJECT_COUNTS_MAX_OO] = {0}; + struct smcinvoke_tzcb_req *tzcb_req = cb_txn->cb_req; + union smcinvoke_tz_args *tz_args = tzcb_req->args; + + tzcb_req->result = user_req->result; + FOR_ARGS(i, tzcb_req->hdr.counts, BO) { + union smcinvoke_arg tmp_arg; + + if (copy_from_user((uint8_t *)&tmp_arg, u64_to_user_ptr( + user_req->buf_addr + i * sizeof(union smcinvoke_arg)), + sizeof(union smcinvoke_arg))) { + ret = -EFAULT; + goto out; + } + if (tmp_arg.b.size > tz_args[i].b.size) + goto out; + if (copy_from_user((uint8_t *)(tzcb_req) + tz_args[i].b.offset, + u64_to_user_ptr(tmp_arg.b.addr), + tmp_arg.b.size)) { + ret = -EFAULT; goto out; } + } - nr_args = object_counts_num_buffers(req.counts) + - object_counts_num_objects(req.counts); + FOR_ARGS(i, tzcb_req->hdr.counts, OO) { + union smcinvoke_arg tmp_arg; - if (req.argsize != sizeof(union smcinvoke_arg)) { - ret = -EINVAL; + if (copy_from_user((uint8_t *)&tmp_arg, u64_to_user_ptr( + user_req->buf_addr + i * sizeof(union smcinvoke_arg)), + sizeof(union smcinvoke_arg))) { + ret = -EFAULT; goto out; } + ret = get_tzhandle_from_uhandle(tmp_arg.o.fd, 0, &arr_filp[i], + &(tz_args[i].handle)); + if (ret) + goto out; + tzhandles_to_release[i] = tz_args[i].handle; + } + ret = 0; +out: + if (ret) + release_tzhandles(tzhandles_to_release, OBJECT_COUNTS_MAX_OO); + return ret; +} - if (nr_args) { +static void process_piggyback_data(void *buf, size_t buf_size) +{ + int i; + struct smcinvoke_tzcb_req req = {0}; + struct smcinvoke_piggyback_msg *msg = buf; + int32_t *objs = msg->objs; + + dmac_flush_range(buf, buf + buf_size); + if (msg->counts) + dmac_inv_range(buf, buf + buf_size); + + for (i = 0; i < msg->counts; i++) { + req.hdr.op = msg->op; + req.hdr.counts = 0; /* release op does not require any args */ + req.hdr.tzhandle = objs[i]; + process_tzcb_req(&req, sizeof(struct smcinvoke_tzcb_req), NULL); + /* cbobjs_in_flight will be adjusted during CB processing */ + } +} - args_buf = kzalloc(nr_args * req.argsize, GFP_KERNEL); - if (!args_buf) { - ret = -ENOMEM; - goto out; - } - ret = copy_from_user(args_buf, - (void __user *)(uintptr_t)(req.args), - nr_args * req.argsize); +static long process_ack_local_obj(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + int ret = -1; + int32_t local_obj = SMCINVOKE_USERSPACE_OBJ_NULL; + struct smcinvoke_file_data *filp_data = filp->private_data; + + if (_IOC_SIZE(cmd) != sizeof(int32_t)) + return -EINVAL; + + ret = copy_from_user(&local_obj, (void __user *)(uintptr_t)arg, + sizeof(int32_t)); + if (ret) + return -EFAULT; + + mutex_lock(&g_smcinvoke_lock); + if (UHANDLE_IS_CB_OBJ(local_obj)) + ret = put_pending_cbobj_locked(filp_data->server_id, + UHANDLE_GET_CB_OBJ(local_obj)); + mutex_unlock(&g_smcinvoke_lock); + + return ret; +} + +static long process_server_req(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + int ret = -1; + int64_t server_fd = -1; + struct smcinvoke_server server_req = {0}; + struct smcinvoke_server_info *server_info = NULL; + + if (_IOC_SIZE(cmd) != sizeof(server_req)) + return -EINVAL; + + ret = copy_from_user(&server_req, (void __user *)(uintptr_t)arg, + sizeof(server_req)); + if (ret) + return -EFAULT; + + server_info = kzalloc(sizeof(*server_info), GFP_KERNEL); + if (!server_info) + return -ENOMEM; + init_waitqueue_head(&server_info->req_wait_q); + init_waitqueue_head(&server_info->rsp_wait_q); + server_info->cb_buf_size = server_req.cb_buf_size; + hash_init(server_info->reqs_table); + hash_init(server_info->responses_table); + INIT_LIST_HEAD(&server_info->pending_cbobjs); + + mutex_lock(&g_smcinvoke_lock); + + server_info->server_id = next_cb_server_id_locked(); + hash_add(g_cb_servers, &server_info->hash, + server_info->server_id); + if (g_max_cb_buf_size < server_req.cb_buf_size) + g_max_cb_buf_size = server_req.cb_buf_size; + + mutex_unlock(&g_smcinvoke_lock); + ret = get_fd_for_obj(SMCINVOKE_OBJ_TYPE_SERVER, + server_info->server_id, &server_fd); + + if (ret) { + mutex_lock(&g_smcinvoke_lock); + hash_del(&server_info->hash); + mutex_unlock(&g_smcinvoke_lock); + kfree(server_info); + } + return server_fd; +} + +static long process_accept_req(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + int ret = -1; + struct smcinvoke_file_data *server_obj = filp->private_data; + struct smcinvoke_accept user_args = {0}; + struct smcinvoke_cb_txn *cb_txn = NULL; + struct smcinvoke_server_info *server_info = NULL; + + if (_IOC_SIZE(cmd) != sizeof(struct smcinvoke_accept)) + return -EINVAL; + + if (copy_from_user(&user_args, (void __user *)arg, + sizeof(struct smcinvoke_accept))) + return -EFAULT; + + if (user_args.argsize != sizeof(union smcinvoke_arg)) + return -EINVAL; + + /* ACCEPT is available only on server obj */ + if (server_obj->context_type != SMCINVOKE_OBJ_TYPE_SERVER) + return -EPERM; + + mutex_lock(&g_smcinvoke_lock); + server_info = find_cb_server_locked(server_obj->server_id); + mutex_unlock(&g_smcinvoke_lock); + if (!server_info) + return -EINVAL; + + /* First check if it has response otherwise wait for req */ + if (user_args.has_resp) { + mutex_lock(&g_smcinvoke_lock); + cb_txn = find_cbtxn_locked(server_info, user_args.txn_id, + SMCINVOKE_REQ_PROCESSING); + mutex_unlock(&g_smcinvoke_lock); + /* cb_txn can be null if userspace provides wrong txn id. */ + if (!cb_txn) { + pr_err("%s: Invalid txn received = %d\n", + __func__, user_args.txn_id); + goto out; + } + ret = marshal_out_tzcb_req(&user_args, cb_txn, + cb_txn->filp_to_release); + /* + * if client did not set error and we get error locally + * we return local error to TA + */ + if (ret && cb_txn->cb_req->result == 0) + cb_txn->cb_req->result = OBJECT_ERROR_UNAVAIL; + + if (OBJECT_OP_METHODID(user_args.op) == OBJECT_OP_RELEASE) + put_pending_cbobj_locked( + TZHANDLE_GET_SERVER(cb_txn->cb_req->hdr.tzhandle), + TZHANDLE_GET_OBJID(cb_txn->cb_req->hdr.tzhandle)); + + cb_txn->state = SMCINVOKE_REQ_PROCESSED; + wake_up(&server_info->rsp_wait_q); + /* + * if marshal_out fails, we should let userspace release + * any ref/obj it created for CB processing + */ + if (ret && OBJECT_COUNTS_NUM_OO(user_args.counts)) + goto out; + } + /* + * Once response has been delivered, thread will wait for another + * callback req to process. + */ + do { + ret = wait_event_interruptible(server_info->req_wait_q, + !hash_empty(server_info->reqs_table)); + if (ret) + goto out; + + mutex_lock(&g_smcinvoke_lock); + cb_txn = find_cbtxn_locked(server_info, + SMCINVOKE_NEXT_AVAILABLE_TXN, + SMCINVOKE_REQ_PLACED); + mutex_unlock(&g_smcinvoke_lock); + if (cb_txn) { + cb_txn->state = SMCINVOKE_REQ_PROCESSING; + ret = marshal_in_tzcb_req(cb_txn, &user_args, + server_obj->server_id); if (ret) { - ret = -EFAULT; - goto out; + cb_txn->cb_req->result = OBJECT_ERROR_UNAVAIL; + cb_txn->state = SMCINVOKE_REQ_PROCESSED; + wake_up_interruptible(&server_info->rsp_wait_q); + continue; } + mutex_lock(&g_smcinvoke_lock); + hash_add(server_info->responses_table, &cb_txn->hash, + cb_txn->txn_id); + mutex_unlock(&g_smcinvoke_lock); + ret = copy_to_user((void __user *)arg, &user_args, + sizeof(struct smcinvoke_accept)); } + } while (!cb_txn); +out: + return ret; +} - inmsg_size = compute_in_msg_size(&req, args_buf); - in_msg = (void *)__get_free_pages(GFP_KERNEL, - get_order(inmsg_size)); - if (!in_msg) { +static long process_invoke_req(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + int ret = -1, nr_args = 0; + struct smcinvoke_cmd_req req = {0}; + void *in_msg = NULL, *out_msg = NULL; + size_t inmsg_size = 0, outmsg_size = SMCINVOKE_TZ_MIN_BUF_SIZE; + union smcinvoke_arg *args_buf = NULL; + struct smcinvoke_file_data *tzobj = filp->private_data; + /* + * Hold reference to remote object until invoke op is not + * completed. Release once invoke is done. + */ + struct file *filp_to_release[OBJECT_COUNTS_MAX_OO] = {NULL}; + /* + * If anything goes wrong, release alloted tzhandles for + * local objs which could be either CBObj or MemObj. + */ + int32_t tzhandles_to_release[OBJECT_COUNTS_MAX_OO] = {0}; + bool tz_acked = false; + + if (_IOC_SIZE(cmd) != sizeof(req)) { + ret = -EINVAL; + goto out; + } + if (tzobj->context_type != SMCINVOKE_OBJ_TYPE_TZ_OBJ) { + ret = -EPERM; + goto out; + } + ret = copy_from_user(&req, (void __user *)arg, sizeof(req)); + if (ret) { + ret = -EFAULT; + goto out; + } + + nr_args = OBJECT_COUNTS_NUM_buffers(req.counts) + + OBJECT_COUNTS_NUM_objects(req.counts); + + if (req.argsize != sizeof(union smcinvoke_arg)) { + ret = -EINVAL; + goto out; + } + + if (nr_args) { + args_buf = kcalloc(nr_args, req.argsize, GFP_KERNEL); + if (!args_buf) { ret = -ENOMEM; goto out; } - out_msg = (void *)__get_free_page(GFP_KERNEL); - if (!out_msg) { - ret = -ENOMEM; + ret = copy_from_user(args_buf, u64_to_user_ptr(req.args), + nr_args * req.argsize); + + if (ret) { + ret = -EFAULT; goto out; } + } - ret = marshal_in(&req, args_buf, tzobj->tzhandle, in_msg, - inmsg_size, filp_to_release); - if (ret) - goto out; + inmsg_size = compute_in_msg_size(&req, args_buf); + in_msg = (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP, + get_order(inmsg_size)); + if (!in_msg) { + ret = -ENOMEM; + goto out; + } + memset(in_msg, 0, inmsg_size); + + mutex_lock(&g_smcinvoke_lock); + outmsg_size = PAGE_ALIGN(g_max_cb_buf_size); + mutex_unlock(&g_smcinvoke_lock); + out_msg = (void *)__get_free_pages(GFP_KERNEL | __GFP_COMP, + get_order(outmsg_size)); + if (!out_msg) { + ret = -ENOMEM; + goto out; + } + memset(out_msg, 0, outmsg_size); - ret = prepare_send_scm_msg(in_msg, inmsg_size, out_msg, - SMCINVOKE_TZ_MIN_BUF_SIZE, &req.result); - if (ret) - goto out; + ret = marshal_in_invoke_req(&req, args_buf, tzobj->tzhandle, in_msg, + inmsg_size, filp_to_release, tzhandles_to_release); + if (ret) + goto out; + + ret = prepare_send_scm_msg(in_msg, inmsg_size, out_msg, outmsg_size, + &req, args_buf, &tz_acked); + /* + * If scm_call is success, TZ owns responsibility to release + * refs for local objs. + */ + if (tz_acked == false) + goto out; + memset(tzhandles_to_release, 0, sizeof(tzhandles_to_release)); + + /* + * if invoke op results in an err, no need to marshal_out and + * copy args buf to user space + */ + if (!req.result) { /* - * if invoke op results in an err, no need to marshal_out and - * copy args buf to user space + * Dont check ret of marshal_out because there might be a + * FD for OO which userspace must release even if an error + * occurs. Releasing FD from user space is much simpler than + * doing here. ORing of ret is reqd not to miss past error */ - if (!req.result) { - ret = marshal_out(in_msg, inmsg_size, &req, args_buf); + ret |= copy_to_user(u64_to_user_ptr(req.args), args_buf, + nr_args * req.argsize); + } + /* copy result of invoke op */ + ret |= copy_to_user((void __user *)arg, &req, sizeof(req)); + if (ret) + goto out; - ret |= copy_to_user( - (void __user *)(uintptr_t)(req.args), - args_buf, nr_args * req.argsize); - } - ret |= copy_to_user((void __user *)arg, &req, sizeof(req)); - if (ret) - goto out; + /* Outbuf could be carrying local objs to be released. */ + process_piggyback_data(out_msg, outmsg_size); +out: + release_filp(filp_to_release, OBJECT_COUNTS_MAX_OO); + if (ret) + release_tzhandles(tzhandles_to_release, OBJECT_COUNTS_MAX_OO); + free_pages((long)out_msg, get_order(outmsg_size)); + free_pages((long)in_msg, get_order(inmsg_size)); + kfree(args_buf); + return ret; +} + +static long smcinvoke_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + long ret = 0; + switch (cmd) { + case SMCINVOKE_IOCTL_INVOKE_REQ: + ret = process_invoke_req(filp, cmd, arg); + break; + case SMCINVOKE_IOCTL_ACCEPT_REQ: + ret = process_accept_req(filp, cmd, arg); + break; + case SMCINVOKE_IOCTL_SERVER_REQ: + ret = process_server_req(filp, cmd, arg); + break; + case SMCINVOKE_IOCTL_ACK_LOCAL_OBJ: + ret = process_ack_local_obj(filp, cmd, arg); break; default: ret = -ENOIOCTLCMD; break; } -out: - free_page((long)out_msg); - free_pages((long)in_msg, get_order(inmsg_size)); - kfree(args_buf); - for (i = 0; i < object_counts_max_OO; i++) { - if (filp_to_release[i]) - fput(filp_to_release[i]); - } - return ret; } static int smcinvoke_open(struct inode *nodp, struct file *filp) { - struct smcinvoke_tzobj_context *tzcxt = NULL; + struct smcinvoke_file_data *tzcxt = NULL; tzcxt = kzalloc(sizeof(*tzcxt), GFP_KERNEL); if (!tzcxt) return -ENOMEM; tzcxt->tzhandle = SMCINVOKE_TZ_ROOT_OBJ; + tzcxt->context_type = SMCINVOKE_OBJ_TYPE_TZ_OBJ; filp->private_data = tzcxt; return 0; } +static int destroy_cb_server(uint16_t server_id) +{ + struct smcinvoke_server_info *server = NULL; + + mutex_lock(&g_smcinvoke_lock); + server = find_cb_server_locked(server_id); + if (server) { + if (!list_empty(&server->pending_cbobjs)) { + server->state = SMCINVOKE_SERVER_STATE_DEFUNCT; + wake_up_interruptible(&server->rsp_wait_q); + /* + * we dont worry about threads waiting on req_wait_q + * because server can't be closed as long as there is + * atleast one accept thread active + */ + } else { + hash_del(&server->hash); + kfree(server); + } + } + mutex_unlock(&g_smcinvoke_lock); + return 0; +} + static int smcinvoke_release(struct inode *nodp, struct file *filp) { - int ret = 0, smcinvoke_result = 0; + int ret = 0; + bool release_handles; uint8_t *in_buf = NULL; uint8_t *out_buf = NULL; struct smcinvoke_msg_hdr hdr = {0}; - struct smcinvoke_tzobj_context *tzobj = filp->private_data; - uint32_t tzhandle = tzobj->tzhandle; + struct smcinvoke_file_data *file_data = filp->private_data; + struct smcinvoke_cmd_req req = {0}; + uint32_t tzhandle = 0; + if (file_data->context_type == SMCINVOKE_OBJ_TYPE_SERVER) { + ret = destroy_cb_server(file_data->server_id); + goto out; + } + + tzhandle = file_data->tzhandle; /* Root object is special in sense it is indestructible */ if (!tzhandle || tzhandle == SMCINVOKE_TZ_ROOT_OBJ) goto out; - in_buf = (uint8_t *)__get_free_page(GFP_KERNEL); - out_buf = (uint8_t *)__get_free_page(GFP_KERNEL); - if (!in_buf || !out_buf) + in_buf = (uint8_t *)__get_free_page(GFP_KERNEL | __GFP_COMP); + out_buf = (uint8_t *)__get_free_page(GFP_KERNEL | __GFP_COMP); + if (!in_buf || !out_buf) { + ret = -ENOMEM; goto out; + } hdr.tzhandle = tzhandle; - hdr.op = object_op_RELEASE; + hdr.op = OBJECT_OP_RELEASE; hdr.counts = 0; *(struct smcinvoke_msg_hdr *)in_buf = hdr; - ret = prepare_send_scm_msg(in_buf, SMCINVOKE_TZ_MIN_BUF_SIZE, - out_buf, SMCINVOKE_TZ_MIN_BUF_SIZE, &smcinvoke_result); + ret = prepare_send_scm_msg(in_buf, SMCINVOKE_TZ_MIN_BUF_SIZE, out_buf, + SMCINVOKE_TZ_MIN_BUF_SIZE, &req, NULL, &release_handles); out: kfree(filp->private_data); free_page((long)in_buf); @@ -512,7 +1700,7 @@ static int smcinvoke_release(struct inode *nodp, struct file *filp) return ret; } -static int __init smcinvoke_init(void) +static int smcinvoke_probe(struct platform_device *pdev) { unsigned int baseminor = 0; unsigned int count = 1; @@ -538,7 +1726,7 @@ static int __init smcinvoke_init(void) goto exit_destroy_class; } - cdev_init(&smcinvoke_cdev, &smcinvoke_fops); + cdev_init(&smcinvoke_cdev, &g_smcinvoke_fops); smcinvoke_cdev.owner = THIS_MODULE; rc = cdev_add(&smcinvoke_cdev, MKDEV(MAJOR(smcinvoke_device_no), 0), @@ -547,6 +1735,8 @@ static int __init smcinvoke_init(void) pr_err("cdev_add failed %d for %s\n", rc, SMCINVOKE_DEV); goto exit_destroy_device; } + smcinvoke_pdev = pdev; + return 0; exit_destroy_device: @@ -555,11 +1745,10 @@ static int __init smcinvoke_init(void) class_destroy(driver_class); exit_unreg_chrdev_region: unregister_chrdev_region(smcinvoke_device_no, count); - return rc; } -static void __exit smcinvoke_exit(void) +static int smcinvoke_remove(struct platform_device *pdev) { int count = 1; @@ -567,8 +1756,37 @@ static void __exit smcinvoke_exit(void) device_destroy(driver_class, smcinvoke_device_no); class_destroy(driver_class); unregister_chrdev_region(smcinvoke_device_no, count); + return 0; } -device_initcall(smcinvoke_init); + +static const struct of_device_id smcinvoke_match[] = { + { + .compatible = "qcom,smcinvoke", + }, + {}, +}; + +static struct platform_driver smcinvoke_plat_driver = { + .probe = smcinvoke_probe, + .remove = smcinvoke_remove, + .driver = { + .name = "smcinvoke", + .owner = THIS_MODULE, + .of_match_table = smcinvoke_match, + }, +}; + +static int smcinvoke_init(void) +{ + return platform_driver_register(&smcinvoke_plat_driver); +} + +static void smcinvoke_exit(void) +{ + platform_driver_unregister(&smcinvoke_plat_driver); +} + +module_init(smcinvoke_init); module_exit(smcinvoke_exit); MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/qcom/smcinvoke_object.h b/drivers/soc/qcom/smcinvoke_object.h index 2761f87e14f5..792a96bb686f 100644 --- a/drivers/soc/qcom/smcinvoke_object.h +++ b/drivers/soc/qcom/smcinvoke_object.h @@ -14,38 +14,76 @@ #include -#define object_op_METHOD_MASK ((uint32_t)0x0000FFFFu) -#define object_op_RELEASE (object_op_METHOD_MASK - 0) -#define object_op_RETAIN (object_op_METHOD_MASK - 1) +/* + * Method bits are not modified by transport layers. These describe the + * method (member function) being requested by the client. + */ +#define OBJECT_OP_METHOD_MASK (0x0000FFFFu) +#define OBJECT_OP_METHODID(op) ((op) & OBJECT_OP_METHOD_MASK) +#define OBJECT_OP_RELEASE (OBJECT_OP_METHOD_MASK - 0) +#define OBJECT_OP_RETAIN (OBJECT_OP_METHOD_MASK - 1) +#define OBJECT_OP_MAP_REGION 0 -#define object_counts_max_BI 0xF -#define object_counts_max_BO 0xF -#define object_counts_max_OI 0xF -#define object_counts_max_OO 0xF +#define OBJECT_COUNTS_MAX_BI 0xF +#define OBJECT_COUNTS_MAX_BO 0xF +#define OBJECT_COUNTS_MAX_OI 0xF +#define OBJECT_COUNTS_MAX_OO 0xF /* unpack counts */ -#define object_counts_num_BI(k) ((size_t) (((k) >> 0) & object_counts_max_BI)) -#define object_counts_num_BO(k) ((size_t) (((k) >> 4) & object_counts_max_BO)) -#define object_counts_num_OI(k) ((size_t) (((k) >> 8) & object_counts_max_OI)) -#define object_counts_num_OO(k) ((size_t) (((k) >> 12) & object_counts_max_OO)) -#define object_counts_num_buffers(k) \ - (object_counts_num_BI(k) + object_counts_num_BO(k)) +#define OBJECT_COUNTS_NUM_BI(k) ((size_t) (((k) >> 0) & OBJECT_COUNTS_MAX_BI)) +#define OBJECT_COUNTS_NUM_BO(k) ((size_t) (((k) >> 4) & OBJECT_COUNTS_MAX_BO)) +#define OBJECT_COUNTS_NUM_OI(k) ((size_t) (((k) >> 8) & OBJECT_COUNTS_MAX_OI)) +#define OBJECT_COUNTS_NUM_OO(k) ((size_t) (((k) >> 12) & OBJECT_COUNTS_MAX_OO)) +#define OBJECT_COUNTS_NUM_buffers(k) \ + (OBJECT_COUNTS_NUM_BI(k) + OBJECT_COUNTS_NUM_BO(k)) -#define object_counts_num_objects(k) \ - (object_counts_num_OI(k) + object_counts_num_OO(k)) +#define OBJECT_COUNTS_NUM_objects(k) \ + (OBJECT_COUNTS_NUM_OI(k) + OBJECT_COUNTS_NUM_OO(k)) /* Indices into args[] */ -#define object_counts_index_BI(k) 0 -#define object_counts_index_BO(k) \ - (object_counts_index_BI(k) + object_counts_num_BI(k)) -#define object_counts_index_OI(k) \ - (object_counts_index_BO(k) + object_counts_num_BO(k)) -#define object_counts_index_OO(k) \ - (object_counts_index_OI(k) + object_counts_num_OI(k)) -#define object_counts_total(k) \ - (object_counts_index_OO(k) + object_counts_num_OO(k)) +#define OBJECT_COUNTS_INDEX_BI(k) 0 +#define OBJECT_COUNTS_INDEX_BO(k) \ + (OBJECT_COUNTS_INDEX_BI(k) + OBJECT_COUNTS_NUM_BI(k)) +#define OBJECT_COUNTS_INDEX_OI(k) \ + (OBJECT_COUNTS_INDEX_BO(k) + OBJECT_COUNTS_NUM_BO(k)) +#define OBJECT_COUNTS_INDEX_OO(k) \ + (OBJECT_COUNTS_INDEX_OI(k) + OBJECT_COUNTS_NUM_OI(k)) +#define OBJECT_COUNTS_TOTAL(k) \ + (OBJECT_COUNTS_INDEX_OO(k) + OBJECT_COUNTS_NUM_OO(k)) + +#define OBJECT_COUNTS_PACK(in_bufs, out_bufs, in_objs, out_objs) \ + ((uint32_t) ((in_bufs) | ((out_bufs) << 4) | \ + ((in_objs) << 8) | ((out_objs) << 12))) + + +/* Object_invoke return codes */ + +#define OBJECT_isOK(err) ((err) == 0) +#define OBJECT_isERROR(err) ((err) != 0) + +/* Generic error codes */ + +#define OBJECT_OK 0 /* non-specific success code */ +#define OBJECT_ERROR 1 /* non-specific error */ +#define OBJECT_ERROR_INVALID 2 /* unsupported/unrecognized request */ +#define OBJECT_ERROR_SIZE_IN 3 /* supplied buffer/string too large */ +#define OBJECT_ERROR_SIZE_OUT 4 /* supplied output buffer too small */ + +#define OBJECT_ERROR_USERBASE 10 /* start of user-defined error range */ + +/* Transport layer error codes */ +#define OBJECT_ERROR_DEFUNCT -90 /* object no longer exists */ +#define OBJECT_ERROR_ABORT -91 /* calling thread must exit */ +#define OBJECT_ERROR_BADOBJ -92 /* invalid object context */ +#define OBJECT_ERROR_NOSLOTS -93 /* caller's object table full */ +#define OBJECT_ERROR_MAXARGS -94 /* too many args */ +#define OBJECT_ERROR_MAXDATA -95 /* buffers too large */ +#define OBJECT_ERROR_UNAVAIL -96 /* the request could not be processed */ +#define OBJECT_ERROR_KMEM -97 /* kernel out of memory */ +#define OBJECT_ERROR_REMOTE -98 /* local method sent to remote object */ +#define OBJECT_ERROR_BUSY -99 /* Object is busy */ #endif /* __SMCINVOKE_OBJECT_H */ diff --git a/include/uapi/linux/smcinvoke.h b/include/uapi/linux/smcinvoke.h index 1dc9a63c15e5..adb8968c5323 100644 --- a/include/uapi/linux/smcinvoke.h +++ b/include/uapi/linux/smcinvoke.h @@ -7,18 +7,19 @@ #define SMCINVOKE_USERSPACE_OBJ_NULL -1 struct smcinvoke_buf { - uint64_t addr; - uint64_t size; + uint64_t addr; + uint64_t size; }; struct smcinvoke_obj { - int64_t fd; - int64_t reserved; + int64_t fd; + int32_t cb_server_fd; + int32_t reserved; }; union smcinvoke_arg { - struct smcinvoke_buf b; - struct smcinvoke_obj o; + struct smcinvoke_buf b; + struct smcinvoke_obj o; }; /* @@ -30,11 +31,47 @@ union smcinvoke_arg { * @args - args is pointer to buffer having all arguments */ struct smcinvoke_cmd_req { - uint32_t op; - uint32_t counts; - int32_t result; - uint32_t argsize; - uint64_t __user args; + uint32_t op; + uint32_t counts; + int32_t result; + uint32_t argsize; + uint64_t args; +}; + +/* + * struct smcinvoke_accept: structure to process CB req from TEE + * @has_resp: IN: Whether IOCTL is carrying response data + * @txn_id: OUT: An id that should be passed as it is for response + * @result: IN: Outcome of operation op + * @cbobj_id: OUT: Callback object which is target of operation op + * @op: OUT: Operation to be performed on target object + * @counts: OUT: Number of arguments, embedded in buffer pointed by + * buf_addr, to complete operation + * @reserved: IN/OUT: Usage is not defined but should be set to 0. + * @argsize: IN: Size of any argument, all of equal size, embedded + * in buffer pointed by buf_addr + * @buf_len: IN: Len of buffer pointed by buf_addr + * @buf_addr: IN: Buffer containing all arguments which are needed + * to complete operation op + */ +struct smcinvoke_accept { + uint32_t has_resp; + uint32_t txn_id; + int32_t result; + int32_t cbobj_id; + uint32_t op; + uint32_t counts; + int32_t reserved; + uint32_t argsize; + uint64_t buf_len; + uint64_t buf_addr; +}; + +/* + * @cb_buf_size: IN: Max buffer size for any callback obj implemented by client + */ +struct smcinvoke_server { + uint32_t cb_buf_size; }; #define SMCINVOKE_IOC_MAGIC 0x98 @@ -42,4 +79,13 @@ struct smcinvoke_cmd_req { #define SMCINVOKE_IOCTL_INVOKE_REQ \ _IOWR(SMCINVOKE_IOC_MAGIC, 1, struct smcinvoke_cmd_req) +#define SMCINVOKE_IOCTL_ACCEPT_REQ \ + _IOWR(SMCINVOKE_IOC_MAGIC, 2, struct smcinvoke_accept) + +#define SMCINVOKE_IOCTL_SERVER_REQ \ + _IOWR(SMCINVOKE_IOC_MAGIC, 3, struct smcinvoke_server) + +#define SMCINVOKE_IOCTL_ACK_LOCAL_OBJ \ + _IOWR(SMCINVOKE_IOC_MAGIC, 4, int32_t) + #endif /* _UAPI_SMCINVOKE_H_ */ -- GitLab From 18c5591ca9ac55ca1f614a94b2f625a4193bcf87 Mon Sep 17 00:00:00 2001 From: Dinesh K Garg Date: Fri, 15 Jun 2018 14:19:03 -0700 Subject: [PATCH 1009/1299] ARM: dts: msm: Add smcinvoke node for SM8150 Current SMCInvoke based framework supports communication between TZ and HLOS where objects are owned by TZ i.e. services are provided by TZ. However, if TZ needs a service from Linux, it has to invoke operation on an object owned by Linux. Such objects are called local objects which could be either callabck objects or memory objects. Callback objects provide services such as operations on a file. Memory objects provide large memory sharing facility between TZ and Linux. Adding smcinvoke node to support local objects. Change-Id: I0a9905ad84828a1707401c122bc3076b913dafdc Signed-off-by: Dinesh K Garg --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index afc1a293c19d..b032e56f840b 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -2840,6 +2840,12 @@ qcom,qsee-reentrancy-support = <2>; }; + qcom_smcinvoke: smcinvoke@87900000 { + compatible = "qcom,smcinvoke"; + reg = <0x87900000 0x2200000>; + reg-names = "secapp-region"; + }; + qcom_rng: qrng@793000 { compatible = "qcom,msm-rng"; reg = <0x793000 0x1000>; -- GitLab From ed291cfa36306fe62c5359a052f26dc6ba802f6d Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Mon, 2 Jul 2018 11:40:41 -0700 Subject: [PATCH 1010/1299] ARM: dts: msm: Modify video node values for SM8150 v2 Video node values on SM8150 V2 are different when compared to SM8150 V1, so modify them accordingly. Change-Id: Iedf259772d05a0f72d55c7b34553c18bfebcd331 Signed-off-by: Maheshwar Ajja --- arch/arm64/boot/dts/qcom/sm8150-v2.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi index cbe3b4b67955..f36921fb2ade 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi @@ -42,3 +42,21 @@ compatible = "qcom,npucc-sm8150-v2", "syscon"; }; #include "msm-arm-smmu-sm8150-v2.dtsi" + +&msm_vidc { + qcom,allowed-clock-rates = <240000000 338000000 + 365000000 444000000 533000000>; + + non_secure_cb { + iommus = <&apps_smmu 0x2300 0x60>; + }; + secure_bitstream_cb { + iommus = <&apps_smmu 0x2301 0x4>; + }; + secure_pixel_cb { + iommus = <&apps_smmu 0x2303 0x20>; + }; + secure_non_pixel_cb { + iommus = <&apps_smmu 0x2304 0x60>; + }; +}; -- GitLab From 6dfb61274b3bc37841ce30a182e91b7fb56cafb4 Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Tue, 19 Dec 2017 18:18:26 -0800 Subject: [PATCH 1011/1299] msm: vidc: Consider operating rate in load calculations Include operating rate in fps (frames per second) which will be used to derive load and bandwidth calculations to resolve HFR (high frame rate) usecases. Change-Id: I1e4b15dc2e73ef88c7ba76a9c28483d1f52dd388 Signed-off-by: Maheshwar Ajja --- .../media/platform/msm/vidc/msm_vidc_clocks.c | 34 +++++++++++++------ .../media/platform/msm/vidc/msm_vidc_common.c | 15 +++----- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c index 5fd419c3b14f..39921c98329e 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c @@ -100,6 +100,19 @@ int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst) return NUM_MBS_PER_FRAME(height, width); } +static int msm_vidc_get_fps(struct msm_vidc_inst *inst) +{ + int fps; + + if ((inst->clk_data.operating_rate >> 16) > inst->prop.fps) + fps = (inst->clk_data.operating_rate >> 16) ? + (inst->clk_data.operating_rate >> 16) : 1; + else + fps = inst->prop.fps; + + return fps; +} + void update_recon_stats(struct msm_vidc_inst *inst, struct recon_stats_type *recon_stats) { @@ -284,12 +297,7 @@ int msm_comm_vote_bus(struct msm_vidc_core *core) msm_comm_g_ctrl_for_id(inst, V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES) != 0; - if (inst->clk_data.operating_rate) - vote_data[i].fps = - (inst->clk_data.operating_rate >> 16) ? - inst->clk_data.operating_rate >> 16 : 1; - else - vote_data[i].fps = inst->prop.fps; + vote_data[i].fps = msm_vidc_get_fps(inst); vote_data[i].power_mode = 0; if (msm_vidc_clock_voting || is_turbo || @@ -609,7 +617,7 @@ static unsigned long msm_vidc_calc_freq_ar50(struct msm_vidc_inst *inst, struct msm_vidc_core *core = NULL; int i = 0; struct allowed_clock_rates_table *allowed_clks_tbl = NULL; - u64 rate = 0; + u64 rate = 0, fps; struct clock_data *dcvs = NULL; core = inst->core; @@ -618,6 +626,8 @@ static unsigned long msm_vidc_calc_freq_ar50(struct msm_vidc_inst *inst, mbs_per_second = msm_comm_get_inst_load_per_core(inst, LOAD_CALC_NO_QUIRKS); + fps = msm_vidc_get_fps(inst); + /* * Calculate vpp, vsp cycles separately for encoder and decoder. * Even though, most part is common now, in future it may change @@ -640,7 +650,7 @@ static unsigned long msm_vidc_calc_freq_ar50(struct msm_vidc_inst *inst, vsp_cycles = mbs_per_second * inst->clk_data.entry->vsp_cycles; /* 10 / 7 is overhead factor */ - vsp_cycles += ((inst->prop.fps * filled_len * 8) * 10) / 7; + vsp_cycles += ((fps * filled_len * 8) * 10) / 7; } else { dprintk(VIDC_ERR, "Unknown session type = %s\n", __func__); @@ -681,7 +691,7 @@ static unsigned long msm_vidc_calc_freq(struct msm_vidc_inst *inst, struct msm_vidc_core *core = NULL; int i = 0; struct allowed_clock_rates_table *allowed_clks_tbl = NULL; - u64 rate = 0; + u64 rate = 0, fps; struct clock_data *dcvs = NULL; u32 operating_rate, vsp_factor_num = 10, vsp_factor_den = 7; @@ -691,6 +701,8 @@ static unsigned long msm_vidc_calc_freq(struct msm_vidc_inst *inst, mbs_per_second = msm_comm_get_inst_load_per_core(inst, LOAD_CALC_NO_QUIRKS); + fps = msm_vidc_get_fps(inst); + /* * Calculate vpp, vsp cycles separately for encoder and decoder. * Even though, most part is common now, in future it may change @@ -726,7 +738,7 @@ static unsigned long msm_vidc_calc_freq(struct msm_vidc_inst *inst, vsp_cycles = mbs_per_second * inst->clk_data.entry->vsp_cycles; /* 10 / 7 is overhead factor */ - vsp_cycles += ((inst->prop.fps * filled_len * 8) * 10) / 7; + vsp_cycles += ((fps * filled_len * 8) * 10) / 7; } else { dprintk(VIDC_ERR, "Unknown session type = %s\n", __func__); @@ -1373,7 +1385,7 @@ static inline int msm_vidc_power_save_mode_enable(struct msm_vidc_inst *inst, } mbs_per_frame = msm_vidc_get_mbs_per_frame(inst); if (mbs_per_frame > inst->core->resources.max_hq_mbs_per_frame || - inst->prop.fps > inst->core->resources.max_hq_fps) { + msm_vidc_get_fps(inst) > inst->core->resources.max_hq_fps) { enable = true; } diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 40d97e9e83d7..7e5657cf6dcd 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -733,18 +733,13 @@ static int msm_comm_get_mbs_per_sec(struct msm_vidc_inst *inst) capture_port_mbs = NUM_MBS_PER_FRAME(inst->prop.width[CAPTURE_PORT], inst->prop.height[CAPTURE_PORT]); - if (inst->clk_data.operating_rate) { + if ((inst->clk_data.operating_rate >> 16) > inst->prop.fps) fps = (inst->clk_data.operating_rate >> 16) ? inst->clk_data.operating_rate >> 16 : 1; - /* - * Check if operating rate is less than fps. - * If Yes, then use fps to scale clocks - */ - fps = fps > inst->prop.fps ? fps : inst->prop.fps; - return max(output_port_mbs, capture_port_mbs) * fps; - } else { - return max(output_port_mbs, capture_port_mbs) * inst->prop.fps; - } + else + fps = inst->prop.fps; + + return max(output_port_mbs, capture_port_mbs) * fps; } int msm_comm_get_inst_load(struct msm_vidc_inst *inst, -- GitLab From 2baec42a834c229fe8e24d64d9e1afb172ccafb5 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Mon, 2 Jul 2018 16:25:41 -0700 Subject: [PATCH 1012/1299] msm: ipa: EOT based on packet threshold Request GSI HW for EOT based on packet threshold in addition to time threshold which is currently in use. This change allows scaling uplink data rates. Change-Id: Ia7fe53f5944b1aee4ab58904289f391b7f4559db Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa_dp.c | 19 +++++++++++++------ drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index b8703ff4dfb0..f27efa4379b0 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -79,6 +79,8 @@ #define IPA_SEND_MAX_DESC (20) +#define IPA_EOT_THRESH 32 + static struct sk_buff *ipa3_get_skb_ipa_rx(unsigned int len, gfp_t flags); static void ipa3_replenish_wlan_rx_cache(struct ipa3_sys_context *sys); static void ipa3_replenish_rx_cache(struct ipa3_sys_context *sys); @@ -236,18 +238,19 @@ static void ipa3_send_nop_desc(struct work_struct *work) } list_add_tail(&tx_pkt->link, &sys->head_desc_list); sys->nop_pending = false; - spin_unlock_bh(&sys->spinlock); memset(&nop_xfer, 0, sizeof(nop_xfer)); nop_xfer.type = GSI_XFER_ELEM_NOP; nop_xfer.flags = GSI_XFER_FLAG_EOT; nop_xfer.xfer_user_data = tx_pkt; if (gsi_queue_xfer(sys->ep->gsi_chan_hdl, 1, &nop_xfer, true)) { + spin_unlock_bh(&sys->spinlock); IPAERR("gsi_queue_xfer for ch:%lu failed\n", sys->ep->gsi_chan_hdl); queue_work(sys->wq, &sys->work); return; } + spin_unlock_bh(&sys->spinlock); /* make sure TAG process is sent before clocks are gated */ ipa3_ctx->tag_process_before_gating = true; @@ -406,11 +409,14 @@ int ipa3_send(struct ipa3_sys_context *sys, } if (i == (num_desc - 1)) { - if (!sys->use_comm_evt_ring) { + if (!sys->use_comm_evt_ring || + (sys->pkt_sent % IPA_EOT_THRESH == 0)) { gsi_xfer[i].flags |= GSI_XFER_FLAG_EOT; gsi_xfer[i].flags |= GSI_XFER_FLAG_BEI; + } else { + send_nop = true; } gsi_xfer[i].xfer_user_data = tx_pkt_first; @@ -429,11 +435,12 @@ int ipa3_send(struct ipa3_sys_context *sys, goto failure; } - - if (sys->use_comm_evt_ring && !sys->nop_pending) { + if (send_nop && !sys->nop_pending) sys->nop_pending = true; - send_nop = true; - } + else + send_nop = false; + + sys->pkt_sent++; spin_unlock_bh(&sys->spinlock); /* set the timer for sending the NOP descriptor */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index dc312e715b1f..e0fa028257da 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -693,6 +693,7 @@ struct ipa3_sys_context { struct work_struct repl_work; void (*repl_hdlr)(struct ipa3_sys_context *sys); struct ipa3_repl_ctx repl; + u32 pkt_sent; /* ordering is important - mutable fields go above */ struct ipa3_ep_context *ep; -- GitLab From 7ab238c1c78763c3a57d295528e680f08ba039d1 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Mon, 2 Jul 2018 16:20:53 -0700 Subject: [PATCH 1013/1299] msm: ipa: add module params for outstanding on wan Add module params to configure outstanding packet thresholds to rmnet_ipa. This allows tuning of these parameters on the fly. Change-Id: I023b546e4e47602884ec35ca596499621f80d86a Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 37 ++++++++++++--------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index 118ce429e827..bbdbfdb5104e 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -40,6 +40,22 @@ #include "ipa_trace.h" +#define OUTSTANDING_HIGH_DEFAULT 256 +#define OUTSTANDING_HIGH_CTL_DEFAULT (OUTSTANDING_HIGH_DEFAULT + 32) +#define OUTSTANDING_LOW_DEFAULT 128 + +static unsigned int outstanding_high = OUTSTANDING_HIGH_DEFAULT; +module_param(outstanding_high, uint, 0644); +MODULE_PARM_DESC(outstanding_high, "Outstanding high"); + +static unsigned int outstanding_high_ctl = OUTSTANDING_HIGH_CTL_DEFAULT; +module_param(outstanding_high_ctl, uint, 0644); +MODULE_PARM_DESC(outstanding_high_ctl, "Outstanding high control"); + +static unsigned int outstanding_low = OUTSTANDING_LOW_DEFAULT; +module_param(outstanding_low, uint, 0644); +MODULE_PARM_DESC(outstanding_low, "Outstanding low"); + #define WWAN_METADATA_SHFT 24 #define WWAN_METADATA_MASK 0xFF000000 #define WWAN_DATA_LEN 2000 @@ -48,9 +64,6 @@ #define TAILROOM 0 /* for padding by mux layer */ #define MAX_NUM_OF_MUX_CHANNEL 15 /* max mux channels */ #define UL_FILTER_RULE_HANDLE_START 69 -#define DEFAULT_OUTSTANDING_HIGH 128 -#define DEFAULT_OUTSTANDING_HIGH_CTL (DEFAULT_OUTSTANDING_HIGH+32) -#define DEFAULT_OUTSTANDING_LOW 64 #define IPA_WWAN_DEV_NAME "rmnet_ipa%d" #define IPA_UPSTEAM_WLAN_IFACE_NAME "wlan0" @@ -102,8 +115,6 @@ struct ipa3_rmnet_plat_drv_res { * @net: network interface struct implemented by this driver * @stats: iface statistics * @outstanding_pkts: number of packets sent to IPA without TX complete ACKed - * @outstanding_high: number of outstanding packets allowed - * @outstanding_low: number of outstanding packets which shall cause * @ch_id: channel id * @lock: spinlock for mutual exclusion * @device_status: holds device status @@ -114,9 +125,6 @@ struct ipa3_wwan_private { struct net_device *net; struct net_device_stats stats; atomic_t outstanding_pkts; - int outstanding_high_ctl; - int outstanding_high; - int outstanding_low; uint32_t ch_id; spinlock_t lock; struct completion resource_granted_completion; @@ -1085,7 +1093,7 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev) if (netif_queue_stopped(dev)) { if (qmap_check && atomic_read(&wwan_ptr->outstanding_pkts) < - wwan_ptr->outstanding_high_ctl) { + outstanding_high_ctl) { pr_err("[%s]Queue stop, send ctrl pkts\n", dev->name); goto send; } else { @@ -1096,11 +1104,11 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev) /* checking High WM hit */ if (atomic_read(&wwan_ptr->outstanding_pkts) >= - wwan_ptr->outstanding_high) { + outstanding_high) { if (!qmap_check) { IPAWANDBG_LOW("pending(%d)/(%d)- stop(%d)\n", atomic_read(&wwan_ptr->outstanding_pkts), - wwan_ptr->outstanding_high, + outstanding_high, netif_queue_stopped(dev)); IPAWANDBG_LOW("qmap_chk(%d)\n", qmap_check); netif_stop_queue(dev); @@ -1203,10 +1211,9 @@ static void apps_ipa_tx_complete_notify(void *priv, __netif_tx_lock_bh(netdev_get_tx_queue(dev, 0)); if (!atomic_read(&rmnet_ipa3_ctx->is_ssr) && netif_queue_stopped(wwan_ptr->net) && - atomic_read(&wwan_ptr->outstanding_pkts) < - (wwan_ptr->outstanding_low)) { + atomic_read(&wwan_ptr->outstanding_pkts) < outstanding_low) { IPAWANDBG_LOW("Outstanding low (%d) - waking up queue\n", - wwan_ptr->outstanding_low); + outstanding_low); netif_wake_queue(wwan_ptr->net); } @@ -2375,8 +2382,6 @@ static int ipa3_wwan_probe(struct platform_device *pdev) sizeof(*(rmnet_ipa3_ctx->wwan_priv))); IPAWANDBG("wwan_ptr (private) = %pK", rmnet_ipa3_ctx->wwan_priv); rmnet_ipa3_ctx->wwan_priv->net = dev; - rmnet_ipa3_ctx->wwan_priv->outstanding_high = DEFAULT_OUTSTANDING_HIGH; - rmnet_ipa3_ctx->wwan_priv->outstanding_low = DEFAULT_OUTSTANDING_LOW; atomic_set(&rmnet_ipa3_ctx->wwan_priv->outstanding_pkts, 0); spin_lock_init(&rmnet_ipa3_ctx->wwan_priv->lock); init_completion( -- GitLab From 7501b9758d4e9850af9b0139e817bfd1e62778ba Mon Sep 17 00:00:00 2001 From: Shaoqing Liu Date: Thu, 21 Jun 2018 15:56:07 +0800 Subject: [PATCH 1014/1299] coresight: csr: delete the spinlock in csr_remove function Deleted the spinlock call since it caused kernel panic happened. In addition, add mutex lock protection when access list. Change-Id: I3148ccd329226afdd8d00443e4f095610ac16516 Signed-off-by: Shaoqing Liu --- drivers/hwtracing/coresight/coresight-csr.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-csr.c b/drivers/hwtracing/coresight/coresight-csr.c index e4101963b4ab..1637ad234110 100644 --- a/drivers/hwtracing/coresight/coresight-csr.c +++ b/drivers/hwtracing/coresight/coresight-csr.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "coresight-priv.h" @@ -88,6 +89,8 @@ struct csr_drvdata { }; static LIST_HEAD(csr_list); +static DEFINE_MUTEX(csr_lock); + #define to_csr_drvdata(c) container_of(c, struct csr_drvdata, csr) void msm_qdss_csr_enable_bam_to_usb(struct coresight_csr *csr) @@ -236,12 +239,15 @@ EXPORT_SYMBOL(coresight_csr_set_byte_cntr); struct coresight_csr *coresight_csr_get(const char *name) { struct coresight_csr *csr; - + mutex_lock(&csr_lock); list_for_each_entry(csr, &csr_list, link) { - if (!strcmp(csr->name, name)) + if (!strcmp(csr->name, name)) { + mutex_unlock(&csr_lock); return csr; + } } + mutex_unlock(&csr_lock); return ERR_PTR(-EINVAL); } EXPORT_SYMBOL(coresight_csr_get); @@ -391,7 +397,10 @@ static int csr_probe(struct platform_device *pdev) spin_lock_init(&drvdata->spin_lock); drvdata->csr.name = ((struct coresight_platform_data *) (pdev->dev.platform_data))->name; + + mutex_lock(&csr_lock); list_add_tail(&drvdata->csr.link, &csr_list); + mutex_unlock(&csr_lock); dev_info(dev, "CSR initialized: %s\n", drvdata->csr.name); return 0; @@ -399,12 +408,13 @@ static int csr_probe(struct platform_device *pdev) static int csr_remove(struct platform_device *pdev) { - unsigned long flags; struct csr_drvdata *drvdata = platform_get_drvdata(pdev); - spin_lock_irqsave(&drvdata->spin_lock, flags); + mutex_lock(&csr_lock); + list_del(&drvdata->csr.link); + mutex_unlock(&csr_lock); + coresight_unregister(drvdata->csdev); - spin_unlock_irqrestore(&drvdata->spin_lock, flags); return 0; } -- GitLab From 6bbcae55c9592b5d6bcd0b4626ffe68a1602a018 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Tue, 3 Jul 2018 10:00:54 +0530 Subject: [PATCH 1015/1299] ARM: dts: msm: Update PM-QoS values for sm8150 Different devices like usb, gpu, sde, sdhc and ufs uses different QoS values. Based on exit latencies on sm8150, these all values are blocking deeper LPMs and allows only WFI mode. For scenarios where one request is already active that allow only WFI mode LPM and new request is added that also allows only WFI mode but the value is different. For such cases QoS framework still notifies cpuidle to wake up CPU from idle to reselect new mode based on new aggregated QoS value. Update QoS values to same (WFI exit latency + 1) for all devices blocking same LPM mode to avoid such wake ups. Change-Id: Iae8aea829f308418df980130bdfb42a19ca8ea9d Signed-off-by: Maulik Shah --- arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi | 2 +- arch/arm64/boot/dts/qcom/sm8150-sde.dtsi | 2 +- arch/arm64/boot/dts/qcom/sm8150.dtsi | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi b/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi index ab10631ce6bf..7d74d28e9f10 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi @@ -93,7 +93,7 @@ qcom,tsens-name = "tsens_tz_sensor12"; #cooling-cells = <2>; - qcom,pm-qos-active-latency = <460>; + qcom,pm-qos-active-latency = <44>; clocks = <&clock_gpucc GPU_CC_CXO_CLK>, <&clock_gcc GCC_DDRSS_GPU_AXI_CLK>, diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi index 295fb680c8ef..8626a0517ef1 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi @@ -196,7 +196,7 @@ qcom,sde-cdp-setting = <1 1>, <1 0>; qcom,sde-qos-cpu-mask = <0x3>; - qcom,sde-qos-cpu-dma-latency = <300>; + qcom,sde-qos-cpu-dma-latency = <44>; /* offsets are relative to "mdp_phys + qcom,sde-off */ diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index 41affd70e865..09ec3beb8232 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -2288,7 +2288,7 @@ /* PM QoS */ qcom,pm-qos-cpu-groups = <0x0f 0xf0>; - qcom,pm-qos-cpu-group-latency-us = <70 70>; + qcom,pm-qos-cpu-group-latency-us = <44 44>; qcom,pm-qos-default-cpu = <0>; pinctrl-names = "dev-reset-assert", "dev-reset-deassert"; @@ -2487,9 +2487,9 @@ /* PM QoS */ qcom,pm-qos-irq-type = "affine_irq"; - qcom,pm-qos-irq-latency = <70 70>; + qcom,pm-qos-irq-latency = <44 44>; qcom,pm-qos-cpu-groups = <0x3f 0xc0>; - qcom,pm-qos-legacy-latency-us = <70 70>, <70 70>; + qcom,pm-qos-legacy-latency-us = <44 44>, <44 44>; status = "disabled"; }; @@ -2709,7 +2709,7 @@ qcom,msm_cdsp_rm { compatible = "qcom,msm-cdsp-rm"; - qcom,qos-latency-us = <100>; + qcom,qos-latency-us = <44>; qcom,qos-maxhold-ms = <20>; }; }; -- GitLab From 7ec5f26a33b67091be568da2d737e75e961efe29 Mon Sep 17 00:00:00 2001 From: Shawn Shin Date: Thu, 4 Jan 2018 13:50:35 -0800 Subject: [PATCH 1016/1299] soc: qcom: add microdump collector Collects data from SMEM region when modem crashes and stores it under /dev to expose to user space Change-Id: I6b79a2ea7f7d9d7507e8c44dd1d385a185759ac1 Signed-off-by: Shawn Shin --- drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/microdump_collector.c | 152 +++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 drivers/soc/qcom/microdump_collector.c diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index ff06b4a5b107..d26ad6184979 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -64,6 +64,7 @@ ifdef CONFIG_MSM_SUBSYSTEM_RESTART obj-y += subsystem_notif.o obj-y += subsystem_restart.o obj-y += ramdump.o + obj-y += microdump_collector.o endif obj-$(CONFIG_QCOM_EUD) += eud.o obj-$(CONFIG_QSEE_IPC_IRQ) += qsee_ipc_irq.o diff --git a/drivers/soc/qcom/microdump_collector.c b/drivers/soc/qcom/microdump_collector.c new file mode 100644 index 000000000000..d55f3d177cdc --- /dev/null +++ b/drivers/soc/qcom/microdump_collector.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#define SMEM_SSR_REASON_MSS0 421 +#define SMEM_SSR_DATA_MSS0 611 +#define SMEM_MODEM 1 + +/* + * This program collects the data from SMEM regions whenever the modem crashes + * and stores it in /dev/ramdump_microdump_modem so as to expose it to + * user space. + */ + +struct microdump_data { + struct ramdump_device *microdump_dev; + void *microdump_modem_notify_handler; + struct notifier_block microdump_modem_ssr_nb; +}; + +static struct microdump_data *drv; + +static int microdump_modem_notifier_nb(struct notifier_block *nb, + unsigned long code, void *data) +{ + int ret = 0; + size_t size_reason = 0, size_data = 0; + char *crash_reason = NULL; + char *crash_data = NULL; + struct ramdump_segment segment[2]; + + if (SUBSYS_RAMDUMP_NOTIFICATION != code && SUBSYS_SOC_RESET != code) + return NOTIFY_OK; + + memset(segment, 0, sizeof(segment)); + + crash_reason = qcom_smem_get(QCOM_SMEM_HOST_ANY + , SMEM_SSR_REASON_MSS0, &size_reason); + + if (IS_ERR_OR_NULL(crash_reason)) { + pr_info("%s: smem %d not available\n", + __func__, SMEM_SSR_REASON_MSS0); + goto out; + } + + segment[0].v_address = crash_reason; + segment[0].size = size_reason; + + crash_data = qcom_smem_get(SMEM_MODEM + , SMEM_SSR_DATA_MSS0, &size_data); + + if (IS_ERR_OR_NULL(crash_data)) { + pr_info("%s: smem %d not available\n", + __func__, SMEM_SSR_DATA_MSS0); + goto out; + } + + segment[1].v_address = crash_data; + segment[1].size = size_data; + + ret = do_ramdump(drv->microdump_dev, segment, 2); + if (ret) + pr_info("%s: do_ramdump() failed\n", __func__); + +out: + return NOTIFY_OK; +} + +static int microdump_modem_ssr_register_notifier(struct microdump_data *drv) +{ + int ret = 0; + + drv->microdump_modem_ssr_nb.notifier_call = microdump_modem_notifier_nb; + + drv->microdump_modem_notify_handler = + subsys_notif_register_notifier("modem", + &drv->microdump_modem_ssr_nb); + + if (IS_ERR(drv->microdump_modem_notify_handler)) { + pr_err("Modem register notifier failed: %ld\n", + PTR_ERR(drv->microdump_modem_notify_handler)); + ret = -EINVAL; + } + + return ret; +} + +static void microdump_modem_ssr_unregister_notifier(struct microdump_data *drv) +{ + subsys_notif_unregister_notifier(drv->microdump_modem_notify_handler, + &drv->microdump_modem_ssr_nb); + drv->microdump_modem_notify_handler = NULL; +} + +/* + * microdump_init() - Registers kernel module for microdump collector + * + * Creates device file /dev/ramdump_microdump_modem and registers handler for + * modem SSR events. + * + * Returns 0 on success and negative error code in case of errors + */ +static int __init microdump_init(void) +{ + int ret = -ENOMEM; + + drv = kzalloc(sizeof(struct microdump_data), GFP_KERNEL); + if (!drv) + goto out; + + drv->microdump_dev = create_ramdump_device("microdump_modem", NULL); + if (!drv->microdump_dev) { + pr_err("%s: Unable to create a microdump_modem ramdump device\n" + , __func__); + ret = -ENODEV; + goto out_kfree; + } + + ret = microdump_modem_ssr_register_notifier(drv); + if (ret) { + destroy_ramdump_device(drv->microdump_dev); + goto out_kfree; + } + return ret; + +out_kfree: + pr_err("%s: Failed to register microdump collector\n", __func__); + kfree(drv); + drv = NULL; +out: + return ret; +} + +static void __exit microdump_exit(void) +{ + microdump_modem_ssr_unregister_notifier(drv); + destroy_ramdump_device(drv->microdump_dev); + kfree(drv); +} + +module_init(microdump_init); +module_exit(microdump_exit); + +MODULE_DESCRIPTION("Microdump Collector"); +MODULE_LICENSE("GPL v2"); -- GitLab From 73afc99a5e8aa32149ebf65aebe17a702d12463e Mon Sep 17 00:00:00 2001 From: Srinivas Ramana Date: Mon, 2 Jul 2018 18:11:22 +0530 Subject: [PATCH 1017/1299] ARM: dts: msm: Correct the cache sizes on sm6150 Correct the cache sizes and cache dump sizes of sm6150 as per the hardware definition. Change-Id: Ic57e17e33bf58191798aded39ce4cef7d8a2f25f Signed-off-by: Srinivas Ramana --- arch/arm64/boot/dts/qcom/sm6150.dtsi | 284 ++++++++++++++++----------- 1 file changed, 166 insertions(+), 118 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index d972e8692da9..f35441c022d7 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -56,7 +56,7 @@ next-level-cache = <&L2_0>; L2_0: l2-cache { compatible = "arm,arch-cache"; - cache-size = <0x20000>; + cache-size = <0x10000>; cache-level = <2>; next-level-cache = <&L3_0>; @@ -69,16 +69,16 @@ L1_I_0: l1-icache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x8800>; }; L1_D_0: l1-dcache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x9000>; }; - L1_TLB_0: l1-tlb { - qcom,dump-size = <0x3000>; + L2_TLB_0: l2-tlb { + qcom,dump-size = <0x5000>; }; }; @@ -88,26 +88,26 @@ reg = <0x0 0x100>; enable-method = "psci"; cache-size = <0x8000>; - next-level-cache = <&L2_1>; - L2_1: l2-cache { + next-level-cache = <&L2_100>; + L2_100: l2-cache { compatible = "arm,arch-cache"; - cache-size = <0x20000>; + cache-size = <0x10000>; cache-level = <2>; next-level-cache = <&L3_0>; }; - L1_I_1: l1-icache { + L1_I_100: l1-icache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x8800>; }; - L1_D_1: l1-dcache { + L1_D_100: l1-dcache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x9000>; }; - L1_TLB_1: l1-tlb { - qcom,dump-size = <0x3000>; + L2_TLB_100: l1-tlb { + qcom,dump-size = <0x5000>; }; }; @@ -118,26 +118,26 @@ reg = <0x0 0x200>; enable-method = "psci"; cache-size = <0x8000>; - next-level-cache = <&L2_2>; - L2_2: l2-cache { + next-level-cache = <&L2_200>; + L2_200: l2-cache { compatible = "arm,arch-cache"; - cache-size = <0x20000>; + cache-size = <0x10000>; cache-level = <2>; next-level-cache = <&L3_0>; }; - L1_I_2: l1-icache { + L1_I_200: l1-icache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x8800>; }; - L1_D_2: l1-dcache { + L1_D_200: l1-dcache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x9000>; }; - L1_TLB_2: l1-tlb { - qcom,dump-size = <0x3000>; + L2_TLB_200: l1-tlb { + qcom,dump-size = <0x5000>; }; }; @@ -147,26 +147,26 @@ reg = <0x0 0x300>; enable-method = "psci"; cache-size = <0x8000>; - next-level-cache = <&L2_3>; - L2_3: l2-cache { + next-level-cache = <&L2_300>; + L2_300: l2-cache { compatible = "arm,arch-cache"; - cache-size = <0x20000>; + cache-size = <0x10000>; cache-level = <2>; next-level-cache = <&L3_0>; }; - L1_I_3: l1-icache { + L1_I_300: l1-icache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x8800>; }; - L1_D_3: l1-dcache { + L1_D_300: l1-dcache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x9000>; }; - L1_TLB_3: l1-tlb { - qcom,dump-size = <0x3000>; + L2_TLB_300: l1-tlb { + qcom,dump-size = <0x5000>; }; }; @@ -176,26 +176,26 @@ reg = <0x0 0x400>; enable-method = "psci"; cache-size = <0x8000>; - next-level-cache = <&L2_4>; - L2_4: l2-cache { + next-level-cache = <&L2_400>; + L2_400: l2-cache { compatible = "arm,arch-cache"; - cache-size = <0x20000>; + cache-size = <0x10000>; cache-level = <2>; next-level-cache = <&L3_0>; }; - L1_I_4: l1-icache { + L1_I_400: l1-icache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x8800>; }; - L1_D_4: l1-dcache { + L1_D_400: l1-dcache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x9000>; }; - L1_TLB_4: l1-tlb { - qcom,dump-size = <0x3000>; + L2_TLB_400: l1-tlb { + qcom,dump-size = <0x5000>; }; }; @@ -205,26 +205,26 @@ reg = <0x0 0x500>; enable-method = "psci"; cache-size = <0x8000>; - next-level-cache = <&L2_5>; - L2_5: l2-cache { + next-level-cache = <&L2_500>; + L2_500: l2-cache { compatible = "arm,arch-cache"; - cache-size = <0x20000>; + cache-size = <0x10000>; cache-level = <2>; next-level-cache = <&L3_0>; }; - L1_I_5: l1-icache { + L1_I_500: l1-icache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x8800>; }; - L1_D_5: l1-dcache { + L1_D_500: l1-dcache { compatible = "arm,arch-cache"; - qcom,dump-size = <0xa000>; + qcom,dump-size = <0x9000>; }; - L1_TLB_5: l1-tlb { - qcom,dump-size = <0x3000>; + L2_TLB_500: l1-tlb { + qcom,dump-size = <0x5000>; }; }; @@ -234,26 +234,35 @@ reg = <0x0 0x600>; enable-method = "psci"; cache-size = <0x10000>; - next-level-cache = <&L2_6>; - L2_6: l2-cache { + next-level-cache = <&L2_600>; + L2_600: l2-cache { compatible = "arm,arch-cache"; cache-size = <0x40000>; cache-level = <2>; next-level-cache = <&L3_0>; + qcom,dump-size = <0x48000>; }; - L1_I_100: l1-icache { + L1_I_600: l1-icache { compatible = "arm,arch-cache"; - qcom,dump-size = <0x14000>; + qcom,dump-size = <0x11000>; }; - L1_D_100: l1-dcache { + L1_D_600: l1-dcache { compatible = "arm,arch-cache"; - qcom,dump-size = <0x14000>; + qcom,dump-size = <0x12000>; }; - L1_TLB_100: l1-tlb { - qcom,dump-size = <0x3c00>; + L1_ITLB_600: l1-itlb { + qcom,dump-size = <0x300>; + }; + + L1_DTLB_600: l1-dtlb { + qcom,dump-size = <0x480>; + }; + + L2_TLB_600: l2-tlb { + qcom,dump-size = <0x7800>; }; }; @@ -263,26 +272,35 @@ reg = <0x0 0x700>; enable-method = "psci"; cache-size = <0x10000>; - next-level-cache = <&L2_7>; - L2_7: l2-cache { + next-level-cache = <&L2_700>; + L2_700: l2-cache { compatible = "arm,arch-cache"; cache-size = <0x40000>; cache-level = <2>; next-level-cache = <&L3_0>; + qcom,dump-size = <0x48000>; }; - L1_I_200: l1-icache { + L1_I_700: l1-icache { compatible = "arm,arch-cache"; - qcom,dump-size = <0x14000>; + qcom,dump-size = <0x11000>; }; - L1_D_200: l1-dcache { + L1_D_700: l1-dcache { compatible = "arm,arch-cache"; - qcom,dump-size = <0x14000>; + qcom,dump-size = <0x12000>; }; - L1_TLB_200: l1-tlb { - qcom,dump-size = <0x3c00>; + L1_ITLB_700: l1-itlb { + qcom,dump-size = <0x300>; + }; + + L1_DTLB_700: l1-dtlb { + qcom,dump-size = <0x480>; + }; + + L2_TLB_700: l2-tlb { + qcom,dump-size = <0x7800>; }; }; @@ -806,38 +824,38 @@ qcom,dump-id = <0x60>; }; - qcom,l1_i_cache1 { - qcom,dump-node = <&L1_I_1>; + qcom,l1_i_cache100 { + qcom,dump-node = <&L1_I_100>; qcom,dump-id = <0x61>; }; - qcom,l1_i_cache2 { - qcom,dump-node = <&L1_I_2>; + qcom,l1_i_cache200 { + qcom,dump-node = <&L1_I_200>; qcom,dump-id = <0x62>; }; - qcom,l1_i_cache3 { - qcom,dump-node = <&L1_I_3>; + qcom,l1_i_cache300 { + qcom,dump-node = <&L1_I_300>; qcom,dump-id = <0x63>; }; - qcom,l1_i_cache4 { - qcom,dump-node = <&L1_I_4>; + qcom,l1_i_cache400 { + qcom,dump-node = <&L1_I_400>; qcom,dump-id = <0x64>; }; - qcom,l1_i_cache5 { - qcom,dump-node = <&L1_I_5>; + qcom,l1_i_cache500 { + qcom,dump-node = <&L1_I_500>; qcom,dump-id = <0x65>; }; - qcom,l1_i_cache100 { - qcom,dump-node = <&L1_I_100>; + qcom,l1_i_cache600 { + qcom,dump-node = <&L1_I_600>; qcom,dump-id = <0x66>; }; - qcom,l1_i_cache200 { - qcom,dump-node = <&L1_I_200>; + qcom,l1_i_cache700 { + qcom,dump-node = <&L1_I_700>; qcom,dump-id = <0x67>; }; @@ -846,79 +864,109 @@ qcom,dump-id = <0x80>; }; - qcom,l1_d_cache1 { - qcom,dump-node = <&L1_D_1>; + qcom,l1_d_cache100 { + qcom,dump-node = <&L1_D_100>; qcom,dump-id = <0x81>; }; - qcom,l1_d_cache2 { - qcom,dump-node = <&L1_D_2>; + qcom,l1_d_cache200 { + qcom,dump-node = <&L1_D_200>; qcom,dump-id = <0x82>; }; - qcom,l1_d_cache3 { - qcom,dump-node = <&L1_D_3>; + qcom,l1_d_cache300 { + qcom,dump-node = <&L1_D_300>; qcom,dump-id = <0x83>; }; - qcom,l1_d_cache4 { - qcom,dump-node = <&L1_D_4>; + qcom,l1_d_cache400 { + qcom,dump-node = <&L1_D_400>; qcom,dump-id = <0x84>; }; - qcom,l1_d_cache5 { - qcom,dump-node = <&L1_D_5>; + qcom,l1_d_cache500 { + qcom,dump-node = <&L1_D_500>; qcom,dump-id = <0x85>; }; - qcom,l1_d_cache100 { - qcom,dump-node = <&L1_D_100>; + qcom,l1_d_cache600 { + qcom,dump-node = <&L1_D_600>; qcom,dump-id = <0x86>; }; - qcom,l1_d_cache200 { - qcom,dump-node = <&L1_D_200>; + qcom,l1_d_cache700 { + qcom,dump-node = <&L1_D_700>; qcom,dump-id = <0x87>; }; - qcom,l1_tlb_dump0 { - qcom,dump-node = <&L1_TLB_0>; - qcom,dump-id = <0x20>; + qcom,l1_i_tlb_dump600 { + qcom,dump-node = <&L1_ITLB_600>; + qcom,dump-id = <0x26>; }; - qcom,l1_tlb_dump1 { - qcom,dump-node = <&L1_TLB_1>; - qcom,dump-id = <0x21>; + qcom,l1_i_tlb_dump700 { + qcom,dump-node = <&L1_ITLB_700>; + qcom,dump-id = <0x27>; }; - qcom,l1_tlb_dump2 { - qcom,dump-node = <&L1_TLB_2>; - qcom,dump-id = <0x22>; + qcom,l1_d_tlb_dump600 { + qcom,dump-node = <&L1_DTLB_600>; + qcom,dump-id = <0x46>; }; - qcom,l1_tlb_dump3 { - qcom,dump-node = <&L1_TLB_3>; - qcom,dump-id = <0x23>; + qcom,l1_d_tlb_dump700 { + qcom,dump-node = <&L1_DTLB_700>; + qcom,dump-id = <0x47>; }; - qcom,l1_tlb_dump4 { - qcom,dump-node = <&L1_TLB_4>; - qcom,dump-id = <0x24>; + qcom,l2_cache_dump600 { + qcom,dump-node = <&L2_600>; + qcom,dump-id = <0xc6>; }; - qcom,l1_tlb_dump5 { - qcom,dump-node = <&L1_TLB_5>; - qcom,dump-id = <0x25>; + qcom,l2_cache_dump700 { + qcom,dump-node = <&L2_700>; + qcom,dump-id = <0xc7>; }; - qcom,l1_tlb_dump100 { - qcom,dump-node = <&L1_TLB_100>; - qcom,dump-id = <0x26>; + qcom,l2_tlb_dump0 { + qcom,dump-node = <&L2_TLB_0>; + qcom,dump-id = <0x120>; }; - qcom,l1_tlb_dump200 { - qcom,dump-node = <&L1_TLB_200>; - qcom,dump-id = <0x27>; + qcom,l2_tlb_dump100 { + qcom,dump-node = <&L2_TLB_100>; + qcom,dump-id = <0x121>; + }; + + qcom,l2_tlb_dump200 { + qcom,dump-node = <&L2_TLB_200>; + qcom,dump-id = <0x122>; + }; + + qcom,l2_tlb_dump300 { + qcom,dump-node = <&L2_TLB_300>; + qcom,dump-id = <0x123>; + }; + + qcom,l2_tlb_dump400 { + qcom,dump-node = <&L2_TLB_400>; + qcom,dump-id = <0x124>; + }; + + qcom,l2_tlb_dump500 { + qcom,dump-node = <&L2_TLB_500>; + qcom,dump-id = <0x125>; + }; + + qcom,l2_tlb_dump600 { + qcom,dump-node = <&L2_TLB_600>; + qcom,dump-id = <0x126>; + }; + + qcom,l2_tlb_dump700 { + qcom,dump-node = <&L2_TLB_700>; + qcom,dump-id = <0x127>; }; }; -- GitLab From 03a76b01bb43334a79dc0652811f8a53c2a957db Mon Sep 17 00:00:00 2001 From: Shi Zhongbo Date: Mon, 2 Jul 2018 14:32:15 +0800 Subject: [PATCH 1018/1299] msm: vidc: Revise printed msg type for format constraint Change printed message type from error to info when format constraint unavailable. Change-Id: If9ea8dfc6f4b957d9c54a030f2678835c70cceb5 Signed-off-by: Zhongbo Shi --- drivers/media/platform/msm/vidc/msm_venc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 700b809660b8..fdf6b4cfda20 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -2751,7 +2751,7 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) f->fmt.pix_mp.pixelformat); if (!fmt_constraint) { - dprintk(VIDC_ERR, + dprintk(VIDC_INFO, "Format constraint not required for %d on OUTPUT port\n", f->fmt.pix_mp.pixelformat); } else { -- GitLab From 7d4d3fe4aac48024f1ab8d403f68f8b56e4d8ffc Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Wed, 27 Jun 2018 15:21:34 +0300 Subject: [PATCH 1019/1299] ARM: dts: msm: add ipa and gsi nodes for sdxprairie Add devicetree nodes for IPA and GSI drivers. This is to enable IPA and GSI H/W blocks for embedded and tethered IP packet processing offload. CRs-fixed: 2268754 Change-Id: Ib8557ed543a97f9d54fb35b5688358fa5d1fc1cb Signed-off-by: Ghanim Fodi --- arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi | 4 ++ arch/arm64/boot/dts/qcom/sdxprairie.dtsi | 56 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi index 7f755519de7a..3d05e32ac5ca 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi @@ -21,3 +21,7 @@ clock-frequency = <48000>; }; }; + +&ipa_hw { + qcom,ipa-hw-mode = <1>; /* IPA hw type = Virtual */ +}; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi index b7c1780fed8a..5c9007a353cc 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi @@ -168,6 +168,62 @@ pinctrl-1 = <&uart3_console_sleep>; status = "ok"; }; + + qcom,msm_gsi { + compatible = "qcom,msm_gsi"; + }; + + ipa_hw: qcom,ipa@01e00000 { + compatible = "qcom,ipa"; + reg = <0x1e00000 0xc0000>, + <0x1e04000 0x23000>; + reg-names = "ipa-base", "gsi-base"; + interrupts = + <0 241 IRQ_TYPE_NONE>, + <0 47 IRQ_TYPE_NONE>; + interrupt-names = "ipa-irq", "gsi-irq"; + qcom,ipa-hw-ver = <17>; /* IPA core version = IPAv4.5 */ + qcom,ipa-hw-mode = <0>; + qcom,ee = <0>; + qcom,use-ipa-tethering-bridge; + qcom,mhi-event-ring-id-limits = <9 10>; /* start and end */ + qcom,modem-cfg-emb-pipe-flt; + qcom,use-ipa-pm; + qcom,bandwidth-vote-for-ipa; + qcom,msm-bus,name = "ipa"; + qcom,msm-bus,num-cases = <5>; + qcom,msm-bus,num-paths = <4>; + qcom,msm-bus,vectors-KBps = + /* No vote */ + <90 512 0 0>, + <90 585 0 0>, + <1 676 0 0>, + <143 777 0 0>, + /* SVS2 */ + <90 512 900000 1800000>, + <90 585 300000 600000>, + <1 676 90000 179000>, /*gcc_config_noc_clk_src */ + <143 777 0 120>, /* IB defined for IPA2X_clk in MHz*/ + /* SVS */ + <90 512 1530000 3060000>, + <90 585 400000 800000>, + <1 676 100000 199000>, + <143 777 0 250>, /* IB defined for IPA2X_clk in MHz*/ + /* NOMINAL */ + <90 512 2592000 5184000>, + <90 585 800000 1600000>, + <1 676 200000 399000>, + <143 777 0 440>, /* IB defined for IPA2X_clk in MHz*/ + /* TURBO */ + <90 512 2592000 5184000>, + <90 585 960000 1920000>, + <1 676 266000 531000>, + <143 777 0 500>; /* IB defined for IPA clk in MHz*/ + qcom,bus-vector-names = "MIN", "SVS2", "SVS", "NOMINAL", + "TURBO"; + qcom,throughput-threshold = <310 600 1000>; + qcom,scaling-exceptions = <>; + }; }; #include "sdxprairie-pinctrl.dtsi" -- GitLab From cee29012d6854f1c4115b88f8acb72e4be37b02c Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Wed, 27 Jun 2018 12:10:27 +0300 Subject: [PATCH 1020/1299] msm: ipa4: Adapt IPA resource groups for IPA 4.5 Add support for the new group, QDSS. Adapt the resource groups to their new numbers. Configure different min/max resource limits per resource group that are appropriate for IPA4.5. CRs-fixed: 2268613 Change-Id: I560218d7dbd2eb5c67802a13e5789f7dad6a6ae2 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 146 ++++++++++++++---- .../msm/ipa/ipa_v3/ipahal/ipahal_reg.c | 83 ++++++++++ .../msm/ipa/ipa_v3/ipahal/ipahal_reg.h | 6 +- .../msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h | 12 +- 4 files changed, 216 insertions(+), 31 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 494085aab114..acbdd4daa4d1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -147,6 +147,17 @@ #define IPA_v4_2_GROUP_UL_DL (0) #define IPA_v4_2_SRC_GROUP_MAX (1) #define IPA_v4_2_DST_GROUP_MAX (1) + +#define IPA_v4_5_MHI_GROUP_PCIE (0) +#define IPA_v4_5_ETHERNET (0) +#define IPA_v4_5_GROUP_UL_DL (1) +#define IPA_v4_5_MHI_GROUP_DDR (1) +#define IPA_v4_5_MHI_GROUP_DMA (2) +#define IPA_v4_5_MHI_GROUP_QDSS (3) +#define IPA_v4_5_GROUP_UC_RX_Q (4) +#define IPA_v4_5_SRC_GROUP_MAX (5) +#define IPA_v4_5_DST_GROUP_MAX (5) + #define IPA_GROUP_MAX IPA_v3_0_GROUP_MAX enum ipa_rsrc_grp_type_src { @@ -334,7 +345,34 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config [IPA_v4_0_RSRC_GRP_TYPE_SRC_ACK_ENTRIES] = { {5, 5}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, }, - + [IPA_4_5] = { + /* not used UL_DL not used not used UC_RX_Q + * other are invalid + */ + [IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { + {0, 0}, {1, 63}, {0, 0}, {0, 0}, {1, 63}, {0, 0} }, + [IPA_v4_0_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = { + {0, 0}, {14, 14}, {0, 0}, {0, 0}, {3, 3}, {0, 0} }, + [IPA_v4_0_RSRC_GRP_TYPE_SRC_DESCRIPTOR_BUFF] = { + {0, 0}, {18, 18}, {0, 0}, {0, 0}, {8, 8}, {0, 0} }, + [IPA_v4_0_RSRC_GRP_TYPE_SRC_HPS_DMARS] = { + {0, 0}, {0, 63}, {0, 0}, {0, 0}, {0, 63}, {0, 0} }, + [IPA_v4_0_RSRC_GRP_TYPE_SRC_ACK_ENTRIES] = { + {0, 0}, {24, 24}, {0, 0}, {0, 0}, {8, 8}, {0, 0} }, + }, + [IPA_4_5_MHI] = { + /* PCIE DDR DMA QDSS not used other are invalid */ + [IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = { + {3, 8}, {4, 11}, {1, 1}, {1, 1}, {0, 0}, {0, 0} }, + [IPA_v4_0_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = { + {9, 9}, {12, 12}, {2, 2}, {2, 2}, {0, 0}, {0, 0} }, + [IPA_v4_0_RSRC_GRP_TYPE_SRC_DESCRIPTOR_BUFF] = { + {9, 9}, {14, 14}, {4, 4}, {4, 4}, {0, 0}, {0, 0} }, + [IPA_v4_0_RSRC_GRP_TYPE_SRC_HPS_DMARS] = { + {0, 63}, {0, 63}, {0, 63}, {0, 63}, {0, 0}, {0, 0} }, + [IPA_v4_0_RSRC_GRP_TYPE_SRC_ACK_ENTRIES] = { + {22, 22}, {16, 16}, {6, 6}, {2, 2}, {0, 0}, {0, 0} }, + }, }; static const struct rsrc_min_max ipa3_rsrc_dst_grp_config @@ -397,6 +435,20 @@ static const struct rsrc_min_max ipa3_rsrc_dst_grp_config [IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = { {1, 63}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, }, + [IPA_4_5] = { + /* ETH UL/DL/DPL not used not used uC other are invalid */ + [IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = { + {16, 16}, {5, 5}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, + [IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = { + {2, 63}, {1, 63}, {0, 0}, {0, 0}, {0, 2}, {0, 0} }, + }, + [IPA_4_5_MHI] = { + /* PCIE/DPL DDR DMA QDSS uC other are invalid */ + [IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = { + {16, 16}, {5, 5}, {2, 2}, {2, 2}, {0, 0}, {0, 0} }, + [IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = { + {2, 63}, {1, 63}, {1, 2}, {1, 2}, {0, 2}, {0, 0} }, + }, }; static const struct rsrc_min_max ipa3_rsrc_rx_grp_config @@ -441,6 +493,18 @@ static const struct rsrc_min_max ipa3_rsrc_rx_grp_config [IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = { {4, 4}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, }, + [IPA_4_5] = { + /* not used UL_DL not used not used UC_RX_Q + * other are invalid + */ + [IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = { + {0, 0}, {3, 3}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }, + }, + [IPA_4_5_MHI] = { + /* PCIE DDR DMA QDSS not used other are invalid */ + [IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] = { + { 3, 3 }, {3, 3}, {3, 3}, {3, 3}, {0, 0}, { 0, 0 } }, + }, }; @@ -474,10 +538,6 @@ static const u32 ipa3_rsrc_rx_grp_hps_weight_config /* LWA_DL UL_DL not used UC_RX_Q, other are invalid */ [IPA_RSRC_GRP_TYPE_RX_HPS_WEIGHT_CONFIG] = { 1, 1, 1, 1, 0, 0 }, }, - [IPA_4_2] = { - /* UL_DL, other are invalid */ - [IPA_RSRC_GRP_TYPE_RX_HPS_WEIGHT_CONFIG] = { 1, 0, 0, 0, 0, 0 }, - }, }; enum ipa_ees { @@ -5458,11 +5518,23 @@ static void ipa3_write_rsrc_grp_type_reg(int group_index, case IPA_4_5_MHI: if (src) { switch (group_index) { - case IPA_v4_2_GROUP_UL_DL: + case IPA_v4_5_MHI_GROUP_PCIE: + case IPA_v4_5_GROUP_UL_DL: ipahal_write_reg_n_fields( IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n, n, val); break; + case IPA_v4_5_MHI_GROUP_DMA: + case IPA_v4_5_MHI_GROUP_QDSS: + ipahal_write_reg_n_fields( + IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n, + n, val); + break; + case IPA_v4_5_GROUP_UC_RX_Q: + ipahal_write_reg_n_fields( + IPA_SRC_RSRC_GRP_45_RSRC_TYPE_n, + n, val); + break; default: IPAERR( " Invalid source resource group,index #%d\n", @@ -5471,11 +5543,23 @@ static void ipa3_write_rsrc_grp_type_reg(int group_index, } } else { switch (group_index) { - case IPA_v4_2_GROUP_UL_DL: + case IPA_v4_5_MHI_GROUP_PCIE: + case IPA_v4_5_GROUP_UL_DL: ipahal_write_reg_n_fields( IPA_DST_RSRC_GRP_01_RSRC_TYPE_n, n, val); break; + case IPA_v4_5_MHI_GROUP_DMA: + case IPA_v4_5_MHI_GROUP_QDSS: + ipahal_write_reg_n_fields( + IPA_DST_RSRC_GRP_23_RSRC_TYPE_n, + n, val); + break; + case IPA_v4_5_GROUP_UC_RX_Q: + ipahal_write_reg_n_fields( + IPA_DST_RSRC_GRP_45_RSRC_TYPE_n, + n, val); + break; default: IPAERR( " Invalid destination resource group,index #%d\n", @@ -5492,7 +5576,8 @@ static void ipa3_write_rsrc_grp_type_reg(int group_index, } } -static void ipa3_configure_rx_hps_clients(int depth, bool min) +static void ipa3_configure_rx_hps_clients(int depth, + int max_clnt_in_depth, int base_index, bool min) { int i; struct ipahal_reg_rx_hps_clients val; @@ -5500,23 +5585,19 @@ static void ipa3_configure_rx_hps_clients(int depth, bool min) hw_type_idx = ipa3_get_hw_type_index(); - /* - * depth 0 contains 4 first clients out of 6 - * depth 1 contains 2 last clients out of 6 - */ - for (i = 0 ; i < (depth ? 2 : 4) ; i++) { + for (i = 0 ; i < max_clnt_in_depth ; i++) { if (min) val.client_minmax[i] = ipa3_rsrc_rx_grp_config [hw_type_idx] [IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] - [!depth ? i : 4 + i].min; + [i + base_index].min; else val.client_minmax[i] = ipa3_rsrc_rx_grp_config [hw_type_idx] [IPA_RSRC_GRP_TYPE_RX_HPS_CMDQ] - [!depth ? i : 4 + i].max; + [i + base_index].max; } if (depth) { ipahal_write_reg_fields(min ? IPA_RX_HPS_CLIENTS_MIN_DEPTH_1 : @@ -5566,9 +5647,9 @@ void ipa3_set_resorce_groups_min_max_limits(void) int dst_grp_idx_max; struct ipahal_reg_rsrc_grp_cfg val; u8 hw_type_idx; + int rx_hps_max_clnt_in_depth0; IPADBG("ENTER\n"); - IPADBG("Assign source rsrc groups min-max limits\n"); hw_type_idx = ipa3_get_hw_type_index(); switch (hw_type_idx) { @@ -5604,8 +5685,8 @@ void ipa3_set_resorce_groups_min_max_limits(void) case IPA_4_5_MHI: src_rsrc_type_max = IPA_v4_0_RSRC_GRP_TYPE_SRC_MAX; dst_rsrc_type_max = IPA_v4_0_RSRC_GRP_TYPE_DST_MAX; - src_grp_idx_max = IPA_v4_2_SRC_GROUP_MAX; - dst_grp_idx_max = IPA_v4_2_DST_GROUP_MAX; + src_grp_idx_max = IPA_v4_5_SRC_GROUP_MAX; + dst_grp_idx_max = IPA_v4_5_DST_GROUP_MAX; break; default: IPAERR("invalid hw type index\n"); @@ -5613,6 +5694,7 @@ void ipa3_set_resorce_groups_min_max_limits(void) return; } + IPADBG("Assign source rsrc groups min-max limits\n"); for (i = 0; i < src_rsrc_type_max; i++) { for (j = 0; j < src_grp_idx_max; j = j + 2) { val.x_min = @@ -5628,7 +5710,6 @@ void ipa3_set_resorce_groups_min_max_limits(void) } IPADBG("Assign destination rsrc groups min-max limits\n"); - for (i = 0; i < dst_rsrc_type_max; i++) { for (j = 0; j < dst_grp_idx_max; j = j + 2) { val.x_min = @@ -5643,7 +5724,7 @@ void ipa3_set_resorce_groups_min_max_limits(void) } } - /* move resource group configuration from HLOS to TZ */ + /* move rx_hps resource group configuration from HLOS to TZ */ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_1) { IPAERR("skip configuring ipa_rx_hps_clients from HLOS\n"); return; @@ -5651,18 +5732,29 @@ void ipa3_set_resorce_groups_min_max_limits(void) IPADBG("Assign RX_HPS CMDQ rsrc groups min-max limits\n"); - ipa3_configure_rx_hps_clients(0, true); - ipa3_configure_rx_hps_clients(0, false); + /* Starting IPA4.5 have 5 RX_HPS_CMDQ */ + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) + rx_hps_max_clnt_in_depth0 = 4; + else + rx_hps_max_clnt_in_depth0 = 5; - /* only hw_type v3_0\3_1 have 6 RX_HPS_CMDQ and needs depth 1*/ + ipa3_configure_rx_hps_clients(0, rx_hps_max_clnt_in_depth0, 0, true); + ipa3_configure_rx_hps_clients(0, rx_hps_max_clnt_in_depth0, 0, false); + + /* + * IPA 3.0/3.1 uses 6 RX_HPS_CMDQ and needs depths1 for that + * which has two clients + */ if (ipa3_ctx->ipa_hw_type <= IPA_HW_v3_1) { - ipa3_configure_rx_hps_clients(1, true); - ipa3_configure_rx_hps_clients(1, false); + ipa3_configure_rx_hps_clients(1, 2, rx_hps_max_clnt_in_depth0, + true); + ipa3_configure_rx_hps_clients(1, 2, rx_hps_max_clnt_in_depth0, + false); } - /* In IPA4.2 no support to HPS weight config*/ + /* Starting IPA4.2 no support to HPS weight config */ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5 && - (ipa3_ctx->ipa_hw_type != IPA_HW_v4_2)) + (ipa3_ctx->ipa_hw_type < IPA_HW_v4_2)) ipa3_configure_rx_hps_weight(); IPADBG("EXIT\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c index ef1d140e3695..f60d7e7d96f3 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c @@ -213,6 +213,33 @@ static void ipareg_construct_rx_hps_clients_depth0_v3_5( IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK_V3_5(3)); } +static void ipareg_construct_rx_hps_clients_depth0_v4_5( + enum ipahal_reg_name reg, const void *fields, u32 *val) +{ + struct ipahal_reg_rx_hps_clients *clients = + (struct ipahal_reg_rx_hps_clients *)fields; + + IPA_SETFIELD_IN_REG(*val, clients->client_minmax[0], + IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_0_SHFT_v4_5, + IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_0_BMSK_v4_5); + + IPA_SETFIELD_IN_REG(*val, clients->client_minmax[1], + IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_1_SHFT_v4_5, + IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_1_BMSK_v4_5); + + IPA_SETFIELD_IN_REG(*val, clients->client_minmax[2], + IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_2_SHFT_v4_5, + IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_2_BMSK_v4_5); + + IPA_SETFIELD_IN_REG(*val, clients->client_minmax[3], + IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_3_SHFT_v4_5, + IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_3_BMSK_v4_5); + + IPA_SETFIELD_IN_REG(*val, clients->client_minmax[4], + IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_4_SHFT_v4_5, + IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_4_BMSK_v4_5); +} + static void ipareg_construct_rsrg_grp_xy( enum ipahal_reg_name reg, const void *fields, u32 *val) { @@ -258,6 +285,32 @@ static void ipareg_construct_rsrg_grp_xy_v3_5( IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MAX_LIM_BMSK_V3_5); } +static void ipareg_construct_rsrg_grp_xy_v4_5( + enum ipahal_reg_name reg, const void *fields, u32 *val) +{ + struct ipahal_reg_rsrc_grp_cfg *grp = + (struct ipahal_reg_rsrc_grp_cfg *)fields; + + IPA_SETFIELD_IN_REG(*val, grp->x_min, + IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MIN_LIM_SHFT_V3_5, + IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MIN_LIM_BMSK_V3_5); + IPA_SETFIELD_IN_REG(*val, grp->x_max, + IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MAX_LIM_SHFT_V3_5, + IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MAX_LIM_BMSK_V3_5); + + /* SRC_45 and DST_45 register has only X fields at ipa V4_5 */ + if (reg == IPA_SRC_RSRC_GRP_45_RSRC_TYPE_n || + reg == IPA_DST_RSRC_GRP_45_RSRC_TYPE_n) + return; + + IPA_SETFIELD_IN_REG(*val, grp->y_min, + IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MIN_LIM_SHFT_V3_5, + IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MIN_LIM_BMSK_V3_5); + IPA_SETFIELD_IN_REG(*val, grp->y_max, + IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MAX_LIM_SHFT_V3_5, + IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MAX_LIM_BMSK_V3_5); +} + static void ipareg_construct_hash_cfg_n( enum ipahal_reg_name reg, const void *fields, u32 *val) { @@ -2271,6 +2324,8 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = { [IPA_HW_v4_0][IPA_ENDP_YELLOW_RED_MARKER] = { ipareg_construct_dummy, ipareg_parse_dummy, 0x00000CC0, 0x70, 10, 23, 1}, + + /* IPA4.2 */ [IPA_HW_v4_2][IPA_IDLE_INDICATION_CFG] = { ipareg_construct_idle_indication_cfg, ipareg_parse_dummy, 0x00000240, 0, 0, 0, 0}, @@ -2278,6 +2333,34 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = { ipareg_construct_endp_init_hol_block_timer_n_v4_2, ipareg_parse_dummy, 0x00000830, 0x70, 8, 17, 1}, + + /* IPA4.5 */ + [IPA_HW_v4_5][IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n] = { + ipareg_construct_rsrg_grp_xy_v4_5, ipareg_parse_dummy, + 0x00000400, 0x20, 0, 0, 0}, + [IPA_HW_v4_5][IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n] = { + ipareg_construct_rsrg_grp_xy_v4_5, ipareg_parse_dummy, + 0x00000404, 0x20, 0, 0, 0}, + [IPA_HW_v4_5][IPA_SRC_RSRC_GRP_45_RSRC_TYPE_n] = { + ipareg_construct_rsrg_grp_xy_v4_5, ipareg_parse_dummy, + 0x00000408, 0x20, 0, 0, 0}, + [IPA_HW_v4_5][IPA_DST_RSRC_GRP_01_RSRC_TYPE_n] = { + ipareg_construct_rsrg_grp_xy_v4_5, ipareg_parse_dummy, + 0x00000500, 0x20, 0, 0, 0}, + [IPA_HW_v4_5][IPA_DST_RSRC_GRP_23_RSRC_TYPE_n] = { + ipareg_construct_rsrg_grp_xy_v4_5, ipareg_parse_dummy, + 0x00000504, 0x20, 0, 0, 0}, + [IPA_HW_v4_5][IPA_DST_RSRC_GRP_45_RSRC_TYPE_n] = { + ipareg_construct_rsrg_grp_xy_v4_5, ipareg_parse_dummy, + 0x00000508, 0x20, 0, 0, 0}, + [IPA_HW_v4_5][IPA_RX_HPS_CLIENTS_MIN_DEPTH_0] = { + ipareg_construct_rx_hps_clients_depth0_v4_5, + ipareg_parse_dummy, + 0x000023c4, 0, 0, 0, 0}, + [IPA_HW_v4_5][IPA_RX_HPS_CLIENTS_MAX_DEPTH_0] = { + ipareg_construct_rx_hps_clients_depth0_v4_5, + ipareg_parse_dummy, + 0x000023cc, 0, 0, 0, 0}, }; void ipahal_print_all_regs(bool print_to_dmesg) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h index a788d348d06d..494a0d7cb5c6 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h @@ -368,7 +368,7 @@ struct ipahal_reg_debug_cnt_ctrl { }; /* - * struct ipahal_reg_rsrc_grp_cfg - Mix/Max values for two rsrc groups + * struct ipahal_reg_rsrc_grp_cfg - Min/Max values for two rsrc groups * @x_min - first group min value * @x_max - first group max value * @y_min - second group min value @@ -383,11 +383,11 @@ struct ipahal_reg_rsrc_grp_cfg { /* * struct ipahal_reg_rx_hps_clients - Min or Max values for RX HPS clients - * @client_minmax - Min or Max values. In case of depth 0 the 4 values + * @client_minmax - Min or Max values. In case of depth 0 the 4 or 5 values * are used. In case of depth 1, only the first 2 values are used */ struct ipahal_reg_rx_hps_clients { - u32 client_minmax[4]; + u32 client_minmax[5]; }; /* diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h index 2f7803ad5d6e..b4166435a11d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h @@ -365,11 +365,21 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type); #define IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MIN_LIM_BMSK_V3_5 0x3F #define IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MIN_LIM_SHFT_V3_5 0 -/* IPA_IPA_IPA_RX_HPS_CLIENTS_MIN/MAX_DEPTH_0/1 registers */ +/* IPA_RX_HPS_CLIENTS_MIN/MAX_DEPTH_0/1 registers */ #define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK(n) (0x7F << (8 * (n))) #define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK_V3_5(n) \ (0xF << (8 * (n))) #define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(n) (8 * (n)) +#define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_4_BMSK_v4_5 0xF0000000 +#define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_4_SHFT_v4_5 28 +#define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_3_BMSK_v4_5 0xF000000 +#define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_3_SHFT_v4_5 24 +#define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_2_BMSK_v4_5 0xF0000 +#define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_2_SHFT_v4_5 16 +#define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_1_BMSK_v4_5 0xF00 +#define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_1_SHFT_v4_5 8 +#define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_0_BMSK_v4_5 0xF +#define IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_0_CLIENT_0_SHFT_v4_5 0 /* IPA_QSB_MAX_WRITES register */ #define IPA_QSB_MAX_WRITES_GEN_QMB_0_MAX_WRITES_BMSK (0xf) -- GitLab From be33f0a375b3d5f2420f3a0a5aefea3cc8226ae7 Mon Sep 17 00:00:00 2001 From: Tingwei Zhang Date: Fri, 13 Apr 2018 11:28:05 +0800 Subject: [PATCH 1021/1299] soc: qcom: dcc_v2: Avoid huge memory allcation Check size of DCC configuration. Limit the size according to SRAM size. Change-Id: Ib846c92458e2fef8c45128b9b83d1c549b293370 Signed-off-by: Tingwei Zhang --- drivers/soc/qcom/dcc_v2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c index 234830752435..2ded804ab9f1 100644 --- a/drivers/soc/qcom/dcc_v2.c +++ b/drivers/soc/qcom/dcc_v2.c @@ -889,7 +889,8 @@ static int dcc_config_add(struct dcc_drvdata *drvdata, unsigned int addr, goto err; } - if (!len) { + /* Check the len to avoid allocate huge memory */ + if (!len || len > (drvdata->ram_size / 8)) { dev_err(drvdata->dev, "DCC: Invalid length\n"); ret = -EINVAL; goto err; -- GitLab From 1d107219217f24ca8fe726b56749cf34b7f5aa10 Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Tue, 3 Jul 2018 12:21:49 +0300 Subject: [PATCH 1022/1299] msm: ipa: Enable Hashable routing and filtering IPA rules Enable back the hashable routing and filtering rules support at IPA HAL for IPA4.5 after they were disabled at IPA 4.2. CRs-Fixed: 2272062 Change-Id: Ifbb28207deaaf8b85d30ee9774f0cfce2cb17598 Signed-off-by: Ghanim Fodi --- .../msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c index 1c21ed21cc94..6ca88e8ced5f 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c @@ -579,6 +579,49 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { }, }, + /* IPAv4.5 */ + [IPA_HW_v4_5] = { + true, + IPA3_0_HW_TBL_WIDTH, + IPA3_0_HW_TBL_SYSADDR_ALIGNMENT, + IPA3_0_HW_TBL_LCLADDR_ALIGNMENT, + IPA3_0_HW_TBL_BLK_SIZE_ALIGNMENT, + IPA3_0_HW_RULE_START_ALIGNMENT, + IPA3_0_HW_TBL_HDR_WIDTH, + IPA3_0_HW_TBL_ADDR_MASK, + IPA3_0_RULE_MAX_PRIORITY, + IPA3_0_RULE_MIN_PRIORITY, + IPA3_0_LOW_RULE_ID, + IPA3_0_RULE_ID_BIT_LEN, + IPA3_0_HW_RULE_BUF_SIZE, + ipa_write_64, + ipa_fltrt_create_flt_bitmap, + ipa_fltrt_create_tbl_addr, + ipa_fltrt_parse_tbl_addr, + ipa_rt_gen_hw_rule, + ipa_flt_gen_hw_rule_ipav4, + ipa_flt_generate_eq, + ipa_rt_parse_hw_rule, + ipa_flt_parse_hw_rule_ipav4, + { + [IPA_TOS_EQ] = 0, + [IPA_PROTOCOL_EQ] = 1, + [IPA_TC_EQ] = 2, + [IPA_OFFSET_MEQ128_0] = 3, + [IPA_OFFSET_MEQ128_1] = 4, + [IPA_OFFSET_MEQ32_0] = 5, + [IPA_OFFSET_MEQ32_1] = 6, + [IPA_IHL_OFFSET_MEQ32_0] = 7, + [IPA_IHL_OFFSET_MEQ32_1] = 8, + [IPA_METADATA_COMPARE] = 9, + [IPA_IHL_OFFSET_RANGE16_0] = 10, + [IPA_IHL_OFFSET_RANGE16_1] = 11, + [IPA_IHL_OFFSET_EQ_32] = 12, + [IPA_IHL_OFFSET_EQ_16] = 13, + [IPA_FL_EQ] = 14, + [IPA_IS_FRAG] = 15, + }, + }, }; static int ipa_flt_generate_eq(enum ipa_ip_type ipt, -- GitLab From 3ce79716a9ff97cfe2283606aed360ff7a8e3955 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 7 Jun 2018 09:13:48 -0700 Subject: [PATCH 1023/1299] x86/spectre_v1: Disable compiler optimizations over array_index_mask_nospec() commit eab6870fee877258122a042bfd99ee7908c40280 upstream. Mark Rutland noticed that GCC optimization passes have the potential to elide necessary invocations of the array_index_mask_nospec() instruction sequence, so mark the asm() volatile. Mark explains: "The volatile will inhibit *some* cases where the compiler could lift the array_index_nospec() call out of a branch, e.g. where there are multiple invocations of array_index_nospec() with the same arguments: if (idx < foo) { idx1 = array_idx_nospec(idx, foo) do_something(idx1); } < some other code > if (idx < foo) { idx2 = array_idx_nospec(idx, foo); do_something_else(idx2); } ... since the compiler can determine that the two invocations yield the same result, and reuse the first result (likely the same register as idx was in originally) for the second branch, effectively re-writing the above as: if (idx < foo) { idx = array_idx_nospec(idx, foo); do_something(idx); } < some other code > if (idx < foo) { do_something_else(idx); } ... if we don't take the first branch, then speculatively take the second, we lose the nospec protection. There's more info on volatile asm in the GCC docs: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile " Reported-by: Mark Rutland Signed-off-by: Dan Williams Acked-by: Mark Rutland Acked-by: Thomas Gleixner Acked-by: Linus Torvalds Cc: Cc: Peter Zijlstra Fixes: babdde2698d4 ("x86: Implement array_index_mask_nospec") Link: https://lkml.kernel.org/lkml/152838798950.14521.4893346294059739135.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/barrier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index 4db77731e130..a04f0c242a28 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h @@ -38,7 +38,7 @@ static inline unsigned long array_index_mask_nospec(unsigned long index, { unsigned long mask; - asm ("cmp %1,%2; sbb %0,%0;" + asm volatile ("cmp %1,%2; sbb %0,%0;" :"=r" (mask) :"g"(size),"r" (index) :"cc"); -- GitLab From dbb37d98b93d239269420cd9848bd730cb33530b Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Thu, 21 Jun 2018 10:43:31 +0200 Subject: [PATCH 1024/1299] x86/xen: Add call of speculative_store_bypass_ht_init() to PV paths commit 74899d92e66663dc7671a8017b3146dcd4735f3b upstream. Commit: 1f50ddb4f418 ("x86/speculation: Handle HT correctly on AMD") ... added speculative_store_bypass_ht_init() to the per-CPU initialization sequence. speculative_store_bypass_ht_init() needs to be called on each CPU for PV guests, too. Reported-by: Brian Woods Tested-by: Brian Woods Signed-off-by: Juergen Gross Cc: Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: boris.ostrovsky@oracle.com Cc: xen-devel@lists.xenproject.org Fixes: 1f50ddb4f4189243c05926b842dc1a0332195f31 ("x86/speculation: Handle HT correctly on AMD") Link: https://lore.kernel.org/lkml/20180621084331.21228-1-jgross@suse.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/smp_pv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c index c0c756c76afe..db6d90e451de 100644 --- a/arch/x86/xen/smp_pv.c +++ b/arch/x86/xen/smp_pv.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -70,6 +71,8 @@ static void cpu_bringup(void) cpu_data(cpu).x86_max_cores = 1; set_cpu_sibling_map(cpu); + speculative_store_bypass_ht_init(); + xen_setup_cpu_clockevents(); notify_cpu_starting(cpu); @@ -250,6 +253,8 @@ static void __init xen_pv_smp_prepare_cpus(unsigned int max_cpus) } set_cpu_sibling_map(0); + speculative_store_bypass_ht_init(); + xen_pmu_init(0); if (xen_smp_intr_init(0) || xen_smp_intr_init_pv(0)) -- GitLab From 1d1dd2011adca8fa1e0715a83fc751eae31acf1d Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 25 May 2018 14:41:39 -0700 Subject: [PATCH 1025/1299] x86/mce: Improve error message when kernel cannot recover commit c7d606f560e4c698884697fef503e4abacdd8c25 upstream. Since we added support to add recovery from some errors inside the kernel in: commit b2f9d678e28c ("x86/mce: Check for faults tagged in EXTABLE_CLASS_FAULT exception table entries") we have done a less than stellar job at reporting the cause of recoverable machine checks that occur in other parts of the kernel. The user just gets the unhelpful message: mce: [Hardware Error]: Machine check: Action required: unknown MCACOD doubly unhelpful when they check the manual for the reported IA32_MSR_STATUS.MCACOD and see that it is listed as one of the standard recoverable values. Add an extra rule to the MCE severity table to catch this case and report it as: mce: [Hardware Error]: Machine check: Data load in unrecoverable area of kernel Fixes: b2f9d678e28c ("x86/mce: Check for faults tagged in EXTABLE_CLASS_FAULT exception table entries") Signed-off-by: Tony Luck Signed-off-by: Thomas Gleixner Cc: Qiuxu Zhuo Cc: Ashok Raj Cc: stable@vger.kernel.org # 4.6+ Cc: Dan Williams Cc: Borislav Petkov Link: https://lkml.kernel.org/r/4cc7c465150a9a48b8b9f45d0b840278e77eb9b5.1527283897.git.tony.luck@intel.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce-severity.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c index 4b8187639c2d..c51353569492 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-severity.c +++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c @@ -143,6 +143,11 @@ static struct severity { SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_INSTR), USER ), + MCESEV( + PANIC, "Data load in unrecoverable area of kernel", + SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA), + KERNEL + ), #endif MCESEV( PANIC, "Action required: unknown MCACOD", -- GitLab From d292f33b74942e1419311887b0054794d779ce3f Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 25 May 2018 14:42:09 -0700 Subject: [PATCH 1026/1299] x86/mce: Check for alternate indication of machine check recovery on Skylake commit 4c5717da1d021cf368eabb3cb1adcaead56c0d1e upstream. Currently we just check the "CAPID0" register to see whether the CPU can recover from machine checks. But there are also some special SKUs which do not have all advanced RAS features, but do enable machine check recovery for use with NVDIMMs. Add a check for any of bits {8:5} in the "CAPID5" register (each reports some NVDIMM mode available, if any of them are set, then the system supports memory machine check recovery). Signed-off-by: Tony Luck Signed-off-by: Thomas Gleixner Cc: Qiuxu Zhuo Cc: Ashok Raj Cc: stable@vger.kernel.org # 4.9 Cc: Dan Williams Cc: Borislav Petkov Link: https://lkml.kernel.org/r/03cbed6e99ddafb51c2eadf9a3b7c8d7a0cc204e.1527283897.git.tony.luck@intel.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/quirks.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 697a4ce04308..736348ead421 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -645,12 +645,19 @@ static void quirk_intel_brickland_xeon_ras_cap(struct pci_dev *pdev) /* Skylake */ static void quirk_intel_purley_xeon_ras_cap(struct pci_dev *pdev) { - u32 capid0; + u32 capid0, capid5; pci_read_config_dword(pdev, 0x84, &capid0); + pci_read_config_dword(pdev, 0x98, &capid5); - if ((capid0 & 0xc0) == 0xc0) + /* + * CAPID0{7:6} indicate whether this is an advanced RAS SKU + * CAPID5{8:5} indicate that various NVDIMM usage modes are + * enabled, so memory machine check recovery is also enabled. + */ + if ((capid0 & 0xc0) == 0xc0 || (capid5 & 0x1e0)) static_branch_inc(&mcsafe_key); + } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0ec3, quirk_intel_brickland_xeon_ras_cap); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2fc0, quirk_intel_brickland_xeon_ras_cap); -- GitLab From 5b8e086891b038adc667f3ae2f6839f76b54b264 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 22 Jun 2018 11:54:23 +0200 Subject: [PATCH 1027/1299] x86/mce: Fix incorrect "Machine check from unknown source" message commit 40c36e2741d7fe1e66d6ec55477ba5fd19c9c5d2 upstream. Some injection testing resulted in the following console log: mce: [Hardware Error]: CPU 22: Machine Check Exception: f Bank 1: bd80000000100134 mce: [Hardware Error]: RIP 10: {pmem_do_bvec+0x11d/0x330 [nd_pmem]} mce: [Hardware Error]: TSC c51a63035d52 ADDR 3234bc4000 MISC 88 mce: [Hardware Error]: PROCESSOR 0:50654 TIME 1526502199 SOCKET 0 APIC 38 microcode 2000043 mce: [Hardware Error]: Run the above through 'mcelog --ascii' Kernel panic - not syncing: Machine check from unknown source This confused everybody because the first line quite clearly shows that we found a logged error in "Bank 1", while the last line says "unknown source". The problem is that the Linux code doesn't do the right thing for a local machine check that results in a fatal error. It turns out that we know very early in the handler whether the machine check is fatal. The call to mce_no_way_out() has checked all the banks for the CPU that took the local machine check. If it says we must crash, we can do so right away with the right messages. We do scan all the banks again. This means that we might initially not see a problem, but during the second scan find something fatal. If this happens we print a slightly different message (so I can see if it actually every happens). [ bp: Remove unneeded severity assignment. ] Signed-off-by: Tony Luck Signed-off-by: Borislav Petkov Signed-off-by: Thomas Gleixner Cc: Ashok Raj Cc: Dan Williams Cc: Qiuxu Zhuo Cc: linux-edac Cc: stable@vger.kernel.org # 4.2 Link: http://lkml.kernel.org/r/52e049a497e86fd0b71c529651def8871c804df0.1527283897.git.tony.luck@intel.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 28d27de08545..1ca0617d7113 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1205,13 +1205,18 @@ void do_machine_check(struct pt_regs *regs, long error_code) lmce = m.mcgstatus & MCG_STATUS_LMCES; /* + * Local machine check may already know that we have to panic. + * Broadcast machine check begins rendezvous in mce_start() * Go through all banks in exclusion of the other CPUs. This way we * don't report duplicated events on shared banks because the first one - * to see it will clear it. If this is a Local MCE, then no need to - * perform rendezvous. + * to see it will clear it. */ - if (!lmce) + if (lmce) { + if (no_way_out) + mce_panic("Fatal local machine check", &m, msg); + } else { order = mce_start(&no_way_out); + } for (i = 0; i < cfg->banks; i++) { __clear_bit(i, toclear); @@ -1287,12 +1292,17 @@ void do_machine_check(struct pt_regs *regs, long error_code) no_way_out = worst >= MCE_PANIC_SEVERITY; } else { /* - * Local MCE skipped calling mce_reign() - * If we found a fatal error, we need to panic here. + * If there was a fatal machine check we should have + * already called mce_panic earlier in this function. + * Since we re-read the banks, we might have found + * something new. Check again to see if we found a + * fatal error. We call "mce_severity()" again to + * make sure we have the right "msg". */ - if (worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3) - mce_panic("Machine check from unknown source", - NULL, NULL); + if (worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3) { + mce_severity(&m, cfg->tolerant, &msg, true); + mce_panic("Local fatal machine check!", &m, msg); + } } /* -- GitLab From 64d44661e2207a408783360f3029b9a2c48a6daf Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 22 Jun 2018 11:54:28 +0200 Subject: [PATCH 1028/1299] x86/mce: Do not overwrite MCi_STATUS in mce_no_way_out() commit 1f74c8a64798e2c488f86efc97e308b85fb7d7aa upstream. mce_no_way_out() does a quick check during #MC to see whether some of the MCEs logged would require the kernel to panic immediately. And it passes a struct mce where MCi_STATUS gets written. However, after having saved a valid status value, the next iteration of the loop which goes over the MCA banks on the CPU, overwrites the valid status value because we're using struct mce as storage instead of a temporary variable. Which leads to MCE records with an empty status value: mce: [Hardware Error]: CPU 0: Machine Check Exception: 6 Bank 0: 0000000000000000 mce: [Hardware Error]: RIP 10: {trigger_mce+0x7/0x10} In order to prevent the loss of the status register value, return immediately when severity is a panic one so that we can panic immediately with the first fatal MCE logged. This is also the intention of this function and not to noodle over the banks while a fatal MCE is already logged. Tony: read the rest of the MCA bank to populate the struct mce fully. Suggested-by: Tony Luck Signed-off-by: Borislav Petkov Signed-off-by: Thomas Gleixner Cc: Link: https://lkml.kernel.org/r/20180622095428.626-8-bp@alien8.de Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 1ca0617d7113..58f887f5e036 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -760,23 +760,25 @@ EXPORT_SYMBOL_GPL(machine_check_poll); static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp, struct pt_regs *regs) { - int i, ret = 0; char *tmp; + int i; for (i = 0; i < mca_cfg.banks; i++) { m->status = mce_rdmsrl(msr_ops.status(i)); - if (m->status & MCI_STATUS_VAL) { - __set_bit(i, validp); - if (quirk_no_way_out) - quirk_no_way_out(i, m, regs); - } + if (!(m->status & MCI_STATUS_VAL)) + continue; + + __set_bit(i, validp); + if (quirk_no_way_out) + quirk_no_way_out(i, m, regs); if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) { + mce_read_aux(m, i); *msg = tmp; - ret = 1; + return 1; } } - return ret; + return 0; } /* -- GitLab From ab693cc665ca539d3d79783fd1699fc52697469a Mon Sep 17 00:00:00 2001 From: Siarhei Liakh Date: Thu, 14 Jun 2018 19:36:07 +0000 Subject: [PATCH 1029/1299] x86: Call fixup_exception() before notify_die() in math_error() commit 3ae6295ccb7cf6d344908209701badbbbb503e40 upstream. fpu__drop() has an explicit fwait which under some conditions can trigger a fixable FPU exception while in kernel. Thus, we should attempt to fixup the exception first, and only call notify_die() if the fixup failed just like in do_general_protection(). The original call sequence incorrectly triggers KDB entry on debug kernels under particular FPU-intensive workloads. Andy noted, that this makes the whole conditional irq enable thing even more inconsistent, but fixing that it outside the scope of this. Signed-off-by: Siarhei Liakh Signed-off-by: Thomas Gleixner Reviewed-by: Andy Lutomirski Cc: "H. Peter Anvin" Cc: "Borislav Petkov" Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/DM5PR11MB201156F1CAB2592B07C79A03B17D0@DM5PR11MB2011.namprd11.prod.outlook.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/traps.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index ef4efb931efa..ed8d78fd4f8c 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -828,16 +828,18 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" : "simd exception"; - if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP) - return; cond_local_irq_enable(regs); if (!user_mode(regs)) { - if (!fixup_exception(regs, trapnr)) { - task->thread.error_code = error_code; - task->thread.trap_nr = trapnr; + if (fixup_exception(regs, trapnr)) + return; + + task->thread.error_code = error_code; + task->thread.trap_nr = trapnr; + + if (notify_die(DIE_TRAP, str, regs, error_code, + trapnr, SIGFPE) != NOTIFY_STOP) die(str, regs, error_code); - } return; } -- GitLab From da9ad89c72d58df3534fed2963972e932c70fdd7 Mon Sep 17 00:00:00 2001 From: Michael Schmitz Date: Mon, 14 May 2018 23:10:53 +1200 Subject: [PATCH 1030/1299] m68k/mm: Adjust VM area to be unmapped by gap size for __iounmap() commit 3f90f9ef2dda316d64e420d5d51ba369587ccc55 upstream. If 020/030 support is enabled, get_io_area() leaves an IO_SIZE gap between mappings which is added to the vm_struct representing the mapping. __ioremap() uses the actual requested size (after alignment), while __iounmap() is passed the size from the vm_struct. On 020/030, early termination descriptors are used to set up mappings of extent 'size', which are validated on unmapping. The unmapped gap of size IO_SIZE defeats the sanity check of the pmd tables, causing __iounmap() to loop forever on 030. On 040/060, unmapping of page table entries does not check for a valid mapping, so the umapping loop always completes there. Adjust size to be unmapped by the gap that had been added in the vm_struct prior. This fixes the hang in atari_platform_init() reported a long time ago, and a similar one reported by Finn recently (addressed by removing ioremap() use from the SWIM driver. Tested on my Falcon in 030 mode - untested but should work the same on 040/060 (the extra page tables cleared there would never have been set up anyway). Signed-off-by: Michael Schmitz [geert: Minor commit description improvements] [geert: This was fixed in 2.4.23, but not in 2.5.x] Signed-off-by: Geert Uytterhoeven Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- arch/m68k/mm/kmap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c index c2a38321c96d..3b420f6d8822 100644 --- a/arch/m68k/mm/kmap.c +++ b/arch/m68k/mm/kmap.c @@ -89,7 +89,8 @@ static inline void free_io_area(void *addr) for (p = &iolist ; (tmp = *p) ; p = &tmp->next) { if (tmp->addr == addr) { *p = tmp->next; - __iounmap(tmp->addr, tmp->size); + /* remove gap added in get_io_area() */ + __iounmap(tmp->addr, tmp->size - IO_SIZE); kfree(tmp); return; } -- GitLab From 60711b27c5f5d1dda01078df21520cfb63d06419 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 11 Apr 2018 20:50:14 -0400 Subject: [PATCH 1031/1299] m68k/mac: Fix SWIM memory resource end address commit 3e2816c1078eb2b5a3276eb83d4da156b3e2d04f upstream. The resource size is 0x2000 == end - start + 1. Therefore end == start + 0x2000 - 1. Cc: Laurent Vivier Cc: stable@vger.kernel.org # v4.14+ Tested-by: Stan Johnson Signed-off-by: Finn Thain Acked-by: Laurent Vivier Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- arch/m68k/mac/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 22123f7e8f75..2004b3f72d80 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -1017,7 +1017,7 @@ int __init mac_platform_init(void) struct resource swim_rsrc = { .flags = IORESOURCE_MEM, .start = (resource_size_t)swim_base, - .end = (resource_size_t)swim_base + 0x2000, + .end = (resource_size_t)swim_base + 0x1FFF, }; platform_device_register_simple("swim", -1, &swim_rsrc, 1); -- GitLab From 980899da5dc9249aef2329ae662f16a97062e8b1 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 8 May 2018 10:55:09 +0200 Subject: [PATCH 1032/1299] serial: sh-sci: Use spin_{try}lock_irqsave instead of open coding version commit 8afb1d2c12163f77777f84616a8e9444d0050ebe upstream. Commit 40f70c03e33a ("serial: sh-sci: add locking to console write function to avoid SMP lockup") copied the strategy to avoid locking problems in conjuncture with the console from the UART8250 driver. Instead using directly spin_{try}lock_irqsave(), local_irq_save() followed by spin_{try}lock() was used. While this is correct on mainline, for -rt it is a problem. spin_{try}lock() will check if it is running in a valid context. Since the local_irq_save() has already been executed, the context has changed and spin_{try}lock() will complain. The reason why spin_{try}lock() complains is that on -rt the spin locks are turned into mutexes and therefore can sleep. Sleeping with interrupts disabled is not valid. BUG: sleeping function called from invalid context at /home/wagi/work/rt/v4.4-cip-rt/kernel/locking/rtmutex.c:995 in_atomic(): 0, irqs_disabled(): 128, pid: 778, name: irq/76-eth0 CPU: 0 PID: 778 Comm: irq/76-eth0 Not tainted 4.4.126-test-cip22-rt14-00403-gcd03665c8318 #12 Hardware name: Generic RZ/G1 (Flattened Device Tree) Backtrace: [] (dump_backtrace) from [] (show_stack+0x18/0x1c) r7:c06b01f0 r6:60010193 r5:00000000 r4:c06b01f0 [] (show_stack) from [] (dump_stack+0x78/0x94) [] (dump_stack) from [] (___might_sleep+0x134/0x194) r7:60010113 r6:c06d3559 r5:00000000 r4:ffffe000 [] (___might_sleep) from [] (rt_spin_lock+0x20/0x74) r5:c06f4d60 r4:c06f4d60 [] (rt_spin_lock) from [] (serial_console_write+0x100/0x118) r5:c06f4d60 r4:c06f4d60 [] (serial_console_write) from [] (call_console_drivers.constprop.15+0x10c/0x124) r10:c06d2894 r9:c04e18b0 r8:00000028 r7:00000000 r6:c06d3559 r5:c06d2798 r4:c06b9914 r3:c02576e4 [] (call_console_drivers.constprop.15) from [] (console_unlock+0x32c/0x430) r10:c06d30d8 r9:00000028 r8:c06dd518 r7:00000005 r6:00000000 r5:c06d2798 r4:c06d2798 r3:00000028 [] (console_unlock) from [] (vprintk_emit+0x394/0x4f0) r10:c06d2798 r9:c06d30ee r8:00000006 r7:00000005 r6:c06a78fc r5:00000027 r4:00000003 [] (vprintk_emit) from [] (vprintk+0x28/0x30) r10:c060bd46 r9:00001000 r8:c06b9a90 r7:c06b9a90 r6:c06b994c r5:c06b9a3c r4:c0062fa8 [] (vprintk) from [] (vprintk_default+0x10/0x14) [] (vprintk_default) from [] (printk+0x78/0x84) [] (printk) from [] (credit_entropy_bits+0x17c/0x2cc) r3:00000001 r2:decade60 r1:c061a5ee r0:c061a523 r4:00000006 [] (credit_entropy_bits) from [] (add_interrupt_randomness+0x160/0x178) r10:466e7196 r9:1f536000 r8:fffeef74 r7:00000000 r6:c06b9a60 r5:c06b9a3c r4:dfbcf680 [] (add_interrupt_randomness) from [] (irq_thread+0x1e8/0x248) r10:c006537c r9:c06cdf21 r8:c0064fcc r7:df791c24 r6:df791c00 r5:ffffe000 r4:df525180 [] (irq_thread) from [] (kthread+0x108/0x11c) r10:00000000 r9:00000000 r8:c0065184 r7:df791c00 r6:00000000 r5:df791d00 r4:decac000 [] (kthread) from [] (ret_from_fork+0x14/0x3c) r8:00000000 r7:00000000 r6:00000000 r5:c003fa9c r4:df791d00 Cc: Sebastian Andrzej Siewior Signed-off-by: Daniel Wagner Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c6daa315ee4e..8bc8fe2b75f7 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2854,16 +2854,15 @@ static void serial_console_write(struct console *co, const char *s, unsigned long flags; int locked = 1; - local_irq_save(flags); #if defined(SUPPORT_SYSRQ) if (port->sysrq) locked = 0; else #endif if (oops_in_progress) - locked = spin_trylock(&port->lock); + locked = spin_trylock_irqsave(&port->lock, flags); else - spin_lock(&port->lock); + spin_lock_irqsave(&port->lock, flags); /* first save SCSCR then disable interrupts, keep clock source */ ctrl = serial_port_in(port, SCSCR); @@ -2883,8 +2882,7 @@ static void serial_console_write(struct console *co, const char *s, serial_port_out(port, SCSCR, ctrl); if (locked) - spin_unlock(&port->lock); - local_irq_restore(flags); + spin_unlock_irqrestore(&port->lock, flags); } static int serial_console_setup(struct console *co, char *options) -- GitLab From 8ae5d476a3b7bd7938abcd0f926925c7c81fd79b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 20 Apr 2018 09:14:56 -0500 Subject: [PATCH 1033/1299] signal/xtensa: Consistenly use SIGBUS in do_unaligned_user commit 7de712ccc096b81d23cc0a941cd9b8cb3956605d upstream. While working on changing this code to use force_sig_fault I discovered that do_unaliged_user is sets si_signo to SIGBUS and passes SIGSEGV to force_sig_info. Which is just b0rked. The code is reporting a SIGBUS error so replace the SIGSEGV with SIGBUS. Cc: Chris Zankel Cc: Max Filippov Cc: linux-xtensa@linux-xtensa.org Cc: stable@vger.kernel.org Acked-by: Max Filippov Fixes: 5a0015d62668 ("[PATCH] xtensa: Architecture support for Tensilica Xtensa Part 3") Signed-off-by: "Eric W. Biederman" Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index bae697a06a98..2986bc88a18e 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -336,7 +336,7 @@ do_unaligned_user (struct pt_regs *regs) info.si_errno = 0; info.si_code = BUS_ADRALN; info.si_addr = (void *) regs->excvaddr; - force_sig_info(SIGSEGV, &info, current); + force_sig_info(SIGBUS, &info, current); } #endif -- GitLab From b7ac0389770aacc2dc91d17dc44fd4dcc1438faf Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 26 Apr 2018 10:53:00 +0200 Subject: [PATCH 1034/1299] PM / Domains: Fix error path during attach in genpd commit 72038df3c580c4c326b83c86149d7ac34007532a upstream. In case the PM domain fails to be powered on in genpd_dev_pm_attach(), it returns -EPROBE_DEFER, but keeping the device attached to its PM domain. This leads to problems when the next attempt to attach is re-tried. More precisely, in that situation an -EEXIST error code is returned, because the device already has its PM domain pointer assigned, from the first attempt. Now, because of the sloppy error handling by the existing callers of dev_pm_domain_attach(), probing is allowed to continue when -EEXIST is returned. However, in such case there are no guarantees that the PM domain is powered on by genpd, which may lead to hangs when buses/drivers tried to access their devices. Let's fix this behaviour, simply by detaching the device when powering on fails in genpd_dev_pm_attach(). Cc: v4.11+ # v4.11+ Signed-off-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/domain.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index b3b78079aa9f..c276ba1c0a19 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2162,6 +2162,9 @@ int genpd_dev_pm_attach(struct device *dev) genpd_lock(pd); ret = genpd_power_on(pd, 0); genpd_unlock(pd); + + if (ret) + genpd_remove_device(pd, dev); out: return ret ? -EPROBE_DEFER : 0; } -- GitLab From ba0be5973f9e5eef705409a021159a6cc0571135 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 14 Jun 2018 10:01:52 +0200 Subject: [PATCH 1035/1299] PM / core: Fix supplier device runtime PM usage counter imbalance commit 47e5abfb546a3ace23a77453dc2e9db92704c5ac upstream. If a device link is added via device_link_add() by the driver of the link's consumer device, the supplier's runtime PM usage counter is going to be dropped by the pm_runtime_put_suppliers() call in driver_probe_device(). However, in that case it is not incremented unless the supplier driver is already present and the link is not stateless. That leads to a runtime PM usage counter imbalance for the supplier device in a few cases. To prevent that from happening, bump up the supplier runtime PM usage counter in device_link_add() for all links with the DL_FLAG_PM_RUNTIME flag set that are added at the consumer probe time. Use pm_runtime_get_noresume() for that as the callers of device_link_add() who want the supplier to be resumed by it are expected to pass DL_FLAG_RPM_ACTIVE in flags to it anyway, but additionally resume the supplier if the link is added during consumer driver probe to retain the existing behavior for the callers depending on it. Fixes: 21d5c57b3726 (PM / runtime: Use device links) Reported-by: Ulf Hansson Reviewed-by: Ulf Hansson Tested-by: Marek Szyprowski Cc: 4.10+ # 4.10+ Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index a359934ffd85..b054cb2fd2b9 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -217,6 +217,13 @@ struct device_link *device_link_add(struct device *consumer, link->rpm_active = true; } pm_runtime_new_link(consumer); + /* + * If the link is being added by the consumer driver at probe + * time, balance the decrementation of the supplier's runtime PM + * usage counter after consumer probe in driver_probe_device(). + */ + if (consumer->links.status == DL_DEV_PROBING) + pm_runtime_get_noresume(supplier); } get_device(supplier); link->supplier = supplier; @@ -235,12 +242,12 @@ struct device_link *device_link_add(struct device *consumer, switch (consumer->links.status) { case DL_DEV_PROBING: /* - * Balance the decrementation of the supplier's - * runtime PM usage counter after consumer probe - * in driver_probe_device(). + * Some callers expect the link creation during + * consumer driver probe to resume the supplier + * even without DL_FLAG_RPM_ACTIVE. */ if (flags & DL_FLAG_PM_RUNTIME) - pm_runtime_get_sync(supplier); + pm_runtime_resume(supplier); link->status = DL_STATE_CONSUMER_PROBE; break; -- GitLab From 8b03376580c9c2b4d239bc43527bb9a35dc2078e Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Thu, 14 Jun 2018 15:56:08 +0200 Subject: [PATCH 1036/1299] PM / OPP: Update voltage in case freq == old_freq commit c5c2a97b3ac7d1ec19e7cff9e38caca6afefc3de upstream. This commit fixes a rare but possible case when the clk rate is updated without update of the regulator voltage. At boot up, CPUfreq checks if the system is running at the right freq. This is a sanity check in case a bootloader set clk rate that is outside of freq table present with cpufreq core. In such cases system can be unstable so better to change it to a freq that is preset in freq-table. The CPUfreq takes next freq that is >= policy->cur and this is our target_freq that needs to be set now. dev_pm_opp_set_rate(dev, target_freq) checks the target_freq and the old_freq (a current rate). If these are equal it returns early. If not, it searches for OPP (old_opp) that fits best to old_freq (not listed in the table) and updates old_freq (!). Here, we can end up with old_freq = old_opp.rate = target_freq, which is not handled in _generic_set_opp_regulator(). It's supposed to update voltage only when freq > old_freq || freq > old_freq. if (freq > old_freq) { ret = _set_opp_voltage(dev, reg, new_supply); [...] if (freq < old_freq) { ret = _set_opp_voltage(dev, reg, new_supply); if (ret) It results in, no voltage update while clk rate is updated. Example: freq-table = { 1000MHz 1.15V 666MHZ 1.10V 333MHz 1.05V } boot-up-freq = 800MHz # not listed in freq-table freq = target_freq = 1GHz old_freq = 800Mhz old_opp = _find_freq_ceil(opp_table, &old_freq); #(old_freq is modified!) old_freq = 1GHz Fixes: 6a0712f6f199 ("PM / OPP: Add dev_pm_opp_set_rate()") Cc: 4.6+ # v4.6+ Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/opp/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 0459b1204694..d4862775b9f6 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -552,7 +552,7 @@ static int _generic_set_opp_regulator(const struct opp_table *opp_table, } /* Scaling up? Scale voltage before frequency */ - if (freq > old_freq) { + if (freq >= old_freq) { ret = _set_opp_voltage(dev, reg, new_supply); if (ret) goto restore_voltage; -- GitLab From 3c22218ed86921ac18b4554093a1034feb3ebb5b Mon Sep 17 00:00:00 2001 From: Maxim Moseychuk Date: Thu, 4 Jan 2018 21:43:03 +0300 Subject: [PATCH 1037/1299] usb: do not reset if a low-speed or full-speed device timed out commit 6e01827ed93947895680fbdad68c072a0f4e2450 upstream. Some low-speed and full-speed devices (for example, bluetooth) do not have time to initialize. For them, ETIMEDOUT is a valid error. We need to give them another try. Otherwise, they will never be initialized correctly and in dmesg will be messages "Bluetooth: hci0 command 0x1002 tx timeout" or similars. Fixes: 264904ccc33c ("usb: retry reset if a device times out") Cc: stable Signed-off-by: Maxim Moseychuk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 442be7f312f6..e5f77e611451 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4519,7 +4519,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * reset. But only on the first attempt, * lest we get into a time out/reset loop */ - if (r == 0 || (r == -ETIMEDOUT && retries == 0)) + if (r == 0 || (r == -ETIMEDOUT && + retries == 0 && + udev->speed > USB_SPEED_FULL)) break; } udev->descriptor.bMaxPacketSize0 = -- GitLab From 4e0ce7053a12dcc0fc19628fccea7f0bed77eaf5 Mon Sep 17 00:00:00 2001 From: Ingo Flaschberger Date: Tue, 1 May 2018 16:10:33 +0200 Subject: [PATCH 1038/1299] 1wire: family module autoload fails because of upper/lower case mismatch. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 065c09563c872e52813a17218c52cd642be1dca6 upstream. 1wire family module autoload fails because of upper/lower  case mismatch. Signed-off-by: Ingo Flaschberger Acked-by: Evgeniy Polyakov Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 0c2a5a8327bd..6f9e9505b34c 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -750,7 +750,7 @@ int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) /* slave modules need to be loaded in a context with unlocked mutex */ mutex_unlock(&dev->mutex); - request_module("w1-family-0x%02x", rn->family); + request_module("w1-family-0x%02X", rn->family); mutex_lock(&dev->mutex); spin_lock(&w1_flock); -- GitLab From 040fecfd714a67decf3334727da4d6ea99a2f576 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 4 Jun 2018 12:13:26 +0100 Subject: [PATCH 1039/1299] ASoC: dapm: delete dapm_kcontrol_data paths list before freeing it commit ff2faf1289c1f81b5b26b9451dd1c2006aac8db8 upstream. dapm_kcontrol_data is freed as part of dapm_kcontrol_free(), leaving the paths pointer dangling in the list. This leads to system crash when we try to unload and reload sound card. I hit this bug during ADSP crash/reboot test case on Dragon board DB410c. Without this patch, on SLAB Poisoning enabled build, kernel crashes with "BUG kmalloc-128 (Tainted: G W ): Poison overwritten" Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- sound/soc/soc-dapm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dcef67a9bd48..1c9f6a0d234f 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -430,6 +430,8 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, static void dapm_kcontrol_free(struct snd_kcontrol *kctl) { struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl); + + list_del(&data->paths); kfree(data->wlist); kfree(data); } -- GitLab From 7a1d79de77f531a4d227f93554215678f8c7ad31 Mon Sep 17 00:00:00 2001 From: Paul Handrigan Date: Fri, 4 May 2018 16:37:41 -0500 Subject: [PATCH 1040/1299] ASoC: cs35l35: Add use_single_rw to regmap config commit 6a6ad7face95af0b9e6aaf1eb2261eb70240b89b upstream. Add the use_single_rw flag to regmap config since the device does not support bulk transactions over i2c. Signed-off-by: Paul Handrigan Signed-off-by: Mark Brown Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/cs35l35.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index 129978d1243e..51ce53e23599 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c @@ -1106,6 +1106,7 @@ static struct regmap_config cs35l35_regmap = { .readable_reg = cs35l35_readable_register, .precious_reg = cs35l35_precious_register, .cache_type = REGCACHE_RBTREE, + .use_single_rw = true, }; static irqreturn_t cs35l35_irq(int irq, void *data) -- GitLab From b5e8118779e54b6e31a00e7e96fb4be94b62a18f Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Sat, 28 Apr 2018 22:51:38 +0200 Subject: [PATCH 1041/1299] ASoC: cirrus: i2s: Fix LRCLK configuration commit 2d534113be9a2aa532a1ae127a57e83558aed358 upstream. The bit responsible for LRCLK polarity is i2s_tlrs (0), not i2s_trel (2) (refer to "EP93xx User's Guide"). Previously card drivers which specified SND_SOC_DAIFMT_NB_IF actually got SND_SOC_DAIFMT_NB_NF, an adaptation is necessary to retain the old behavior. Signed-off-by: Alexander Sverdlin Signed-off-by: Mark Brown Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- sound/soc/cirrus/edb93xx.c | 2 +- sound/soc/cirrus/ep93xx-i2s.c | 8 ++++---- sound/soc/cirrus/snappercl15.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c index c53bd6f2c2d7..3d011abaa266 100644 --- a/sound/soc/cirrus/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c @@ -67,7 +67,7 @@ static struct snd_soc_dai_link edb93xx_dai = { .cpu_dai_name = "ep93xx-i2s", .codec_name = "spi0.0", .codec_dai_name = "cs4271-hifi", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &edb93xx_ops, }; diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 934f8aefdd90..38c240c97041 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -213,24 +213,24 @@ static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: /* Negative bit clock, lrclk low on left word */ - clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL); + clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_LRS); break; case SND_SOC_DAIFMT_NB_IF: /* Negative bit clock, lrclk low on right word */ clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP; - clk_cfg |= EP93XX_I2S_CLKCFG_REL; + clk_cfg |= EP93XX_I2S_CLKCFG_LRS; break; case SND_SOC_DAIFMT_IB_NF: /* Positive bit clock, lrclk low on left word */ clk_cfg |= EP93XX_I2S_CLKCFG_CKP; - clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + clk_cfg &= ~EP93XX_I2S_CLKCFG_LRS; break; case SND_SOC_DAIFMT_IB_IF: /* Positive bit clock, lrclk low on right word */ - clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL; + clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_LRS; break; } diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index 2334ec19e7eb..11ff7b2672b2 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c @@ -72,7 +72,7 @@ static struct snd_soc_dai_link snappercl15_dai = { .codec_dai_name = "tlv320aic23-hifi", .codec_name = "tlv320aic23-codec.0-001a", .platform_name = "ep93xx-i2s", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &snappercl15_ops, }; -- GitLab From b2291a435c292743cc6f9ec528e9e2d72cabfa9a Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Sat, 28 Apr 2018 22:51:39 +0200 Subject: [PATCH 1042/1299] ASoC: cirrus: i2s: Fix {TX|RX}LinCtrlData setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 5d302ed3cc80564fb835bed5fdba1e1250ecc9e5 upstream. According to "EP93xx User’s Guide", I2STXLinCtrlData and I2SRXLinCtrlData registers actually have different format. The only currently used bit (Left_Right_Justify) has different position. Fix this and simplify the whole setup taking into account the fact that both registers have zero default value. The practical effect of the above is repaired SND_SOC_DAIFMT_RIGHT_J support (currently unused). Signed-off-by: Alexander Sverdlin Signed-off-by: Mark Brown Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- sound/soc/cirrus/ep93xx-i2s.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 38c240c97041..0dc3852c4621 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -51,7 +51,9 @@ #define EP93XX_I2S_WRDLEN_24 (1 << 0) #define EP93XX_I2S_WRDLEN_32 (2 << 0) -#define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */ +#define EP93XX_I2S_RXLINCTRLDATA_R_JUST BIT(1) /* Right justify */ + +#define EP93XX_I2S_TXLINCTRLDATA_R_JUST BIT(2) /* Right justify */ #define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */ #define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */ @@ -170,25 +172,25 @@ static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); - unsigned int clk_cfg, lin_ctrl; + unsigned int clk_cfg; + unsigned int txlin_ctrl = 0; + unsigned int rxlin_ctrl = 0; clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); - lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: clk_cfg |= EP93XX_I2S_CLKCFG_REL; - lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; break; case SND_SOC_DAIFMT_LEFT_J: clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; - lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; break; case SND_SOC_DAIFMT_RIGHT_J: clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; - lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST; + rxlin_ctrl |= EP93XX_I2S_RXLINCTRLDATA_R_JUST; + txlin_ctrl |= EP93XX_I2S_TXLINCTRLDATA_R_JUST; break; default: @@ -237,8 +239,8 @@ static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* Write new register values */ ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg); ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg); - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl); - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl); + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, rxlin_ctrl); + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, txlin_ctrl); return 0; } -- GitLab From 0cf93821e34da487c5c86d0078c70dcd47b9ae7e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Jun 2018 11:28:20 +0200 Subject: [PATCH 1043/1299] thermal: bcm2835: Stop using printk format %pCr commit bd2a07f71a1e2e198f8a30cb551d9defe422d83d upstream. Printk format "%pCr" will be removed soon, as clk_get_rate() must not be called in atomic context. Replace it by printing the variable that already holds the clock rate. Note that calling clk_get_rate() is safe here, as the code runs in task context. Link: http://lkml.kernel.org/r/1527845302-12159-3-git-send-email-geert+renesas@glider.be To: Jia-Ju Bai To: Jonathan Corbet To: Michael Turquette To: Stephen Boyd To: Zhang Rui To: Eduardo Valentin To: Eric Anholt To: Stefan Wahren To: Greg Kroah-Hartman Cc: Sergey Senozhatsky Cc: Petr Mladek Cc: Linus Torvalds Cc: Steven Rostedt Cc: linux-doc@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org # 4.12+ Signed-off-by: Geert Uytterhoeven Acked-by: Stefan Wahren Signed-off-by: Petr Mladek Signed-off-by: Greg Kroah-Hartman --- drivers/thermal/broadcom/bcm2835_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c index a4d6a0e2e993..23ad4f9f2143 100644 --- a/drivers/thermal/broadcom/bcm2835_thermal.c +++ b/drivers/thermal/broadcom/bcm2835_thermal.c @@ -213,8 +213,8 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) rate = clk_get_rate(data->clk); if ((rate < 1920000) || (rate > 5000000)) dev_warn(&pdev->dev, - "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n", - data->clk, data->clk); + "Clock %pCn running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n", + data->clk, rate); /* register of thermal sensor and get info from DT */ tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data, -- GitLab From 9fcc267de242acb5da81861334519c150c3dc445 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Jun 2018 11:28:19 +0200 Subject: [PATCH 1044/1299] clk: renesas: cpg-mssr: Stop using printk format %pCr commit ef4b0be62641d296cf4c0ad8f75ab83ab066ed51 upstream. Printk format "%pCr" will be removed soon, as clk_get_rate() must not be called in atomic context. Replace it by open-coding the operation. This is safe here, as the code runs in task context. Link: http://lkml.kernel.org/r/1527845302-12159-2-git-send-email-geert+renesas@glider.be To: Jia-Ju Bai To: Jonathan Corbet To: Michael Turquette To: Stephen Boyd To: Zhang Rui To: Eduardo Valentin To: Eric Anholt To: Stefan Wahren To: Greg Kroah-Hartman Cc: Sergey Senozhatsky Cc: Petr Mladek Cc: Linus Torvalds Cc: Steven Rostedt Cc: linux-doc@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Geert Uytterhoeven Cc: stable@vger.kernel.org # 4.5+ Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Signed-off-by: Petr Mladek Signed-off-by: Greg Kroah-Hartman --- drivers/clk/renesas/renesas-cpg-mssr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index e580a5e6346c..30c23b882675 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -248,8 +248,9 @@ struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec, dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx, PTR_ERR(clk)); else - dev_dbg(dev, "clock (%u, %u) is %pC at %pCr Hz\n", - clkspec->args[0], clkspec->args[1], clk, clk); + dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n", + clkspec->args[0], clkspec->args[1], clk, + clk_get_rate(clk)); return clk; } @@ -314,7 +315,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, if (IS_ERR_OR_NULL(clk)) goto fail; - dev_dbg(dev, "Core clock %pC at %pCr Hz\n", clk, clk); + dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); priv->clks[id] = clk; return; @@ -380,7 +381,7 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, if (IS_ERR(clk)) goto fail; - dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk); + dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); priv->clks[id] = clk; return; -- GitLab From ea0ac01f68aa01cc391f18148342fc4ecc912860 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Jun 2018 11:28:22 +0200 Subject: [PATCH 1045/1299] lib/vsprintf: Remove atomic-unsafe support for %pCr commit 666902e42fd8344b923c02dc5b0f37948ff4f225 upstream. "%pCr" formats the current rate of a clock, and calls clk_get_rate(). The latter obtains a mutex, hence it must not be called from atomic context. Remove support for this rarely-used format, as vsprintf() (and e.g. printk()) must be callable from any context. Any remaining out-of-tree users will start seeing the clock's name printed instead of its rate. Reported-by: Jia-Ju Bai Fixes: 900cca2944254edd ("lib/vsprintf: add %pC{,n,r} format specifiers for clocks") Link: http://lkml.kernel.org/r/1527845302-12159-5-git-send-email-geert+renesas@glider.be To: Jia-Ju Bai To: Jonathan Corbet To: Michael Turquette To: Stephen Boyd To: Zhang Rui To: Eduardo Valentin To: Eric Anholt To: Stefan Wahren To: Greg Kroah-Hartman Cc: Sergey Senozhatsky Cc: Petr Mladek Cc: Linus Torvalds Cc: Steven Rostedt Cc: linux-doc@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Geert Uytterhoeven Cc: stable@vger.kernel.org # 4.1+ Signed-off-by: Geert Uytterhoeven Signed-off-by: Petr Mladek Signed-off-by: Greg Kroah-Hartman --- Documentation/printk-formats.txt | 3 +-- lib/vsprintf.c | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index 361789df51ec..d1aecf53badb 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -397,11 +397,10 @@ struct clk %pC pll1 %pCn pll1 - %pCr 1560000000 For printing struct clk structures. ``%pC`` and ``%pCn`` print the name (Common Clock Framework) or address (legacy clock framework) of the -structure; ``%pCr`` prints the current clock rate. +structure. Passed by reference. diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 86c3385b9eb3..4a990f3fd345 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1392,9 +1392,6 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec, return string(buf, end, NULL, spec); switch (fmt[1]) { - case 'r': - return number(buf, end, clk_get_rate(clk), spec); - case 'n': default: #ifdef CONFIG_COMMON_CLK -- GitLab From 5f7a15af646d8c9cf52f7d86b43a590fabf4e808 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Mon, 14 May 2018 15:40:29 -0400 Subject: [PATCH 1046/1299] ftrace/selftest: Have the reset_trigger code be a bit more careful commit 756b56a9e832e063edc83be7c3889e98c536dd2b upstream. The trigger code is picky in how it can be disabled as there may be dependencies between different events and synthetic events. Change the order on how triggers are reset. 1) Reset triggers of all synthetic events first 2) Remove triggers with actions attached to them 3) Remove all other triggers If this order isn't followed, then some triggers will not be reset, and an error may happen because a trigger is busy. Cc: stable@vger.kernel.org Fixes: cfa0963dc474f ("kselftests/ftrace : Add event trigger testcases") Reviewed-by: Namhyung Kim Acked-by: Masami Hiramatsu Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman --- .../testing/selftests/ftrace/test.d/functions | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions index f2019b37370d..6a4982d029bf 100644 --- a/tools/testing/selftests/ftrace/test.d/functions +++ b/tools/testing/selftests/ftrace/test.d/functions @@ -15,14 +15,29 @@ reset_tracer() { # reset the current tracer echo nop > current_tracer } -reset_trigger() { # reset all current setting triggers - grep -v ^# events/*/*/trigger | +reset_trigger_file() { + # remove action triggers first + grep -H ':on[^:]*(' $@ | + while read line; do + cmd=`echo $line | cut -f2- -d: | cut -f1 -d" "` + file=`echo $line | cut -f1 -d:` + echo "!$cmd" >> $file + done + grep -Hv ^# $@ | while read line; do cmd=`echo $line | cut -f2- -d: | cut -f1 -d" "` - echo "!$cmd" > `echo $line | cut -f1 -d:` + file=`echo $line | cut -f1 -d:` + echo "!$cmd" > $file done } +reset_trigger() { # reset all current setting triggers + if [ -d events/synthetic ]; then + reset_trigger_file events/synthetic/*/trigger + fi + reset_trigger_file events/*/*/trigger +} + reset_events_filter() { # reset all current setting filters grep -v ^none events/*/*/filter | while read line; do -- GitLab From 5eff5dbf3108017efe46ad3803b2122dfd1128b5 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 24 Mar 2018 17:57:49 +0100 Subject: [PATCH 1047/1299] mips: ftrace: fix static function graph tracing commit 6fb8656646f996d1eef42e6d56203c4915cb9e08 upstream. ftrace_graph_caller was never run after calling ftrace_trace_function, breaking the function graph tracer. Fix this, bringing it in line with the x86 implementation. While we're at it, also streamline the control flow of _mcount a bit to reduce the number of branches. This issue was reported before: https://www.linux-mips.org/archives/linux-mips/2014-11/msg00295.html Signed-off-by: Matthias Schiffer Tested-by: Matt Redfearn Patchwork: https://patchwork.linux-mips.org/patch/18929/ Signed-off-by: Paul Burton Cc: stable@vger.kernel.org # v3.17+ Signed-off-by: Greg Kroah-Hartman --- arch/mips/kernel/mcount.S | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index f2ee7e1e3342..cff52b283e03 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -119,10 +119,20 @@ NESTED(_mcount, PT_SIZE, ra) EXPORT_SYMBOL(_mcount) PTR_LA t1, ftrace_stub PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ - bne t1, t2, static_trace + beq t1, t2, fgraph_trace nop + MCOUNT_SAVE_REGS + + move a0, ra /* arg1: self return address */ + jalr t2 /* (1) call *ftrace_trace_function */ + move a1, AT /* arg2: parent's return address */ + + MCOUNT_RESTORE_REGS + +fgraph_trace: #ifdef CONFIG_FUNCTION_GRAPH_TRACER + PTR_LA t1, ftrace_stub PTR_L t3, ftrace_graph_return bne t1, t3, ftrace_graph_caller nop @@ -131,24 +141,11 @@ EXPORT_SYMBOL(_mcount) bne t1, t3, ftrace_graph_caller nop #endif - b ftrace_stub -#ifdef CONFIG_32BIT - addiu sp, sp, 8 -#else - nop -#endif -static_trace: - MCOUNT_SAVE_REGS - - move a0, ra /* arg1: self return address */ - jalr t2 /* (1) call *ftrace_trace_function */ - move a1, AT /* arg2: parent's return address */ - - MCOUNT_RESTORE_REGS #ifdef CONFIG_32BIT addiu sp, sp, 8 #endif + .globl ftrace_stub ftrace_stub: RETURN_BACK -- GitLab From 26e03f8dcd347a543f62eb58831ff417736d9d53 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 30 May 2018 08:19:22 -0400 Subject: [PATCH 1048/1299] branch-check: fix long->int truncation when profiling branches commit 2026d35741f2c3ece73c11eb7e4a15d7c2df9ebe upstream. The function __builtin_expect returns long type (see the gcc documentation), and so do macros likely and unlikely. Unfortunatelly, when CONFIG_PROFILE_ANNOTATED_BRANCHES is selected, the macros likely and unlikely expand to __branch_check__ and __branch_check__ truncates the long type to int. This unintended truncation may cause bugs in various kernel code (we found a bug in dm-writecache because of it), so it's better to fix __branch_check__ to return long. Link: http://lkml.kernel.org/r/alpine.LRH.2.02.1805300818140.24812@file01.intranet.prod.int.rdu2.redhat.com Cc: Ingo Molnar Cc: stable@vger.kernel.org Fixes: 1f0d69a9fc815 ("tracing: profile likely and unlikely annotations") Signed-off-by: Mikulas Patocka Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman --- include/linux/compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 853929f98962..a704d032713b 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -21,7 +21,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, #define unlikely_notrace(x) __builtin_expect(!!(x), 0) #define __branch_check__(x, expect, is_constant) ({ \ - int ______r; \ + long ______r; \ static struct ftrace_likely_data \ __attribute__((__aligned__(4))) \ __attribute__((section("_ftrace_annotated_branch"))) \ -- GitLab From 3ffecef63d0932c3becceb1ef166e95e9a1ca33d Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 22 May 2018 08:14:51 -0500 Subject: [PATCH 1049/1299] ipmi:bt: Set the timeout before doing a capabilities check commit fe50a7d0393a552e4539da2d31261a59d6415950 upstream. There was one place where the timeout value for an operation was not being set, if a capabilities request was done from idle. Move the timeout value setting to before where that change might be requested. IMHO the cause here is the invisible returns in the macros. Maybe that's a job for later, though. Reported-by: Nordmark Claes Signed-off-by: Corey Minyard Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/char/ipmi/ipmi_bt_sm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index feafdab734ae..4835b588b783 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c @@ -522,11 +522,12 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) if (status & BT_H_BUSY) /* clear a leftover H_BUSY */ BT_CONTROL(BT_H_BUSY); + bt->timeout = bt->BT_CAP_req2rsp; + /* Read BT capabilities if it hasn't been done yet */ if (!bt->BT_CAP_outreqs) BT_STATE_CHANGE(BT_STATE_CAPABILITIES_BEGIN, SI_SM_CALL_WITHOUT_DELAY); - bt->timeout = bt->BT_CAP_req2rsp; BT_SI_SM_RETURN(SI_SM_IDLE); case BT_STATE_XACTION_START: -- GitLab From affd84024cbedfc0ee091396d064fbf1366ea8fe Mon Sep 17 00:00:00 2001 From: Amit Pundir Date: Mon, 16 Apr 2018 12:10:24 +0530 Subject: [PATCH 1050/1299] Bluetooth: hci_qca: Avoid missing rampatch failure with userspace fw loader commit 7dc5fe0814c35ec4e7d2e8fa30abab72e0e6a172 upstream. AOSP use userspace firmware loader to load firmwares, which will return -EAGAIN in case qca/rampatch_00440302.bin is not found. Since there is no rampatch for dragonboard820c QCA controller revision, just make it work as is. CC: Loic Poulain CC: Nicolas Dechesne CC: Marcel Holtmann CC: Johan Hedberg CC: Stable Signed-off-by: Amit Pundir Signed-off-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/hci_qca.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index c9f0ac083a3e..6f4ebd5e54c8 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -936,6 +936,12 @@ static int qca_setup(struct hci_uart *hu) } else if (ret == -ENOENT) { /* No patch/nvm-config found, run with original fw/config */ ret = 0; + } else if (ret == -EAGAIN) { + /* + * Userspace firmware loader will return -EAGAIN in case no + * patch/nvm-config is found, so run with original fw/config. + */ + ret = 0; } /* Setup bdaddr */ -- GitLab From a47c3c48769ab1e41f1dd53aa116a89f1f208aa1 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Fri, 11 May 2018 19:54:19 +0900 Subject: [PATCH 1051/1299] printk: fix possible reuse of va_list variable commit 988a35f8da1dec5a8cd2788054d1e717be61bf25 upstream. I noticed that there is a possibility that printk_safe_log_store() causes kernel oops because "args" parameter is passed to vsnprintf() again when atomic_cmpxchg() detected that we raced. Fix this by using va_copy(). Link: http://lkml.kernel.org/r/201805112002.GIF21216.OFVHFOMLJtQFSO@I-love.SAKURA.ne.jp Cc: Peter Zijlstra Cc: Steven Rostedt Cc: dvyukov@google.com Cc: syzkaller@googlegroups.com Cc: fengguang.wu@intel.com Cc: linux-kernel@vger.kernel.org Signed-off-by: Tetsuo Handa Fixes: 42a0bb3f71383b45 ("printk/nmi: generic solution for safe printk in NMI") Cc: 4.7+ # v4.7+ Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek Signed-off-by: Greg Kroah-Hartman --- kernel/printk/printk_safe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 3cdaeaef9ce1..d989cc238198 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -85,6 +85,7 @@ static __printf(2, 0) int printk_safe_log_store(struct printk_safe_seq_buf *s, { int add; size_t len; + va_list ap; again: len = atomic_read(&s->len); @@ -103,7 +104,9 @@ static __printf(2, 0) int printk_safe_log_store(struct printk_safe_seq_buf *s, if (!len) smp_rmb(); - add = vscnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, args); + va_copy(ap, args); + add = vscnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, ap); + va_end(ap); if (!add) return 0; -- GitLab From 02832578eb9d4572a3194e50e5d2268ff049f9f4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 2 Feb 2018 09:54:14 -0800 Subject: [PATCH 1052/1299] fuse: fix congested state leak on aborted connections commit 8a301eb16d99983a4961f884690ec97b92e7dcfe upstream. If a connection gets aborted while congested, FUSE can leave nr_wb_congested[] stuck until reboot causing wait_iff_congested() to wait spuriously which can lead to severe performance degradation. The leak is caused by gating congestion state clearing with fc->connected test in request_end(). This was added way back in 2009 by 26c3679101db ("fuse: destroy bdi on umount"). While the commit description doesn't explain why the test was added, it most likely was to avoid dereferencing bdi after it got destroyed. Since then, bdi lifetime rules have changed many times and now we're always guaranteed to have access to the bdi while the superblock is alive (fc->sb). Drop fc->connected conditional to avoid leaking congestion states. Signed-off-by: Tejun Heo Reported-by: Joshua Miller Cc: Johannes Weiner Cc: stable@vger.kernel.org # v2.6.29+ Acked-by: Jan Kara Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/fuse/dev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 13c65dd2d37d..261fd13a75c6 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -381,8 +381,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) if (!fc->blocked && waitqueue_active(&fc->blocked_waitq)) wake_up(&fc->blocked_waitq); - if (fc->num_background == fc->congestion_threshold && - fc->connected && fc->sb) { + if (fc->num_background == fc->congestion_threshold && fc->sb) { clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC); clear_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC); } -- GitLab From 2f7bf369b5f8699231398aef585cb680828f3ac9 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 8 Feb 2018 15:17:38 +0100 Subject: [PATCH 1053/1299] fuse: atomic_o_trunc should truncate pagecache commit df0e91d488276086bc07da2e389986cae0048c37 upstream. Fuse has an "atomic_o_trunc" mode, where userspace filesystem uses the O_TRUNC flag in the OPEN request to truncate the file atomically with the open. In this mode there's no need to send a SETATTR request to userspace after the open, so fuse_do_setattr() checks this mode and returns. But this misses the important step of truncating the pagecache. Add the missing parts of truncation to the ATTR_OPEN branch. Reported-by: Chad Austin Fixes: 6ff958edbf39 ("fuse: add atomic open+truncate support") Signed-off-by: Miklos Szeredi Cc: Signed-off-by: Greg Kroah-Hartman --- fs/fuse/dir.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 24967382a7b1..7a980b4462d9 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1629,8 +1629,19 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, return err; if (attr->ia_valid & ATTR_OPEN) { - if (fc->atomic_o_trunc) + /* This is coming from open(..., ... | O_TRUNC); */ + WARN_ON(!(attr->ia_valid & ATTR_SIZE)); + WARN_ON(attr->ia_size != 0); + if (fc->atomic_o_trunc) { + /* + * No need to send request to userspace, since actual + * truncation has already been done by OPEN. But still + * need to truncate page cache. + */ + i_size_write(inode, 0); + truncate_pagecache(inode, 0); return 0; + } file = NULL; } -- GitLab From 3a37d85a90dafb4986dbfc356c6d662f0db665a8 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 1 May 2018 13:12:14 +0900 Subject: [PATCH 1054/1299] fuse: don't keep dead fuse_conn at fuse_fill_super(). commit 543b8f8662fe6d21f19958b666ab0051af9db21a upstream. syzbot is reporting use-after-free at fuse_kill_sb_blk() [1]. Since sb->s_fs_info field is not cleared after fc was released by fuse_conn_put() when initialization failed, fuse_kill_sb_blk() finds already released fc and tries to hold the lock. Fix this by clearing sb->s_fs_info field after calling fuse_conn_put(). [1] https://syzkaller.appspot.com/bug?id=a07a680ed0a9290585ca424546860464dd9658db Signed-off-by: Tetsuo Handa Reported-by: syzbot Fixes: 3b463ae0c626 ("fuse: invalidation reverse calls") Cc: John Muir Cc: Csaba Henk Cc: Anand Avati Cc: # v2.6.31 Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/fuse/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 94a745acaef8..a13ecefa9cd1 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -1176,6 +1176,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) fuse_dev_free(fud); err_put_conn: fuse_conn_put(fc); + sb->s_fs_info = NULL; err_fput: fput(file); err: -- GitLab From 69829f749a432eeb1c208b113bfec598a23ee823 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 31 May 2018 12:26:10 +0200 Subject: [PATCH 1055/1299] fuse: fix control dir setup and teardown commit 6becdb601bae2a043d7fb9762c4d48699528ea6e upstream. syzbot is reporting NULL pointer dereference at fuse_ctl_remove_conn() [1]. Since fc->ctl_ndents is incremented by fuse_ctl_add_conn() when new_inode() failed, fuse_ctl_remove_conn() reaches an inode-less dentry and tries to clear d_inode(dentry)->i_private field. Fix by only adding the dentry to the array after being fully set up. When tearing down the control directory, do d_invalidate() on it to get rid of any mounts that might have been added. [1] https://syzkaller.appspot.com/bug?id=f396d863067238959c91c0b7cfc10b163638cac6 Reported-by: syzbot Fixes: bafa96541b25 ("[PATCH] fuse: add control filesystem") Cc: # v2.6.18 Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/fuse/control.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/fs/fuse/control.c b/fs/fuse/control.c index b9ea99c5b5b3..5be0339dcceb 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -211,10 +211,11 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent, if (!dentry) return NULL; - fc->ctl_dentry[fc->ctl_ndents++] = dentry; inode = new_inode(fuse_control_sb); - if (!inode) + if (!inode) { + dput(dentry); return NULL; + } inode->i_ino = get_next_ino(); inode->i_mode = mode; @@ -228,6 +229,9 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent, set_nlink(inode, nlink); inode->i_private = fc; d_add(dentry, inode); + + fc->ctl_dentry[fc->ctl_ndents++] = dentry; + return dentry; } @@ -284,7 +288,10 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc) for (i = fc->ctl_ndents - 1; i >= 0; i--) { struct dentry *dentry = fc->ctl_dentry[i]; d_inode(dentry)->i_private = NULL; - d_drop(dentry); + if (!i) { + /* Get rid of submounts: */ + d_invalidate(dentry); + } dput(dentry); } drop_nlink(d_inode(fuse_control_sb->s_root)); -- GitLab From 5fefd9a5d97a45bc2927acc0aa53a098e80a4d41 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 30 May 2018 18:48:04 +0530 Subject: [PATCH 1056/1299] powerpc/mm/hash: Add missing isync prior to kernel stack SLB switch commit 91d06971881f71d945910de128658038513d1b24 upstream. Currently we do not have an isync, or any other context synchronizing instruction prior to the slbie/slbmte in _switch() that updates the SLB entry for the kernel stack. However that is not correct as outlined in the ISA. From Power ISA Version 3.0B, Book III, Chapter 11, page 1133: "Changing the contents of ... the contents of SLB entries ... can have the side effect of altering the context in which data addresses and instruction addresses are interpreted, and in which instructions are executed and data accesses are performed. ... These side effects need not occur in program order, and therefore may require explicit synchronization by software. ... The synchronizing instruction before the context-altering instruction ensures that all instructions up to and including that synchronizing instruction are fetched and executed in the context that existed before the alteration." And page 1136: "For data accesses, the context synchronizing instruction before the slbie, slbieg, slbia, slbmte, tlbie, or tlbiel instruction ensures that all preceding instructions that access data storage have completed to a point at which they have reported all exceptions they will cause." We're not aware of any bugs caused by this, but it should be fixed regardless. Add the missing isync when updating kernel stack SLB entry. Cc: stable@vger.kernel.org Signed-off-by: Aneesh Kumar K.V [mpe: Flesh out change log with more ISA text & explanation] Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/entry_64.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 6f07c687fc05..c194f4c8e66b 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -597,6 +597,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) * actually hit this code path. */ + isync slbie r6 slbie r6 /* Workaround POWER5 < DD2.1 issue */ slbmte r7,r0 -- GitLab From c12d24161611e6038631778e614581edc4647eb6 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Thu, 17 May 2018 15:37:15 +1000 Subject: [PATCH 1057/1299] powerpc/ptrace: Fix setting 512B aligned breakpoints with PTRACE_SET_DEBUGREG commit 4f7c06e26ec9cf7fe9f0c54dc90079b6a4f4b2c3 upstream. In commit e2a800beaca1 ("powerpc/hw_brk: Fix off by one error when validating DAWR region end") we fixed setting the DAWR end point to its max value via PPC_PTRACE_SETHWDEBUG. Unfortunately we broke PTRACE_SET_DEBUGREG when setting a 512 byte aligned breakpoint. PTRACE_SET_DEBUGREG currently sets the length of the breakpoint to zero (memset() in hw_breakpoint_init()). This worked with arch_validate_hwbkpt_settings() before the above patch was applied but is now broken if the breakpoint is 512byte aligned. This sets the length of the breakpoint to 8 bytes when using PTRACE_SET_DEBUGREG. Fixes: e2a800beaca1 ("powerpc/hw_brk: Fix off by one error when validating DAWR region end") Cc: stable@vger.kernel.org # v3.11+ Signed-off-by: Michael Neuling Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/ptrace.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index f52ad5bb7109..81750d9624ab 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -2362,6 +2362,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, /* Create a new breakpoint request if one doesn't exist already */ hw_breakpoint_init(&attr); attr.bp_addr = hw_brk.address; + attr.bp_len = 8; arch_bp_generic_fields(hw_brk.type, &attr.bp_type); -- GitLab From 1ab9092356a13ab26cf28f35943571bb35d5d875 Mon Sep 17 00:00:00 2001 From: Anju T Sudhakar Date: Wed, 16 May 2018 12:05:18 +0530 Subject: [PATCH 1058/1299] powerpc/perf: Fix memory allocation for core-imc based on num_possible_cpus() commit d2032678e57fc508d7878307badde8f89b632ba3 upstream. Currently memory is allocated for core-imc based on cpu_present_mask, which has bit 'cpu' set iff cpu is populated. We use (cpu number / threads per core) as the array index to access the memory. Under some circumstances firmware marks a CPU as GUARDed CPU and boot the system, until cleared of errors, these CPU's are unavailable for all subsequent boots. GUARDed CPUs are possible but not present from linux view, so it blows a hole when we assume the max length of our allocation is driven by our max present cpus, where as one of the cpus might be online and be beyond the max present cpus, due to the hole. So (cpu number / threads per core) value bounds the array index and leads to memory overflow. Call trace observed during a guard test: Faulting instruction address: 0xc000000000149f1c cpu 0x69: Vector: 380 (Data Access Out of Range) at [c000003fea303420] pc:c000000000149f1c: prefetch_freepointer+0x14/0x30 lr:c00000000014e0f8: __kmalloc+0x1a8/0x1ac sp:c000003fea3036a0 msr:9000000000009033 dar:c9c54b2c91dbf6b7 current = 0xc000003fea2c0000 paca = 0xc00000000fddd880 softe: 3 irq_happened: 0x01 pid = 1, comm = swapper/104 Linux version 4.16.7-openpower1 (smc@smc-desktop) (gcc version 6.4.0 (Buildroot 2018.02.1-00006-ga8d1126)) #2 SMP Fri May 4 16:44:54 PDT 2018 enter ? for help call trace: __kmalloc+0x1a8/0x1ac (unreliable) init_imc_pmu+0x7f4/0xbf0 opal_imc_counters_probe+0x3fc/0x43c platform_drv_probe+0x48/0x80 driver_probe_device+0x22c/0x308 __driver_attach+0xa0/0xd8 bus_for_each_dev+0x88/0xb4 driver_attach+0x2c/0x40 bus_add_driver+0x1e8/0x228 driver_register+0xd0/0x114 __platform_driver_register+0x50/0x64 opal_imc_driver_init+0x24/0x38 do_one_initcall+0x150/0x15c kernel_init_freeable+0x250/0x254 kernel_init+0x1c/0x150 ret_from_kernel_thread+0x5c/0xc8 Allocating memory for core-imc based on cpu_possible_mask, which has bit 'cpu' set iff cpu is populatable, will fix this issue. Reported-by: Pridhiviraj Paidipeddi Signed-off-by: Anju T Sudhakar Reviewed-by: Balbir Singh Tested-by: Pridhiviraj Paidipeddi Fixes: 39a846db1d57 ("powerpc/perf: Add core IMC PMU support") Cc: stable@vger.kernel.org # v4.14+ Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/perf/imc-pmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c index da6ba9ba73ed..b73961b95c34 100644 --- a/arch/powerpc/perf/imc-pmu.c +++ b/arch/powerpc/perf/imc-pmu.c @@ -1131,7 +1131,7 @@ static int init_nest_pmu_ref(void) static void cleanup_all_core_imc_memory(void) { - int i, nr_cores = DIV_ROUND_UP(num_present_cpus(), threads_per_core); + int i, nr_cores = DIV_ROUND_UP(num_possible_cpus(), threads_per_core); struct imc_mem_info *ptr = core_imc_pmu->mem_info; int size = core_imc_pmu->counter_mem_size; @@ -1239,7 +1239,7 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent, if (!pmu_ptr->pmu.name) return -ENOMEM; - nr_cores = DIV_ROUND_UP(num_present_cpus(), threads_per_core); + nr_cores = DIV_ROUND_UP(num_possible_cpus(), threads_per_core); pmu_ptr->mem_info = kcalloc(nr_cores, sizeof(struct imc_mem_info), GFP_KERNEL); -- GitLab From 919c9b8187bc8aa66388e50248c7f6c5b0c87e97 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Thu, 17 May 2018 15:37:14 +1000 Subject: [PATCH 1059/1299] powerpc/ptrace: Fix enforcement of DAWR constraints commit cd6ef7eebf171bfcba7dc2df719c2a4958775040 upstream. Back when we first introduced the DAWR, in commit 4ae7ebe9522a ("powerpc: Change hardware breakpoint to allow longer ranges"), we screwed up the constraint making it a 1024 byte boundary rather than a 512. This makes the check overly permissive. Fortunately GDB is the only real user and it always did they right thing, so we never noticed. This fixes the constraint to 512 bytes. Fixes: 4ae7ebe9522a ("powerpc: Change hardware breakpoint to allow longer ranges") Cc: stable@vger.kernel.org # v3.9+ Signed-off-by: Michael Neuling Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/hw_breakpoint.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c index 53b9c1dfd7d9..ceafad83ef50 100644 --- a/arch/powerpc/kernel/hw_breakpoint.c +++ b/arch/powerpc/kernel/hw_breakpoint.c @@ -175,8 +175,8 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) if (cpu_has_feature(CPU_FTR_DAWR)) { length_max = 512 ; /* 64 doublewords */ /* DAWR region can't cross 512 boundary */ - if ((bp->attr.bp_addr >> 10) != - ((bp->attr.bp_addr + bp->attr.bp_len - 1) >> 10)) + if ((bp->attr.bp_addr >> 9) != + ((bp->attr.bp_addr + bp->attr.bp_len - 1) >> 9)) return -EINVAL; } if (info->len > -- GitLab From 0e8bb91c6dd6a77c60279c4fd83975ef257ed3c2 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Wed, 30 May 2018 19:22:50 +1000 Subject: [PATCH 1060/1299] powerpc/powernv/ioda2: Remove redundant free of TCE pages commit 98fd72fe82527fd26618062b60cfd329451f2329 upstream. When IODA2 creates a PE, it creates an IOMMU table with it_ops::free set to pnv_ioda2_table_free() which calls pnv_pci_ioda2_table_free_pages(). Since iommu_tce_table_put() calls it_ops::free when the last reference to the table is released, explicit call to pnv_pci_ioda2_table_free_pages() is not needed so let's remove it. This should fix double free in the case of PCI hotuplug as pnv_pci_ioda2_table_free_pages() does not reset neither iommu_table::it_base nor ::it_size. This was not exposed by SRIOV as it uses different code path via pnv_pcibios_sriov_disable(). IODA1 does not inialize it_ops::free so it does not have this issue. Fixes: c5f7700bbd2e ("powerpc/powernv: Dynamically release PE") Cc: stable@vger.kernel.org # v4.8+ Signed-off-by: Alexey Kardashevskiy Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/powernv/pci-ioda.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 57f9e55f4352..677b29ef4532 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -3591,7 +3591,6 @@ static void pnv_pci_ioda2_release_pe_dma(struct pnv_ioda_pe *pe) WARN_ON(pe->table_group.group); } - pnv_pci_ioda2_table_free_pages(tbl); iommu_tce_table_put(tbl); } -- GitLab From 134e70c22eb0a47dcb30f20859f331344b5018db Mon Sep 17 00:00:00 2001 From: Haren Myneni Date: Mon, 4 Jun 2018 18:33:38 +1000 Subject: [PATCH 1061/1299] powerpc/powernv: copy/paste - Mask SO bit in CR commit 75743649064ec0cf5ddd69f240ef23af66dde16e upstream. NX can set the 3rd bit in CR register for XER[SO] (Summary overflow) which is not related to paste request. The current paste function returns failure for a successful request when this bit is set. So mask this bit and check the proper return status. Fixes: 2392c8c8c045 ("powerpc/powernv/vas: Define copy/paste interfaces") Cc: stable@vger.kernel.org # v4.14+ Signed-off-by: Haren Myneni Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/powernv/copy-paste.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/powernv/copy-paste.h b/arch/powerpc/platforms/powernv/copy-paste.h index c9a503623431..e9a6c35f8a29 100644 --- a/arch/powerpc/platforms/powernv/copy-paste.h +++ b/arch/powerpc/platforms/powernv/copy-paste.h @@ -42,5 +42,6 @@ static inline int vas_paste(void *paste_address, int offset) : "b" (offset), "b" (paste_address) : "memory", "cr0"); - return (cr >> CR0_SHIFT) & CR0_MASK; + /* We mask with 0xE to ignore SO */ + return (cr >> CR0_SHIFT) & 0xE; } -- GitLab From a5d49dfb20c943d6b9b49bdca3142795db2c55ef Mon Sep 17 00:00:00 2001 From: Akshay Adiga Date: Wed, 16 May 2018 17:32:14 +0530 Subject: [PATCH 1062/1299] powerpc/powernv/cpuidle: Init all present cpus for deep states commit ac9816dcbab53c57bcf1d7b15370b08f1e284318 upstream. Init all present cpus for deep states instead of "all possible" cpus. Init fails if a possible cpu is guarded. Resulting in making only non-deep states available for cpuidle/hotplug. Stewart says, this means that for single threaded workloads, if you guard out a CPU core you'll not get WoF (Workload Optimised Frequency), which means that performance goes down when you wouldn't expect it to. Fixes: 77b54e9f213f ("powernv/powerpc: Add winkle support for offline cpus") Cc: stable@vger.kernel.org # v3.19+ Signed-off-by: Akshay Adiga Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/powernv/idle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index 443d5ca71995..028d6d12ba32 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c @@ -78,7 +78,7 @@ static int pnv_save_sprs_for_deep_states(void) uint64_t msr_val = MSR_IDLE; uint64_t psscr_val = pnv_deepest_stop_psscr_val; - for_each_possible_cpu(cpu) { + for_each_present_cpu(cpu) { uint64_t pir = get_hard_smp_processor_id(cpu); uint64_t hsprg0_val = (uint64_t)&paca[cpu]; @@ -741,7 +741,7 @@ static int __init pnv_init_idle_states(void) int cpu; pr_info("powernv: idle: Saving PACA pointers of all CPUs in their thread sibling PACA\n"); - for_each_possible_cpu(cpu) { + for_each_present_cpu(cpu) { int base_cpu = cpu_first_thread_sibling(cpu); int idx = cpu_thread_in_core(cpu); int i; -- GitLab From 3b185e667b5222f170a337d57ca338fd2f66f828 Mon Sep 17 00:00:00 2001 From: "Gautham R. Shenoy" Date: Thu, 31 May 2018 17:45:09 +0530 Subject: [PATCH 1063/1299] cpuidle: powernv: Fix promotion from snooze if next state disabled commit 0a4ec6aa035a52c422eceb2ed51ed88392a3d6c2 upstream. The commit 78eaa10f027c ("cpuidle: powernv/pseries: Auto-promotion of snooze to deeper idle state") introduced a timeout for the snooze idle state so that it could be eventually be promoted to a deeper idle state. The snooze timeout value is static and set to the target residency of the next idle state, which would train the cpuidle governor to pick the next idle state eventually. The unfortunate side-effect of this is that if the next idle state(s) is disabled, the CPU will forever remain in snooze, despite the fact that the system is completely idle, and other deeper idle states are available. This patch fixes the issue by dynamically setting the snooze timeout to the target residency of the next enabled state on the device. Before Patch: POWER8 : Only nap disabled. $ cpupower monitor sleep 30 sleep took 30.01297 seconds and exited with status 0 |Idle_Stats PKG |CORE|CPU | snoo | Nap | Fast 0| 8| 0| 96.41| 0.00| 0.00 0| 8| 1| 96.43| 0.00| 0.00 0| 8| 2| 96.47| 0.00| 0.00 0| 8| 3| 96.35| 0.00| 0.00 0| 8| 4| 96.37| 0.00| 0.00 0| 8| 5| 96.37| 0.00| 0.00 0| 8| 6| 96.47| 0.00| 0.00 0| 8| 7| 96.47| 0.00| 0.00 POWER9: Shallow states (stop0lite, stop1lite, stop2lite, stop0, stop1, stop2) disabled: $ cpupower monitor sleep 30 sleep took 30.05033 seconds and exited with status 0 |Idle_Stats PKG |CORE|CPU | snoo | stop | stop | stop | stop | stop | stop | stop | stop 0| 16| 0| 89.79| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00 0| 16| 1| 90.12| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00 0| 16| 2| 90.21| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00 0| 16| 3| 90.29| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00 After Patch: POWER8 : Only nap disabled. $ cpupower monitor sleep 30 sleep took 30.01200 seconds and exited with status 0 |Idle_Stats PKG |CORE|CPU | snoo | Nap | Fast 0| 8| 0| 16.58| 0.00| 77.21 0| 8| 1| 18.42| 0.00| 75.38 0| 8| 2| 4.70| 0.00| 94.09 0| 8| 3| 17.06| 0.00| 81.73 0| 8| 4| 3.06| 0.00| 95.73 0| 8| 5| 7.00| 0.00| 96.80 0| 8| 6| 1.00| 0.00| 98.79 0| 8| 7| 5.62| 0.00| 94.17 POWER9: Shallow states (stop0lite, stop1lite, stop2lite, stop0, stop1, stop2) disabled: $ cpupower monitor sleep 30 sleep took 30.02110 seconds and exited with status 0 |Idle_Stats PKG |CORE|CPU | snoo | stop | stop | stop | stop | stop | stop | stop | stop 0| 0| 0| 0.69| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 9.39| 89.70 0| 0| 1| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.05| 93.21 0| 0| 2| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 89.93 0| 0| 3| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 0.00| 93.26 Fixes: 78eaa10f027c ("cpuidle: powernv/pseries: Auto-promotion of snooze to deeper idle state") Cc: stable@vger.kernel.org # v4.2+ Signed-off-by: Gautham R. Shenoy Reviewed-by: Balbir Singh Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/cpuidle/cpuidle-powernv.c | 32 +++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c index e06605b21841..1d7d5d121d55 100644 --- a/drivers/cpuidle/cpuidle-powernv.c +++ b/drivers/cpuidle/cpuidle-powernv.c @@ -43,9 +43,31 @@ struct stop_psscr_table { static struct stop_psscr_table stop_psscr_table[CPUIDLE_STATE_MAX] __read_mostly; -static u64 snooze_timeout __read_mostly; +static u64 default_snooze_timeout __read_mostly; static bool snooze_timeout_en __read_mostly; +static u64 get_snooze_timeout(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + int i; + + if (unlikely(!snooze_timeout_en)) + return default_snooze_timeout; + + for (i = index + 1; i < drv->state_count; i++) { + struct cpuidle_state *s = &drv->states[i]; + struct cpuidle_state_usage *su = &dev->states_usage[i]; + + if (s->disabled || su->disable) + continue; + + return s->target_residency * tb_ticks_per_usec; + } + + return default_snooze_timeout; +} + static int snooze_loop(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -56,7 +78,7 @@ static int snooze_loop(struct cpuidle_device *dev, local_irq_enable(); - snooze_exit_time = get_tb() + snooze_timeout; + snooze_exit_time = get_tb() + get_snooze_timeout(dev, drv, index); ppc64_runlatch_off(); HMT_very_low(); while (!need_resched()) { @@ -463,11 +485,9 @@ static int powernv_idle_probe(void) cpuidle_state_table = powernv_states; /* Device tree can indicate more idle states */ max_idle_state = powernv_add_idle_states(); - if (max_idle_state > 1) { + default_snooze_timeout = TICK_USEC * tb_ticks_per_usec; + if (max_idle_state > 1) snooze_timeout_en = true; - snooze_timeout = powernv_states[1].target_residency * - tb_ticks_per_usec; - } } else return -ENODEV; -- GitLab From 56fbab60aa47c64898c3d18540322c317ada32ef Mon Sep 17 00:00:00 2001 From: Mahesh Salgaonkar Date: Fri, 27 Apr 2018 11:53:18 +0530 Subject: [PATCH 1064/1299] powerpc/fadump: Unregister fadump on kexec down path. commit 722cde76d68e8cc4f3de42e71c82fd40dea4f7b9 upstream. Unregister fadump on kexec down path otherwise the fadump registration in new kexec-ed kernel complains that fadump is already registered. This makes new kernel to continue using fadump registered by previous kernel which may lead to invalid vmcore generation. Hence this patch fixes this issue by un-registering fadump in fadump_cleanup() which is called during kexec path so that new kernel can register fadump with new valid values. Fixes: b500afff11f6 ("fadump: Invalidate registration and release reserved memory for general use.") Cc: stable@vger.kernel.org # v3.4+ Signed-off-by: Mahesh Salgaonkar Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/fadump.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 29d2b6050140..d0020bc1f209 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -1155,6 +1155,9 @@ void fadump_cleanup(void) init_fadump_mem_struct(&fdm, be64_to_cpu(fdm_active->cpu_state_data.destination_address)); fadump_invalidate_dump(&fdm); + } else if (fw_dump.dump_registered) { + /* Un-register Firmware-assisted dump if it was registered. */ + fadump_unregister_dump(&fdm); } } -- GitLab From 971a55574b4789c64d43c6d34f5549c337567731 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 14 May 2018 11:29:38 +0800 Subject: [PATCH 1065/1299] soc: rockchip: power-domain: Fix wrong value when power up pd with writemask commit 9e59c5f66c624b43c766a9fe3b2430e0e976bf0e upstream. Solve the pd could only ever turn off but never turn them on again, if the pd registers have the writemask bits. So far this affects the rk3328 only. Fixes: 79bb17ce8edb ("soc: rockchip: power-domain: Support domain control in hiword-registers") Cc: stable@vger.kernel.org Signed-off-by: Finley Xiao Signed-off-by: Elaine Zhang Reviewed-by: Ulf Hansson Signed-off-by: Heiko Stuebner Signed-off-by: Greg Kroah-Hartman --- drivers/soc/rockchip/pm_domains.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 40b75748835f..ba009bb9d82b 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -255,7 +255,7 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, return; else if (pd->info->pwr_w_mask) regmap_write(pmu->regmap, pmu->info->pwr_offset, - on ? pd->info->pwr_mask : + on ? pd->info->pwr_w_mask : (pd->info->pwr_mask | pd->info->pwr_w_mask)); else regmap_update_bits(pmu->regmap, pmu->info->pwr_offset, -- GitLab From c9debbd1a5b84014d8651da82ca30651d83ca322 Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Fri, 18 May 2018 15:12:23 +0530 Subject: [PATCH 1066/1299] cxl: Disable prefault_mode in Radix mode commit b6c84ba22ff3a198eb8d5552cf9b8fda1d792e54 upstream. Currently we see a kernel-oops reported on Power-9 while attaching a context to an AFU, with radix-mode and sysfs attr 'prefault_mode' set to anything other than 'none'. The backtrace of the oops is of this form: Unable to handle kernel paging request for data at address 0x00000080 Faulting instruction address: 0xc00800000bcf3b20 cpu 0x1: Vector: 300 (Data Access) at [c00000037f003800] pc: c00800000bcf3b20: cxl_load_segment+0x178/0x290 [cxl] lr: c00800000bcf39f0: cxl_load_segment+0x48/0x290 [cxl] sp: c00000037f003a80 msr: 9000000000009033 dar: 80 dsisr: 40000000 current = 0xc00000037f280000 paca = 0xc0000003ffffe600 softe: 3 irq_happened: 0x01 pid = 3529, comm = afp_no_int cxl_prefault+0xfc/0x248 [cxl] process_element_entry_psl9+0xd8/0x1a0 [cxl] cxl_attach_dedicated_process_psl9+0x44/0x130 [cxl] native_attach_process+0xc0/0x130 [cxl] afu_ioctl+0x3f4/0x5e0 [cxl] do_vfs_ioctl+0xdc/0x890 ksys_ioctl+0x68/0xf0 sys_ioctl+0x40/0xa0 system_call+0x58/0x6c The issue is caused as on Power-8 the AFU attr 'prefault_mode' was used to improve initial storage fault performance by prefaulting process segments. However on Power-9 with radix mode we don't have Storage-Segments that we can prefault. Also prefaulting process Pages will be too costly and fine-grained. Hence, since the prefaulting mechanism doesn't makes sense of radix-mode, this patch updates prefault_mode_store() to not allow any other value apart from CXL_PREFAULT_NONE when radix mode is enabled. Fixes: f24be42aab37 ("cxl: Add psl9 specific code") Cc: stable@vger.kernel.org # v4.12+ Signed-off-by: Vaibhav Jain Acked-by: Frederic Barrat Acked-by: Andrew Donnellan Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-class-cxl | 4 +++- drivers/misc/cxl/sysfs.c | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-class-cxl b/Documentation/ABI/testing/sysfs-class-cxl index 640f65e79ef1..267920a1874b 100644 --- a/Documentation/ABI/testing/sysfs-class-cxl +++ b/Documentation/ABI/testing/sysfs-class-cxl @@ -69,7 +69,9 @@ Date: September 2014 Contact: linuxppc-dev@lists.ozlabs.org Description: read/write Set the mode for prefaulting in segments into the segment table - when performing the START_WORK ioctl. Possible values: + when performing the START_WORK ioctl. Only applicable when + running under hashed page table mmu. + Possible values: none: No prefaulting (default) work_element_descriptor: Treat the work element descriptor as an effective address and diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index a8b6d6a635e9..393a80bdb846 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c @@ -331,12 +331,20 @@ static ssize_t prefault_mode_store(struct device *device, struct cxl_afu *afu = to_cxl_afu(device); enum prefault_modes mode = -1; - if (!strncmp(buf, "work_element_descriptor", 23)) - mode = CXL_PREFAULT_WED; - if (!strncmp(buf, "all", 3)) - mode = CXL_PREFAULT_ALL; if (!strncmp(buf, "none", 4)) mode = CXL_PREFAULT_NONE; + else { + if (!radix_enabled()) { + + /* only allowed when not in radix mode */ + if (!strncmp(buf, "work_element_descriptor", 23)) + mode = CXL_PREFAULT_WED; + if (!strncmp(buf, "all", 3)) + mode = CXL_PREFAULT_ALL; + } else { + dev_err(device, "Cannot prefault with radix enabled\n"); + } + } if (mode == -1) return -EINVAL; -- GitLab From eda170a9fe51284303f4999957e57e1c4b3c9ff3 Mon Sep 17 00:00:00 2001 From: David Rivshin Date: Wed, 25 Apr 2018 21:15:01 +0100 Subject: [PATCH 1067/1299] ARM: 8764/1: kgdb: fix NUMREGBYTES so that gdb_regs[] is the correct size commit 76ed0b803a2ab793a1b27d1dfe0de7955282cd34 upstream. NUMREGBYTES (which is used as the size for gdb_regs[]) is incorrectly based on DBG_MAX_REG_NUM instead of GDB_MAX_REGS. DBG_MAX_REG_NUM is the number of total registers, while GDB_MAX_REGS is the number of 'unsigned longs' it takes to serialize those registers. Since FP registers require 3 'unsigned longs' each, DBG_MAX_REG_NUM is smaller than GDB_MAX_REGS. This causes GDB 8.0 give the following error on connect: "Truncated register 19 in remote 'g' packet" This also causes the register serialization/deserialization logic to overflow gdb_regs[], overwriting whatever follows. Fixes: 834b2964b7ab ("kgdb,arm: fix register dump") Cc: # 2.6.37+ Signed-off-by: David Rivshin Acked-by: Rabin Vincent Tested-by: Daniel Thompson Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/kgdb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h index 3b73fdcf3627..8de1100d1067 100644 --- a/arch/arm/include/asm/kgdb.h +++ b/arch/arm/include/asm/kgdb.h @@ -77,7 +77,7 @@ extern int kgdb_fault_expected; #define KGDB_MAX_NO_CPUS 1 #define BUFMAX 400 -#define NUMREGBYTES (DBG_MAX_REG_NUM << 2) +#define NUMREGBYTES (GDB_MAX_REGS << 2) #define NUMCRITREGBYTES (32 << 2) #define _R0 0 -- GitLab From 3db24d2e192f1ccf1723550184e38f94d173e8ab Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Fri, 22 Jun 2018 13:37:34 -0500 Subject: [PATCH 1068/1299] ARM: dts: Fix SPI node for Arria10 commit 975ba94c2c3aca4d9f1ae26f3916d7787495ce86 upstream. Remove the unused bus-num node and change num-chipselect to num-cs to match SPI bindings. Cc: stable@vger.kernel.org Fixes: f2d6f8f817814 ("ARM: dts: socfpga: Add SPI Master1 for Arria10 SR chip") Signed-off-by: Thor Thayer Signed-off-by: Dinh Nguyen Signed-off-by: Olof Johansson Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/socfpga_arria10.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index bead79e4b2aa..9138f834bad4 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -593,8 +593,7 @@ #size-cells = <0>; reg = <0xffda5000 0x100>; interrupts = <0 102 4>; - num-chipselect = <4>; - bus-num = <0>; + num-cs = <4>; /*32bit_access;*/ tx-dma-channel = <&pdma 16>; rx-dma-channel = <&pdma 17>; -- GitLab From 3482130d8d1e60b5b08ed09874dbfafa9908df98 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 10 May 2018 14:52:23 +0200 Subject: [PATCH 1069/1299] ARM: dts: socfpga: Fix NAND controller node compatible commit d9a695f3c8098ac9684689774a151cff30d8aa25 upstream. The compatible string for the Denali NAND controller is incorrect, fix it by replacing it with one matching the DT bindings and the driver. Cc: stable@vger.kernel.org Signed-off-by: Marek Vasut Fixes: d837a80d19 ("ARM: dts: socfpga: add nand controller nodes") Cc: Steffen Trumtrar Signed-off-by: Dinh Nguyen Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/socfpga.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index 8d9f42a422cb..dcbb05076019 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi @@ -744,7 +744,7 @@ nand0: nand@ff900000 { #address-cells = <0x1>; #size-cells = <0x1>; - compatible = "denali,denali-nand-dt"; + compatible = "altr,socfpga-denali-nand"; reg = <0xff900000 0x100000>, <0xffb80000 0x10000>; reg-names = "nand_data", "denali_reg"; -- GitLab From ae6647c78ff831380851869344161f460896892a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 10 May 2018 16:37:26 +0200 Subject: [PATCH 1070/1299] ARM: dts: socfpga: Fix NAND controller clock supply commit 4eda9b766b042ea38d84df91581b03f6145a2ab0 upstream. The Denali NAND x-clock should be supplied by nand_x_clk, not by nand_clk. Fix this, otherwise the Denali driver gets incorrect clock frequency information and incorrectly configures the NAND timing. Cc: stable@vger.kernel.org Signed-off-by: Marek Vasut Fixes: d837a80d19 ("ARM: dts: socfpga: add nand controller nodes") Cc: Steffen Trumtrar Signed-off-by: Dinh Nguyen Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/socfpga.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index dcbb05076019..10d2fa183a9f 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi @@ -750,7 +750,7 @@ reg-names = "nand_data", "denali_reg"; interrupts = <0x0 0x90 0x4>; dma-mask = <0xffffffff>; - clocks = <&nand_clk>; + clocks = <&nand_x_clk>; status = "disabled"; }; -- GitLab From 14ca7d344e271c89858858abb3757642bc4c7a76 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Mon, 14 May 2018 10:15:19 -0500 Subject: [PATCH 1071/1299] ARM: dts: socfpga: Fix NAND controller node compatible for Arria10 commit 3877ef7a1ccecaae378c497e1dcddbc2dccb664c upstream. The NAND compatible "denali,denal-nand-dt" property has never been used and is obsolete. Remove it. Cc: stable@vger.kernel.org Fixes: f549af06e9b6("ARM: dts: socfpga: Add NAND device tree for Arria10") Signed-off-by: Dinh Nguyen Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/socfpga_arria10.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index 9138f834bad4..791ca15c799e 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -632,7 +632,7 @@ nand: nand@ffb90000 { #address-cells = <1>; #size-cells = <1>; - compatible = "denali,denali-nand-dt", "altr,socfpga-denali-nand"; + compatible = "altr,socfpga-denali-nand"; reg = <0xffb90000 0x72000>, <0xffb80000 0x10000>; reg-names = "nand_data", "denali_reg"; -- GitLab From cdfa28c29ad4b5933c84ac13293739040fa1a3e9 Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Thu, 7 Jun 2018 12:32:05 +0100 Subject: [PATCH 1072/1299] arm64: Fix syscall restarting around signal suppressed by tracer commit 0fe42512b2f03f9e5a20b9f55ef1013a68b4cd48 upstream. Commit 17c2895 ("arm64: Abstract syscallno manipulation") abstracts out the pt_regs.syscallno value for a syscall cancelled by a tracer as NO_SYSCALL, and provides helpers to set and check for this condition. However, the way this was implemented has the unintended side-effect of disabling part of the syscall restart logic. This comes about because the second in_syscall() check in do_signal() re-evaluates the "in a syscall" condition based on the updated pt_regs instead of the original pt_regs. forget_syscall() is explicitly called prior to the second check in order to prevent restart logic in the ret_to_user path being spuriously triggered, which means that the second in_syscall() check always yields false. This triggers a failure in tools/testing/selftests/seccomp/seccomp_bpf.c, when using ptrace to suppress a signal that interrups a nanosleep() syscall. Misbehaviour of this type is only expected in the case where a tracer suppresses a signal and the target process is either being single-stepped or the interrupted syscall attempts to restart via -ERESTARTBLOCK. This patch restores the old behaviour by performing the in_syscall() check only once at the start of the function. Fixes: 17c289586009 ("arm64: Abstract syscallno manipulation") Signed-off-by: Dave Martin Reported-by: Sumit Semwal Cc: Will Deacon Cc: # 4.14.x- Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/signal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 0bdc96c61bc0..43442b3a463f 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -676,11 +676,12 @@ static void do_signal(struct pt_regs *regs) unsigned long continue_addr = 0, restart_addr = 0; int retval = 0; struct ksignal ksig; + bool syscall = in_syscall(regs); /* * If we were from a system call, check for system call restarting... */ - if (in_syscall(regs)) { + if (syscall) { continue_addr = regs->pc; restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4); retval = regs->regs[0]; @@ -732,7 +733,7 @@ static void do_signal(struct pt_regs *regs) * Handle restarting a different system call. As above, if a debugger * has chosen to restart at a different PC, ignore the restart. */ - if (in_syscall(regs) && regs->pc == restart_addr) { + if (syscall && regs->pc == restart_addr) { if (retval == -ERESTART_RESTARTBLOCK) setup_restart_syscall(regs); user_rewind_single_step(current); -- GitLab From ee6ae5ac75abf889e89c7ad3cdb75bb15d0a6308 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 22 Jun 2018 10:25:25 +0100 Subject: [PATCH 1073/1299] arm64: kpti: Use early_param for kpti= command-line option commit b5b7dd647f2d21b93f734ce890671cd908e69b0a upstream. We inspect __kpti_forced early on as part of the cpufeature enable callback which remaps the swapper page table using non-global entries. Ensure that __kpti_forced has been updated to reflect the kpti= command-line option before we start using it. Fixes: ea1e3de85e94 ("arm64: entry: Add fake CPU feature for unmapping the kernel at EL0") Cc: # 4.16.x- Reported-by: Wei Xu Tested-by: Sudeep Holla Tested-by: Wei Xu Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/cpufeature.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 345d4e521191..718822ab6e4b 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -877,7 +877,7 @@ static int __init parse_kpti(char *str) __kpti_forced = enabled ? 1 : -1; return 0; } -__setup("kpti=", parse_kpti); +early_param("kpti", parse_kpti); #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ static const struct arm64_cpu_capabilities arm64_features[] = { -- GitLab From 64df84dcf1e4dd3b63c60dd6f36473d19060af48 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 22 Jun 2018 16:23:45 +0100 Subject: [PATCH 1074/1299] arm64: mm: Ensure writes to swapper are ordered wrt subsequent cache maintenance commit 71c8fc0c96abf8e53e74ed4d891d671e585f9076 upstream. When rewriting swapper using nG mappings, we must performance cache maintenance around each page table access in order to avoid coherency problems with the host's cacheable alias under KVM. To ensure correct ordering of the maintenance with respect to Device memory accesses made with the Stage-1 MMU disabled, DMBs need to be added between the maintenance and the corresponding memory access. This patch adds a missing DMB between writing a new page table entry and performing a clean+invalidate on the same line. Fixes: f992b4dfd58b ("arm64: kpti: Add ->enable callback to remap swapper using nG mappings") Cc: # 4.16.x- Acked-by: Mark Rutland Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/mm/proc.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index e338165000e6..bf0821b7b1ab 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -196,8 +196,9 @@ ENDPROC(idmap_cpu_replace_ttbr1) .macro __idmap_kpti_put_pgtable_ent_ng, type orr \type, \type, #PTE_NG // Same bit for blocks and pages - str \type, [cur_\()\type\()p] // Update the entry and ensure it - dc civac, cur_\()\type\()p // is visible to all CPUs. + str \type, [cur_\()\type\()p] // Update the entry and ensure + dmb sy // that it is visible to all + dc civac, cur_\()\type\()p // CPUs. .endm /* -- GitLab From 728ea2302acc19cd83164b38408fd5f84e5153b2 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 26 Apr 2018 12:50:46 +0200 Subject: [PATCH 1075/1299] ARM64: dts: meson: disable sd-uhs modes on the libretech-cc commit d5b4885b1dff72ac670b518cfeaac719d768bd4d upstream. There is a problem with the sd-uhs mode when doing a soft reboot. Switching back from 1.8v to 3.3v messes with the card, which no longer respond (timeout errors). According to the specification, we should perform a card reset (power cycling the card) but this is something we cannot control on this design. Then the only solution to restore the communication with the card is an "unplug-plug" which is not acceptable Until we find a solution, if any, disable the sd-uhs modes on this design. For the people using uhs at the moment, there will a performance drop as a result. Fixes: 3cde63ebc85c ("ARM64: dts: meson-gxl: libretech-cc: enable high speed modes") Signed-off-by: Jerome Brunet Cc: stable@vger.kernel.org Signed-off-by: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts index 64c54c92e214..d71cbf596d1f 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts @@ -205,9 +205,6 @@ bus-width = <4>; cap-sd-highspeed; - sd-uhs-sdr12; - sd-uhs-sdr25; - sd-uhs-sdr50; max-frequency = <100000000>; disable-wp; -- GitLab From 4910cc250b4dab82b42a743377d359abaee07b73 Mon Sep 17 00:00:00 2001 From: Frank Rowand Date: Wed, 16 May 2018 21:19:51 -0700 Subject: [PATCH 1076/1299] of: overlay: validate offset from property fixups commit 482137bf2aecd887ebfa8756456764a2f6a0e545 upstream. The smatch static checker marks the data in offset as untrusted, leading it to warn: drivers/of/resolver.c:125 update_usages_of_a_phandle_reference() error: buffer underflow 'prop->value' 's32min-s32max' Add check to verify that offset is within the property data. Reported-by: Dan Carpenter Signed-off-by: Frank Rowand Cc: Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- drivers/of/resolver.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index 99309cb7d372..3bf4b6489fd0 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -129,6 +129,11 @@ static int update_usages_of_a_phandle_reference(struct device_node *overlay, goto err_fail; } + if (offset < 0 || offset + sizeof(__be32) > prop->length) { + err = -EINVAL; + goto err_fail; + } + *(__be32 *)(prop->value + offset) = cpu_to_be32(phandle); } -- GitLab From 6ba51909693c7bf8c463b9c90f7f8726b710fe42 Mon Sep 17 00:00:00 2001 From: Stefan M Schaeckeler Date: Mon, 21 May 2018 16:26:14 -0700 Subject: [PATCH 1077/1299] of: unittest: for strings, account for trailing \0 in property length field commit 3b9cf7905fe3ab35ab437b5072c883e609d3498d upstream. For strings, account for trailing \0 in property length field: This is consistent with how dtc builds string properties. Function __of_prop_dup() would misbehave on such properties as it duplicates properties based on the property length field creating new string values without trailing \0s. Signed-off-by: Stefan M Schaeckeler Reviewed-by: Frank Rowand Tested-by: Frank Rowand Cc: Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- drivers/of/unittest.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 168ef0bbabde..985a85f281a8 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -164,20 +164,20 @@ static void __init of_unittest_dynamic(void) /* Add a new property - should pass*/ prop->name = "new-property"; prop->value = "new-property-data"; - prop->length = strlen(prop->value); + prop->length = strlen(prop->value) + 1; unittest(of_add_property(np, prop) == 0, "Adding a new property failed\n"); /* Try to add an existing property - should fail */ prop++; prop->name = "new-property"; prop->value = "new-property-data-should-fail"; - prop->length = strlen(prop->value); + prop->length = strlen(prop->value) + 1; unittest(of_add_property(np, prop) != 0, "Adding an existing property should have failed\n"); /* Try to modify an existing property - should pass */ prop->value = "modify-property-data-should-pass"; - prop->length = strlen(prop->value); + prop->length = strlen(prop->value) + 1; unittest(of_update_property(np, prop) == 0, "Updating an existing property should have passed\n"); @@ -185,7 +185,7 @@ static void __init of_unittest_dynamic(void) prop++; prop->name = "modify-property"; prop->value = "modify-missing-property-data-should-pass"; - prop->length = strlen(prop->value); + prop->length = strlen(prop->value) + 1; unittest(of_update_property(np, prop) == 0, "Updating a missing property should have passed\n"); -- GitLab From 1ed6871464b813c9fbdfac6878ce96af7725f614 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 4 Jun 2018 15:14:08 +0100 Subject: [PATCH 1078/1299] of: platform: stop accessing invalid dev in of_platform_device_destroy commit 522811e944ed9b36806faa019faec10f9d259cca upstream. Immediately after the platform_device_unregister() the device will be cleaned up. Accessing the freed pointer immediately after that will crash the system. Found this bug when kernel is built with CONFIG_PAGE_POISONING and testing loading/unloading audio drivers in a loop on Qcom platforms. Fix this by moving of_node_clear_flag() just before the unregister calls. Below is the crash trace: Unable to handle kernel paging request at virtual address 6b6b6b6b6b6c03 Mem abort info: ESR = 0x96000021 Exception class = DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 Data abort info: ISV = 0, ISS = 0x00000021 CM = 0, WnR = 0 [006b6b6b6b6b6c03] address between user and kernel address ranges Internal error: Oops: 96000021 [#1] PREEMPT SMP Modules linked in: CPU: 2 PID: 1784 Comm: sh Tainted: G W 4.17.0-rc7-02230-ge3a63a7ef641-dirty #204 Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT) pstate: 80000005 (Nzcv daif -PAN -UAO) pc : clear_bit+0x18/0x2c lr : of_platform_device_destroy+0x64/0xb8 sp : ffff00000c9c3930 x29: ffff00000c9c3930 x28: ffff80003d39b200 x27: ffff000008bb1000 x26: 0000000000000040 x25: 0000000000000124 x24: ffff80003a9a3080 x23: 0000000000000060 x22: ffff00000939f518 x21: ffff80003aa79e98 x20: ffff80003aa3dae0 x19: ffff80003aa3c890 x18: ffff800009feb794 x17: 0000000000000000 x16: 0000000000000000 x15: ffff800009feb790 x14: 0000000000000000 x13: ffff80003a058778 x12: ffff80003a058728 x11: ffff80003a058750 x10: 0000000000000000 x9 : 0000000000000006 x8 : ffff80003a825988 x7 : bbbbbbbbbbbbbbbb x6 : 0000000000000001 x5 : 0000000000000000 x4 : 0000000000000001 x3 : 0000000000000008 x2 : 0000000000000001 x1 : 6b6b6b6b6b6b6c03 x0 : 0000000000000000 Process sh (pid: 1784, stack limit = 0x (ptrval)) Call trace: clear_bit+0x18/0x2c q6afe_remove+0x20/0x38 apr_device_remove+0x30/0x70 device_release_driver_internal+0x170/0x208 device_release_driver+0x14/0x20 bus_remove_device+0xcc/0x150 device_del+0x10c/0x310 device_unregister+0x1c/0x70 apr_remove_device+0xc/0x18 device_for_each_child+0x50/0x80 apr_remove+0x18/0x20 rpmsg_dev_remove+0x38/0x68 device_release_driver_internal+0x170/0x208 device_release_driver+0x14/0x20 bus_remove_device+0xcc/0x150 device_del+0x10c/0x310 device_unregister+0x1c/0x70 qcom_smd_remove_device+0xc/0x18 device_for_each_child+0x50/0x80 qcom_smd_unregister_edge+0x3c/0x70 smd_subdev_remove+0x18/0x28 rproc_stop+0x48/0xd8 rproc_shutdown+0x60/0xe8 state_store+0xbc/0xf8 dev_attr_store+0x18/0x28 sysfs_kf_write+0x3c/0x50 kernfs_fop_write+0x118/0x1e0 __vfs_write+0x18/0x110 vfs_write+0xa4/0x1a8 ksys_write+0x48/0xb0 sys_write+0xc/0x18 el0_svc_naked+0x30/0x34 Code: d2800022 8b400c21 f9800031 9ac32043 (c85f7c22) ---[ end trace 32020935775616a2 ]--- Signed-off-by: Srinivas Kandagatla Cc: stable@vger.kernel.org Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- drivers/of/platform.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index ac15d0e3d27d..0f49718c6012 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -533,6 +533,9 @@ int of_platform_device_destroy(struct device *dev, void *data) if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS)) device_for_each_child(dev, NULL, of_platform_device_destroy); + of_node_clear_flag(dev->of_node, OF_POPULATED); + of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); + if (dev->bus == &platform_bus_type) platform_device_unregister(to_platform_device(dev)); #ifdef CONFIG_ARM_AMBA @@ -540,8 +543,6 @@ int of_platform_device_destroy(struct device *dev, void *data) amba_device_unregister(to_amba_device(dev)); #endif - of_node_clear_flag(dev->of_node, OF_POPULATED); - of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); return 0; } EXPORT_SYMBOL_GPL(of_platform_device_destroy); -- GitLab From 1bf1a5e21798518fd6a025c6e0c0168955f5e8e6 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Wed, 9 May 2018 11:55:35 -0700 Subject: [PATCH 1079/1299] tpm: fix use after free in tpm2_load_context() commit 8c81c24758ffbf17cf06c6835d361ffa57be2f0e upstream. If load context command returns with TPM2_RC_HANDLE or TPM2_RC_REFERENCE_H0 then we have use after free in line 114 and double free in 117. Fixes: 4d57856a21ed2 ("tpm2: add session handle context saving and restoring to the space code") Cc: stable@vger.kernel.org Signed-off-by: Tadeusz Struk Reviewed-by: Jarkko Sakkinen Signed-off--by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm2-space.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index e2e059d8ffec..d26ea7513226 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -102,8 +102,9 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 *buf, * TPM_RC_REFERENCE_H0 means the session has been * flushed outside the space */ - rc = -ENOENT; + *handle = 0; tpm_buf_destroy(&tbuf); + return -ENOENT; } else if (rc > 0) { dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n", __func__, rc); -- GitLab From c41cb9cb5611747d64c3d569c1e9937f3d90e965 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 22 May 2018 14:37:18 -0700 Subject: [PATCH 1080/1299] tpm: fix race condition in tpm_common_write() commit 3ab2011ea368ec3433ad49e1b9e1c7b70d2e65df upstream. There is a race condition in tpm_common_write function allowing two threads on the same /dev/tpm, or two different applications on the same /dev/tpmrm to overwrite each other commands/responses. Fixed this by taking the priv->buffer_mutex early in the function. Also converted the priv->data_pending from atomic to a regular size_t type. There is no need for it to be atomic since it is only touched under the protection of the priv->buffer_mutex. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Tadeusz Struk Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm-dev-common.c | 40 ++++++++++++++----------------- drivers/char/tpm/tpm-dev.h | 2 +- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 461bf0b8a094..98cf36fb068d 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c @@ -37,7 +37,7 @@ static void timeout_work(struct work_struct *work) struct file_priv *priv = container_of(work, struct file_priv, work); mutex_lock(&priv->buffer_mutex); - atomic_set(&priv->data_pending, 0); + priv->data_pending = 0; memset(priv->data_buffer, 0, sizeof(priv->data_buffer)); mutex_unlock(&priv->buffer_mutex); } @@ -46,7 +46,6 @@ void tpm_common_open(struct file *file, struct tpm_chip *chip, struct file_priv *priv) { priv->chip = chip; - atomic_set(&priv->data_pending, 0); mutex_init(&priv->buffer_mutex); setup_timer(&priv->user_read_timer, user_reader_timeout, (unsigned long)priv); @@ -59,29 +58,24 @@ ssize_t tpm_common_read(struct file *file, char __user *buf, size_t size, loff_t *off) { struct file_priv *priv = file->private_data; - ssize_t ret_size; - ssize_t orig_ret_size; + ssize_t ret_size = 0; int rc; del_singleshot_timer_sync(&priv->user_read_timer); flush_work(&priv->work); - ret_size = atomic_read(&priv->data_pending); - if (ret_size > 0) { /* relay data */ - orig_ret_size = ret_size; - if (size < ret_size) - ret_size = size; + mutex_lock(&priv->buffer_mutex); - mutex_lock(&priv->buffer_mutex); + if (priv->data_pending) { + ret_size = min_t(ssize_t, size, priv->data_pending); rc = copy_to_user(buf, priv->data_buffer, ret_size); - memset(priv->data_buffer, 0, orig_ret_size); + memset(priv->data_buffer, 0, priv->data_pending); if (rc) ret_size = -EFAULT; - mutex_unlock(&priv->buffer_mutex); + priv->data_pending = 0; } - atomic_set(&priv->data_pending, 0); - + mutex_unlock(&priv->buffer_mutex); return ret_size; } @@ -92,17 +86,19 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, size_t in_size = size; ssize_t out_size; + if (in_size > TPM_BUFSIZE) + return -E2BIG; + + mutex_lock(&priv->buffer_mutex); + /* Cannot perform a write until the read has cleared either via * tpm_read or a user_read_timer timeout. This also prevents split * buffered writes from blocking here. */ - if (atomic_read(&priv->data_pending) != 0) + if (priv->data_pending != 0) { + mutex_unlock(&priv->buffer_mutex); return -EBUSY; - - if (in_size > TPM_BUFSIZE) - return -E2BIG; - - mutex_lock(&priv->buffer_mutex); + } if (copy_from_user (priv->data_buffer, (void __user *) buf, in_size)) { @@ -133,7 +129,7 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, return out_size; } - atomic_set(&priv->data_pending, out_size); + priv->data_pending = out_size; mutex_unlock(&priv->buffer_mutex); /* Set a timeout by which the reader must come claim the result */ @@ -150,5 +146,5 @@ void tpm_common_release(struct file *file, struct file_priv *priv) del_singleshot_timer_sync(&priv->user_read_timer); flush_work(&priv->work); file->private_data = NULL; - atomic_set(&priv->data_pending, 0); + priv->data_pending = 0; } diff --git a/drivers/char/tpm/tpm-dev.h b/drivers/char/tpm/tpm-dev.h index ba3b6f9dacf7..b24cfb4d3ee1 100644 --- a/drivers/char/tpm/tpm-dev.h +++ b/drivers/char/tpm/tpm-dev.h @@ -8,7 +8,7 @@ struct file_priv { struct tpm_chip *chip; /* Data passed to and from the tpm via the read/write calls */ - atomic_t data_pending; + size_t data_pending; struct mutex buffer_mutex; struct timer_list user_read_timer; /* user needs to claim result */ -- GitLab From e884ed82995ad9d31b6fa93bbaa7870a584700dd Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 18 May 2018 17:07:01 -0700 Subject: [PATCH 1081/1299] IB/qib: Fix DMA api warning with debug kernel commit 0252f73334f9ef68868e4684200bea3565a4fcee upstream. The following error occurs in a debug build when running MPI PSM: [ 307.415911] WARNING: CPU: 4 PID: 23867 at lib/dma-debug.c:1158 check_unmap+0x4ee/0xa20 [ 307.455661] ib_qib 0000:05:00.0: DMA-API: device driver failed to check map error[device address=0x00000000df82b000] [size=4096 bytes] [mapped as page] [ 307.517494] Modules linked in: [ 307.531584] ib_isert iscsi_target_mod ib_srpt target_core_mod rpcrdma sunrpc ib_srp scsi_transport_srp scsi_tgt ib_iser libiscsi ib_ipoib scsi_transport_iscsi rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm ib_cm iw_cm ib_qib intel_powerclamp coretemp rdmavt intel_rapl iosf_mbi kvm_intel kvm irqbypass crc32_pclmul ghash_clmulni_intel ipmi_ssif ib_core aesni_intel sg ipmi_si lrw gf128mul dca glue_helper ipmi_devintf iTCO_wdt gpio_ich hpwdt iTCO_vendor_support ablk_helper hpilo acpi_power_meter cryptd ipmi_msghandler ie31200_edac shpchp pcc_cpufreq lpc_ich pcspkr ip_tables xfs libcrc32c sd_mod crc_t10dif crct10dif_generic mgag200 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm ahci crct10dif_pclmul crct10dif_common drm crc32c_intel libahci tg3 libata serio_raw ptp i2c_core [ 307.846113] pps_core dm_mirror dm_region_hash dm_log dm_mod [ 307.866505] CPU: 4 PID: 23867 Comm: mpitests-IMB-MP Kdump: loaded Not tainted 3.10.0-862.el7.x86_64.debug #1 [ 307.911178] Hardware name: HP ProLiant DL320e Gen8, BIOS J05 11/09/2013 [ 307.944206] Call Trace: [ 307.956973] [] dump_stack+0x19/0x1b [ 307.982201] [] __warn+0xd8/0x100 [ 308.005999] [] warn_slowpath_fmt+0x5f/0x80 [ 308.034260] [] check_unmap+0x4ee/0xa20 [ 308.060801] [] ? page_add_file_rmap+0x2a/0x1d0 [ 308.090689] [] debug_dma_unmap_page+0x9d/0xb0 [ 308.120155] [] ? might_fault+0xa0/0xb0 [ 308.146656] [] qib_tid_free.isra.14+0x215/0x2a0 [ib_qib] [ 308.180739] [] qib_write+0x894/0x1280 [ib_qib] [ 308.210733] [] ? __inode_security_revalidate+0x70/0x80 [ 308.244837] [] ? security_file_permission+0x27/0xb0 [ 308.266025] qib_ib0.8006: multicast join failed for ff12:401b:8006:0000:0000:0000:ffff:ffff, status -22 [ 308.323421] [] vfs_write+0xc3/0x1f0 [ 308.347077] [] ? fget_light+0xfc/0x510 [ 308.372533] [] SyS_write+0x8a/0x100 [ 308.396456] [] system_call_fastpath+0x1c/0x21 The code calls a qib_map_page() which has never correctly tested for a mapping error. Fix by testing for pci_dma_mapping_error() in all cases and properly handling the failure in the caller. Additionally, streamline qib_map_page() arguments to satisfy just the single caller. Cc: Reviewed-by: Alex Estrin Tested-by: Don Dutile Reviewed-by: Don Dutile Signed-off-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/qib/qib.h | 3 +-- drivers/infiniband/hw/qib/qib_file_ops.c | 10 +++++++--- drivers/infiniband/hw/qib/qib_user_pages.c | 20 ++++++++++++-------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index f9e1c69603a5..7f19f25d09fd 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -1448,8 +1448,7 @@ u64 qib_sps_ints(void); /* * dma_addr wrappers - all 0's invalid for hw */ -dma_addr_t qib_map_page(struct pci_dev *, struct page *, unsigned long, - size_t, int); +int qib_map_page(struct pci_dev *d, struct page *p, dma_addr_t *daddr); const char *qib_get_unit_name(int unit); const char *qib_get_card_name(struct rvt_dev_info *rdi); struct pci_dev *qib_get_pci_dev(struct rvt_dev_info *rdi); diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c index 9396c1807cc3..40efc9151ec4 100644 --- a/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/drivers/infiniband/hw/qib/qib_file_ops.c @@ -364,6 +364,8 @@ static int qib_tid_update(struct qib_ctxtdata *rcd, struct file *fp, goto done; } for (i = 0; i < cnt; i++, vaddr += PAGE_SIZE) { + dma_addr_t daddr; + for (; ntids--; tid++) { if (tid == tidcnt) tid = 0; @@ -380,12 +382,14 @@ static int qib_tid_update(struct qib_ctxtdata *rcd, struct file *fp, ret = -ENOMEM; break; } + ret = qib_map_page(dd->pcidev, pagep[i], &daddr); + if (ret) + break; + tidlist[i] = tid + tidoff; /* we "know" system pages and TID pages are same size */ dd->pageshadow[ctxttid + tid] = pagep[i]; - dd->physshadow[ctxttid + tid] = - qib_map_page(dd->pcidev, pagep[i], 0, PAGE_SIZE, - PCI_DMA_FROMDEVICE); + dd->physshadow[ctxttid + tid] = daddr; /* * don't need atomic or it's overhead */ diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c index ce83ba9a12ef..16543d5e80c3 100644 --- a/drivers/infiniband/hw/qib/qib_user_pages.c +++ b/drivers/infiniband/hw/qib/qib_user_pages.c @@ -99,23 +99,27 @@ static int __qib_get_user_pages(unsigned long start_page, size_t num_pages, * * I'm sure we won't be so lucky with other iommu's, so FIXME. */ -dma_addr_t qib_map_page(struct pci_dev *hwdev, struct page *page, - unsigned long offset, size_t size, int direction) +int qib_map_page(struct pci_dev *hwdev, struct page *page, dma_addr_t *daddr) { dma_addr_t phys; - phys = pci_map_page(hwdev, page, offset, size, direction); + phys = pci_map_page(hwdev, page, 0, PAGE_SIZE, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(hwdev, phys)) + return -ENOMEM; - if (phys == 0) { - pci_unmap_page(hwdev, phys, size, direction); - phys = pci_map_page(hwdev, page, offset, size, direction); + if (!phys) { + pci_unmap_page(hwdev, phys, PAGE_SIZE, PCI_DMA_FROMDEVICE); + phys = pci_map_page(hwdev, page, 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(hwdev, phys)) + return -ENOMEM; /* * FIXME: If we get 0 again, we should keep this page, * map another, then free the 0 page. */ } - - return phys; + *daddr = phys; + return 0; } /** -- GitLab From 49e1083214c68a151b9395388791061a8d0de710 Mon Sep 17 00:00:00 2001 From: Alex Estrin Date: Wed, 2 May 2018 06:43:15 -0700 Subject: [PATCH 1082/1299] IB/{hfi1, qib}: Add handling of kernel restart commit 8d3e71136a080d007620472f50c7b3e63ba0f5cf upstream. A warm restart will fail to unload the driver, leaving link state potentially flapping up to the point the BIOS resets the adapter. Correct the issue by hooking the shutdown pci method, which will bring port down. Cc: # 4.9.x Reviewed-by: Mike Marciniszyn Signed-off-by: Alex Estrin Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/hfi1/hfi.h | 1 + drivers/infiniband/hw/hfi1/init.c | 13 +++++++++++++ drivers/infiniband/hw/qib/qib.h | 1 + drivers/infiniband/hw/qib/qib_init.c | 13 +++++++++++++ 4 files changed, 28 insertions(+) diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index ccc7b9b8637e..13a7bcaa58e6 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h @@ -1851,6 +1851,7 @@ struct cc_state *get_cc_state_protected(struct hfi1_pportdata *ppd) #define HFI1_HAS_SDMA_TIMEOUT 0x8 #define HFI1_HAS_SEND_DMA 0x10 /* Supports Send DMA */ #define HFI1_FORCED_FREEZE 0x80 /* driver forced freeze mode */ +#define HFI1_SHUTDOWN 0x100 /* device is shutting down */ /* IB dword length mask in PBC (lower 11 bits); same for all chips */ #define HFI1_PBC_LENGTH_MASK ((1 << 11) - 1) diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index 918dbd350c71..c5f50279c4f4 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c @@ -1029,6 +1029,10 @@ static void shutdown_device(struct hfi1_devdata *dd) unsigned pidx; int i; + if (dd->flags & HFI1_SHUTDOWN) + return; + dd->flags |= HFI1_SHUTDOWN; + for (pidx = 0; pidx < dd->num_pports; ++pidx) { ppd = dd->pport + pidx; @@ -1353,6 +1357,7 @@ void hfi1_disable_after_error(struct hfi1_devdata *dd) static void remove_one(struct pci_dev *); static int init_one(struct pci_dev *, const struct pci_device_id *); +static void shutdown_one(struct pci_dev *); #define DRIVER_LOAD_MSG "Intel " DRIVER_NAME " loaded: " #define PFX DRIVER_NAME ": " @@ -1369,6 +1374,7 @@ static struct pci_driver hfi1_pci_driver = { .name = DRIVER_NAME, .probe = init_one, .remove = remove_one, + .shutdown = shutdown_one, .id_table = hfi1_pci_tbl, .err_handler = &hfi1_pci_err_handler, }; @@ -1780,6 +1786,13 @@ static void remove_one(struct pci_dev *pdev) postinit_cleanup(dd); } +static void shutdown_one(struct pci_dev *pdev) +{ + struct hfi1_devdata *dd = pci_get_drvdata(pdev); + + shutdown_device(dd); +} + /** * hfi1_create_rcvhdrq - create a receive header queue * @dd: the hfi1_ib device diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 7f19f25d09fd..1dda4a2623c9 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -1250,6 +1250,7 @@ static inline struct qib_ibport *to_iport(struct ib_device *ibdev, u8 port) #define QIB_BADINTR 0x8000 /* severe interrupt problems */ #define QIB_DCA_ENABLED 0x10000 /* Direct Cache Access enabled */ #define QIB_HAS_QSFP 0x20000 /* device (card instance) has QSFP */ +#define QIB_SHUTDOWN 0x40000 /* device is shutting down */ /* * values for ppd->lflags (_ib_port_ related flags) diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index c5a4c65636d6..7ba7d2122f3b 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -850,6 +850,10 @@ static void qib_shutdown_device(struct qib_devdata *dd) struct qib_pportdata *ppd; unsigned pidx; + if (dd->flags & QIB_SHUTDOWN) + return; + dd->flags |= QIB_SHUTDOWN; + for (pidx = 0; pidx < dd->num_pports; ++pidx) { ppd = dd->pport + pidx; @@ -1189,6 +1193,7 @@ void qib_disable_after_error(struct qib_devdata *dd) static void qib_remove_one(struct pci_dev *); static int qib_init_one(struct pci_dev *, const struct pci_device_id *); +static void qib_shutdown_one(struct pci_dev *); #define DRIVER_LOAD_MSG "Intel " QIB_DRV_NAME " loaded: " #define PFX QIB_DRV_NAME ": " @@ -1206,6 +1211,7 @@ static struct pci_driver qib_driver = { .name = QIB_DRV_NAME, .probe = qib_init_one, .remove = qib_remove_one, + .shutdown = qib_shutdown_one, .id_table = qib_pci_tbl, .err_handler = &qib_pci_err_handler, }; @@ -1556,6 +1562,13 @@ static void qib_remove_one(struct pci_dev *pdev) qib_postinit_cleanup(dd); } +static void qib_shutdown_one(struct pci_dev *pdev) +{ + struct qib_devdata *dd = pci_get_drvdata(pdev); + + qib_shutdown_device(dd); +} + /** * qib_create_rcvhdrq - create a receive header queue * @dd: the qlogic_ib device -- GitLab From 1c82abc1b26ae3ce8c81f939e579b9e44452b81b Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Wed, 23 May 2018 15:30:31 +0300 Subject: [PATCH 1083/1299] IB/mlx4: Mark user MR as writable if actual virtual memory is writable commit d8f9cc328c8888369880e2527e9186d745f2bbf6 upstream. To allow rereg_user_mr to modify the MR from read-only to writable without using get_user_pages again, we needed to define the initial MR as writable. However, this was originally done unconditionally, without taking into account the writability of the underlying virtual memory. As a result, any attempt to register a read-only MR over read-only virtual memory failed. To fix this, do not add the writable flag bit when the user virtual memory is not writable (e.g. const memory). However, when the underlying memory is NOT writable (and we therefore do not define the initial MR as writable), the IB core adds a "force writable" flag to its user-pages request. If this succeeds, the reg_user_mr caller gets a writable copy of the original pages. If the user-space caller then does a rereg_user_mr operation to enable writability, this will succeed. This should not be allowed, since the original virtual memory was not writable. Cc: Fixes: 9376932d0c26 ("IB/mlx4_ib: Add support for user MR re-registration") Signed-off-by: Jason Gunthorpe Signed-off-by: Jack Morgenstein Signed-off-by: Leon Romanovsky Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/mlx4/mr.c | 50 +++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index e80a7f764a74..1587cedee13e 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c @@ -131,6 +131,40 @@ int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt, return err; } +static struct ib_umem *mlx4_get_umem_mr(struct ib_ucontext *context, u64 start, + u64 length, u64 virt_addr, + int access_flags) +{ + /* + * Force registering the memory as writable if the underlying pages + * are writable. This is so rereg can change the access permissions + * from readable to writable without having to run through ib_umem_get + * again + */ + if (!ib_access_writable(access_flags)) { + struct vm_area_struct *vma; + + down_read(¤t->mm->mmap_sem); + /* + * FIXME: Ideally this would iterate over all the vmas that + * cover the memory, but for now it requires a single vma to + * entirely cover the MR to support RO mappings. + */ + vma = find_vma(current->mm, start); + if (vma && vma->vm_end >= start + length && + vma->vm_start <= start) { + if (vma->vm_flags & VM_WRITE) + access_flags |= IB_ACCESS_LOCAL_WRITE; + } else { + access_flags |= IB_ACCESS_LOCAL_WRITE; + } + + up_read(¤t->mm->mmap_sem); + } + + return ib_umem_get(context, start, length, access_flags, 0); +} + struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt_addr, int access_flags, struct ib_udata *udata) @@ -145,10 +179,8 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, if (!mr) return ERR_PTR(-ENOMEM); - /* Force registering the memory as writable. */ - /* Used for memory re-registeration. HCA protects the access */ - mr->umem = ib_umem_get(pd->uobject->context, start, length, - access_flags | IB_ACCESS_LOCAL_WRITE, 0); + mr->umem = mlx4_get_umem_mr(pd->uobject->context, start, length, + virt_addr, access_flags); if (IS_ERR(mr->umem)) { err = PTR_ERR(mr->umem); goto err_free; @@ -215,6 +247,9 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, } if (flags & IB_MR_REREG_ACCESS) { + if (ib_access_writable(mr_access_flags) && !mmr->umem->writable) + return -EPERM; + err = mlx4_mr_hw_change_access(dev->dev, *pmpt_entry, convert_access(mr_access_flags)); @@ -228,10 +263,9 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, mlx4_mr_rereg_mem_cleanup(dev->dev, &mmr->mmr); ib_umem_release(mmr->umem); - mmr->umem = ib_umem_get(mr->uobject->context, start, length, - mr_access_flags | - IB_ACCESS_LOCAL_WRITE, - 0); + mmr->umem = + mlx4_get_umem_mr(mr->uobject->context, start, length, + virt_addr, mr_access_flags); if (IS_ERR(mmr->umem)) { err = PTR_ERR(mmr->umem); /* Prevent mlx4_ib_dereg_mr from free'ing invalid pointer */ -- GitLab From 96fb9b88385f9b8b308cf2c8b050cd38ed038a59 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Wed, 23 May 2018 15:30:30 +0300 Subject: [PATCH 1084/1299] IB/core: Make testing MR flags for writability a static inline function commit 08bb558ac11ab944e0539e78619d7b4c356278bd upstream. Make the MR writability flags check, which is performed in umem.c, a static inline function in file ib_verbs.h This allows the function to be used by low-level infiniband drivers. Cc: Signed-off-by: Jason Gunthorpe Signed-off-by: Jack Morgenstein Signed-off-by: Leon Romanovsky Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/umem.c | 11 +---------- include/rdma/ib_verbs.h | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index 2b6c9b516070..d76455edd292 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -119,16 +119,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, umem->length = size; umem->address = addr; umem->page_shift = PAGE_SHIFT; - /* - * We ask for writable memory if any of the following - * access flags are set. "Local write" and "remote write" - * obviously require write access. "Remote atomic" can do - * things like fetch and add, which will modify memory, and - * "MW bind" can change permissions by binding a window. - */ - umem->writable = !!(access & - (IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE | - IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_MW_BIND)); + umem->writable = ib_access_writable(access); if (access & IB_ACCESS_ON_DEMAND) { ret = ib_umem_odp_get(context, umem, access); diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 08f3d8699a27..5a24b4c700e5 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -3558,6 +3558,20 @@ static inline int ib_check_mr_access(int flags) return 0; } +static inline bool ib_access_writable(int access_flags) +{ + /* + * We have writable memory backing the MR if any of the following + * access flags are set. "Local write" and "remote write" obviously + * require write access. "Remote atomic" can do things like fetch and + * add, which will modify memory, and "MW bind" can change permissions + * by binding a window. + */ + return access_flags & + (IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE | + IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_MW_BIND); +} + /** * ib_check_mr_status: lightweight check of MR status. * This routine may provide status checks on a selected -- GitLab From c06f8c2173b2c848b28c4cf2ee2e82c4f791c638 Mon Sep 17 00:00:00 2001 From: Erez Shitrit Date: Mon, 21 May 2018 11:41:01 +0300 Subject: [PATCH 1085/1299] IB/mlx5: Fetch soft WQE's on fatal error state commit 7b74a83cf54a3747e22c57e25712bd70eef8acee upstream. On fatal error the driver simulates CQE's for ULPs that rely on completion of all their posted work-request. For the GSI traffic, the mlx5 has its own mechanism that sends the completions via software CQE's directly to the relevant CQ. This should be kept in fatal error too, so the driver should simulate such CQE's with the specified error state in order to complete GSI QP work requests. Without the fix the next deadlock might appears: schedule_timeout+0x274/0x350 wait_for_common+0xec/0x240 mcast_remove_one+0xd0/0x120 [ib_core] ib_unregister_device+0x12c/0x230 [ib_core] mlx5_ib_remove+0xc4/0x270 [mlx5_ib] mlx5_detach_device+0x184/0x1a0 [mlx5_core] mlx5_unload_one+0x308/0x340 [mlx5_core] mlx5_pci_err_detected+0x74/0xe0 [mlx5_core] Cc: # 4.7 Fixes: 89ea94a7b6c4 ("IB/mlx5: Reset flow support for IB kernel ULPs") Signed-off-by: Erez Shitrit Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/mlx5/cq.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c index d804880d637a..be6612fc33ac 100644 --- a/drivers/infiniband/hw/mlx5/cq.c +++ b/drivers/infiniband/hw/mlx5/cq.c @@ -646,7 +646,7 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq, } static int poll_soft_wc(struct mlx5_ib_cq *cq, int num_entries, - struct ib_wc *wc) + struct ib_wc *wc, bool is_fatal_err) { struct mlx5_ib_dev *dev = to_mdev(cq->ibcq.device); struct mlx5_ib_wc *soft_wc, *next; @@ -659,6 +659,10 @@ static int poll_soft_wc(struct mlx5_ib_cq *cq, int num_entries, mlx5_ib_dbg(dev, "polled software generated completion on CQ 0x%x\n", cq->mcq.cqn); + if (unlikely(is_fatal_err)) { + soft_wc->wc.status = IB_WC_WR_FLUSH_ERR; + soft_wc->wc.vendor_err = MLX5_CQE_SYNDROME_WR_FLUSH_ERR; + } wc[npolled++] = soft_wc->wc; list_del(&soft_wc->list); kfree(soft_wc); @@ -679,12 +683,17 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) spin_lock_irqsave(&cq->lock, flags); if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { - mlx5_ib_poll_sw_comp(cq, num_entries, wc, &npolled); + /* make sure no soft wqe's are waiting */ + if (unlikely(!list_empty(&cq->wc_list))) + soft_polled = poll_soft_wc(cq, num_entries, wc, true); + + mlx5_ib_poll_sw_comp(cq, num_entries - soft_polled, + wc + soft_polled, &npolled); goto out; } if (unlikely(!list_empty(&cq->wc_list))) - soft_polled = poll_soft_wc(cq, num_entries, wc); + soft_polled = poll_soft_wc(cq, num_entries, wc, false); for (npolled = 0; npolled < num_entries - soft_polled; npolled++) { if (mlx5_poll_one(cq, &cur_qp, wc + soft_polled + npolled)) -- GitLab From 7d4aaca8d0937ea5ff434f5a7039f27e163f476a Mon Sep 17 00:00:00 2001 From: Alex Estrin Date: Tue, 15 May 2018 18:31:39 -0700 Subject: [PATCH 1086/1299] IB/isert: Fix for lib/dma_debug check_sync warning commit 763b69654bfb88ea3230d015e7d755ee8339f8ee upstream. The following error message occurs on a target host in a debug build during session login: [ 3524.411874] WARNING: CPU: 5 PID: 12063 at lib/dma-debug.c:1207 check_sync+0x4ec/0x5b0 [ 3524.421057] infiniband hfi1_0: DMA-API: device driver tries to sync DMA memory it has not allocated [device address=0x0000000000000000] [size=76 bytes] ......snip ..... [ 3524.535846] CPU: 5 PID: 12063 Comm: iscsi_np Kdump: loaded Not tainted 3.10.0-862.el7.x86_64.debug #1 [ 3524.546764] Hardware name: Dell Inc. PowerEdge R430/03XKDV, BIOS 1.2.6 06/08/2015 [ 3524.555740] Call Trace: [ 3524.559102] [] dump_stack+0x19/0x1b [ 3524.565477] [] __warn+0xd8/0x100 [ 3524.571557] [] warn_slowpath_fmt+0x5f/0x80 [ 3524.578610] [] check_sync+0x4ec/0x5b0 [ 3524.585177] [] ? set_cpus_allowed_ptr+0x5f/0x1c0 [ 3524.592812] [] debug_dma_sync_single_for_cpu+0x80/0x90 [ 3524.601029] [] ? x2apic_send_IPI_mask+0x13/0x20 [ 3524.608574] [] ? native_smp_send_reschedule+0x5b/0x80 [ 3524.616699] [] ? resched_curr+0xf6/0x140 [ 3524.623567] [] isert_create_send_desc.isra.26+0xe0/0x110 [ib_isert] [ 3524.633060] [] isert_put_login_tx+0x55/0x8b0 [ib_isert] [ 3524.641383] [] ? try_to_wake_up+0x1a4/0x430 [ 3524.648561] [] iscsi_target_do_tx_login_io+0xdd/0x230 [iscsi_target_mod] [ 3524.658557] [] iscsi_target_do_login+0x1a7/0x600 [iscsi_target_mod] [ 3524.668084] [] ? kstrdup+0x49/0x60 [ 3524.674420] [] iscsi_target_start_negotiation+0x56/0xc0 [iscsi_target_mod] [ 3524.684656] [] __iscsi_target_login_thread+0x90e/0x1070 [iscsi_target_mod] [ 3524.694901] [] ? __iscsi_target_login_thread+0x1070/0x1070 [iscsi_target_mod] [ 3524.705446] [] ? __iscsi_target_login_thread+0x1070/0x1070 [iscsi_target_mod] [ 3524.715976] [] iscsi_target_login_thread+0x28/0x60 [iscsi_target_mod] [ 3524.725739] [] kthread+0xef/0x100 [ 3524.732007] [] ? insert_kthread_work+0x80/0x80 [ 3524.739540] [] ret_from_fork_nospec_begin+0x21/0x21 [ 3524.747558] [] ? insert_kthread_work+0x80/0x80 [ 3524.755088] ---[ end trace 23f8bf9238bd1ed8 ]--- [ 3595.510822] iSCSI/iqn.1994-05.com.redhat:537fa56299: Unsupported SCSI Opcode 0xa3, sending CHECK_CONDITION. The code calls dma_sync on login_tx_desc->dma_addr prior to initializing it with dma-mapped address. login_tx_desc is a part of iser_conn structure and is used only once during login negotiation, so the issue is fixed by eliminating dma_sync call for this buffer using a special case routine. Cc: Reviewed-by: Mike Marciniszyn Reviewed-by: Don Dutile Signed-off-by: Alex Estrin Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/isert/ib_isert.c | 26 ++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index e770c17cbca9..9369e7ceb321 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -885,15 +885,9 @@ isert_login_post_send(struct isert_conn *isert_conn, struct iser_tx_desc *tx_des } static void -isert_create_send_desc(struct isert_conn *isert_conn, - struct isert_cmd *isert_cmd, - struct iser_tx_desc *tx_desc) +__isert_create_send_desc(struct isert_device *device, + struct iser_tx_desc *tx_desc) { - struct isert_device *device = isert_conn->device; - struct ib_device *ib_dev = device->ib_device; - - ib_dma_sync_single_for_cpu(ib_dev, tx_desc->dma_addr, - ISER_HEADERS_LEN, DMA_TO_DEVICE); memset(&tx_desc->iser_header, 0, sizeof(struct iser_ctrl)); tx_desc->iser_header.flags = ISCSI_CTRL; @@ -906,6 +900,20 @@ isert_create_send_desc(struct isert_conn *isert_conn, } } +static void +isert_create_send_desc(struct isert_conn *isert_conn, + struct isert_cmd *isert_cmd, + struct iser_tx_desc *tx_desc) +{ + struct isert_device *device = isert_conn->device; + struct ib_device *ib_dev = device->ib_device; + + ib_dma_sync_single_for_cpu(ib_dev, tx_desc->dma_addr, + ISER_HEADERS_LEN, DMA_TO_DEVICE); + + __isert_create_send_desc(device, tx_desc); +} + static int isert_init_tx_hdrs(struct isert_conn *isert_conn, struct iser_tx_desc *tx_desc) @@ -993,7 +1001,7 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, struct iser_tx_desc *tx_desc = &isert_conn->login_tx_desc; int ret; - isert_create_send_desc(isert_conn, NULL, tx_desc); + __isert_create_send_desc(device, tx_desc); memcpy(&tx_desc->iscsi_header, &login->rsp[0], sizeof(struct iscsi_hdr)); -- GitLab From c32951862c1a32c978643fc3cc5d47cc70c33da4 Mon Sep 17 00:00:00 2001 From: Max Gurtovoy Date: Thu, 31 May 2018 11:05:23 +0300 Subject: [PATCH 1087/1299] IB/isert: fix T10-pi check mask setting commit 0e12af84cdd3056460f928adc164f9e87f4b303b upstream. A copy/paste bug (probably) caused setting of an app_tag check mask in case where a ref_tag check was needed. Fixes: 38a2d0d429f1 ("IB/isert: convert to the generic RDMA READ/WRITE API") Fixes: 9e961ae73c2c ("IB/isert: Support T10-PI protected transactions") Cc: stable@vger.kernel.org Reviewed-by: Christoph Hellwig Reviewed-by: Sagi Grimberg Reviewed-by: Martin K. Petersen Signed-off-by: Max Gurtovoy Signed-off-by: Jason Gunthorpe Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/isert/ib_isert.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 9369e7ceb321..ee3f630c9217 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -2116,7 +2116,7 @@ isert_set_sig_attrs(struct se_cmd *se_cmd, struct ib_sig_attrs *sig_attrs) sig_attrs->check_mask = (se_cmd->prot_checks & TARGET_DIF_CHECK_GUARD ? 0xc0 : 0) | - (se_cmd->prot_checks & TARGET_DIF_CHECK_REFTAG ? 0x30 : 0) | + (se_cmd->prot_checks & TARGET_DIF_CHECK_APPTAG ? 0x30 : 0) | (se_cmd->prot_checks & TARGET_DIF_CHECK_REFTAG ? 0x0f : 0); return 0; } -- GitLab From 9e81f9a2cef15c7563181a00d103c2b2fb4184eb Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Wed, 2 May 2018 06:42:44 -0700 Subject: [PATCH 1088/1299] IB/hfi1: Fix fault injection init/exit issues commit 8c79d8223bb11b2f005695a32ddd3985de97727c upstream. There are config dependent code paths that expose panics in unload paths both in this file and in debugfs_remove_recursive() because CONFIG_FAULT_INJECTION and CONFIG_FAULT_INJECTION_DEBUG_FS can be set independently. Having CONFIG_FAULT_INJECTION set and CONFIG_FAULT_INJECTION_DEBUG_FS reset causes fault_create_debugfs_attr() to return an error. The debugfs.c routines tolerate failures, but the module unload panics dereferencing a NULL in the two exit routines. If that is fixed, the dir passed to debugfs_remove_recursive comes from a memory location that was freed and potentially reused causing a segfault or corrupting memory. Here is an example of the NULL deref panic: [66866.286829] BUG: unable to handle kernel NULL pointer dereference at 0000000000000088 [66866.295602] IP: hfi1_dbg_ibdev_exit+0x2a/0x80 [hfi1] [66866.301138] PGD 858496067 P4D 858496067 PUD 8433a7067 PMD 0 [66866.307452] Oops: 0000 [#1] SMP [66866.310953] Modules linked in: hfi1(-) rdmavt rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm iw_cm ib_cm ib_core rpcsec_gss_krb5 nfsv4 dns_resolver nfsv3 nfs fscache sb_edac x86_pkg_temp_thermal intel_powerclamp vfat fat coretemp kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcbc aesni_intel iTCO_wdt iTCO_vendor_support crypto_simd mei_me glue_helper cryptd mxm_wmi ipmi_si pcspkr lpc_ich sg mei ioatdma ipmi_devintf i2c_i801 mfd_core shpchp ipmi_msghandler wmi acpi_power_meter acpi_cpufreq nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables ext4 mbcache jbd2 sd_mod mgag200 drm_kms_helper syscopyarea sysfillrect sysimgblt igb fb_sys_fops ttm ahci ptp crc32c_intel libahci pps_core drm dca libata i2c_algo_bit i2c_core [last unloaded: opa_vnic] [66866.385551] CPU: 8 PID: 7470 Comm: rmmod Not tainted 4.14.0-mam-tid-rdma #2 [66866.393317] Hardware name: Intel Corporation S2600WT2/S2600WT2, BIOS SE5C610.86B.01.01.0018.C4.072020161249 07/20/2016 [66866.405252] task: ffff88084f28c380 task.stack: ffffc90008454000 [66866.411866] RIP: 0010:hfi1_dbg_ibdev_exit+0x2a/0x80 [hfi1] [66866.417984] RSP: 0018:ffffc90008457da0 EFLAGS: 00010202 [66866.423812] RAX: 0000000000000000 RBX: ffff880857de0000 RCX: 0000000180040001 [66866.431773] RDX: 0000000180040002 RSI: ffffea0021088200 RDI: 0000000040000000 [66866.439734] RBP: ffffc90008457da8 R08: ffff88084220e000 R09: 0000000180040001 [66866.447696] R10: 000000004220e001 R11: ffff88084220e000 R12: ffff88085a31c000 [66866.455657] R13: ffffffffa07c9820 R14: ffffffffa07c9890 R15: ffff881059d78100 [66866.463618] FS: 00007f6876047740(0000) GS:ffff88085f800000(0000) knlGS:0000000000000000 [66866.472644] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [66866.479053] CR2: 0000000000000088 CR3: 0000000856357006 CR4: 00000000001606e0 [66866.487013] Call Trace: [66866.489747] remove_one+0x1f/0x220 [hfi1] [66866.494221] pci_device_remove+0x39/0xc0 [66866.498596] device_release_driver_internal+0x141/0x210 [66866.504424] driver_detach+0x3f/0x80 [66866.508409] bus_remove_driver+0x55/0xd0 [66866.512784] driver_unregister+0x2c/0x50 [66866.517164] pci_unregister_driver+0x2a/0xa0 [66866.521934] hfi1_mod_cleanup+0x10/0xaa2 [hfi1] [66866.526988] SyS_delete_module+0x171/0x250 [66866.531558] do_syscall_64+0x67/0x1b0 [66866.535644] entry_SYSCALL64_slow_path+0x25/0x25 [66866.540792] RIP: 0033:0x7f6875525c27 [66866.544777] RSP: 002b:00007ffd48528e78 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0 [66866.553224] RAX: ffffffffffffffda RBX: 0000000001cc01d0 RCX: 00007f6875525c27 [66866.561185] RDX: 00007f6875596000 RSI: 0000000000000800 RDI: 0000000001cc0238 [66866.569146] RBP: 0000000000000000 R08: 00007f68757e9060 R09: 00007f6875596000 [66866.577120] R10: 00007ffd48528c00 R11: 0000000000000206 R12: 00007ffd48529db4 [66866.585080] R13: 0000000000000000 R14: 0000000001cc01d0 R15: 0000000001cc0010 [66866.593040] Code: 90 0f 1f 44 00 00 48 83 3d a3 8b 03 00 00 55 48 89 e5 53 48 89 fb 74 4e 48 8d bf 18 0c 00 00 e8 9d f2 ff ff 48 8b 83 20 0c 00 00 <48> 8b b8 88 00 00 00 e8 2a 21 b3 e0 48 8b bb 20 0c 00 00 e8 0e [66866.614127] RIP: hfi1_dbg_ibdev_exit+0x2a/0x80 [hfi1] RSP: ffffc90008457da0 [66866.621885] CR2: 0000000000000088 [66866.625618] ---[ end trace c4817425783fb092 ]--- Fix by insuring that upon failure from fault_create_debugfs_attr() the parent pointer for the routines is always set to NULL and guards added in the exit routines to insure that debugfs_remove_recursive() is not called when when the parent pointer is NULL. Fixes: 0181ce31b260 ("IB/hfi1: Add receive fault injection feature") Cc: # 4.14.x Reviewed-by: Michael J. Ruhl Signed-off-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/hfi1/debugfs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/debugfs.c b/drivers/infiniband/hw/hfi1/debugfs.c index 36ae1fd86502..f661b387e916 100644 --- a/drivers/infiniband/hw/hfi1/debugfs.c +++ b/drivers/infiniband/hw/hfi1/debugfs.c @@ -1179,7 +1179,8 @@ DEBUGFS_FILE_OPS(fault_stats); static void fault_exit_opcode_debugfs(struct hfi1_ibdev *ibd) { - debugfs_remove_recursive(ibd->fault_opcode->dir); + if (ibd->fault_opcode) + debugfs_remove_recursive(ibd->fault_opcode->dir); kfree(ibd->fault_opcode); ibd->fault_opcode = NULL; } @@ -1207,6 +1208,7 @@ static int fault_init_opcode_debugfs(struct hfi1_ibdev *ibd) &ibd->fault_opcode->attr); if (IS_ERR(ibd->fault_opcode->dir)) { kfree(ibd->fault_opcode); + ibd->fault_opcode = NULL; return -ENOENT; } @@ -1230,7 +1232,8 @@ static int fault_init_opcode_debugfs(struct hfi1_ibdev *ibd) static void fault_exit_packet_debugfs(struct hfi1_ibdev *ibd) { - debugfs_remove_recursive(ibd->fault_packet->dir); + if (ibd->fault_packet) + debugfs_remove_recursive(ibd->fault_packet->dir); kfree(ibd->fault_packet); ibd->fault_packet = NULL; } @@ -1256,6 +1259,7 @@ static int fault_init_packet_debugfs(struct hfi1_ibdev *ibd) &ibd->fault_opcode->attr); if (IS_ERR(ibd->fault_packet->dir)) { kfree(ibd->fault_packet); + ibd->fault_packet = NULL; return -ENOENT; } -- GitLab From 2bd28cba43bd24ad3c8b485c3ab4bb4a65564b0c Mon Sep 17 00:00:00 2001 From: "Michael J. Ruhl" Date: Wed, 2 May 2018 06:43:07 -0700 Subject: [PATCH 1089/1299] IB/hfi1: Reorder incorrect send context disable commit a93a0a31111231bb1949f4a83b17238f0fa32d6a upstream. User send context integrity bits are cleared before the context is disabled. If the send context is still processing data, any packets that need those integrity bits will cause an error and halt the send context. During the disable handling, the driver waits for the context to drain. If the context is halted, the driver will eventually timeout because the context won't drain and then incorrectly bounce the link. Reorder the bit clearing and the context disable. Examine the software state and send context status as well as the egress status to determine if a send context is in the halted state. Promote the check macros to static functions for consistency with the new check and to follow kernel style. Remove an unused define that refers to the egress timeout. Cc: # 4.9.x Reviewed-by: Mitko Haralanov Reviewed-by: Mike Marciniszyn Signed-off-by: Michael J. Ruhl Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/hfi1/file_ops.c | 2 +- drivers/infiniband/hw/hfi1/pio.c | 44 +++++++++++++++++++++------ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c index ee2253d06984..cb6ff9d77caf 100644 --- a/drivers/infiniband/hw/hfi1/file_ops.c +++ b/drivers/infiniband/hw/hfi1/file_ops.c @@ -807,8 +807,8 @@ static int hfi1_file_close(struct inode *inode, struct file *fp) * checks to default and disable the send context. */ if (uctxt->sc) { - set_pio_integrity(uctxt->sc); sc_disable(uctxt->sc); + set_pio_integrity(uctxt->sc); } hfi1_free_ctxt_rcv_groups(uctxt); diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c index 7108a4b5e94c..a95ac6246559 100644 --- a/drivers/infiniband/hw/hfi1/pio.c +++ b/drivers/infiniband/hw/hfi1/pio.c @@ -50,8 +50,6 @@ #include "qp.h" #include "trace.h" -#define SC_CTXT_PACKET_EGRESS_TIMEOUT 350 /* in chip cycles */ - #define SC(name) SEND_CTXT_##name /* * Send Context functions @@ -977,15 +975,40 @@ void sc_disable(struct send_context *sc) } /* return SendEgressCtxtStatus.PacketOccupancy */ -#define packet_occupancy(r) \ - (((r) & SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_PACKET_OCCUPANCY_SMASK)\ - >> SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_PACKET_OCCUPANCY_SHIFT) +static u64 packet_occupancy(u64 reg) +{ + return (reg & + SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_PACKET_OCCUPANCY_SMASK) + >> SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_PACKET_OCCUPANCY_SHIFT; +} /* is egress halted on the context? */ -#define egress_halted(r) \ - ((r) & SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_HALT_STATUS_SMASK) +static bool egress_halted(u64 reg) +{ + return !!(reg & SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_HALT_STATUS_SMASK); +} -/* wait for packet egress, optionally pause for credit return */ +/* is the send context halted? */ +static bool is_sc_halted(struct hfi1_devdata *dd, u32 hw_context) +{ + return !!(read_kctxt_csr(dd, hw_context, SC(STATUS)) & + SC(STATUS_CTXT_HALTED_SMASK)); +} + +/** + * sc_wait_for_packet_egress + * @sc: valid send context + * @pause: wait for credit return + * + * Wait for packet egress, optionally pause for credit return + * + * Egress halt and Context halt are not necessarily the same thing, so + * check for both. + * + * NOTE: The context halt bit may not be set immediately. Because of this, + * it is necessary to check the SW SFC_HALTED bit (set in the IRQ) and the HW + * context bit to determine if the context is halted. + */ static void sc_wait_for_packet_egress(struct send_context *sc, int pause) { struct hfi1_devdata *dd = sc->dd; @@ -997,8 +1020,9 @@ static void sc_wait_for_packet_egress(struct send_context *sc, int pause) reg_prev = reg; reg = read_csr(dd, sc->hw_context * 8 + SEND_EGRESS_CTXT_STATUS); - /* done if egress is stopped */ - if (egress_halted(reg)) + /* done if any halt bits, SW or HW are set */ + if (sc->flags & SCF_HALTED || + is_sc_halted(dd, sc->hw_context) || egress_halted(reg)) break; reg = packet_occupancy(reg); if (reg == 0) -- GitLab From 964705c4a69183182362977c28786e789a384700 Mon Sep 17 00:00:00 2001 From: Sebastian Sanchez Date: Wed, 2 May 2018 06:43:39 -0700 Subject: [PATCH 1090/1299] IB/hfi1: Optimize kthread pointer locking when queuing CQ entries commit af8aab71370a692eaf7e7969ba5b1a455ac20113 upstream. All threads queuing CQ entries on different CQs are unnecessarily synchronized by a spin lock to check if the CQ kthread worker hasn't been destroyed before queuing an CQ entry. The lock used in 6efaf10f163d ("IB/rdmavt: Avoid queuing work into a destroyed cq kthread worker") is a device global lock and will have poor performance at scale as completions are entered from a large number of CPUs. Convert to use RCU where the read side of RCU is rvt_cq_enter() to determine that the worker is alive prior to triggering the completion event. Apply write side RCU semantics in rvt_driver_cq_init() and rvt_cq_exit(). Fixes: 6efaf10f163d ("IB/rdmavt: Avoid queuing work into a destroyed cq kthread worker") Cc: # 4.14.x Reviewed-by: Mike Marciniszyn Signed-off-by: Sebastian Sanchez Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/sw/rdmavt/cq.c | 31 +++++++++++++++++++------------ include/rdma/rdma_vt.h | 2 +- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/sw/rdmavt/cq.c b/drivers/infiniband/sw/rdmavt/cq.c index 88fa4d44ab5f..76a86f805233 100644 --- a/drivers/infiniband/sw/rdmavt/cq.c +++ b/drivers/infiniband/sw/rdmavt/cq.c @@ -121,17 +121,20 @@ void rvt_cq_enter(struct rvt_cq *cq, struct ib_wc *entry, bool solicited) if (cq->notify == IB_CQ_NEXT_COMP || (cq->notify == IB_CQ_SOLICITED && (solicited || entry->status != IB_WC_SUCCESS))) { + struct kthread_worker *worker; + /* * This will cause send_complete() to be called in * another thread. */ - spin_lock(&cq->rdi->n_cqs_lock); - if (likely(cq->rdi->worker)) { + rcu_read_lock(); + worker = rcu_dereference(cq->rdi->worker); + if (likely(worker)) { cq->notify = RVT_CQ_NONE; cq->triggered++; - kthread_queue_work(cq->rdi->worker, &cq->comptask); + kthread_queue_work(worker, &cq->comptask); } - spin_unlock(&cq->rdi->n_cqs_lock); + rcu_read_unlock(); } spin_unlock_irqrestore(&cq->lock, flags); @@ -513,7 +516,7 @@ int rvt_driver_cq_init(struct rvt_dev_info *rdi) int cpu; struct kthread_worker *worker; - if (rdi->worker) + if (rcu_access_pointer(rdi->worker)) return 0; spin_lock_init(&rdi->n_cqs_lock); @@ -525,7 +528,7 @@ int rvt_driver_cq_init(struct rvt_dev_info *rdi) return PTR_ERR(worker); set_user_nice(worker->task, MIN_NICE); - rdi->worker = worker; + RCU_INIT_POINTER(rdi->worker, worker); return 0; } @@ -537,15 +540,19 @@ void rvt_cq_exit(struct rvt_dev_info *rdi) { struct kthread_worker *worker; - /* block future queuing from send_complete() */ - spin_lock_irq(&rdi->n_cqs_lock); - worker = rdi->worker; + if (!rcu_access_pointer(rdi->worker)) + return; + + spin_lock(&rdi->n_cqs_lock); + worker = rcu_dereference_protected(rdi->worker, + lockdep_is_held(&rdi->n_cqs_lock)); if (!worker) { - spin_unlock_irq(&rdi->n_cqs_lock); + spin_unlock(&rdi->n_cqs_lock); return; } - rdi->worker = NULL; - spin_unlock_irq(&rdi->n_cqs_lock); + RCU_INIT_POINTER(rdi->worker, NULL); + spin_unlock(&rdi->n_cqs_lock); + synchronize_rcu(); kthread_destroy_worker(worker); } diff --git a/include/rdma/rdma_vt.h b/include/rdma/rdma_vt.h index 1ba84a78f1c5..c653af91da16 100644 --- a/include/rdma/rdma_vt.h +++ b/include/rdma/rdma_vt.h @@ -409,7 +409,7 @@ struct rvt_dev_info { spinlock_t pending_lock; /* protect pending mmap list */ /* CQ */ - struct kthread_worker *worker; /* per device cq worker */ + struct kthread_worker __rcu *worker; /* per device cq worker */ u32 n_cqs_allocated; /* number of CQs allocated for device */ spinlock_t n_cqs_lock; /* protect count of in use cqs */ -- GitLab From a336999251226e5451afce56173c322cdc9d873a Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Thu, 31 May 2018 11:30:09 -0700 Subject: [PATCH 1091/1299] IB/hfi1: Fix user context tail allocation for DMA_RTAIL commit 1bc0299d976e000ececc6acd76e33b4582646cb7 upstream. The following code fails to allocate a buffer for the tail address that the hardware DMAs into when the user context DMA_RTAIL is set. if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL)) { rcd->rcvhdrtail_kvaddr = dma_zalloc_coherent( &dd->pcidev->dev, PAGE_SIZE, &dma_hdrqtail, gfp_flags); if (!rcd->rcvhdrtail_kvaddr) goto bail_free; rcd->rcvhdrqtailaddr_dma = dma_hdrqtail; } So the rcvhdrtail_kvaddr would then be NULL. The mmap logic fails to check for a NULL rcvhdrtail_kvaddr. The fix is to test for both user and kernel DMA_TAIL options during the allocation as well as testing for a NULL rcvhdrtail_kvaddr during the mmap processing. Additionally, all downstream testing of the capmask for DMA_RTAIL have been eliminated in favor of testing rcvhdrtail_kvaddr. Cc: # 4.9.x Reviewed-by: Michael J. Ruhl Signed-off-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Jason Gunthorpe Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/hfi1/chip.c | 8 ++++---- drivers/infiniband/hw/hfi1/file_ops.c | 2 +- drivers/infiniband/hw/hfi1/init.c | 9 ++++----- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 259562282668..33cf1734c4e5 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -6829,7 +6829,7 @@ static void rxe_kernel_unfreeze(struct hfi1_devdata *dd) } rcvmask = HFI1_RCVCTRL_CTXT_ENB; /* HFI1_RCVCTRL_TAILUPD_[ENB|DIS] needs to be set explicitly */ - rcvmask |= HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL) ? + rcvmask |= rcd->rcvhdrtail_kvaddr ? HFI1_RCVCTRL_TAILUPD_ENB : HFI1_RCVCTRL_TAILUPD_DIS; hfi1_rcvctrl(dd, rcvmask, rcd); hfi1_rcd_put(rcd); @@ -8341,7 +8341,7 @@ static inline int check_packet_present(struct hfi1_ctxtdata *rcd) u32 tail; int present; - if (!HFI1_CAP_IS_KSET(DMA_RTAIL)) + if (!rcd->rcvhdrtail_kvaddr) present = (rcd->seq_cnt == rhf_rcv_seq(rhf_to_cpu(get_rhf_addr(rcd)))); else /* is RDMA rtail */ @@ -11813,7 +11813,7 @@ void hfi1_rcvctrl(struct hfi1_devdata *dd, unsigned int op, /* reset the tail and hdr addresses, and sequence count */ write_kctxt_csr(dd, ctxt, RCV_HDR_ADDR, rcd->rcvhdrq_dma); - if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL)) + if (rcd->rcvhdrtail_kvaddr) write_kctxt_csr(dd, ctxt, RCV_HDR_TAIL_ADDR, rcd->rcvhdrqtailaddr_dma); rcd->seq_cnt = 1; @@ -11893,7 +11893,7 @@ void hfi1_rcvctrl(struct hfi1_devdata *dd, unsigned int op, rcvctrl |= RCV_CTXT_CTRL_INTR_AVAIL_SMASK; if (op & HFI1_RCVCTRL_INTRAVAIL_DIS) rcvctrl &= ~RCV_CTXT_CTRL_INTR_AVAIL_SMASK; - if (op & HFI1_RCVCTRL_TAILUPD_ENB && rcd->rcvhdrqtailaddr_dma) + if ((op & HFI1_RCVCTRL_TAILUPD_ENB) && rcd->rcvhdrtail_kvaddr) rcvctrl |= RCV_CTXT_CTRL_TAIL_UPD_SMASK; if (op & HFI1_RCVCTRL_TAILUPD_DIS) { /* See comment on RcvCtxtCtrl.TailUpd above */ diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c index cb6ff9d77caf..9abc5a9c47a0 100644 --- a/drivers/infiniband/hw/hfi1/file_ops.c +++ b/drivers/infiniband/hw/hfi1/file_ops.c @@ -622,7 +622,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma) ret = -EINVAL; goto done; } - if (flags & VM_WRITE) { + if ((flags & VM_WRITE) || !uctxt->rcvhdrtail_kvaddr) { ret = -EPERM; goto done; } diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index c5f50279c4f4..ee5cbdfeb3ab 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c @@ -1808,7 +1808,6 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) u64 reg; if (!rcd->rcvhdrq) { - dma_addr_t dma_hdrqtail; gfp_t gfp_flags; /* @@ -1834,13 +1833,13 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) goto bail; } - if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL)) { + if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL) || + HFI1_CAP_UGET_MASK(rcd->flags, DMA_RTAIL)) { rcd->rcvhdrtail_kvaddr = dma_zalloc_coherent( - &dd->pcidev->dev, PAGE_SIZE, &dma_hdrqtail, - gfp_flags); + &dd->pcidev->dev, PAGE_SIZE, + &rcd->rcvhdrqtailaddr_dma, gfp_flags); if (!rcd->rcvhdrtail_kvaddr) goto bail_free; - rcd->rcvhdrqtailaddr_dma = dma_hdrqtail; } rcd->rcvhdrq_size = amt; -- GitLab From 786c8d79f34f0c54d3f9028e994e397207ae769c Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Tue, 29 May 2018 14:56:14 +0300 Subject: [PATCH 1092/1299] RDMA/mlx4: Discard unknown SQP work requests commit 6b1ca7ece15e94251d1d0d919f813943e4a58059 upstream. There is no need to crash the machine if unknown work request was received in SQP MAD. Cc: # 3.6 Fixes: 37bfc7c1e83f ("IB/mlx4: SR-IOV multiplex and demultiplex MADs") Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/mlx4/mad.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 0793a21d76f4..d604b3d5aa3e 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -1934,7 +1934,6 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work) "buf:%lld\n", wc.wr_id); break; default: - BUG_ON(1); break; } } else { -- GitLab From d097e5b5a1bc3cc601f11b61455210414c4f8b59 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 4 May 2018 15:35:46 -0400 Subject: [PATCH 1093/1299] xprtrdma: Return -ENOBUFS when no pages are available commit a8f688ec437dc2045cc8f0c89fe877d5803850da upstream. The use of -EAGAIN in rpcrdma_convert_iovs() is a latent bug: the transport never calls xprt_write_space() when more pages become available. -ENOBUFS will trigger the correct "delay briefly and call again" logic. Fixes: 7a89f9c626e3 ("xprtrdma: Honor ->send_request API contract") Signed-off-by: Chuck Lever Cc: stable@vger.kernel.org # 4.8+ Signed-off-by: Anna Schumaker Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtrdma/rpc_rdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 491ae9fc561f..991d5a96f35b 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -229,7 +229,7 @@ rpcrdma_convert_iovs(struct rpcrdma_xprt *r_xprt, struct xdr_buf *xdrbuf, */ *ppages = alloc_page(GFP_ATOMIC); if (!*ppages) - return -EAGAIN; + return -ENOBUFS; } seg->mr_page = *ppages; seg->mr_offset = (char *)page_base; -- GitLab From 746c1362c434d4c4d48eb53fa0ef757bc191e55f Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Wed, 30 May 2018 18:32:26 +0900 Subject: [PATCH 1094/1299] mtd: cfi_cmdset_0002: Change write buffer to check correct value commit dfeae1073583dc35c33b32150e18b7048bbb37e6 upstream. For the word write it is checked if the chip has the correct value. But it is not checked for the write buffer as only checked if ready. To make sure for the write buffer change to check the value. It is enough as this patch is only checking the last written word. Since it is described by data sheets to check the operation status. Signed-off-by: Tokunori Ikegami Reviewed-by: Joakim Tjernlund Cc: Chris Packham Cc: Brian Norris Cc: David Woodhouse Cc: Boris Brezillon Cc: Marek Vasut Cc: Richard Weinberger Cc: Cyrille Pitchen Cc: linux-mtd@lists.infradead.org Cc: stable@vger.kernel.org Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/chips/cfi_cmdset_0002.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index d524a64ed754..db4411258c2a 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -1880,7 +1880,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, if (time_after(jiffies, timeo) && !chip_ready(map, adr)) break; - if (chip_ready(map, adr)) { + if (chip_good(map, adr, datum)) { xip_enable(map, chip, adr); goto op_done; } -- GitLab From 80349943d56c1fdf361e6cf2f1f44ca7d210675c Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Wed, 6 Jun 2018 12:13:27 +0200 Subject: [PATCH 1095/1299] mtd: cfi_cmdset_0002: Use right chip in do_ppb_xxlock() commit f93aa8c4de307069c270b2d81741961162bead6c upstream. do_ppb_xxlock() fails to add chip->start when querying for lock status (and chip_ready test), which caused false status reports. Fix that by adding adr += chip->start and adjust call sites accordingly. Fixes: 1648eaaa1575 ("mtd: cfi_cmdset_0002: Support Persistent Protection Bits (PPB) locking") Cc: stable@vger.kernel.org Signed-off-by: Joakim Tjernlund Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/chips/cfi_cmdset_0002.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index db4411258c2a..dc577d3b246b 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -2553,8 +2553,9 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map, unsigned long timeo; int ret; + adr += chip->start; mutex_lock(&chip->mutex); - ret = get_chip(map, chip, adr + chip->start, FL_LOCKING); + ret = get_chip(map, chip, adr, FL_LOCKING); if (ret) { mutex_unlock(&chip->mutex); return ret; @@ -2572,8 +2573,8 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map, if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) { chip->state = FL_LOCKING; - map_write(map, CMD(0xA0), chip->start + adr); - map_write(map, CMD(0x00), chip->start + adr); + map_write(map, CMD(0xA0), adr); + map_write(map, CMD(0x00), adr); } else if (thunk == DO_XXLOCK_ONEBLOCK_UNLOCK) { /* * Unlocking of one specific sector is not supported, so we @@ -2611,7 +2612,7 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map, map_write(map, CMD(0x00), chip->start); chip->state = FL_READY; - put_chip(map, chip, adr + chip->start); + put_chip(map, chip, adr); mutex_unlock(&chip->mutex); return ret; -- GitLab From 2f11a0c8c23ab092feef59a941c373b0f93c51d7 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Wed, 6 Jun 2018 12:13:28 +0200 Subject: [PATCH 1096/1299] mtd: cfi_cmdset_0002: fix SEGV unlocking multiple chips commit 5fdfc3dbad099281bf027a353d5786c09408a8e5 upstream. cfi_ppb_unlock() tries to relock all sectors that were locked before unlocking the whole chip. This locking used the chip start address + the FULL offset from the first flash chip, thereby forming an illegal address. Fix that by using the chip offset(adr). Fixes: 1648eaaa1575 ("mtd: cfi_cmdset_0002: Support Persistent Protection Bits (PPB) locking") Cc: stable@vger.kernel.org Signed-off-by: Joakim Tjernlund Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/chips/cfi_cmdset_0002.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index dc577d3b246b..b6cbe683c9c2 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -2535,7 +2535,7 @@ static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) struct ppb_lock { struct flchip *chip; - loff_t offset; + unsigned long adr; int locked; }; @@ -2671,7 +2671,7 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs, */ if ((adr < ofs) || (adr >= (ofs + len))) { sect[sectors].chip = &cfi->chips[chipnum]; - sect[sectors].offset = offset; + sect[sectors].adr = adr; sect[sectors].locked = do_ppb_xxlock( map, &cfi->chips[chipnum], adr, 0, DO_XXLOCK_ONEBLOCK_GETLOCK); @@ -2715,7 +2715,7 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs, */ for (i = 0; i < sectors; i++) { if (sect[i].locked) - do_ppb_xxlock(map, sect[i].chip, sect[i].offset, 0, + do_ppb_xxlock(map, sect[i].chip, sect[i].adr, 0, DO_XXLOCK_ONEBLOCK_LOCK); } -- GitLab From fbbde9343c3e2452f304cc7715d77d4c9481ac3a Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Wed, 6 Jun 2018 12:13:29 +0200 Subject: [PATCH 1097/1299] mtd: cfi_cmdset_0002: Fix unlocking requests crossing a chip boudary commit 0cd8116f172eed018907303dbff5c112690eeb91 upstream. The "sector is in requested range" test used to determine whether sectors should be re-locked or not is done on a variable that is reset everytime we cross a chip boundary, which can lead to some blocks being re-locked while the caller expect them to be unlocked. Fix the check to make sure this cannot happen. Fixes: 1648eaaa1575 ("mtd: cfi_cmdset_0002: Support Persistent Protection Bits (PPB) locking") Cc: stable@vger.kernel.org Signed-off-by: Joakim Tjernlund Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/chips/cfi_cmdset_0002.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index b6cbe683c9c2..c3e90e67f3f4 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -2669,7 +2669,7 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs, * sectors shall be unlocked, so lets keep their locking * status at "unlocked" (locked=0) for the final re-locking. */ - if ((adr < ofs) || (adr >= (ofs + len))) { + if ((offset < ofs) || (offset >= (ofs + len))) { sect[sectors].chip = &cfi->chips[chipnum]; sect[sectors].adr = adr; sect[sectors].locked = do_ppb_xxlock( -- GitLab From c375d0bd66840b9932353332e0e0a304581d0575 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Wed, 6 Jun 2018 12:13:30 +0200 Subject: [PATCH 1098/1299] mtd: cfi_cmdset_0002: Avoid walking all chips when unlocking. commit f1ce87f6080b1dda7e7b1eda3da332add19d87b9 upstream. cfi_ppb_unlock() walks all flash chips when unlocking sectors, avoid walking chips unaffected by the unlock operation. Fixes: 1648eaaa1575 ("mtd: cfi_cmdset_0002: Support Persistent Protection Bits (PPB) locking") Cc: stable@vger.kernel.org Signed-off-by: Joakim Tjernlund Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/chips/cfi_cmdset_0002.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index c3e90e67f3f4..ac76c10c042f 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -2685,6 +2685,8 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs, i++; if (adr >> cfi->chipshift) { + if (offset >= (ofs + len)) + break; adr = 0; chipnum++; -- GitLab From 43f6a09c8c5b181afff4956fe748b7d6d481618d Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Sun, 3 Jun 2018 23:02:01 +0900 Subject: [PATCH 1099/1299] MIPS: BCM47XX: Enable 74K Core ExternalSync for PCIe erratum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 2a027b47dba6b77ab8c8e47b589ae9bbc5ac6175 upstream. The erratum and workaround are described by BCM5300X-ES300-RDS.pdf as below. R10: PCIe Transactions Periodically Fail Description: The BCM5300X PCIe does not maintain transaction ordering. This may cause PCIe transaction failure. Fix Comment: Add a dummy PCIe configuration read after a PCIe configuration write to ensure PCIe configuration access ordering. Set ES bit of CP0 configu7 register to enable sync function so that the sync instruction is functional. Resolution: hndpci.c: extpci_write_config() hndmips.c: si_mips_init() mipsinc.h CONF7_ES This is fixed by the CFE MIPS bcmsi chipset driver also for BCM47XX. Also the dummy PCIe configuration read is already implemented in the Linux BCMA driver. Enable ExternalSync in Config7 when CONFIG_BCMA_DRIVER_PCI_HOSTMODE=y too so that the sync instruction is externalised. Signed-off-by: Tokunori Ikegami Reviewed-by: Paul Burton Acked-by: Hauke Mehrtens Cc: Chris Packham Cc: Rafał Miłecki Cc: linux-mips@linux-mips.org Cc: stable@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/19461/ Signed-off-by: James Hogan Signed-off-by: Greg Kroah-Hartman --- arch/mips/bcm47xx/setup.c | 6 ++++++ arch/mips/include/asm/mipsregs.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 6054d49e608e..8c9cbf13d32a 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -212,6 +212,12 @@ static int __init bcm47xx_cpu_fixes(void) */ if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706) cpu_wait = NULL; + + /* + * BCM47XX Erratum "R10: PCIe Transactions Periodically Fail" + * Enable ExternalSync for sync instruction to take effect + */ + set_c0_config7(MIPS_CONF7_ES); break; #endif } diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index a6810923b3f0..60c787d943b0 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -680,6 +680,8 @@ #define MIPS_CONF7_WII (_ULCAST_(1) << 31) #define MIPS_CONF7_RPS (_ULCAST_(1) << 2) +/* ExternalSync */ +#define MIPS_CONF7_ES (_ULCAST_(1) << 8) #define MIPS_CONF7_IAR (_ULCAST_(1) << 10) #define MIPS_CONF7_AR (_ULCAST_(1) << 16) @@ -2745,6 +2747,7 @@ __BUILD_SET_C0(status) __BUILD_SET_C0(cause) __BUILD_SET_C0(config) __BUILD_SET_C0(config5) +__BUILD_SET_C0(config7) __BUILD_SET_C0(intcontrol) __BUILD_SET_C0(intctl) __BUILD_SET_C0(srsmap) -- GitLab From e4a424c550b61d05de509aea2eea6415bb8c185f Mon Sep 17 00:00:00 2001 From: Sridhar Pitchai Date: Tue, 1 May 2018 17:56:32 +0000 Subject: [PATCH 1100/1299] PCI: hv: Make sure the bus domain is really unique commit 29927dfb7f69bcf2ae7fd1cda10997e646a5189c upstream. When Linux runs as a guest VM in Hyper-V and Hyper-V adds the virtual PCI bus to the guest, Hyper-V always provides unique PCI domain. commit 4a9b0933bdfc ("PCI: hv: Use device serial number as PCI domain") overrode unique domain with the serial number of the first device added to the virtual PCI bus. The reason for that patch was to have a consistent and short name for the device, but Hyper-V doesn't provide unique serial numbers. Using non-unique serial numbers as domain IDs leads to duplicate device addresses, which causes PCI bus registration to fail. commit 0c195567a8f6 ("netvsc: transparent VF management") avoids the need for commit 4a9b0933bdfc ("PCI: hv: Use device serial number as PCI domain"). When scripts were used to configure VF devices, the name of the VF needed to be consistent and short, but with commit 0c195567a8f6 ("netvsc: transparent VF management") all the setup is done in the kernel, and we do not need to maintain consistent name. Revert commit 4a9b0933bdfc ("PCI: hv: Use device serial number as PCI domain") so we can reliably support multiple devices being assigned to a guest. Tag the patch for stable kernels containing commit 0c195567a8f6 ("netvsc: transparent VF management"). Fixes: 4a9b0933bdfc ("PCI: hv: Use device serial number as PCI domain") Signed-off-by: Sridhar Pitchai [lorenzo.pieralisi@arm.com: trimmed commit log] Signed-off-by: Lorenzo Pieralisi Cc: stable@vger.kernel.org # v4.14+ Reviewed-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/host/pci-hyperv.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index 0b750228ad70..caea7c618207 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c @@ -1610,17 +1610,6 @@ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus, get_pcichild(hpdev, hv_pcidev_ref_childlist); spin_lock_irqsave(&hbus->device_list_lock, flags); - /* - * When a device is being added to the bus, we set the PCI domain - * number to be the device serial number, which is non-zero and - * unique on the same VM. The serial numbers start with 1, and - * increase by 1 for each device. So device names including this - * can have shorter names than based on the bus instance UUID. - * Only the first device serial number is used for domain, so the - * domain number will not change after the first device is added. - */ - if (list_empty(&hbus->children)) - hbus->sysdata.domain = desc->ser; list_add_tail(&hpdev->list_entry, &hbus->children); spin_unlock_irqrestore(&hbus->device_list_lock, flags); return hpdev; -- GitLab From 78923ba967799cf5125651c345952e790b744940 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 25 Apr 2018 14:27:37 -0600 Subject: [PATCH 1101/1299] PCI: Add ACS quirk for Intel 7th & 8th Gen mobile commit e8440f4bfedc623bee40c84797ac78d9303d0db6 upstream. The specification update indicates these have the same errata for implementing non-standard ACS capabilities. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas CC: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 929d68f744af..35c9b2f4b293 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4377,11 +4377,24 @@ static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags) * 0xa290-0xa29f PCI Express Root port #{0-16} * 0xa2e7-0xa2ee PCI Express Root port #{17-24} * + * Mobile chipsets are also affected, 7th & 8th Generation + * Specification update confirms ACS errata 22, status no fix: (7th Generation + * Intel Processor Family I/O for U/Y Platforms and 8th Generation Intel + * Processor Family I/O for U Quad Core Platforms Specification Update, + * August 2017, Revision 002, Document#: 334660-002)[6] + * Device IDs from I/O datasheet: (7th Generation Intel Processor Family I/O + * for U/Y Platforms and 8th Generation Intel ® Processor Family I/O for U + * Quad Core Platforms, Vol 1 of 2, August 2017, Document#: 334658-003)[7] + * + * 0x9d10-0x9d1b PCI Express Root port #{1-12} + * * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html * [3] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-spec-update.html * [4] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-spec-update.html * [5] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-datasheet-vol-1.html + * [6] https://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-u-y-processor-lines-i-o-spec-update.html + * [7] https://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-u-y-processor-lines-i-o-datasheet-vol-1.html */ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) { @@ -4391,6 +4404,7 @@ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) switch (dev->device) { case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */ case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */ + case 0x9d10 ... 0x9d1b: /* 7th & 8th Gen Mobile */ return true; } -- GitLab From fc0096bceae9385dbed081a7922294cfccfde827 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 27 Apr 2018 13:06:30 -0500 Subject: [PATCH 1102/1299] PCI: Add ACS quirk for Intel 300 series commit f154a718e6cc0d834f5ac4dc4c3b174e65f3659e upstream. Intel 300 series chipset still has the same ACS issue as the previous generations so extend the ACS quirk to cover it as well. Signed-off-by: Mika Westerberg Signed-off-by: Bjorn Helgaas CC: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 35c9b2f4b293..ec2911c4ee42 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4388,6 +4388,11 @@ static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags) * * 0x9d10-0x9d1b PCI Express Root port #{1-12} * + * The 300 series chipset suffers from the same bug so include those root + * ports here as well. + * + * 0xa32c-0xa343 PCI Express Root port #{0-24} + * * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html * [3] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-spec-update.html @@ -4405,6 +4410,7 @@ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */ case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */ case 0x9d10 ... 0x9d1b: /* 7th & 8th Gen Mobile */ + case 0xa32c ... 0xa343: /* 300 series */ return true; } -- GitLab From 226ffbf6135c0a4adf52f6f4c693c26e23d69b90 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 23 May 2018 17:14:39 -0500 Subject: [PATCH 1103/1299] PCI: pciehp: Clear Presence Detect and Data Link Layer Status Changed on resume commit 13c65840feab8109194f9490c9870587173cb29d upstream. After a suspend/resume cycle the Presence Detect or Data Link Layer Status Changed bits might be set. If we don't clear them those events will not fire anymore and nothing happens for instance when a device is now hot-unplugged. Fix this by clearing those bits in a newly introduced function pcie_reenable_notification(). This should be fine because immediately after, we check if the adapter is still present by reading directly from the status register. Signed-off-by: Mika Westerberg Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 2 +- drivers/pci/hotplug/pciehp_core.c | 2 +- drivers/pci/hotplug/pciehp_hpc.c | 13 ++++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 06109d40c4ac..e7d6cfaf3865 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -134,7 +134,7 @@ struct controller *pcie_init(struct pcie_device *dev); int pcie_init_notification(struct controller *ctrl); int pciehp_enable_slot(struct slot *p_slot); int pciehp_disable_slot(struct slot *p_slot); -void pcie_enable_notification(struct controller *ctrl); +void pcie_reenable_notification(struct controller *ctrl); int pciehp_power_on_slot(struct slot *slot); void pciehp_power_off_slot(struct slot *slot); void pciehp_get_power_status(struct slot *slot, u8 *status); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 35d84845d5af..1288289cc85d 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -297,7 +297,7 @@ static int pciehp_resume(struct pcie_device *dev) ctrl = get_service_data(dev); /* reinitialize the chipset's event detection logic */ - pcie_enable_notification(ctrl); + pcie_reenable_notification(ctrl); slot = ctrl->slot; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index e5d5ce9e3010..05832b597e53 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -676,7 +676,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) return handled; } -void pcie_enable_notification(struct controller *ctrl) +static void pcie_enable_notification(struct controller *ctrl) { u16 cmd, mask; @@ -714,6 +714,17 @@ void pcie_enable_notification(struct controller *ctrl) pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, cmd); } +void pcie_reenable_notification(struct controller *ctrl) +{ + /* + * Clear both Presence and Data Link Layer Changed to make sure + * those events still fire after we have re-enabled them. + */ + pcie_capability_write_word(ctrl->pcie->port, PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); + pcie_enable_notification(ctrl); +} + static void pcie_disable_notification(struct controller *ctrl) { u16 mask; -- GitLab From 9e838b2e5a3c2ee04e46302f7d3d644b7dc4daf5 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 28 Feb 2018 18:33:03 -0800 Subject: [PATCH 1104/1299] auxdisplay: fix broken menu commit b5b903fba96a4d1771422efd5c713ebb73f7dc82 upstream. Having the CHARLCD Kconfig symbol between "menuconfig AUXDISPLAY" and "if AUXDISPLAY" breaks the AUXDISPLAY submenus, so move the CHARLCD Kconfig symbol near the end of the file so that the menu display is continuous. Also include ARM_CHARLCD inside of the if AUXDISPLAY/endif block. Geert says that it should be there. Fixes: 39f8ea46724e ("auxdisplay: charlcd: Extract character LCD core from misc/panel") Cc: stable@vger.kernel.org # v4.12 Cc: Geert Uytterhoeven Reviewed-by: Andy Shevchenko Signed-off-by: Randy Dunlap Signed-off-by: Miguel Ojeda Signed-off-by: Greg Kroah-Hartman --- drivers/auxdisplay/Kconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index 2c2ed9cf8796..f9413755177b 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig @@ -14,9 +14,6 @@ menuconfig AUXDISPLAY If you say N, all options in this submenu will be skipped and disabled. -config CHARLCD - tristate "Character LCD core support" if COMPILE_TEST - if AUXDISPLAY config HD44780 @@ -157,8 +154,6 @@ config HT16K33 Say yes here to add support for Holtek HT16K33, RAM mapping 16*8 LED controller driver with keyscan. -endif # AUXDISPLAY - config ARM_CHARLCD bool "ARM Ltd. Character LCD Driver" depends on PLAT_VERSATILE @@ -169,6 +164,8 @@ config ARM_CHARLCD line and the Linux version on the second line, but that's still useful. +endif # AUXDISPLAY + config PANEL tristate "Parallel port LCD/Keypad Panel support" depends on PARPORT @@ -448,3 +445,6 @@ config PANEL_BOOT_MESSAGE printf()-formatted message is valid with newline and escape codes. endif # PANEL + +config CHARLCD + tristate "Character LCD core support" if COMPILE_TEST -- GitLab From 7cc7ae5ce0189f5032fe42eabeb80361eede6783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmiel?= Date: Mon, 16 Apr 2018 17:52:45 +0200 Subject: [PATCH 1105/1299] pinctrl: samsung: Correct EINTG banks order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 5cf9a338db94cfd570aa2607bef1b30996f188e3 upstream. All banks with GPIO interrupts should be at beginning of bank array and without any other types of banks between them. This order is expected by exynos_eint_gpio_irq, when doing interrupt group to bank translation. Otherwise, kernel NULL pointer dereference would happen when trying to handle interrupt, due to wrong bank being looked up. Observed on s5pv210, when trying to handle gpj0 interrupt, where kernel was mapping it to gpi bank. Cc: stable@vger.kernel.org Fixes: 023e06dfa688 ("pinctrl: exynos: add exynos5410 SoC specific data") Fixes: 608a26a7bc04 ("pinctrl: Add s5pv210 support to pinctrl-exynos) Signed-off-by: Paweł Chmiel Reviewed-by: Tomasz Figa Signed-off-by: Krzysztof Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/samsung/pinctrl-exynos-arm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm.c index 92aeea174a56..afeb4876ffb2 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos-arm.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm.c @@ -110,12 +110,12 @@ static const struct samsung_pin_bank_data s5pv210_pin_bank[] __initconst = { EXYNOS_PIN_BANK_EINTG(7, 0x1c0, "gpg1", 0x38), EXYNOS_PIN_BANK_EINTG(7, 0x1e0, "gpg2", 0x3c), EXYNOS_PIN_BANK_EINTG(7, 0x200, "gpg3", 0x40), - EXYNOS_PIN_BANK_EINTN(7, 0x220, "gpi"), EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x44), EXYNOS_PIN_BANK_EINTG(6, 0x260, "gpj1", 0x48), EXYNOS_PIN_BANK_EINTG(8, 0x280, "gpj2", 0x4c), EXYNOS_PIN_BANK_EINTG(8, 0x2a0, "gpj3", 0x50), EXYNOS_PIN_BANK_EINTG(5, 0x2c0, "gpj4", 0x54), + EXYNOS_PIN_BANK_EINTN(7, 0x220, "gpi"), EXYNOS_PIN_BANK_EINTN(8, 0x2e0, "mp01"), EXYNOS_PIN_BANK_EINTN(4, 0x300, "mp02"), EXYNOS_PIN_BANK_EINTN(8, 0x320, "mp03"), @@ -635,7 +635,6 @@ static const struct samsung_pin_bank_data exynos5410_pin_banks0[] __initconst = EXYNOS_PIN_BANK_EINTG(4, 0x100, "gpc3", 0x20), EXYNOS_PIN_BANK_EINTG(7, 0x120, "gpc1", 0x24), EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpc2", 0x28), - EXYNOS_PIN_BANK_EINTN(2, 0x160, "gpm5"), EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpd1", 0x2c), EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpe0", 0x30), EXYNOS_PIN_BANK_EINTG(2, 0x1C0, "gpe1", 0x34), @@ -646,6 +645,7 @@ static const struct samsung_pin_bank_data exynos5410_pin_banks0[] __initconst = EXYNOS_PIN_BANK_EINTG(2, 0x260, "gpg2", 0x48), EXYNOS_PIN_BANK_EINTG(4, 0x280, "gph0", 0x4c), EXYNOS_PIN_BANK_EINTG(8, 0x2A0, "gph1", 0x50), + EXYNOS_PIN_BANK_EINTN(2, 0x160, "gpm5"), EXYNOS_PIN_BANK_EINTN(8, 0x2C0, "gpm7"), EXYNOS_PIN_BANK_EINTN(6, 0x2E0, "gpy0"), EXYNOS_PIN_BANK_EINTN(4, 0x300, "gpy1"), -- GitLab From 55be2e6f50ac817bcb553d79ab703838b2760226 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 7 Jun 2018 13:51:33 -0300 Subject: [PATCH 1106/1299] pinctrl: devicetree: Fix pctldev pointer overwrite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit bc3322bc166a2905bc91f774d7b22773dc7c063a upstream. Commit b89405b6102f ("pinctrl: devicetree: Fix dt_to_map_one_config handling of hogs") causes the pinctrl hog pins to not get initialized on i.MX platforms leaving them with the IOMUX settings untouched. This causes several regressions on i.MX such as: - OV5640 camera driver can not be probed anymore on imx6qdl-sabresd because the camera clock pin is in a pinctrl_hog group and since its pinctrl initialization is skipped, the camera clock is kept in GPIO functionality instead of CLK_CKO function. - Audio stopped working on imx6qdl-wandboard and imx53-qsb for the same reason. Richard Fitzgerald explains the problem: "I see the bug. If the hog node isn't a 1st level child of the pinctrl parent node it will go around the for(;;) loop again but on the first pass I overwrite pctldev with the result of get_pinctrl_dev_from_of_node() so it doesn't point to the pinctrl driver any more." Fix the issue by stashing the original pctldev so it doesn't get overwritten. Fixes: b89405b6102f ("pinctrl: devicetree: Fix dt_to_map_one_config handling of hogs") Cc: Reported-by: Mika Penttilä Reported-by: Steve Longerbeam Suggested-by: Richard Fitzgerald Signed-off-by: Fabio Estevam Reviewed-by: Dong Aisheng Reviewed-by: Richard Fitzgerald Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/devicetree.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index b601039d6c69..c4aa411f5935 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c @@ -101,10 +101,11 @@ struct pinctrl_dev *of_pinctrl_get(struct device_node *np) } static int dt_to_map_one_config(struct pinctrl *p, - struct pinctrl_dev *pctldev, + struct pinctrl_dev *hog_pctldev, const char *statename, struct device_node *np_config) { + struct pinctrl_dev *pctldev = NULL; struct device_node *np_pctldev; const struct pinctrl_ops *ops; int ret; @@ -123,8 +124,10 @@ static int dt_to_map_one_config(struct pinctrl *p, return -EPROBE_DEFER; } /* If we're creating a hog we can use the passed pctldev */ - if (pctldev && (np_pctldev == p->dev->of_node)) + if (hog_pctldev && (np_pctldev == p->dev->of_node)) { + pctldev = hog_pctldev; break; + } pctldev = get_pinctrl_dev_from_of_node(np_pctldev); if (pctldev) break; -- GitLab From 93e1297f9edce474df6839d5434a511cb130a4a2 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 18 Jun 2018 12:47:45 -0700 Subject: [PATCH 1107/1299] cpufreq: intel_pstate: Fix scaling max/min limits with Turbo 3.0 commit ff7c9917143b3a6cf2fa61212a32d67cf259bf9c upstream. When scaling max/min settings are changed, internally they are converted to a ratio using the max turbo 1 core turbo frequency. This works fine when 1 core max is same irrespective of the core. But under Turbo 3.0, this will not be the case. For example: Core 0: max turbo pstate: 43 (4.3GHz) Core 1: max turbo pstate: 45 (4.5GHz) In this case 1 core turbo ratio will be maximum of all, so it will be 45 (4.5GHz). Suppose scaling max is set to 4GHz (ratio 40) for all cores ,then on core one it will be = max_state * policy->max / max_freq; = 43 * (4000000/4500000) = 38 (3.8GHz) = 38 which is 200MHz less than the desired. On core2, it will be correctly set to ratio 40 (4GHz). Same holds true for scaling min frequency limit. So this requires usage of correct turbo max frequency for core one, which in this case is 4.3GHz. So we need to adjust per CPU cpu->pstate.turbo_freq using the maximum HWP ratio of that core. This change uses the HWP capability of a core to adjust max turbo frequency. But since Broadwell HWP doesn't use ratios in the HWP capabilities, we have to use legacy max 1 core turbo ratio. This is not a problem as the HWP capabilities don't differ among cores in Broadwell. We need to check for non Broadwell CPU model for applying this change, though. Signed-off-by: Srinivas Pandruvada Cc: 4.6+ # 4.6+ Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/intel_pstate.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 20226d4243f2..a905bbb45667 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -285,6 +285,7 @@ struct pstate_funcs { static struct pstate_funcs pstate_funcs __read_mostly; static int hwp_active __read_mostly; +static int hwp_mode_bdw __read_mostly; static bool per_cpu_limits __read_mostly; static struct cpufreq_driver *intel_pstate_driver __read_mostly; @@ -1371,7 +1372,15 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); cpu->pstate.scaling = pstate_funcs.get_scaling(); cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling; - cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling; + + if (hwp_active && !hwp_mode_bdw) { + unsigned int phy_max, current_max; + + intel_pstate_get_hwp_max(cpu->cpu, &phy_max, ¤t_max); + cpu->pstate.turbo_freq = phy_max * cpu->pstate.scaling; + } else { + cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling; + } if (pstate_funcs.get_aperf_mperf_shift) cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift(); @@ -2261,28 +2270,36 @@ static inline bool intel_pstate_has_acpi_ppc(void) { return false; } static inline void intel_pstate_request_control_from_smm(void) {} #endif /* CONFIG_ACPI */ +#define INTEL_PSTATE_HWP_BROADWELL 0x01 + +#define ICPU_HWP(model, hwp_mode) \ + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_HWP, hwp_mode } + static const struct x86_cpu_id hwp_support_ids[] __initconst = { - { X86_VENDOR_INTEL, 6, X86_MODEL_ANY, X86_FEATURE_HWP }, + ICPU_HWP(INTEL_FAM6_BROADWELL_X, INTEL_PSTATE_HWP_BROADWELL), + ICPU_HWP(INTEL_FAM6_BROADWELL_XEON_D, INTEL_PSTATE_HWP_BROADWELL), + ICPU_HWP(X86_MODEL_ANY, 0), {} }; static int __init intel_pstate_init(void) { + const struct x86_cpu_id *id; int rc; if (no_load) return -ENODEV; - if (x86_match_cpu(hwp_support_ids)) { + id = x86_match_cpu(hwp_support_ids); + if (id) { copy_cpu_funcs(&core_funcs); if (!no_hwp) { hwp_active++; + hwp_mode_bdw = id->driver_data; intel_pstate.attr = hwp_cpufreq_attrs; goto hwp_cpu_matched; } } else { - const struct x86_cpu_id *id; - id = x86_match_cpu(intel_pstate_cpu_ids); if (!id) return -ENODEV; -- GitLab From 0fe95015fb93d171b6cd0e315b33c26ea33e82f1 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Tue, 12 Jun 2018 17:54:42 +0800 Subject: [PATCH 1108/1299] MIPS: io: Add barrier after register read in inX() commit 18f3e95b90b28318ef35910d21c39908de672331 upstream. While a barrier is present in the outX() functions before the register write, a similar barrier is missing in the inX() functions after the register read. This could allow memory accesses following inX() to observe stale data. This patch is very similar to commit a1cc7034e33d12dc1 ("MIPS: io: Add barrier after register read in readX()"). Because war_io_reorder_wmb() is both used by writeX() and outX(), if readX() need a barrier then so does inX(). Cc: stable@vger.kernel.org Signed-off-by: Huacai Chen Patchwork: https://patchwork.linux-mips.org/patch/19516/ Signed-off-by: Paul Burton Cc: James Hogan Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: Huacai Chen Signed-off-by: Greg Kroah-Hartman --- arch/mips/include/asm/io.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index a7d0b836f2f7..cea8ad864b3f 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -414,6 +414,8 @@ static inline type pfx##in##bwlq##p(unsigned long port) \ __val = *__addr; \ slow; \ \ + /* prevent prefetching of coherent DMA data prematurely */ \ + rmb(); \ return pfx##ioswab##bwlq(__addr, __val); \ } -- GitLab From 88c4318d36337ddaeb21eeae34a405a6b9f93bc0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 22 Jun 2018 16:33:57 +0200 Subject: [PATCH 1109/1299] time: Make sure jiffies_to_msecs() preserves non-zero time periods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit abcbcb80cd09cd40f2089d912764e315459b71f7 upstream. For the common cases where 1000 is a multiple of HZ, or HZ is a multiple of 1000, jiffies_to_msecs() never returns zero when passed a non-zero time period. However, if HZ > 1000 and not an integer multiple of 1000 (e.g. 1024 or 1200, as used on alpha and DECstation), jiffies_to_msecs() may return zero for small non-zero time periods. This may break code that relies on receiving back a non-zero value. jiffies_to_usecs() does not need such a fix: one jiffy can only be less than one µs if HZ > 1000000, and such large values of HZ are already rejected at build time, twice: - include/linux/jiffies.h does #error if HZ >= 12288, - kernel/time/time.c has BUILD_BUG_ON(HZ > USEC_PER_SEC). Broken since forever. Signed-off-by: Geert Uytterhoeven Signed-off-by: Thomas Gleixner Reviewed-by: Arnd Bergmann Cc: John Stultz Cc: Stephen Boyd Cc: linux-alpha@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180622143357.7495-1-geert@linux-m68k.org Signed-off-by: Greg Kroah-Hartman --- kernel/time/time.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/time/time.c b/kernel/time/time.c index 44a8c1402133..319935af02fb 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -28,6 +28,7 @@ */ #include +#include #include #include #include @@ -348,9 +349,10 @@ unsigned int jiffies_to_msecs(const unsigned long j) return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); #else # if BITS_PER_LONG == 32 - return (HZ_TO_MSEC_MUL32 * j) >> HZ_TO_MSEC_SHR32; + return (HZ_TO_MSEC_MUL32 * j + (1ULL << HZ_TO_MSEC_SHR32) - 1) >> + HZ_TO_MSEC_SHR32; # else - return (j * HZ_TO_MSEC_NUM) / HZ_TO_MSEC_DEN; + return DIV_ROUND_UP(j * HZ_TO_MSEC_NUM, HZ_TO_MSEC_DEN); # endif #endif } -- GitLab From 7dfc81992a3e0da45e45eab2f113658f3628f743 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 22 Jun 2018 10:52:51 +0100 Subject: [PATCH 1110/1299] irqchip/gic-v3-its: Don't bind LPI to unavailable NUMA node commit c1797b11a09c8323c92b074fd48b89a936c991d0 upstream. On a NUMA system, if an ITS is local to an offline node, the ITS driver may pick an offline CPU to bind the LPI. In this case, pick an online CPU (and the first one will do). But on some systems, binding an LPI to non-local node CPU may cause deadlock (see Cavium erratum 23144). In this case, just fail the activate and return an error code. Signed-off-by: Yang Yingliang Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Cc: Jason Cooper Cc: Alexandre Belloni Cc: Sumit Garg Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180622095254.5906-5-marc.zyngier@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/irqchip/irq-gic-v3-its.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 13f195c9743e..2ea39a83737f 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -2221,7 +2221,14 @@ static void its_irq_domain_activate(struct irq_domain *domain, cpu_mask = cpumask_of_node(its_dev->its->numa_node); /* Bind the LPI to the first possible CPU */ - cpu = cpumask_first(cpu_mask); + cpu = cpumask_first_and(cpu_mask, cpu_online_mask); + if (cpu >= nr_cpu_ids) { + if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) + return; + + cpu = cpumask_first(cpu_online_mask); + } + its_dev->event_map.col_map[event] = cpu; irq_data_update_effective_affinity(d, cpumask_of(cpu)); -- GitLab From af20e4eccc2d5a6d8985c4ff671cabd2c1ef2016 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sat, 19 May 2018 14:23:54 +0200 Subject: [PATCH 1111/1299] X.509: unpack RSA signatureValue field from BIT STRING commit b65c32ec5a942ab3ada93a048089a938918aba7f upstream. The signatureValue field of a X.509 certificate is encoded as a BIT STRING. For RSA signatures this BIT STRING is of so-called primitive subtype, which contains a u8 prefix indicating a count of unused bits in the encoding. We have to strip this prefix from signature data, just as we already do for key data in x509_extract_key_data() function. This wasn't noticed earlier because this prefix byte is zero for RSA key sizes divisible by 8. Since BIT STRING is a big-endian encoding adding zero prefixes has no bearing on its value. The signature length, however was incorrect, which is a problem for RSA implementations that need it to be exactly correct (like AMD CCP). Signed-off-by: Maciej S. Szmigiero Fixes: c26fd69fa009 ("X.509: Add a crypto key parser for binary (DER) X.509 certificates") Cc: stable@vger.kernel.org Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- crypto/asymmetric_keys/x509_cert_parser.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index ce2df8c9c583..7e6a43ffdcbe 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -249,6 +249,15 @@ int x509_note_signature(void *context, size_t hdrlen, return -EINVAL; } + if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0) { + /* Discard the BIT STRING metadata */ + if (vlen < 1 || *(const u8 *)value != 0) + return -EBADMSG; + + value++; + vlen--; + } + ctx->cert->raw_sig = value; ctx->cert->raw_sig_size = vlen; return 0; -- GitLab From 6101eea47bf3a74345e5d722537cc9531ea85a72 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Mon, 11 Jun 2018 19:24:16 +0100 Subject: [PATCH 1112/1299] Btrfs: fix return value on rename exchange failure commit c5b4a50b74018b3677098151ec5f4fce07d5e6a0 upstream. If we failed during a rename exchange operation after starting/joining a transaction, we would end up replacing the return value, stored in the local 'ret' variable, with the return value from btrfs_end_transaction(). So this could end up returning 0 (success) to user space despite the operation having failed and aborted the transaction, because if there are multiple tasks having a reference on the transaction at the time btrfs_end_transaction() is called by the rename exchange, that function returns 0 (otherwise it returns -EIO and not the original error value). So fix this by not overwriting the return value on error after getting a transaction handle. Fixes: cdd1fedf8261 ("btrfs: add support for RENAME_EXCHANGE and RENAME_WHITEOUT") CC: stable@vger.kernel.org # 4.9+ Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/inode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3a07900971c3..f5b90dc137ec 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -9769,6 +9769,7 @@ static int btrfs_rename_exchange(struct inode *old_dir, u64 new_idx = 0; u64 root_objectid; int ret; + int ret2; bool root_log_pinned = false; bool dest_log_pinned = false; @@ -9965,7 +9966,8 @@ static int btrfs_rename_exchange(struct inode *old_dir, dest_log_pinned = false; } } - ret = btrfs_end_transaction(trans); + ret2 = btrfs_end_transaction(trans); + ret = ret ? ret : ret2; out_notrans: if (new_ino == BTRFS_FIRST_FREE_OBJECTID) up_read(&fs_info->subvol_sem); -- GitLab From d55209eeb1215c66d5e2b8360760c6c2ff53ae93 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 12 Mar 2018 14:06:53 +0200 Subject: [PATCH 1113/1299] iio: adc: ad7791: remove sample freq sysfs attributes commit 7eb6b35d93c356f1afebbfb808bc296d6351e708 upstream. In the current state, these attributes are broken, because they are registered already, and the kernel throws a warning. The first registration happens via the `IIO_CHAN_INFO_SAMP_FREQ` flag from the `ad_sigma_delta` driver. In this commit these attrs are removed, and in the following the IIO_CHAN_INFO_SAMP_FREQ behavior will be implemented, which replaces these hooks. This is done to make things a bit easier to review as there is a bit of overlap in the patch if it's done all at once. Fixes: a13e831fcaa7 ("staging: iio: ad7192: implement IIO_CHAN_INFO_SAMP_FREQ") Signed-off-by: Alexandru Ardelean Cc: Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/adc/ad7791.c | 49 ---------------------------------------- 1 file changed, 49 deletions(-) diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 34e353c43ac8..677f812f372a 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -244,58 +244,9 @@ static int ad7791_read_raw(struct iio_dev *indio_dev, return -EINVAL; } -static const char * const ad7791_sample_freq_avail[] = { - [AD7791_FILTER_RATE_120] = "120", - [AD7791_FILTER_RATE_100] = "100", - [AD7791_FILTER_RATE_33_3] = "33.3", - [AD7791_FILTER_RATE_20] = "20", - [AD7791_FILTER_RATE_16_6] = "16.6", - [AD7791_FILTER_RATE_16_7] = "16.7", - [AD7791_FILTER_RATE_13_3] = "13.3", - [AD7791_FILTER_RATE_9_5] = "9.5", -}; - -static ssize_t ad7791_read_frequency(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7791_state *st = iio_priv(indio_dev); - unsigned int rate = st->filter & AD7791_FILTER_RATE_MASK; - - return sprintf(buf, "%s\n", ad7791_sample_freq_avail[rate]); -} - -static ssize_t ad7791_write_frequency(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7791_state *st = iio_priv(indio_dev); - int i, ret; - - i = sysfs_match_string(ad7791_sample_freq_avail, buf); - if (i < 0) - return i; - - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - st->filter &= ~AD7791_FILTER_RATE_MASK; - st->filter |= i; - ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, sizeof(st->filter), - st->filter); - iio_device_release_direct_mode(indio_dev); - - return len; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - ad7791_read_frequency, - ad7791_write_frequency); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("120 100 33.3 20 16.7 16.6 13.3 9.5"); static struct attribute *ad7791_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, NULL }; -- GitLab From 5d6ad5a030675c6527956cf8737657b6be81b41b Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 8 Apr 2018 21:44:01 +0200 Subject: [PATCH 1114/1299] iio: sca3000: Fix an error handling path in 'sca3000_probe()' commit 4a5b45383ca371e123ba103d34d4b3b87616245c upstream. Use 'devm_iio_kfifo_allocate()' instead of 'iio_kfifo_allocate()' in order to simplify code and avoid a memory leak in an error path in 'sca3000_probe()'. A call to 'sca3000_unconfigure_ring()' was missing. Sent via the next merge window as unimportant bug and there are other patches dependent on it. Signed-off-by: Christophe JAILLET Cc: Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/accel/sca3000.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index 39ab210c44f6..565f7d8d3304 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -1277,7 +1277,7 @@ static int sca3000_configure_ring(struct iio_dev *indio_dev) { struct iio_buffer *buffer; - buffer = iio_kfifo_allocate(); + buffer = devm_iio_kfifo_allocate(&indio_dev->dev); if (!buffer) return -ENOMEM; @@ -1287,11 +1287,6 @@ static int sca3000_configure_ring(struct iio_dev *indio_dev) return 0; } -static void sca3000_unconfigure_ring(struct iio_dev *indio_dev) -{ - iio_kfifo_free(indio_dev->buffer); -} - static inline int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state) { @@ -1547,8 +1542,6 @@ static int sca3000_remove(struct spi_device *spi) if (spi->irq) free_irq(spi->irq, indio_dev); - sca3000_unconfigure_ring(indio_dev); - return 0; } -- GitLab From 2d329968a883f4b64758df6a6c972a02392b3a24 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 19 Apr 2018 21:32:19 -0700 Subject: [PATCH 1115/1299] mm: fix __gup_device_huge vs unmap commit a9b6de77b1a3ff729f7bfc54b2e17711776a416c upstream. get_user_pages_fast() for device pages is missing the typical validation that all page references have been taken while the mapping was valid. Without this validation truncate operations can not reliably coordinate against new page reference events like O_DIRECT. Cc: Fixes: 3565fce3a659 ("mm, x86: get_user_pages() for dax mappings") Reported-by: Jan Kara Reviewed-by: Jan Kara Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- mm/gup.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/mm/gup.c b/mm/gup.c index d2ba0be71441..72c921da0f3b 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1469,32 +1469,48 @@ static int __gup_device_huge(unsigned long pfn, unsigned long addr, return 1; } -static int __gup_device_huge_pmd(pmd_t pmd, unsigned long addr, +static int __gup_device_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, unsigned long end, struct page **pages, int *nr) { unsigned long fault_pfn; + int nr_start = *nr; + + fault_pfn = pmd_pfn(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); + if (!__gup_device_huge(fault_pfn, addr, end, pages, nr)) + return 0; - fault_pfn = pmd_pfn(pmd) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); - return __gup_device_huge(fault_pfn, addr, end, pages, nr); + if (unlikely(pmd_val(orig) != pmd_val(*pmdp))) { + undo_dev_pagemap(nr, nr_start, pages); + return 0; + } + return 1; } -static int __gup_device_huge_pud(pud_t pud, unsigned long addr, +static int __gup_device_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, unsigned long end, struct page **pages, int *nr) { unsigned long fault_pfn; + int nr_start = *nr; + + fault_pfn = pud_pfn(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); + if (!__gup_device_huge(fault_pfn, addr, end, pages, nr)) + return 0; - fault_pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); - return __gup_device_huge(fault_pfn, addr, end, pages, nr); + if (unlikely(pud_val(orig) != pud_val(*pudp))) { + undo_dev_pagemap(nr, nr_start, pages); + return 0; + } + return 1; } #else -static int __gup_device_huge_pmd(pmd_t pmd, unsigned long addr, +static int __gup_device_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, unsigned long end, struct page **pages, int *nr) { BUILD_BUG(); return 0; } -static int __gup_device_huge_pud(pud_t pud, unsigned long addr, +static int __gup_device_huge_pud(pud_t pud, pud_t *pudp, unsigned long addr, unsigned long end, struct page **pages, int *nr) { BUILD_BUG(); @@ -1512,7 +1528,7 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, return 0; if (pmd_devmap(orig)) - return __gup_device_huge_pmd(orig, addr, end, pages, nr); + return __gup_device_huge_pmd(orig, pmdp, addr, end, pages, nr); refs = 0; page = pmd_page(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); @@ -1550,7 +1566,7 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, return 0; if (pud_devmap(orig)) - return __gup_device_huge_pud(orig, addr, end, pages, nr); + return __gup_device_huge_pud(orig, pudp, addr, end, pages, nr); refs = 0; page = pud_page(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); -- GitLab From 2829829c3e61b8ff7245345613f10344e1bf3d22 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Sat, 2 Jun 2018 00:28:53 -0400 Subject: [PATCH 1116/1299] scsi: hpsa: disable device during shutdown commit 0d98ba8d70b0070ac117452ea0b663e26bbf46bf upstream. 'Commit cc27b735ad3a ("PCI/portdrv: Turn off PCIe services during shutdown")' has been added to kernel to shutdown pending PCIe port service interrupts during reboot so that a newly started kexec kernel wouldn't observe pending interrupts. pcie_port_device_remove() is disabling the root port and switches by calling pci_disable_device() after all PCIe service drivers are shutdown. This has been found to cause crashes on HP DL360 Gen9 machines during reboot due to hpsa driver not clearing the bus master bit during the shutdown procedure by calling pci_disable_device(). Disable device as part of the shutdown sequence. Signed-off-by: Sinan Kaya Link: https://bugzilla.kernel.org/show_bug.cgi?id=199779 Fixes: cc27b735ad3a ("PCI/portdrv: Turn off PCIe services during shutdown") Cc: stable@vger.kernel.org Reported-by: Ryan Finnie Tested-by: Don Brace Acked-by: Don Brace Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/hpsa.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 5fbaf13781b6..604a39dba5d0 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8638,7 +8638,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h) kfree(options); } -static void hpsa_shutdown(struct pci_dev *pdev) +static void __hpsa_shutdown(struct pci_dev *pdev) { struct ctlr_info *h; @@ -8653,6 +8653,12 @@ static void hpsa_shutdown(struct pci_dev *pdev) hpsa_disable_interrupt_mode(h); /* pci_init 2 */ } +static void hpsa_shutdown(struct pci_dev *pdev) +{ + __hpsa_shutdown(pdev); + pci_disable_device(pdev); +} + static void hpsa_free_device_info(struct ctlr_info *h) { int i; @@ -8696,7 +8702,7 @@ static void hpsa_remove_one(struct pci_dev *pdev) scsi_remove_host(h->scsi_host); /* init_one 8 */ /* includes hpsa_free_irqs - init_one 4 */ /* includes hpsa_disable_interrupt_mode - pci_init 2 */ - hpsa_shutdown(pdev); + __hpsa_shutdown(pdev); hpsa_free_device_info(h); /* scan */ -- GitLab From 9224583a5ee225969577ba4992322420e805fd2b Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Sun, 3 Jun 2018 22:09:53 -0700 Subject: [PATCH 1117/1299] scsi: qla2xxx: Fix setting lower transfer speed if GPSC fails commit 413c2f33489b134e3cc65d9c3ff7861e8fdfe899 upstream. This patch prevents driver from setting lower default speed of 1 GB/sec, if the switch does not support Get Port Speed Capabilities (GPSC) command. Setting this default speed results into much lower write performance for large sequential WRITE. This patch modifies driver to check for gpsc_supported flags and prevents driver from issuing MBC_SET_PORT_PARAM (001Ah) to set default speed of 1 GB/sec. If driver does not send this mailbox command, firmware assumes maximum supported link speed and will operate at the max speed. Cc: stable@vger.kernel.org Signed-off-by: Himanshu Madhani Reported-by: Eda Zhou Reviewed-by: Ewan D. Milne Tested-by: Ewan D. Milne Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e24f57946a17..bcde6130f121 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -4627,7 +4627,8 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) return; if (fcport->fp_speed == PORT_SPEED_UNKNOWN || - fcport->fp_speed > ha->link_data_rate) + fcport->fp_speed > ha->link_data_rate || + !ha->flags.gpsc_supported) return; rval = qla2x00_set_idma_speed(vha, fcport->loop_id, fcport->fp_speed, -- GitLab From 9db2ad79b8f03d2ddef33e860fb9cf9cd52e7cbc Mon Sep 17 00:00:00 2001 From: Anil Gurumurthy Date: Wed, 6 Jun 2018 08:41:42 -0700 Subject: [PATCH 1118/1299] scsi: qla2xxx: Mask off Scope bits in retry delay commit 3cedc8797b9c0f2222fd45a01f849c57c088828b upstream. Some newer target uses "Status Qualifier" response in a returned "Busy Status". This new response code of 0x4001, which is "Scope" bits, translates to "Affects all units accessible by target". Due to this new value returned in the Scope bits, driver was using that value as timeout value which resulted into driver waiting for 27min timeout. This patch masks off this Scope bits so that driver does not use this value as retry delay time. Cc: Signed-off-by: Anil Gurumurthy Signed-off-by: Giridhar Malavali Signed-off-by: Himanshu Madhani Reviewed-by: Ewan D. Milne Reviewed-by: Martin Wilck Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_isr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 13a00a42b3ca..e073eb16f8a4 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2454,8 +2454,12 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) ox_id = le16_to_cpu(sts24->ox_id); par_sense_len = sizeof(sts24->data); /* Valid values of the retry delay timer are 0x1-0xffef */ - if (sts24->retry_delay > 0 && sts24->retry_delay < 0xfff1) - retry_delay = sts24->retry_delay; + if (sts24->retry_delay > 0 && sts24->retry_delay < 0xfff1) { + retry_delay = sts24->retry_delay & 0x3fff; + ql_dbg(ql_dbg_io, sp->vha, 0x3033, + "%s: scope=%#x retry_delay=%#x\n", __func__, + sts24->retry_delay >> 14, retry_delay); + } } else { if (scsi_status & SS_SENSE_LEN_VALID) sense_len = le16_to_cpu(sts->req_sense_length); -- GitLab From 74da693a03ceaa21c38c604c5e0b314340a84781 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Thu, 17 May 2018 19:14:43 +0200 Subject: [PATCH 1119/1299] scsi: zfcp: fix missing SCSI trace for result of eh_host_reset_handler commit df30781699f53e4fd4c494c6f7dd16e3d5c21d30 upstream. For problem determination we need to see whether and why we were successful or not. This allows deduction of scsi_eh escalation. Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : SCSI Subarea : 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag : schrh_r SCSI host reset handler result Request ID : 0x0000000000000000 none (invalid) SCSI ID : 0xffffffff none (invalid) SCSI LUN : 0xffffffff none (invalid) SCSI LUN high : 0xffffffff none (invalid) SCSI result : 0x00002002 field re-used for midlayer value: SUCCESS or in other cases: 0x2009 == FAST_IO_FAIL SCSI retries : 0xff none (invalid) SCSI allowed : 0xff none (invalid) SCSI scribble : 0xffffffffffffffff none (invalid) SCSI opcode : ffffffff ffffffff ffffffff ffffffff none (invalid) FCP rsp inf cod: 0xff none (invalid) FCP rsp IU : 00000000 00000000 00000000 00000000 none (invalid) 00000000 00000000 v2.6.35 commit a1dbfddd02d2 ("[SCSI] zfcp: Pass return code from fc_block_scsi_eh to scsi eh") introduced the first return with something other than the previously hardcoded single SUCCESS return path. Signed-off-by: Steffen Maier Fixes: a1dbfddd02d2 ("[SCSI] zfcp: Pass return code from fc_block_scsi_eh to scsi eh") Cc: #2.6.38+ Reviewed-by: Jens Remus Reviewed-by: Benjamin Block Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_dbf.c | 40 +++++++++++++++++++++++++++++++++++ drivers/s390/scsi/zfcp_ext.h | 2 ++ drivers/s390/scsi/zfcp_scsi.c | 11 +++++----- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 18c4f933e8b9..b415ba42ca73 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -664,6 +664,46 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, spin_unlock_irqrestore(&dbf->scsi_lock, flags); } +/** + * zfcp_dbf_scsi_eh() - Trace event for special cases of scsi_eh callbacks. + * @tag: Identifier for event. + * @adapter: Pointer to zfcp adapter as context for this event. + * @scsi_id: SCSI ID/target to indicate scope of task management function (TMF). + * @ret: Return value of calling function. + * + * This SCSI trace variant does not depend on any of: + * scsi_cmnd, zfcp_fsf_req, scsi_device. + */ +void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, + unsigned int scsi_id, int ret) +{ + struct zfcp_dbf *dbf = adapter->dbf; + struct zfcp_dbf_scsi *rec = &dbf->scsi_buf; + unsigned long flags; + static int const level = 1; + + if (unlikely(!debug_level_enabled(adapter->dbf->scsi, level))) + return; + + spin_lock_irqsave(&dbf->scsi_lock, flags); + memset(rec, 0, sizeof(*rec)); + + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_SCSI_CMND; + rec->scsi_result = ret; /* re-use field, int is 4 bytes and fits */ + rec->scsi_retries = ~0; + rec->scsi_allowed = ~0; + rec->fcp_rsp_info = ~0; + rec->scsi_id = scsi_id; + rec->scsi_lun = (u32)ZFCP_DBF_INVALID_LUN; + rec->scsi_lun_64_hi = (u32)(ZFCP_DBF_INVALID_LUN >> 32); + rec->host_scribble = ~0; + memset(rec->scsi_opcode, 0xff, ZFCP_DBF_SCSI_OPCODE); + + debug_event(dbf->scsi, level, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->scsi_lock, flags); +} + static debug_info_t *zfcp_dbf_reg(const char *name, int size, int rec_size) { struct debug_info *d; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index b1cbb14fb2ae..5cd028a8c78d 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -52,6 +52,8 @@ extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_scsi(char *, int, struct scsi_cmnd *, struct zfcp_fsf_req *); +extern void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, + unsigned int scsi_id, int ret); /* zfcp_erp.c */ extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 22f9562f415c..93610cb3e5ec 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -323,15 +323,16 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) { struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device); struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; - int ret; + int ret = SUCCESS, fc_ret; zfcp_erp_adapter_reopen(adapter, 0, "schrh_1"); zfcp_erp_wait(adapter); - ret = fc_block_scsi_eh(scpnt); - if (ret) - return ret; + fc_ret = fc_block_scsi_eh(scpnt); + if (fc_ret) + ret = fc_ret; - return SUCCESS; + zfcp_dbf_scsi_eh("schrh_r", adapter, ~0, ret); + return ret; } struct scsi_transport_template *zfcp_scsi_transport_template; -- GitLab From 941e8bee351e5224ab3f5d6de77da82969e723db Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Thu, 17 May 2018 19:14:44 +0200 Subject: [PATCH 1120/1299] scsi: zfcp: fix missing SCSI trace for retry of abort / scsi_eh TMF commit 81979ae63e872ef650a7197f6ce6590059d37172 upstream. We already have a SCSI trace for the end of abort and scsi_eh TMF. Due to zfcp_erp_wait() and fc_block_scsi_eh() time can pass between the start of our eh callback and an actual send/recv of an abort / TMF request. In order to see the temporal sequence including any abort / TMF send retries, add a trace before the above two blocking functions. This supports problem determination with scsi_eh and parallel zfcp ERP. No need to explicitly trace the beginning of our eh callback, since we typically can send an abort / TMF and see its HBA response (in the worst case, it's a pseudo response on dismiss all of adapter recovery, e.g. due to an FSF request timeout [fsrth_1] of the abort / TMF). If we cannot send, we now get a trace record for the first "abrt_wt" or "[lt]r_wait" which denotes almost the beginning of the callback. No need to explicitly trace the wakeup after the above two blocking functions because the next retry loop causes another trace in any case and that is sufficient. Example trace records formatted with zfcpdbf from s390-tools: Timestamp : ... Area : SCSI Subarea : 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag : abrt_wt abort, before zfcp_erp_wait() Request ID : 0x0000000000000000 none (invalid) SCSI ID : 0x SCSI LUN : 0x SCSI LUN high : 0x SCSI result : 0x SCSI retries : 0x SCSI allowed : 0x SCSI scribble : 0x SCSI opcode : FCP rsp inf cod: 0x.. none (invalid) FCP rsp IU : ... none (invalid) Timestamp : ... Area : SCSI Subarea : 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag : lr_wait LUN reset, before zfcp_erp_wait() Request ID : 0x0000000000000000 none (invalid) SCSI ID : 0x SCSI LUN : 0x SCSI LUN high : 0x SCSI result : 0x... unrelated SCSI retries : 0x.. unrelated SCSI allowed : 0x.. unrelated SCSI scribble : 0x... unrelated SCSI opcode : ... unrelated FCP rsp inf cod: 0x.. none (invalid) FCP rsp IU : ... none (invalid) Signed-off-by: Steffen Maier Fixes: 63caf367e1c9 ("[SCSI] zfcp: Improve reliability of SCSI eh handlers in zfcp") Fixes: af4de36d911a ("[SCSI] zfcp: Block scsi_eh thread for rport state BLOCKED") Cc: #2.6.38+ Reviewed-by: Benjamin Block Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_scsi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 93610cb3e5ec..4033ad64b837 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -181,6 +181,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) if (abrt_req) break; + zfcp_dbf_scsi_abort("abrt_wt", scpnt, NULL); zfcp_erp_wait(adapter); ret = fc_block_scsi_eh(scpnt); if (ret) { @@ -277,6 +278,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) if (fsf_req) break; + zfcp_dbf_scsi_devreset("wait", scpnt, tm_flags, NULL); zfcp_erp_wait(adapter); ret = fc_block_scsi_eh(scpnt); if (ret) { -- GitLab From 3d0d31e512f29ad34ea078f1ad86ec074b7311b0 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Thu, 17 May 2018 19:14:45 +0200 Subject: [PATCH 1121/1299] scsi: zfcp: fix misleading REC trigger trace where erp_action setup failed commit 512857a795cbbda5980efa4cdb3c0b6602330408 upstream. If a SCSI device is deleted during scsi_eh host reset, we cannot get a reference to the SCSI device anymore since scsi_device_get returns !=0 by design. Assuming the recovery of adapter and port(s) was successful, zfcp_erp_strategy_followup_success() attempts to trigger a LUN reset for the half-gone SCSI device. Unfortunately, it causes the following confusing trace record which states that zfcp will do a LUN recovery as "ERP need" is ZFCP_ERP_ACTION_REOPEN_LUN == 1 and equals "ERP want". Old example trace record formatted with zfcpdbf from s390-tools: Tag: : ersfs_3 ERP, trigger, unit reopen, port reopen succeeded LUN : 0x WWPN : 0x D_ID : 0x Adapter status : 0x5400050b Port status : 0x54000001 LUN status : 0x40000000 ZFCP_STATUS_COMMON_RUNNING but not ZFCP_STATUS_COMMON_UNBLOCKED as it was closed on close part of adapter reopen ERP want : 0x01 ERP need : 0x01 misleading However, zfcp_erp_setup_act() returns NULL as it cannot get the reference. Hence, zfcp_erp_action_enqueue() takes an early goto out and _NO_ recovery actually happens. We always do want the recovery trigger trace record even if no erp_action could be enqueued as in this case. For other cases where we did not enqueue an erp_action, 'need' has always been zero to indicate this. In order to indicate above goto out, introduce an eyecatcher "flag" to mark the "ERP need" as 'not needed' but still keep the information which erp_action type, that zfcp_erp_required_act() had decided upon, is needed. 0xc_ is chosen to be visibly different from 0x0_ in "ERP want". New example trace record formatted with zfcpdbf from s390-tools: Tag: : ersfs_3 ERP, trigger, unit reopen, port reopen succeeded LUN : 0x WWPN : 0x D_ID : 0x Adapter status : 0x5400050b Port status : 0x54000001 LUN status : 0x40000000 ERP want : 0x01 ERP need : 0xc1 would need LUN ERP, but no action set up ^ Before v2.6.38 commit ae0904f60fab ("[SCSI] zfcp: Redesign of the debug tracing for recovery actions.") we could detect this case because the "erp_action" field in the trace was NULL. The rework removed erp_action as argument and field from the trace. This patch here is for tracing. A fix to allow LUN recovery in the case at hand is a topic for a separate patch. See also commit fdbd1c5e27da ("[SCSI] zfcp: Allow running unit/LUN shutdown without acquiring reference") for a similar case and background info. Signed-off-by: Steffen Maier Fixes: ae0904f60fab ("[SCSI] zfcp: Redesign of the debug tracing for recovery actions.") Cc: #2.6.38+ Reviewed-by: Benjamin Block Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_erp.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index cbb8156bf5e0..379d03419ead 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -35,11 +35,23 @@ enum zfcp_erp_steps { ZFCP_ERP_STEP_LUN_OPENING = 0x2000, }; +/** + * enum zfcp_erp_act_type - Type of ERP action object. + * @ZFCP_ERP_ACTION_REOPEN_LUN: LUN recovery. + * @ZFCP_ERP_ACTION_REOPEN_PORT: Port recovery. + * @ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: Forced port recovery. + * @ZFCP_ERP_ACTION_REOPEN_ADAPTER: Adapter recovery. + * @ZFCP_ERP_ACTION_NONE: Eyecatcher pseudo flag to bitwise or-combine with + * either of the other enum values. + * Used to indicate that an ERP action could not be + * set up despite a detected need for some recovery. + */ enum zfcp_erp_act_type { ZFCP_ERP_ACTION_REOPEN_LUN = 1, ZFCP_ERP_ACTION_REOPEN_PORT = 2, ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, + ZFCP_ERP_ACTION_NONE = 0xc0, }; enum zfcp_erp_act_state { @@ -257,8 +269,10 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, goto out; act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev); - if (!act) + if (!act) { + need |= ZFCP_ERP_ACTION_NONE; /* marker for trace */ goto out; + } atomic_or(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); ++adapter->erp_total_count; list_add_tail(&act->list, &adapter->erp_ready_head); -- GitLab From 071f23266c301c8e07007a8f05f266f9f04c5623 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Thu, 17 May 2018 19:14:46 +0200 Subject: [PATCH 1122/1299] scsi: zfcp: fix missing REC trigger trace on terminate_rport_io early return commit 96d9270499471545048ed8a6d7f425a49762283d upstream. get_device() and its internally used kobject_get() only return NULL if they get passed NULL as argument. zfcp_get_port_by_wwpn() loops over adapter->port_list so the iteration variable port is always non-NULL. Struct device is embedded in struct zfcp_port so &port->dev is always non-NULL. This is the argument to get_device(). However, if we get an fc_rport in terminate_rport_io() for which we cannot find a match within zfcp_get_port_by_wwpn(), the latter can return NULL. v2.6.30 commit 70932935b61e ("[SCSI] zfcp: Fix oops when port disappears") introduced an early return without adding a trace record for this case. Even if we don't need recovery in this case, for debugging we should still see that our callback was invoked originally by scsi_transport_fc. Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : REC Subarea : 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag : sctrpin SCSI terminate rport I/O, no zfcp port LUN : 0xffffffffffffffff none (invalid) WWPN : 0x WWPN D_ID : 0x N_Port-ID Adapter status : 0x... Port status : 0xffffffff unknown (-1) LUN status : 0x00000000 none (invalid) Ready count : 0x... Running count : 0x... ERP want : 0x03 ZFCP_ERP_ACTION_REOPEN_PORT_FORCED ERP need : 0xc0 ZFCP_ERP_ACTION_NONE Signed-off-by: Steffen Maier Fixes: 70932935b61e ("[SCSI] zfcp: Fix oops when port disappears") Cc: #2.6.38+ Reviewed-by: Benjamin Block Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_erp.c | 20 ++++++++++++++++++++ drivers/s390/scsi/zfcp_ext.h | 3 +++ drivers/s390/scsi/zfcp_scsi.c | 5 +++++ 3 files changed, 28 insertions(+) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 379d03419ead..c842ba6473a3 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -283,6 +283,26 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, return retval; } +void zfcp_erp_port_forced_no_port_dbf(char *id, struct zfcp_adapter *adapter, + u64 port_name, u32 port_id) +{ + unsigned long flags; + static /* don't waste stack */ struct zfcp_port tmpport; + + write_lock_irqsave(&adapter->erp_lock, flags); + /* Stand-in zfcp port with fields just good enough for + * zfcp_dbf_rec_trig() and zfcp_dbf_set_common(). + * Under lock because tmpport is static. + */ + atomic_set(&tmpport.status, -1); /* unknown */ + tmpport.wwpn = port_name; + tmpport.d_id = port_id; + zfcp_dbf_rec_trig(id, adapter, &tmpport, NULL, + ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, + ZFCP_ERP_ACTION_NONE); + write_unlock_irqrestore(&adapter->erp_lock, flags); +} + static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask, char *id) { diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 5cd028a8c78d..c1092a11e728 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -58,6 +58,9 @@ extern void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, /* zfcp_erp.c */ extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32); +extern void zfcp_erp_port_forced_no_port_dbf(char *id, + struct zfcp_adapter *adapter, + u64 port_name, u32 port_id); extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *); extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *); extern void zfcp_erp_set_port_status(struct zfcp_port *, u32); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 4033ad64b837..0b6f51424745 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -605,6 +605,11 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) if (port) { zfcp_erp_port_forced_reopen(port, 0, "sctrpi1"); put_device(&port->dev); + } else { + zfcp_erp_port_forced_no_port_dbf( + "sctrpin", adapter, + rport->port_name /* zfcp_scsi_rport_register */, + rport->port_id /* zfcp_scsi_rport_register */); } } -- GitLab From 60ed2673986f6c47a5fd12f328da8d92090524d9 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Thu, 17 May 2018 19:14:47 +0200 Subject: [PATCH 1123/1299] scsi: zfcp: fix missing REC trigger trace on terminate_rport_io for ERP_FAILED commit d70aab55924b44f213fec2b900b095430b33eec6 upstream. For problem determination we always want to see when we were invoked on the terminate_rport_io callback whether we perform something or not. Temporal event sequence of interest with a long fast_io_fail_tmo of 27 sec: loose remote port t workqueue [s] zfcp_q_ IRQ zfcperp === ================== =================== ============================ 0 recv RSCN q p.test_link_work block rport start fast_io_fail_tmo send ADISC ELS 4 recv ADISC fail block zfcp_port port forced reopen send open port 12 recv open port fail q p.gid_pn_work zfcp_erp_wakeup (zfcp_erp_wait would return) GID_PN fail Before this point, we got a SCSI trace with tag "sctrpi1" on fast_io_fail, e.g. with the typical 5 sec setting. port.status |= ERP_FAILED If fast_io_fail_tmo triggers after this point, we missed a SCSI trace. workqueue fc_dl_ ================== 27 fc_timeout_fail_rport_io fc_terminate_rport_io zfcp_scsi_terminate_rport_io zfcp_erp_port_forced_reopen _zfcp_erp_port_forced_reopen if (port.status & ERP_FAILED) return; Therefore, write a trace before above early return. Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : REC Subarea : 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 ZFCP_DBF_REC_TRIG Tag : sctrpi1 SCSI terminate rport I/O LUN : 0xffffffffffffffff none (invalid) WWPN : 0x D_ID : 0x Adapter status : 0x... Port status : 0x... LUN status : 0x00000000 none (invalid) Ready count : 0x... Running count : 0x... ERP want : 0x03 ZFCP_ERP_ACTION_REOPEN_PORT_FORCED ERP need : 0xe0 ZFCP_ERP_ACTION_FAILED Signed-off-by: Steffen Maier Cc: #2.6.38+ Reviewed-by: Benjamin Block Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_erp.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index c842ba6473a3..8e036826d881 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -42,9 +42,13 @@ enum zfcp_erp_steps { * @ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: Forced port recovery. * @ZFCP_ERP_ACTION_REOPEN_ADAPTER: Adapter recovery. * @ZFCP_ERP_ACTION_NONE: Eyecatcher pseudo flag to bitwise or-combine with - * either of the other enum values. + * either of the first four enum values. * Used to indicate that an ERP action could not be * set up despite a detected need for some recovery. + * @ZFCP_ERP_ACTION_FAILED: Eyecatcher pseudo flag to bitwise or-combine with + * either of the first four enum values. + * Used to indicate that ERP not needed because + * the object has ZFCP_STATUS_COMMON_ERP_FAILED. */ enum zfcp_erp_act_type { ZFCP_ERP_ACTION_REOPEN_LUN = 1, @@ -52,6 +56,7 @@ enum zfcp_erp_act_type { ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, ZFCP_ERP_ACTION_NONE = 0xc0, + ZFCP_ERP_ACTION_FAILED = 0xe0, }; enum zfcp_erp_act_state { @@ -379,8 +384,12 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) + if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { + zfcp_dbf_rec_trig(id, port->adapter, port, NULL, + ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, + ZFCP_ERP_ACTION_FAILED); return; + } zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, port->adapter, port, NULL, id, 0); -- GitLab From beadcfcca2577f56e70f99cde38f1307aed09f03 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Thu, 17 May 2018 19:14:48 +0200 Subject: [PATCH 1124/1299] scsi: zfcp: fix missing REC trigger trace for all objects in ERP_FAILED commit 8c3d20aada70042a39c6a6625be037c1472ca610 upstream. That other commit introduced an inconsistency because it would trace on ERP_FAILED for all callers of port forced reopen triggers (not just terminate_rport_io), but it would not trace on ERP_FAILED for all callers of other ERP triggers such as adapter, port regular, LUN. Therefore, generalize that other commit. zfcp_erp_action_enqueue() already had two early outs which re-used the one zfcp_dbf_rec_trig() call. All ERP trigger functions finally run through zfcp_erp_action_enqueue(). So move the special handling for ZFCP_STATUS_COMMON_ERP_FAILED into zfcp_erp_action_enqueue() and add another early out with new trace marker for pseudo ERP need in this case. This removes all early returns from all ERP trigger functions so we always end up at zfcp_dbf_rec_trig(). Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : REC Subarea : 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 ZFCP_DBF_REC_TRIG Tag : ....... LUN : 0x... WWPN : 0x... D_ID : 0x... Adapter status : 0x... Port status : 0x... LUN status : 0x... Ready count : 0x... Running count : 0x... ERP want : 0x0. ZFCP_ERP_ACTION_REOPEN_... ERP need : 0xe0 ZFCP_ERP_ACTION_FAILED Signed-off-by: Steffen Maier Cc: #2.6.38+ Reviewed-by: Benjamin Block Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_erp.c | 79 +++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 8e036826d881..d413fd3f6846 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -143,6 +143,49 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) } } +static int zfcp_erp_handle_failed(int want, struct zfcp_adapter *adapter, + struct zfcp_port *port, + struct scsi_device *sdev) +{ + int need = want; + struct zfcp_scsi_dev *zsdev; + + switch (want) { + case ZFCP_ERP_ACTION_REOPEN_LUN: + zsdev = sdev_to_zfcp(sdev); + if (atomic_read(&zsdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) + need = 0; + break; + case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: + if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) + need = 0; + break; + case ZFCP_ERP_ACTION_REOPEN_PORT: + if (atomic_read(&port->status) & + ZFCP_STATUS_COMMON_ERP_FAILED) { + need = 0; + /* ensure propagation of failed status to new devices */ + zfcp_erp_set_port_status( + port, ZFCP_STATUS_COMMON_ERP_FAILED); + } + break; + case ZFCP_ERP_ACTION_REOPEN_ADAPTER: + if (atomic_read(&adapter->status) & + ZFCP_STATUS_COMMON_ERP_FAILED) { + need = 0; + /* ensure propagation of failed status to new devices */ + zfcp_erp_set_adapter_status( + adapter, ZFCP_STATUS_COMMON_ERP_FAILED); + } + break; + default: + need = 0; + break; + } + + return need; +} + static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, struct zfcp_port *port, struct scsi_device *sdev) @@ -266,6 +309,12 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, int retval = 1, need; struct zfcp_erp_action *act; + need = zfcp_erp_handle_failed(want, adapter, port, sdev); + if (!need) { + need = ZFCP_ERP_ACTION_FAILED; /* marker for trace */ + goto out; + } + if (!adapter->erp_thread) return -EIO; @@ -314,12 +363,6 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, zfcp_erp_adapter_block(adapter, clear_mask); zfcp_scsi_schedule_rports_block(adapter); - /* ensure propagation of failed status to new devices */ - if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { - zfcp_erp_set_adapter_status(adapter, - ZFCP_STATUS_COMMON_ERP_FAILED); - return -EIO; - } return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, NULL, NULL, id, 0); } @@ -338,12 +381,8 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, char *id) zfcp_scsi_schedule_rports_block(adapter); write_lock_irqsave(&adapter->erp_lock, flags); - if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) - zfcp_erp_set_adapter_status(adapter, - ZFCP_STATUS_COMMON_ERP_FAILED); - else - zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, - NULL, NULL, id, 0); + zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, + NULL, NULL, id, 0); write_unlock_irqrestore(&adapter->erp_lock, flags); } @@ -384,13 +423,6 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { - zfcp_dbf_rec_trig(id, port->adapter, port, NULL, - ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, - ZFCP_ERP_ACTION_FAILED); - return; - } - zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, port->adapter, port, NULL, id, 0); } @@ -416,12 +448,6 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { - /* ensure propagation of failed status to new devices */ - zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); - return -EIO; - } - return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, port->adapter, port, NULL, id, 0); } @@ -461,9 +487,6 @@ static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, zfcp_erp_lun_block(sdev, clear); - if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) - return; - zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter, zfcp_sdev->port, sdev, id, act_status); } -- GitLab From a64be479ef08c945a94626e90b11ec46bcb66a5e Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Thu, 17 May 2018 19:14:49 +0200 Subject: [PATCH 1125/1299] scsi: zfcp: fix missing REC trigger trace on enqueue without ERP thread commit 6a76550841d412330bd86aed3238d1888ba70f0e upstream. Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : REC Subarea : 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 ZFCP_DBF_REC_TRIG Tag : ....... LUN : 0x... WWPN : 0x... D_ID : 0x... Adapter status : 0x... Port status : 0x... LUN status : 0x... Ready count : 0x... Running count : 0x... ERP want : 0x0. ZFCP_ERP_ACTION_REOPEN_... ERP need : 0xc0 ZFCP_ERP_ACTION_NONE Signed-off-by: Steffen Maier Cc: #2.6.38+ Reviewed-by: Benjamin Block Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_erp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index d413fd3f6846..7aa243a6cdbf 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -315,8 +315,11 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, goto out; } - if (!adapter->erp_thread) - return -EIO; + if (!adapter->erp_thread) { + need = ZFCP_ERP_ACTION_NONE; /* marker for trace */ + retval = -EIO; + goto out; + } need = zfcp_erp_required_act(want, adapter, port, sdev); if (!need) -- GitLab From a98f1946ea58a21ea8004e07d414ba2f99bc6434 Mon Sep 17 00:00:00 2001 From: Robert Elliott Date: Thu, 31 May 2018 18:36:36 -0500 Subject: [PATCH 1126/1299] linvdimm, pmem: Preserve read-only setting for pmem devices commit 254a4cd50b9fe2291a12b8902e08e56dcc4e9b10 upstream. The pmem driver does not honor a forced read-only setting for very long: $ blockdev --setro /dev/pmem0 $ blockdev --getro /dev/pmem0 1 followed by various commands like these: $ blockdev --rereadpt /dev/pmem0 or $ mkfs.ext4 /dev/pmem0 results in this in the kernel serial log: nd_pmem namespace0.0: region0 read-write, marking pmem0 read-write with the read-only setting lost: $ blockdev --getro /dev/pmem0 0 That's from bus.c nvdimm_revalidate_disk(), which always applies the setting from nd_region (which is initially based on the ACPI NFIT NVDIMM state flags not_armed bit). In contrast, commit 20bd1d026aac ("scsi: sd: Keep disk read-only when re-reading partition") fixed this issue for SCSI devices to preserve the previous setting if it was set to read-only. This patch modifies bus.c to preserve any previous read-only setting. It also eliminates the kernel serial log print except for cases where read-write is changed to read-only, so it doesn't print read-only to read-only non-changes. Cc: Fixes: 581388209405 ("libnvdimm, nfit: handle unarmed dimms, mark namespaces read-only") Signed-off-by: Robert Elliott Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/nvdimm/bus.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index baf283986a7e..2fffd42767c7 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -565,14 +565,18 @@ int nvdimm_revalidate_disk(struct gendisk *disk) { struct device *dev = disk_to_dev(disk)->parent; struct nd_region *nd_region = to_nd_region(dev->parent); - const char *pol = nd_region->ro ? "only" : "write"; + int disk_ro = get_disk_ro(disk); - if (nd_region->ro == get_disk_ro(disk)) + /* + * Upgrade to read-only if the region is read-only preserve as + * read-only if the disk is already read-only. + */ + if (disk_ro || nd_region->ro == disk_ro) return 0; - dev_info(dev, "%s read-%s, marking %s read-%s\n", - dev_name(&nd_region->dev), pol, disk->disk_name, pol); - set_disk_ro(disk, nd_region->ro); + dev_info(dev, "%s read-only, marking %s read-only\n", + dev_name(&nd_region->dev), disk->disk_name); + set_disk_ro(disk, 1); return 0; -- GitLab From b90f3eccf8aa9eb2990e98bf8c67bd613d44aa0f Mon Sep 17 00:00:00 2001 From: Marcin Ziemianowicz Date: Sun, 29 Apr 2018 15:01:11 -0400 Subject: [PATCH 1127/1299] clk: at91: PLL recalc_rate() now using cached MUL and DIV values commit a982e45dc150da3a08907b6dd676b735391704b4 upstream. When a USB device is connected to the USB host port on the SAM9N12 then you get "-62" error which seems to indicate USB replies from the device are timing out. Based on a logic sniffer, I saw the USB bus was running at half speed. The PLL code uses cached MUL and DIV values which get set in set_rate() and applied in prepare(), but the recalc_rate() function instead queries the hardware instead of using these cached values. Therefore, if recalc_rate() is called between a set_rate() and prepare(), the wrong frequency is calculated and later the USB clock divider for the SAM9N12 SOC will be configured for an incorrect clock. In my case, the PLL hardware was set to 96 Mhz before the OHCI driver loads, and therefore the usb clock divider was being set to /2 even though the OHCI driver set the PLL to 48 Mhz. As an alternative explanation, I noticed this was fixed in the past by 87e2ed338f1b ("clk: at91: fix recalc_rate implementation of PLL driver") but the bug was later re-introduced by 1bdf02326b71 ("clk: at91: make use of syscon/regmap internally"). Fixes: 1bdf02326b71 ("clk: at91: make use of syscon/regmap internally) Cc: Signed-off-by: Marcin Ziemianowicz Acked-by: Boris Brezillon Signed-off-by: Stephen Boyd Signed-off-by: Greg Kroah-Hartman --- drivers/clk/at91/clk-pll.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c index 7d3223fc7161..72b6091eb7b9 100644 --- a/drivers/clk/at91/clk-pll.c +++ b/drivers/clk/at91/clk-pll.c @@ -132,19 +132,8 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(hw); - unsigned int pllr; - u16 mul; - u8 div; - - regmap_read(pll->regmap, PLL_REG(pll->id), &pllr); - - div = PLL_DIV(pllr); - mul = PLL_MUL(pllr, pll->layout); - - if (!div || !mul) - return 0; - return (parent_rate / div) * (mul + 1); + return (parent_rate / pll->div) * (pll->mul + 1); } static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, -- GitLab From 88896a963b4e80f5d4f6fe508ab7ce399d7bcb4c Mon Sep 17 00:00:00 2001 From: Michael Trimarchi Date: Wed, 30 May 2018 23:57:44 +0530 Subject: [PATCH 1128/1299] rtc: sun6i: Fix bit_idx value for clk_register_gate commit 09018d4bd7994c2c9f775029bc24589bc85f76fa upstream. clk-gate core will take bit_idx through clk_register_gate and then do clk_gate_ops by using BIT(bit_idx), but rtc-sun6i is passing bit_idx as BIT(bit_idx) it becomes BIT(BIT(bit_idx) which is wrong and eventually external gate clock is not enabling. This patch fixed by passing bit index and the original change introduced from below commit. "rtc: sun6i: Add support for the external oscillator gate" (sha1: 17ecd246414b3a0fe0cb248c86977a8bda465b7b) Signed-off-by: Michael Trimarchi Fixes: 17ecd246414b ("rtc: sun6i: Add support for the external oscillator gate") Cc: stable@vger.kernel.org Signed-off-by: Jagan Teki Acked-by: Maxime Ripard Signed-off-by: Alexandre Belloni Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-sun6i.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 3d2216ccd860..8eb2b6dd36fe 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -74,7 +74,7 @@ #define SUN6I_ALARM_CONFIG_WAKEUP BIT(0) #define SUN6I_LOSC_OUT_GATING 0x0060 -#define SUN6I_LOSC_OUT_GATING_EN BIT(0) +#define SUN6I_LOSC_OUT_GATING_EN_OFFSET 0 /* * Get date values @@ -253,7 +253,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) &clkout_name); rtc->ext_losc = clk_register_gate(NULL, clkout_name, rtc->hw.init->name, 0, rtc->base + SUN6I_LOSC_OUT_GATING, - SUN6I_LOSC_OUT_GATING_EN, 0, + SUN6I_LOSC_OUT_GATING_EN_OFFSET, 0, &rtc->lock); if (IS_ERR(rtc->ext_losc)) { pr_crit("Couldn't register the LOSC external gate\n"); -- GitLab From dfeb333b590c78d0dbadfa00a56635f1b2489d58 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 26 Apr 2018 14:46:29 +1000 Subject: [PATCH 1129/1299] md: fix two problems with setting the "re-add" device state. commit 011abdc9df559ec75779bb7c53a744c69b2a94c6 upstream. If "re-add" is written to the "state" file for a device which is faulty, this has an effect similar to removing and re-adding the device. It should take up the same slot in the array that it previously had, and an accelerated (e.g. bitmap-based) rebuild should happen. The slot that "it previously had" is determined by rdev->saved_raid_disk. However this is not set when a device fails (only when a device is added), and it is cleared when resync completes. This means that "re-add" will normally work once, but may not work a second time. This patch includes two fixes. 1/ when a device fails, record the ->raid_disk value in ->saved_raid_disk before clearing ->raid_disk 2/ when "re-add" is written to a device for which ->saved_raid_disk is not set, fail. I think this is suitable for stable as it can cause re-adding a device to be forced to do a full resync which takes a lot longer and so puts data at more risk. Cc: (v4.1) Fixes: 97f6cd39da22 ("md-cluster: re-add capabilities") Signed-off-by: NeilBrown Reviewed-by: Goldwyn Rodrigues Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 24e64b04424a..7143c8b9284b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2823,7 +2823,8 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) err = 0; } } else if (cmd_match(buf, "re-add")) { - if (test_bit(Faulty, &rdev->flags) && (rdev->raid_disk == -1)) { + if (test_bit(Faulty, &rdev->flags) && (rdev->raid_disk == -1) && + rdev->saved_raid_disk >= 0) { /* clear_bit is performed _after_ all the devices * have their local Faulty bit cleared. If any writes * happen in the meantime in the local node, they @@ -8594,6 +8595,7 @@ static int remove_and_add_spares(struct mddev *mddev, if (mddev->pers->hot_remove_disk( mddev, rdev) == 0) { sysfs_unlink_rdev(mddev, rdev); + rdev->saved_raid_disk = rdev->raid_disk; rdev->raid_disk = -1; removed++; } -- GitLab From db04f92b658083a0a2842919c6d8f9013bff2d08 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 4 Jun 2018 10:39:01 +0100 Subject: [PATCH 1130/1299] rpmsg: smd: do not use mananged resources for endpoints and channels commit 4a2e84c6ed85434ce7843e4844b4d3263f7e233b upstream. All the managed resources would be freed by the time release function is invoked. Handling such memory in qcom_smd_edge_release() would do bad things. Found this issue while testing Audio usecase where the dsp is started up and shutdown in a loop. This patch fixes this issue by using simple kzalloc for allocating channel->name and channel which is then freed in qcom_smd_edge_release(). Without this patch restarting a remoteproc would crash the system. Fixes: 53e2822e56c7 ("rpmsg: Introduce Qualcomm SMD backend") Cc: Signed-off-by: Srinivas Kandagatla Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/rpmsg/qcom_smd.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c index b01774e9fac0..f1a2147a6d84 100644 --- a/drivers/rpmsg/qcom_smd.c +++ b/drivers/rpmsg/qcom_smd.c @@ -1043,12 +1043,12 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed void *info; int ret; - channel = devm_kzalloc(&edge->dev, sizeof(*channel), GFP_KERNEL); + channel = kzalloc(sizeof(*channel), GFP_KERNEL); if (!channel) return ERR_PTR(-ENOMEM); channel->edge = edge; - channel->name = devm_kstrdup(&edge->dev, name, GFP_KERNEL); + channel->name = kstrdup(name, GFP_KERNEL); if (!channel->name) return ERR_PTR(-ENOMEM); @@ -1098,8 +1098,8 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed return channel; free_name_and_channel: - devm_kfree(&edge->dev, channel->name); - devm_kfree(&edge->dev, channel); + kfree(channel->name); + kfree(channel); return ERR_PTR(ret); } @@ -1320,13 +1320,13 @@ static int qcom_smd_parse_edge(struct device *dev, */ static void qcom_smd_edge_release(struct device *dev) { - struct qcom_smd_channel *channel; + struct qcom_smd_channel *channel, *tmp; struct qcom_smd_edge *edge = to_smd_edge(dev); - list_for_each_entry(channel, &edge->channels, list) { - SET_RX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED); - SET_RX_CHANNEL_INFO(channel, head, 0); - SET_RX_CHANNEL_INFO(channel, tail, 0); + list_for_each_entry_safe(channel, tmp, &edge->channels, list) { + list_del(&channel->list); + kfree(channel->name); + kfree(channel); } kfree(edge); -- GitLab From b24d90f4d66d9e1f1313cd9bb47cdf0643894ab1 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 16 May 2018 22:17:03 +0200 Subject: [PATCH 1131/1299] ubi: fastmap: Cancel work upon detach commit 6e7d80161066c99d12580d1b985cb1408bb58cf1 upstream. Ben Hutchings pointed out that 29b7a6fa1ec0 ("ubi: fastmap: Don't flush fastmap work on detach") does not really fix the problem, it just reduces the risk to hit the race window where fastmap work races against free()'ing ubi->volumes[]. The correct approach is making sure that no more fastmap work is in progress before we free ubi data structures. So we cancel fastmap work right after the ubi background thread is stopped. By setting ubi->thread_enabled to zero we make sure that no further work tries to wake the thread. Fixes: 29b7a6fa1ec0 ("ubi: fastmap: Don't flush fastmap work on detach") Fixes: 74cdaf24004a ("UBI: Fastmap: Fix memory leaks while closing the WL sub-system") Cc: stable@vger.kernel.org Cc: Ben Hutchings Cc: Martin Townsend Signed-off-by: Richard Weinberger Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/build.c | 3 +++ drivers/mtd/ubi/wl.c | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index defb1cd8d2e1..18a72da759a0 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -1082,6 +1082,9 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) if (ubi->bgt_thread) kthread_stop(ubi->bgt_thread); +#ifdef CONFIG_MTD_UBI_FASTMAP + cancel_work_sync(&ubi->fm_work); +#endif ubi_debugfs_exit_dev(ubi); uif_close(ubi); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 668b46202507..23a6986d512b 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1505,6 +1505,7 @@ int ubi_thread(void *u) } dbg_wl("background thread \"%s\" is killed", ubi->bgt_name); + ubi->thread_enabled = 0; return 0; } @@ -1514,9 +1515,6 @@ int ubi_thread(void *u) */ static void shutdown_work(struct ubi_device *ubi) { -#ifdef CONFIG_MTD_UBI_FASTMAP - flush_work(&ubi->fm_work); -#endif while (!list_empty(&ubi->works)) { struct ubi_work *wrk; -- GitLab From a23cf10d9abb04652ec2daf93d494dc0e2cd835f Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 28 May 2018 22:04:32 +0200 Subject: [PATCH 1132/1299] ubi: fastmap: Correctly handle interrupted erasures in EBA commit 781932375ffc6411713ee0926ccae8596ed0261c upstream. Fastmap cannot track the LEB unmap operation, therefore it can happen that after an interrupted erasure the mapping still looks good from Fastmap's point of view, while reading from the PEB will cause an ECC error and confuses the upper layer. Instead of teaching users of UBI how to deal with that, we read back the VID header and check for errors. If the PEB is empty or shows ECC errors we fixup the mapping and schedule the PEB for erasure. Fixes: dbb7d2a88d2a ("UBI: Add fastmap core") Cc: Reported-by: martin bayern Signed-off-by: Richard Weinberger Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/eba.c | 90 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 388e46be6ad9..d0884bd9d955 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -490,6 +490,82 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, return err; } +#ifdef CONFIG_MTD_UBI_FASTMAP +/** + * check_mapping - check and fixup a mapping + * @ubi: UBI device description object + * @vol: volume description object + * @lnum: logical eraseblock number + * @pnum: physical eraseblock number + * + * Checks whether a given mapping is valid. Fastmap cannot track LEB unmap + * operations, if such an operation is interrupted the mapping still looks + * good, but upon first read an ECC is reported to the upper layer. + * Normaly during the full-scan at attach time this is fixed, for Fastmap + * we have to deal with it while reading. + * If the PEB behind a LEB shows this symthom we change the mapping to + * %UBI_LEB_UNMAPPED and schedule the PEB for erasure. + * + * Returns 0 on success, negative error code in case of failure. + */ +static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, + int *pnum) +{ + int err; + struct ubi_vid_io_buf *vidb; + + if (!ubi->fast_attach) + return 0; + + vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS); + if (!vidb) + return -ENOMEM; + + err = ubi_io_read_vid_hdr(ubi, *pnum, vidb, 0); + if (err > 0 && err != UBI_IO_BITFLIPS) { + int torture = 0; + + switch (err) { + case UBI_IO_FF: + case UBI_IO_FF_BITFLIPS: + case UBI_IO_BAD_HDR: + case UBI_IO_BAD_HDR_EBADMSG: + break; + default: + ubi_assert(0); + } + + if (err == UBI_IO_BAD_HDR_EBADMSG || err == UBI_IO_FF_BITFLIPS) + torture = 1; + + down_read(&ubi->fm_eba_sem); + vol->eba_tbl->entries[lnum].pnum = UBI_LEB_UNMAPPED; + up_read(&ubi->fm_eba_sem); + ubi_wl_put_peb(ubi, vol->vol_id, lnum, *pnum, torture); + + *pnum = UBI_LEB_UNMAPPED; + } else if (err < 0) { + ubi_err(ubi, "unable to read VID header back from PEB %i: %i", + *pnum, err); + + goto out_free; + } + + err = 0; + +out_free: + ubi_free_vid_buf(vidb); + + return err; +} +#else +static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, + int *pnum) +{ + return 0; +} +#endif + /** * ubi_eba_read_leb - read data. * @ubi: UBI device description object @@ -522,7 +598,13 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, return err; pnum = vol->eba_tbl->entries[lnum].pnum; - if (pnum < 0) { + if (pnum >= 0) { + err = check_mapping(ubi, vol, lnum, &pnum); + if (err < 0) + goto out_unlock; + } + + if (pnum == UBI_LEB_UNMAPPED) { /* * The logical eraseblock is not mapped, fill the whole buffer * with 0xFF bytes. The exception is static volumes for which @@ -930,6 +1012,12 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, return err; pnum = vol->eba_tbl->entries[lnum].pnum; + if (pnum >= 0) { + err = check_mapping(ubi, vol, lnum, &pnum); + if (err < 0) + goto out; + } + if (pnum >= 0) { dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d", len, offset, vol_id, lnum, pnum); -- GitLab From b7261fc5f5748b3f6f1a839dbc5a744b8871dfcd Mon Sep 17 00:00:00 2001 From: Silvio Cesare Date: Fri, 4 May 2018 13:44:02 +1000 Subject: [PATCH 1133/1299] UBIFS: Fix potential integer overflow in allocation commit 353748a359f1821ee934afc579cf04572406b420 upstream. There is potential for the size and len fields in ubifs_data_node to be too large causing either a negative value for the length fields or an integer overflow leading to an incorrect memory allocation. Likewise, when the len field is small, an integer underflow may occur. Signed-off-by: Silvio Cesare Fixes: 1e51764a3c2ac ("UBIFS: add new flash file system") Cc: stable@vger.kernel.org Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- fs/ubifs/journal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 04c4ec6483e5..8ae1cd8611cc 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -1283,10 +1283,11 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in int *new_len) { void *buf; - int err, dlen, compr_type, out_len, old_dlen; + int err, compr_type; + u32 dlen, out_len, old_dlen; out_len = le32_to_cpu(dn->size); - buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS); + buf = kmalloc_array(out_len, WORST_COMPR_FACTOR, GFP_NOFS); if (!buf) return -ENOMEM; -- GitLab From 3db7c40093f6dc58fdfaf2723980955dedadf0a3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 20 Nov 2017 11:45:44 +0100 Subject: [PATCH 1134/1299] backlight: as3711_bl: Fix Device Tree node lookup commit 4a9c8bb2aca5b5a2a15744333729745dd9903562 upstream. Fix child-node lookup during probe, which ended up searching the whole device tree depth-first starting at the parent rather than just matching on its children. To make things worse, the parent mfd node was also prematurely freed. Cc: stable # 3.10 Fixes: 59eb2b5e57ea ("drivers/video/backlight/as3711_bl.c: add OF support") Signed-off-by: Johan Hovold Acked-by: Daniel Thompson Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/as3711_bl.c | 33 ++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/video/backlight/as3711_bl.c b/drivers/video/backlight/as3711_bl.c index 734a9158946b..e55304d5cf07 100644 --- a/drivers/video/backlight/as3711_bl.c +++ b/drivers/video/backlight/as3711_bl.c @@ -262,10 +262,10 @@ static int as3711_bl_register(struct platform_device *pdev, static int as3711_backlight_parse_dt(struct device *dev) { struct as3711_bl_pdata *pdata = dev_get_platdata(dev); - struct device_node *bl = - of_find_node_by_name(dev->parent->of_node, "backlight"), *fb; + struct device_node *bl, *fb; int ret; + bl = of_get_child_by_name(dev->parent->of_node, "backlight"); if (!bl) { dev_dbg(dev, "backlight node not found\n"); return -ENODEV; @@ -279,7 +279,7 @@ static int as3711_backlight_parse_dt(struct device *dev) if (pdata->su1_max_uA <= 0) ret = -EINVAL; if (ret < 0) - return ret; + goto err_put_bl; } fb = of_parse_phandle(bl, "su2-dev", 0); @@ -292,7 +292,7 @@ static int as3711_backlight_parse_dt(struct device *dev) if (pdata->su2_max_uA <= 0) ret = -EINVAL; if (ret < 0) - return ret; + goto err_put_bl; if (of_find_property(bl, "su2-feedback-voltage", NULL)) { pdata->su2_feedback = AS3711_SU2_VOLTAGE; @@ -314,8 +314,10 @@ static int as3711_backlight_parse_dt(struct device *dev) pdata->su2_feedback = AS3711_SU2_CURR_AUTO; count++; } - if (count != 1) - return -EINVAL; + if (count != 1) { + ret = -EINVAL; + goto err_put_bl; + } count = 0; if (of_find_property(bl, "su2-fbprot-lx-sd4", NULL)) { @@ -334,8 +336,10 @@ static int as3711_backlight_parse_dt(struct device *dev) pdata->su2_fbprot = AS3711_SU2_GPIO4; count++; } - if (count != 1) - return -EINVAL; + if (count != 1) { + ret = -EINVAL; + goto err_put_bl; + } count = 0; if (of_find_property(bl, "su2-auto-curr1", NULL)) { @@ -355,11 +359,20 @@ static int as3711_backlight_parse_dt(struct device *dev) * At least one su2-auto-curr* must be specified iff * AS3711_SU2_CURR_AUTO is used */ - if (!count ^ (pdata->su2_feedback != AS3711_SU2_CURR_AUTO)) - return -EINVAL; + if (!count ^ (pdata->su2_feedback != AS3711_SU2_CURR_AUTO)) { + ret = -EINVAL; + goto err_put_bl; + } } + of_node_put(bl); + return 0; + +err_put_bl: + of_node_put(bl); + + return ret; } static int as3711_backlight_probe(struct platform_device *pdev) -- GitLab From f893fca0a4b5ac0ea6003945e791486eac32b90c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 20 Nov 2017 11:45:45 +0100 Subject: [PATCH 1135/1299] backlight: max8925_bl: Fix Device Tree node lookup commit d1cc0ec3da23e44c23712579515494b374f111c9 upstream. Fix child-node lookup during probe, which ended up searching the whole device tree depth-first starting at the parent rather than just matching on its children. To make things worse, the parent mfd node was also prematurely freed, while the child backlight node was leaked. Cc: stable # 3.9 Fixes: 47ec340cb8e2 ("mfd: max8925: Support dt for backlight") Signed-off-by: Johan Hovold Acked-by: Daniel Thompson Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/max8925_bl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index 7b738d60ecc2..f3aa6088f1d9 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c @@ -116,7 +116,7 @@ static void max8925_backlight_dt_init(struct platform_device *pdev) if (!pdata) return; - np = of_find_node_by_name(nproot, "backlight"); + np = of_get_child_by_name(nproot, "backlight"); if (!np) { dev_err(&pdev->dev, "failed to find backlight node\n"); return; @@ -125,6 +125,8 @@ static void max8925_backlight_dt_init(struct platform_device *pdev) if (!of_property_read_u32(np, "maxim,max8925-dual-string", &val)) pdata->dual_string = val; + of_node_put(np); + pdev->dev.platform_data = pdata; } -- GitLab From 779d5f71c2323ef5610e7c3d9bdb73e5f92f660e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 20 Nov 2017 11:45:46 +0100 Subject: [PATCH 1136/1299] backlight: tps65217_bl: Fix Device Tree node lookup commit 2b12dfa124dbadf391cb9a616aaa6b056823bf75 upstream. Fix child-node lookup during probe, which ended up searching the whole device tree depth-first starting at the parent rather than just matching on its children. This would only cause trouble if the child node is missing while there is an unrelated node named "backlight" elsewhere in the tree. Cc: stable # 3.7 Fixes: eebfdc17cc6c ("backlight: Add TPS65217 WLED driver") Signed-off-by: Johan Hovold Acked-by: Daniel Thompson Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/tps65217_bl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c index fd524ad860a5..f45d0c9467db 100644 --- a/drivers/video/backlight/tps65217_bl.c +++ b/drivers/video/backlight/tps65217_bl.c @@ -184,11 +184,11 @@ static struct tps65217_bl_pdata * tps65217_bl_parse_dt(struct platform_device *pdev) { struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); - struct device_node *node = of_node_get(tps->dev->of_node); + struct device_node *node; struct tps65217_bl_pdata *pdata, *err; u32 val; - node = of_find_node_by_name(node, "backlight"); + node = of_get_child_by_name(tps->dev->of_node, "backlight"); if (!node) return ERR_PTR(-ENODEV); -- GitLab From f79c97198b5596fa8052938471bd67ae6ccb4067 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 24 Apr 2018 18:00:10 +0300 Subject: [PATCH 1137/1299] mfd: intel-lpss: Program REMAP register in PIO mode commit d28b62520830b2d0bffa2d98e81afc9f5e537e8b upstream. According to documentation REMAP register has to be programmed in either DMA or PIO mode of the slice. Move the DMA capability check below to let REMAP register be programmed in PIO mode. Cc: stable@vger.kernel.org # 4.3+ Fixes: 4b45efe85263 ("mfd: Add support for Intel Sunrisepoint LPSS devices") Signed-off-by: Andy Shevchenko Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/intel-lpss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index 0e0ab9bb1530..40e8d9b59d07 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -275,11 +275,11 @@ static void intel_lpss_init_dev(const struct intel_lpss *lpss) intel_lpss_deassert_reset(lpss); + intel_lpss_set_remap_addr(lpss); + if (!intel_lpss_has_idma(lpss)) return; - intel_lpss_set_remap_addr(lpss); - /* Make sure that SPI multiblock DMA transfers are re-enabled */ if (lpss->type == LPSS_DEV_SPI) writel(value, lpss->priv + LPSS_PRIV_SSP_REG); -- GitLab From 18be8bd3aceb282c145b74144caaccb51b24bf92 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 18 May 2018 11:38:27 +0300 Subject: [PATCH 1138/1299] mfd: intel-lpss: Fix Intel Cannon Lake LPSS I2C input clock commit 4e93a658576ab115977225c9d0992b97ff19ba8c upstream. Intel Cannon Lake PCH has much higher 216 MHz input clock to LPSS I2C than Sunrisepoint which uses 120 MHz. Preliminary information was that both share the same clock rate but actual silicon implements elevated rate for better support for 3.4 MHz high-speed I2C. This incorrect input clock rate results too high I2C bus clock in case ACPI doesn't provide tuned I2C timing parameters since I2C host controller driver calculates them from input clock rate. Fix this by using the correct rate. We still share the same 230 ns SDA hold time value than Sunrisepoint. Cc: stable@vger.kernel.org Fixes: b418bbff36dd ("mfd: intel-lpss: Add Intel Cannonlake PCI IDs") Reported-by: Jian-Hong Pan Reported-by: Chris Chiu Reported-by: Daniel Drake Signed-off-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Acked-by: Mika Westerberg Tested-by: Jian-Hong Pan Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/intel-lpss-pci.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index d1c46de89eb4..d9ae983095c5 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -124,6 +124,11 @@ static const struct intel_lpss_platform_info apl_i2c_info = { .properties = apl_i2c_properties, }; +static const struct intel_lpss_platform_info cnl_i2c_info = { + .clk_rate = 216000000, + .properties = spt_i2c_properties, +}; + static const struct pci_device_id intel_lpss_pci_ids[] = { /* BXT A-Step */ { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, @@ -207,13 +212,13 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x9daa), (kernel_ulong_t)&spt_info }, { PCI_VDEVICE(INTEL, 0x9dab), (kernel_ulong_t)&spt_info }, { PCI_VDEVICE(INTEL, 0x9dfb), (kernel_ulong_t)&spt_info }, - { PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&spt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&cnl_i2c_info }, { PCI_VDEVICE(INTEL, 0x9dc7), (kernel_ulong_t)&spt_uart_info }, - { PCI_VDEVICE(INTEL, 0x9de8), (kernel_ulong_t)&spt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&spt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&spt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9de8), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&cnl_i2c_info }, /* SPT-H */ { PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0xa128), (kernel_ulong_t)&spt_uart_info }, @@ -240,10 +245,10 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0xa32b), (kernel_ulong_t)&spt_info }, { PCI_VDEVICE(INTEL, 0xa37b), (kernel_ulong_t)&spt_info }, { PCI_VDEVICE(INTEL, 0xa347), (kernel_ulong_t)&spt_uart_info }, - { PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&spt_i2c_info }, - { PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&spt_i2c_info }, - { PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&spt_i2c_info }, - { PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&spt_i2c_info }, + { PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&cnl_i2c_info }, { } }; MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids); -- GitLab From f810961e06c6a8b2cdff26a8bac1e38921608673 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Wed, 11 Apr 2018 16:53:56 +0800 Subject: [PATCH 1139/1299] arm: dts: mt7623: fix invalid memory node being generated commit c0b0d540db1a8bfb041166c4991dd6f624e8de45 upstream. Below two wrong nodes in existing DTS files would cause a fail boot since in fact the address 0 is not the correct place the memory device locates at. memory { device_type = "memory"; reg = <0x0 0x0 0x0 0x0>; }; memory@80000000 { reg = <0x0 0x80000000 0x0 0x40000000>; }; In order to avoid having a memory node starting at address 0, we can't include file skeleton64.dtsi and instead need to explicitly manually define a few of properties the DTS relies on such as #address-cells and #size-cells in root node and device_type in the node memory@80000000. Cc: stable@vger.kernel.org Fixes: 31ac0d69a1d4 ("ARM: dts: mediatek: add MT7623 basic support") Signed-off-by: Sean Wang Cc: Rob Herring Signed-off-by: Matthias Brugger Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/mt7623.dtsi | 3 ++- arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 1 + arch/arm/boot/dts/mt7623n-rfb.dtsi | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index 36983a7d7cfd..185357323572 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -22,11 +22,12 @@ #include #include #include -#include "skeleton64.dtsi" / { compatible = "mediatek,mt7623"; interrupt-parent = <&sysirq>; + #address-cells = <2>; + #size-cells = <2>; cpu_opp_table: opp_table { compatible = "operating-points-v2"; diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts index 7de704575aee..e96c0ca97972 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts @@ -100,6 +100,7 @@ }; memory@80000000 { + device_type = "memory"; reg = <0 0x80000000 0 0x40000000>; }; }; diff --git a/arch/arm/boot/dts/mt7623n-rfb.dtsi b/arch/arm/boot/dts/mt7623n-rfb.dtsi index 256c5fd947bf..43c9d7ca23a0 100644 --- a/arch/arm/boot/dts/mt7623n-rfb.dtsi +++ b/arch/arm/boot/dts/mt7623n-rfb.dtsi @@ -47,6 +47,7 @@ }; memory@80000000 { + device_type = "memory"; reg = <0 0x80000000 0 0x40000000>; }; -- GitLab From 5009bd5b93212a206cdf09bd849779ac63847a73 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 4 Jun 2018 15:56:54 +0300 Subject: [PATCH 1140/1299] perf tools: Fix symbol and object code resolution for vdso32 and vdsox32 commit aef4feace285f27c8ed35830a5d575bec7f3e90a upstream. Fix __kmod_path__parse() so that perf tools does not treat vdso32 and vdsox32 as kernel modules and fail to find the object. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Cc: Wang Nan Cc: stable@vger.kernel.org Fixes: 1f121b03d058 ("perf tools: Deal with kernel module names in '[]' correctly") Link: http://lkml.kernel.org/r/1528117014-30032-3-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/dso.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 00c98c968cb1..505c13bf7e30 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -352,6 +352,8 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, if ((strncmp(name, "[kernel.kallsyms]", 17) == 0) || (strncmp(name, "[guest.kernel.kallsyms", 22) == 0) || (strncmp(name, "[vdso]", 6) == 0) || + (strncmp(name, "[vdso32]", 8) == 0) || + (strncmp(name, "[vdsox32]", 9) == 0) || (strncmp(name, "[vsyscall]", 10) == 0)) { m->kmod = false; -- GitLab From 9e9db211cfb9e29456edc7cbf302b2b4c44b3d87 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 31 May 2018 13:23:42 +0300 Subject: [PATCH 1141/1299] perf intel-pt: Fix sync_switch INTEL_PT_SS_NOT_TRACING commit dbcb82b93f3e8322891e47472c89e63058b81e99 upstream. sync_switch is a facility to synchronize decoding more closely with the point in the kernel when the context actually switched. In one case, INTEL_PT_SS_NOT_TRACING state was not correctly transitioning to INTEL_PT_SS_TRACING state due to a missing case clause. Add it. Signed-off-by: Adrian Hunter Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1527762225-26024-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/intel-pt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index d9573c1fa555..a39fc1200e2d 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -1560,6 +1560,7 @@ static int intel_pt_sample(struct intel_pt_queue *ptq) if (intel_pt_is_switch_ip(ptq, state->to_ip)) { switch (ptq->switch_state) { + case INTEL_PT_SS_NOT_TRACING: case INTEL_PT_SS_UNKNOWN: case INTEL_PT_SS_EXPECTING_SWITCH_IP: err = intel_pt_next_tid(pt, ptq); -- GitLab From e1587f178eb14ae98443494adafde35b8ac6f43c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 31 May 2018 13:23:43 +0300 Subject: [PATCH 1142/1299] perf intel-pt: Fix decoding to accept CBR between FUP and corresponding TIP commit bd2e49ec48feb1855f7624198849eea4610e2286 upstream. It is possible to have a CBR packet between a FUP packet and corresponding TIP packet. Stop treating it as an error. Signed-off-by: Adrian Hunter Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1527762225-26024-3-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index f9157aed1289..e5eb91777383 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1604,7 +1604,6 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder) case INTEL_PT_PSB: case INTEL_PT_TSC: case INTEL_PT_TMA: - case INTEL_PT_CBR: case INTEL_PT_MODE_TSX: case INTEL_PT_BAD: case INTEL_PT_PSBEND: @@ -1620,6 +1619,10 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder) decoder->pkt_step = 0; return -ENOENT; + case INTEL_PT_CBR: + intel_pt_calc_cbr(decoder); + break; + case INTEL_PT_OVF: return intel_pt_overflow(decoder); -- GitLab From 65a163984abe6450c0f7f957581c1a8fc019e946 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 31 May 2018 13:23:44 +0300 Subject: [PATCH 1143/1299] perf intel-pt: Fix MTC timing after overflow commit dd27b87ab5fcf3ea1c060b5e3ab5d31cc78e9f4c upstream. On some platforms, overflows will clear before MTC wraparound, and there is no following TSC/TMA packet. In that case the previous TMA is valid. Since there will be a valid TMA either way, stop setting 'have_tma' to false upon overflow. Signed-off-by: Adrian Hunter Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1527762225-26024-4-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index e5eb91777383..881d7c5e5e2a 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1376,7 +1376,6 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder) { intel_pt_log("ERROR: Buffer overflow\n"); intel_pt_clear_tx_flags(decoder); - decoder->have_tma = false; decoder->cbr = 0; decoder->timestamp_insn_cnt = 0; decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; -- GitLab From 4e7b3632eafa50c8d2225a4f70c7012a0ff8258b Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 31 May 2018 13:23:45 +0300 Subject: [PATCH 1144/1299] perf intel-pt: Fix "Unexpected indirect branch" error commit 9fb523363f6e3984457fee95bb7019395384ffa7 upstream. Some Atom CPUs can produce FUP packets that contain NLIP (next linear instruction pointer) instead of CLIP (current linear instruction pointer). That will result in "Unexpected indirect branch" errors. Fix by comparing IP to NLIP in that case. Signed-off-by: Adrian Hunter Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1527762225-26024-5-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman --- .../util/intel-pt-decoder/intel-pt-decoder.c | 17 +++++++++++++++-- .../util/intel-pt-decoder/intel-pt-decoder.h | 9 +++++++++ tools/perf/util/intel-pt.c | 4 ++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 881d7c5e5e2a..d404bed7003a 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -113,6 +113,7 @@ struct intel_pt_decoder { bool have_cyc; bool fixup_last_mtc; bool have_last_ip; + enum intel_pt_param_flags flags; uint64_t pos; uint64_t last_ip; uint64_t ip; @@ -226,6 +227,8 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) decoder->return_compression = params->return_compression; decoder->branch_enable = params->branch_enable; + decoder->flags = params->flags; + decoder->period = params->period; decoder->period_type = params->period_type; @@ -1097,6 +1100,15 @@ static bool intel_pt_fup_event(struct intel_pt_decoder *decoder) return ret; } +static inline bool intel_pt_fup_with_nlip(struct intel_pt_decoder *decoder, + struct intel_pt_insn *intel_pt_insn, + uint64_t ip, int err) +{ + return decoder->flags & INTEL_PT_FUP_WITH_NLIP && !err && + intel_pt_insn->branch == INTEL_PT_BR_INDIRECT && + ip == decoder->ip + intel_pt_insn->length; +} + static int intel_pt_walk_fup(struct intel_pt_decoder *decoder) { struct intel_pt_insn intel_pt_insn; @@ -1109,10 +1121,11 @@ static int intel_pt_walk_fup(struct intel_pt_decoder *decoder) err = intel_pt_walk_insn(decoder, &intel_pt_insn, ip); if (err == INTEL_PT_RETURN) return 0; - if (err == -EAGAIN) { + if (err == -EAGAIN || + intel_pt_fup_with_nlip(decoder, &intel_pt_insn, ip, err)) { if (intel_pt_fup_event(decoder)) return 0; - return err; + return -EAGAIN; } decoder->set_fup_tx_flags = false; if (err) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h index fc1752d50019..51c18d67f4ca 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h @@ -60,6 +60,14 @@ enum { INTEL_PT_ERR_MAX, }; +enum intel_pt_param_flags { + /* + * FUP packet can contain next linear instruction pointer instead of + * current linear instruction pointer. + */ + INTEL_PT_FUP_WITH_NLIP = 1 << 0, +}; + struct intel_pt_state { enum intel_pt_sample_type type; int err; @@ -106,6 +114,7 @@ struct intel_pt_params { unsigned int mtc_period; uint32_t tsc_ctc_ratio_n; uint32_t tsc_ctc_ratio_d; + enum intel_pt_param_flags flags; }; struct intel_pt_decoder; diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index a39fc1200e2d..3b118fa9da89 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -784,6 +784,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, unsigned int queue_nr) { struct intel_pt_params params = { .get_trace = 0, }; + struct perf_env *env = pt->machine->env; struct intel_pt_queue *ptq; ptq = zalloc(sizeof(struct intel_pt_queue)); @@ -865,6 +866,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, } } + if (env->cpuid && !strncmp(env->cpuid, "GenuineIntel,6,92,", 18)) + params.flags |= INTEL_PT_FUP_WITH_NLIP; + ptq->decoder = intel_pt_decoder_new(¶ms); if (!ptq->decoder) goto out_free; -- GitLab From c3382e70a0435cb93eb09fd39c3419d2f8875b5d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 7 Jun 2018 14:30:02 +0300 Subject: [PATCH 1145/1299] perf intel-pt: Fix packet decoding of CYC packets commit 621a5a327c1e36ffd7bb567f44a559f64f76358f upstream. Use a 64-bit type so that the cycle count is not limited to 32-bits. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1528371002-8862-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c index ba4c9dd18643..d426761a549d 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c @@ -366,7 +366,7 @@ static int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf, if (len < offs) return INTEL_PT_NEED_MORE_BYTES; byte = buf[offs++]; - payload |= (byte >> 1) << shift; + payload |= ((uint64_t)byte >> 1) << shift; } packet->type = INTEL_PT_CYC; -- GitLab From 5cb6105d2211e96250db10cda6202d7e40c3d3fc Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Wed, 18 Oct 2017 06:05:07 -0700 Subject: [PATCH 1146/1299] perf vendor events: Add Goldmont Plus V1 event file commit 65db92e0965ab56e8031d5c804f26d5be0e47047 upstream. Add a Intel event file for perf. Signed-off-by: Kan Liang Acked-by: Andi Kleen Cc: Jiri Olsa Cc: Kan Liang Cc: Sukadev Bhattiprolu Link: http://lkml.kernel.org/r/1508331907-395162-1-git-send-email-kan.liang@intel.com Signed-off-by: Arnaldo Carvalho de Melo Cc: "Jin, Yao" Signed-off-by: Greg Kroah-Hartman --- .../arch/x86/goldmontplus/cache.json | 1453 +++++++++++++++++ .../arch/x86/goldmontplus/frontend.json | 62 + .../arch/x86/goldmontplus/memory.json | 38 + .../arch/x86/goldmontplus/other.json | 98 ++ .../arch/x86/goldmontplus/pipeline.json | 544 ++++++ .../arch/x86/goldmontplus/virtual-memory.json | 218 +++ tools/perf/pmu-events/arch/x86/mapfile.csv | 1 + 7 files changed, 2414 insertions(+) create mode 100644 tools/perf/pmu-events/arch/x86/goldmontplus/cache.json create mode 100644 tools/perf/pmu-events/arch/x86/goldmontplus/frontend.json create mode 100644 tools/perf/pmu-events/arch/x86/goldmontplus/memory.json create mode 100644 tools/perf/pmu-events/arch/x86/goldmontplus/other.json create mode 100644 tools/perf/pmu-events/arch/x86/goldmontplus/pipeline.json create mode 100644 tools/perf/pmu-events/arch/x86/goldmontplus/virtual-memory.json diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/cache.json b/tools/perf/pmu-events/arch/x86/goldmontplus/cache.json new file mode 100644 index 000000000000..b4791b443a66 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/goldmontplus/cache.json @@ -0,0 +1,1453 @@ +[ + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts memory requests originating from the core that miss in the L2 cache.", + "EventCode": "0x2E", + "Counter": "0,1,2,3", + "UMask": "0x41", + "PEBScounters": "0,1,2,3", + "EventName": "LONGEST_LAT_CACHE.MISS", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "L2 cache request misses" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts memory requests originating from the core that reference a cache line in the L2 cache.", + "EventCode": "0x2E", + "Counter": "0,1,2,3", + "UMask": "0x4f", + "PEBScounters": "0,1,2,3", + "EventName": "LONGEST_LAT_CACHE.REFERENCE", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "L2 cache requests" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of demand and prefetch transactions that the L2 XQ rejects due to a full or near full condition which likely indicates back pressure from the intra-die interconnect (IDI) fabric. The XQ may reject transactions from the L2Q (non-cacheable requests), L2 misses and L2 write-back victims.", + "EventCode": "0x30", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "L2_REJECT_XQ.ALL", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Requests rejected by the XQ" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of demand and L1 prefetcher requests rejected by the L2Q due to a full or nearly full condition which likely indicates back pressure from L2Q. It also counts requests that would have gone directly to the XQ, but are rejected due to a full or nearly full condition, indicating back pressure from the IDI link. The L2Q may also reject transactions from a core to insure fairness between cores, or to delay a core's dirty eviction when the address conflicts with incoming external snoops.", + "EventCode": "0x31", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "CORE_REJECT_L2Q.ALL", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Requests rejected by the L2Q" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts when a modified (dirty) cache line is evicted from the data L1 cache and needs to be written back to memory. No count will occur if the evicted line is clean, and hence does not require a writeback.", + "EventCode": "0x51", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "DL1.REPLACEMENT", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "L1 Cache evictions for dirty data" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts cycles that fetch is stalled due to an outstanding ICache miss. That is, the decoder queue is able to accept bytes, but the fetch unit is unable to provide bytes due to an ICache miss. Note: this event is not the same as the total number of cycles spent retrieving instruction cache lines from the memory hierarchy.", + "EventCode": "0x86", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "FETCH_STALL.ICACHE_FILL_PENDING_CYCLES", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Cycles code-fetch stalled due to an outstanding ICache miss." + }, + { + "CollectPEBSRecord": "1", + "EventCode": "0xB7", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE", + "PDIR_COUNTER": "na", + "SampleAfterValue": "100007", + "BriefDescription": "Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts locked memory uops retired. This includes regular locks and bus locks. (To specifically count bus locks only, see the Offcore response event.) A locked access is one with a lock prefix, or an exchange to memory. See the SDM for a complete description of which memory load accesses are locks.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x21", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS", + "SampleAfterValue": "200003", + "BriefDescription": "Locked load uops retired (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts load uops retired where the data requested spans a 64 byte cache line boundary.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x41", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS", + "SampleAfterValue": "200003", + "BriefDescription": "Load uops retired that split a cache-line (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts store uops retired where the data requested spans a 64 byte cache line boundary.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x42", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES", + "SampleAfterValue": "200003", + "BriefDescription": "Stores uops retired that split a cache-line (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts memory uops retired where the data requested spans a 64 byte cache line boundary.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x43", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_UOPS_RETIRED.SPLIT", + "SampleAfterValue": "200003", + "BriefDescription": "Memory uops retired that split a cache-line (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of load uops retired.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x81", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_UOPS_RETIRED.ALL_LOADS", + "SampleAfterValue": "200003", + "BriefDescription": "Load uops retired (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of store uops retired.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x82", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_UOPS_RETIRED.ALL_STORES", + "SampleAfterValue": "200003", + "BriefDescription": "Store uops retired (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of memory uops retired that is either a loads or a store or both.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x83", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_UOPS_RETIRED.ALL", + "SampleAfterValue": "200003", + "BriefDescription": "Memory uops retired (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts load uops retired that hit the L1 data cache.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT", + "SampleAfterValue": "200003", + "BriefDescription": "Load uops retired that hit L1 data cache (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts load uops retired that hit in the L2 cache.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT", + "SampleAfterValue": "200003", + "BriefDescription": "Load uops retired that hit L2 (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts load uops retired that miss the L1 data cache.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS", + "SampleAfterValue": "200003", + "BriefDescription": "Load uops retired that missed L1 data cache (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts load uops retired that miss in the L2 cache.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS", + "SampleAfterValue": "200003", + "BriefDescription": "Load uops retired that missed L2 (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts load uops retired where the cache line containing the data was in the modified state of another core or modules cache (HITM). More specifically, this means that when the load address was checked by other caching agents (typically another processor) in the system, one of those caching agents indicated that they had a dirty copy of the data. Loads that obtain a HITM response incur greater latency than most is typical for a load. In addition, since HITM indicates that some other processor had this data in its cache, it implies that the data was shared between processors, or potentially was a lock or semaphore value. This event is useful for locating sharing, false sharing, and contended locks.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x20", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_UOPS_RETIRED.HITM", + "SampleAfterValue": "200003", + "BriefDescription": "Memory uop retired where cross core or cross module HITM occurred (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts memory load uops retired where the data is retrieved from the WCB (or fill buffer), indicating that the load found its data while that data was in the process of being brought into the L1 cache. Typically a load will receive this indication when some other load or prefetch missed the L1 cache and was in the process of retrieving the cache line containing the data, but that process had not yet finished (and written the data back to the cache). For example, consider load X and Y, both referencing the same cache line that is not in the L1 cache. If load X misses cache first, it obtains and WCB (or fill buffer) and begins the process of requesting the data. When load Y requests the data, it will either hit the WCB, or the L1 cache, depending on exactly what time the request to Y occurs.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x40", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_UOPS_RETIRED.WCB_HIT", + "SampleAfterValue": "200003", + "BriefDescription": "Loads retired that hit WCB (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts memory load uops retired where the data is retrieved from DRAM. Event is counted at retirement, so the speculative loads are ignored. A memory load can hit (or miss) the L1 cache, hit (or miss) the L2 cache, hit DRAM, hit in the WCB or receive a HITM response.", + "EventCode": "0xD1", + "Counter": "0,1,2,3", + "UMask": "0x80", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_LOAD_UOPS_RETIRED.DRAM_HIT", + "SampleAfterValue": "200003", + "BriefDescription": "Loads retired that came from DRAM (Precise event capable)" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand cacheable data reads of full cache lines have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000010001", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand cacheable data reads of full cache lines have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand cacheable data reads of full cache lines hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000040001", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand cacheable data reads of full cache lines hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand cacheable data reads of full cache lines true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200000001", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand cacheable data reads of full cache lines true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand cacheable data reads of full cache lines miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000000001", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand cacheable data reads of full cache lines miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand cacheable data reads of full cache lines outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000000001", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_DATA_RD.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand cacheable data reads of full cache lines outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000010002", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000040002", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200000002", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000000002", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000000002", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_RFO.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand reads for ownership (RFO) requests generated by a write to full data cache line outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000010004", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000040004", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200000004", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000000004", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000000004", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.DEMAND_CODE_RD.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts demand instruction cacheline and I-side prefetch requests that miss the instruction cache outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000010008", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.COREWB.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000040008", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.COREWB.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200000008", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.COREWB.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000000008", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.COREWB.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000000008", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.COREWB.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts the number of writeback transactions caused by L1 or L2 cache evictions outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000010010", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000040010", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200000010", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000000010", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000000010", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L2_DATA_RD.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cacheline reads generated by hardware L2 cache prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000010020", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000040020", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200000020", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000000020", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000000020", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts reads for ownership (RFO) requests generated by L2 prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts bus lock and split lock requests have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000010400", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts bus lock and split lock requests have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts bus lock and split lock requests hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000040400", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts bus lock and split lock requests hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts bus lock and split lock requests true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200000400", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts bus lock and split lock requests true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts bus lock and split lock requests miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000000400", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts bus lock and split lock requests miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts bus lock and split lock requests outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000000400", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.BUS_LOCKS.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts bus lock and split lock requests outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000010800", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000040800", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200000800", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000000800", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000000800", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.FULL_STREAMING_STORES.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts full cache line data writes to uncacheable write combining (USWC) memory region and full cache-line non-temporal writes outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cache lines requests by software prefetch instructions have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000011000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cache lines requests by software prefetch instructions have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cache lines requests by software prefetch instructions hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000041000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cache lines requests by software prefetch instructions hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cache lines requests by software prefetch instructions true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200001000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cache lines requests by software prefetch instructions true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cache lines requests by software prefetch instructions miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000001000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cache lines requests by software prefetch instructions miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cache lines requests by software prefetch instructions outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000001000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.SW_PREFETCH.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cache lines requests by software prefetch instructions outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000012000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000042000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200002000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000002000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000002000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.PF_L1_DATA_RD.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data cache line reads generated by hardware L1 data cache prefetcher outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts any data writes to uncacheable write combining (USWC) memory region have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000014800", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts any data writes to uncacheable write combining (USWC) memory region hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000044800", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts any data writes to uncacheable write combining (USWC) memory region true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200004800", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts any data writes to uncacheable write combining (USWC) memory region miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000004800", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts any data writes to uncacheable write combining (USWC) memory region outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000004800", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.STREAMING_STORES.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts any data writes to uncacheable write combining (USWC) memory region outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts requests to the uncore subsystem have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000018000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts requests to the uncore subsystem have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts requests to the uncore subsystem hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000048000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts requests to the uncore subsystem hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts requests to the uncore subsystem true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200008000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts requests to the uncore subsystem true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts requests to the uncore subsystem miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000008000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts requests to the uncore subsystem miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts requests to the uncore subsystem outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000008000", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts requests to the uncore subsystem outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data reads generated by L1 or L2 prefetchers have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000013010", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data reads generated by L1 or L2 prefetchers hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000043010", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data reads generated by L1 or L2 prefetchers true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200003010", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data reads generated by L1 or L2 prefetchers miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000003010", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data reads generated by L1 or L2 prefetchers outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000003010", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_PF_DATA_RD.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data reads generated by L1 or L2 prefetchers outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data reads (demand & prefetch) have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000013091", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data reads (demand & prefetch) have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data reads (demand & prefetch) hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000043091", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data reads (demand & prefetch) hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data reads (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200003091", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data reads (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data reads (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000003091", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data reads (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data reads (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000003091", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_DATA_RD.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data reads (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000010022", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_RFO.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0000040022", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x0200000022", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x1000000022", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_RFO.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x4000000022", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_RFO.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts reads for ownership (RFO) requests (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) have any transaction responses from the uncore subsystem. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x00000132b7", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_READ.ANY_RESPONSE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) have any transaction responses from the uncore subsystem.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) hit the L2 cache. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x00000432b7", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_HIT", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) hit the L2 cache.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x02000032b7", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_MISS.SNOOP_MISS_OR_NO_SNOOP_NEEDED", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) true miss for the L2 cache with a snoop miss in the other processor module. ", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x10000032b7", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_READ.L2_MISS.HITM_OTHER_CORE", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6, 0x1a7", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) miss the L2 cache with a snoop hit in the other processor module, data forwarding is required.", + "Offcore": "1" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received. Requires MSR_OFFCORE_RESP[0,1] to specify request type and response. (duplicated for both MSRs)", + "EventCode": "0xB7", + "MSRValue": "0x40000032b7", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "OFFCORE_RESPONSE.ANY_READ.OUTSTANDING", + "PDIR_COUNTER": "na", + "MSRIndex": "0x1a6", + "SampleAfterValue": "100007", + "BriefDescription": "Counts data read, code read, and read for ownership (RFO) requests (demand & prefetch) outstanding, per cycle, from the time of the L2 miss to when any response is received.", + "Offcore": "1" + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/frontend.json b/tools/perf/pmu-events/arch/x86/goldmontplus/frontend.json new file mode 100644 index 000000000000..a7878965ceab --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/goldmontplus/frontend.json @@ -0,0 +1,62 @@ +[ + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line and that cache line is in the ICache (hit). The event strives to count on a cache line basis, so that multiple accesses which hit in a single cache line count as one ICACHE.HIT. Specifically, the event counts when straight line code crosses the cache line boundary, or when a branch target is to a new line, and that cache line is in the ICache. This event counts differently than Intel processors based on Silvermont microarchitecture.", + "EventCode": "0x80", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "ICACHE.HIT", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "References per ICache line that are available in the ICache (hit). This event counts differently than Intel processors based on Silvermont microarchitecture" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line and that cache line is not in the ICache (miss). The event strives to count on a cache line basis, so that multiple accesses which miss in a single cache line count as one ICACHE.MISS. Specifically, the event counts when straight line code crosses the cache line boundary, or when a branch target is to a new line, and that cache line is not in the ICache. This event counts differently than Intel processors based on Silvermont microarchitecture.", + "EventCode": "0x80", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "ICACHE.MISSES", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "References per ICache line that are not available in the ICache (miss). This event counts differently than Intel processors based on Silvermont microarchitecture" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts requests to the Instruction Cache (ICache) for one or more bytes in an ICache Line. The event strives to count on a cache line basis, so that multiple fetches to a single cache line count as one ICACHE.ACCESS. Specifically, the event counts when accesses from straight line code crosses the cache line boundary, or when a branch target is to a new line.\r\nThis event counts differently than Intel processors based on Silvermont microarchitecture.", + "EventCode": "0x80", + "Counter": "0,1,2,3", + "UMask": "0x3", + "PEBScounters": "0,1,2,3", + "EventName": "ICACHE.ACCESSES", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "References per ICache line. This event counts differently than Intel processors based on Silvermont microarchitecture" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of times the Microcode Sequencer (MS) starts a flow of uops from the MSROM. It does not count every time a uop is read from the MSROM. The most common case that this counts is when a micro-coded instruction is encountered by the front end of the machine. Other cases include when an instruction encounters a fault, trap, or microcode assist of any sort that initiates a flow of uops. The event will count MS startups for uops that are speculative, and subsequently cleared by branch mispredict or a machine clear.", + "EventCode": "0xE7", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "MS_DECODED.MS_ENTRY", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "MS decode starts" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of times the prediction (from the predecode cache) for instruction length is incorrect.", + "EventCode": "0xE9", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "DECODE_RESTRICTION.PREDECODE_WRONG", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Decode restrictions due to predicting wrong instruction length" + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/memory.json b/tools/perf/pmu-events/arch/x86/goldmontplus/memory.json new file mode 100644 index 000000000000..91e0815f3ffb --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/goldmontplus/memory.json @@ -0,0 +1,38 @@ +[ + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts when a memory load of a uop spans a page boundary (a split) is retired.", + "EventCode": "0x13", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "MISALIGN_MEM_REF.LOAD_PAGE_SPLIT", + "SampleAfterValue": "200003", + "BriefDescription": "Load uops that split a page (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts when a memory store of a uop spans a page boundary (a split) is retired.", + "EventCode": "0x13", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "MISALIGN_MEM_REF.STORE_PAGE_SPLIT", + "SampleAfterValue": "200003", + "BriefDescription": "Store uops that split a page (Precise event capable)" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts machine clears due to memory ordering issues. This occurs when a snoop request happens and the machine is uncertain if memory ordering will be preserved - as another core is in the process of modifying the data.", + "EventCode": "0xC3", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "MACHINE_CLEARS.MEMORY_ORDERING", + "PDIR_COUNTER": "na", + "SampleAfterValue": "20003", + "BriefDescription": "Machine clears due to memory ordering issue" + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/other.json b/tools/perf/pmu-events/arch/x86/goldmontplus/other.json new file mode 100644 index 000000000000..b860374418ab --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/goldmontplus/other.json @@ -0,0 +1,98 @@ +[ + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts cycles that fetch is stalled due to any reason. That is, the decoder queue is able to accept bytes, but the fetch unit is unable to provide bytes. This will include cycles due to an ITLB miss, ICache miss and other events.", + "EventCode": "0x86", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "FETCH_STALL.ALL", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Cycles code-fetch stalled due to any reason." + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts cycles that fetch is stalled due to an outstanding ITLB miss. That is, the decoder queue is able to accept bytes, but the fetch unit is unable to provide bytes due to an ITLB miss. Note: this event is not the same as page walk cycles to retrieve an instruction translation.", + "EventCode": "0x86", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "FETCH_STALL.ITLB_FILL_PENDING_CYCLES", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Cycles the code-fetch stalls and an ITLB miss is outstanding." + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of issue slots per core cycle that were not consumed by the backend due to either a full resource in the backend (RESOURCE_FULL) or due to the processor recovering from some event (RECOVERY).", + "EventCode": "0xCA", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "ISSUE_SLOTS_NOT_CONSUMED.ANY", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Unfilled issue slots per cycle" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of issue slots per core cycle that were not consumed because of a full resource in the backend. Including but not limited to resources such as the Re-order Buffer (ROB), reservation stations (RS), load/store buffers, physical registers, or any other needed machine resource that is currently unavailable. Note that uops must be available for consumption in order for this event to fire. If a uop is not available (Instruction Queue is empty), this event will not count.", + "EventCode": "0xCA", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "ISSUE_SLOTS_NOT_CONSUMED.RESOURCE_FULL", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Unfilled issue slots per cycle because of a full resource in the backend" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of issue slots per core cycle that were not consumed by the backend because allocation is stalled waiting for a mispredicted jump to retire or other branch-like conditions (e.g. the event is relevant during certain microcode flows). Counts all issue slots blocked while within this window including slots where uops were not available in the Instruction Queue.", + "EventCode": "0xCA", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "ISSUE_SLOTS_NOT_CONSUMED.RECOVERY", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Unfilled issue slots per cycle to recover" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts hardware interrupts received by the processor.", + "EventCode": "0xCB", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "HW_INTERRUPTS.RECEIVED", + "PDIR_COUNTER": "na", + "SampleAfterValue": "203", + "BriefDescription": "Hardware interrupts received" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of core cycles during which interrupts are masked (disabled). Increments by 1 each core cycle that EFLAGS.IF is 0, regardless of whether interrupts are pending or not.", + "EventCode": "0xCB", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "HW_INTERRUPTS.MASKED", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Cycles hardware interrupts are masked" + }, + { + "CollectPEBSRecord": "2", + "PublicDescription": "Counts core cycles during which there are pending interrupts, but interrupts are masked (EFLAGS.IF = 0).", + "EventCode": "0xCB", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "HW_INTERRUPTS.PENDING_AND_MASKED", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Cycles pending interrupts are masked" + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/pipeline.json b/tools/perf/pmu-events/arch/x86/goldmontplus/pipeline.json new file mode 100644 index 000000000000..ccf1aed69197 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/goldmontplus/pipeline.json @@ -0,0 +1,544 @@ +[ + { + "PEBS": "2", + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of instructions that retire execution. For instructions that consist of multiple uops, this event counts the retirement of the last uop of the instruction. The counter continues counting during hardware interrupts, traps, and inside interrupt handlers. This event uses fixed counter 0. You cannot collect a PEBs record for this event.", + "EventCode": "0x00", + "Counter": "Fixed counter 0", + "UMask": "0x1", + "PEBScounters": "32", + "EventName": "INST_RETIRED.ANY", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Instructions retired (Fixed event)" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of core cycles while the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. In mobile systems the core frequency may change from time to time. For this reason this event may have a changing ratio with regards to time. This event uses fixed counter 1. You cannot collect a PEBs record for this event.", + "EventCode": "0x00", + "Counter": "Fixed counter 1", + "UMask": "0x2", + "PEBScounters": "33", + "EventName": "CPU_CLK_UNHALTED.CORE", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Core cycles when core is not halted (Fixed event)" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of reference cycles that the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. In mobile systems the core frequency may change from time. This event is not affected by core frequency changes but counts as if the core is running at the maximum frequency all the time. This event uses fixed counter 2. You cannot collect a PEBs record for this event.", + "EventCode": "0x00", + "Counter": "Fixed counter 2", + "UMask": "0x3", + "PEBScounters": "34", + "EventName": "CPU_CLK_UNHALTED.REF_TSC", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Reference cycles when core is not halted (Fixed event)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts a load blocked from using a store forward, but did not occur because the store data was not available at the right time. The forward might occur subsequently when the data is available.", + "EventCode": "0x03", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "LD_BLOCKS.DATA_UNKNOWN", + "SampleAfterValue": "200003", + "BriefDescription": "Loads blocked due to store data not ready (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts a load blocked from using a store forward because of an address/size mismatch, only one of the loads blocked from each store will be counted.", + "EventCode": "0x03", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "LD_BLOCKS.STORE_FORWARD", + "SampleAfterValue": "200003", + "BriefDescription": "Loads blocked due to store forward restriction (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts loads that block because their address modulo 4K matches a pending store.", + "EventCode": "0x03", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "LD_BLOCKS.4K_ALIAS", + "SampleAfterValue": "200003", + "BriefDescription": "Loads blocked because address has 4k partial address false dependence (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts loads blocked because they are unable to find their physical address in the micro TLB (UTLB).", + "EventCode": "0x03", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "LD_BLOCKS.UTLB_MISS", + "SampleAfterValue": "200003", + "BriefDescription": "Loads blocked because address in not in the UTLB (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts anytime a load that retires is blocked for any reason.", + "EventCode": "0x03", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "LD_BLOCKS.ALL_BLOCK", + "SampleAfterValue": "200003", + "BriefDescription": "Loads blocked (Precise event capable)" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts uops issued by the front end and allocated into the back end of the machine. This event counts uops that retire as well as uops that were speculatively executed but didn't retire. The sort of speculative uops that might be counted includes, but is not limited to those uops issued in the shadow of a miss-predicted branch, those uops that are inserted during an assist (such as for a denormal floating point result), and (previously allocated) uops that might be canceled during a machine clear.", + "EventCode": "0x0E", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "UOPS_ISSUED.ANY", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Uops issued to the back end per cycle" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Core cycles when core is not halted. This event uses a (_P)rogrammable general purpose performance counter.", + "EventCode": "0x3C", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "CPU_CLK_UNHALTED.CORE_P", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Core cycles when core is not halted" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Reference cycles when core is not halted. This event uses a (_P)rogrammable general purpose performance counter.", + "EventCode": "0x3C", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "CPU_CLK_UNHALTED.REF", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Reference cycles when core is not halted" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "This event used to measure front-end inefficiencies. I.e. when front-end of the machine is not delivering uops to the back-end and the back-end has is not stalled. This event can be used to identify if the machine is truly front-end bound. When this event occurs, it is an indication that the front-end of the machine is operating at less than its theoretical peak performance. Background: We can think of the processor pipeline as being divided into 2 broader parts: Front-end and Back-end. Front-end is responsible for fetching the instruction, decoding into uops in machine understandable format and putting them into a uop queue to be consumed by back end. The back-end then takes these uops, allocates the required resources. When all resources are ready, uops are executed. If the back-end is not ready to accept uops from the front-end, then we do not want to count these as front-end bottlenecks. However, whenever we have bottlenecks in the back-end, we will have allocation unit stalls and eventually forcing the front-end to wait until the back-end is ready to receive more uops. This event counts only when back-end is requesting more uops and front-end is not able to provide them. When 3 uops are requested and no uops are delivered, the event counts 3. When 3 are requested, and only 1 is delivered, the event counts 2. When only 2 are delivered, the event counts 1. Alternatively stated, the event will not count if 3 uops are delivered, or if the back end is stalled and not requesting any uops at all. Counts indicate missed opportunities for the front-end to deliver a uop to the back end. Some examples of conditions that cause front-end efficiencies are: ICache misses, ITLB misses, and decoder restrictions that limit the front-end bandwidth. Known Issues: Some uops require multiple allocation slots. These uops will not be charged as a front end 'not delivered' opportunity, and will be regarded as a back end problem. For example, the INC instruction has one uop that requires 2 issue slots. A stream of INC instructions will not count as UOPS_NOT_DELIVERED, even though only one instruction can be issued per clock. The low uop issue rate for a stream of INC instructions is considered to be a back end issue.", + "EventCode": "0x9C", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "UOPS_NOT_DELIVERED.ANY", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Uops requested but not-delivered to the back-end per cycle" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of instructions that retire execution. For instructions that consist of multiple uops, this event counts the retirement of the last uop of the instruction. The event continues counting during hardware interrupts, traps, and inside interrupt handlers. This is an architectural performance event. This event uses a (_P)rogrammable general purpose performance counter. *This event is Precise Event capable: The EventingRIP field in the PEBS record is precise to the address of the instruction which caused the event. Note: Because PEBS records can be collected only on IA32_PMC0, only one event can use the PEBS facility at a time.", + "EventCode": "0xC0", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "INST_RETIRED.ANY_P", + "SampleAfterValue": "2000003", + "BriefDescription": "Instructions retired (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts INST_RETIRED.ANY using the Reduced Skid PEBS feature that reduces the shadow in which events aren't counted allowing for a more unbiased distribution of samples across instructions retired.", + "EventCode": "0xC0", + "Counter": "0,1,2,3", + "UMask": "0x0", + "EventName": "INST_RETIRED.PREC_DIST", + "SampleAfterValue": "2000003", + "BriefDescription": "Instructions retired - using Reduced Skid PEBS feature" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts uops which retired.", + "EventCode": "0xC2", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "UOPS_RETIRED.ANY", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Uops retired (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts uops retired that are from the complex flows issued by the micro-sequencer (MS). Counts both the uops from a micro-coded instruction, and the uops that might be generated from a micro-coded assist.", + "EventCode": "0xC2", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "UOPS_RETIRED.MS", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "MS uops retired (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of floating point divide uops retired.", + "EventCode": "0xC2", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "UOPS_RETIRED.FPDIV", + "SampleAfterValue": "2000003", + "BriefDescription": "Floating point divide uops retired (Precise Event Capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of integer divide uops retired.", + "EventCode": "0xC2", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "UOPS_RETIRED.IDIV", + "SampleAfterValue": "2000003", + "BriefDescription": "Integer divide uops retired (Precise Event Capable)" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts machine clears for any reason.", + "EventCode": "0xC3", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "MACHINE_CLEARS.ALL", + "PDIR_COUNTER": "na", + "SampleAfterValue": "20003", + "BriefDescription": "All machine clears" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of times that the processor detects that a program is writing to a code section and has to perform a machine clear because of that modification. Self-modifying code (SMC) causes a severe penalty in all Intel architecture processors.", + "EventCode": "0xC3", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "MACHINE_CLEARS.SMC", + "PDIR_COUNTER": "na", + "SampleAfterValue": "20003", + "BriefDescription": "Self-Modifying Code detected" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts machine clears due to floating point (FP) operations needing assists. For instance, if the result was a floating point denormal, the hardware clears the pipeline and reissues uops to produce the correct IEEE compliant denormal result.", + "EventCode": "0xC3", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "MACHINE_CLEARS.FP_ASSIST", + "PDIR_COUNTER": "na", + "SampleAfterValue": "20003", + "BriefDescription": "Machine clears due to FP assists" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts machine clears due to memory disambiguation. Memory disambiguation happens when a load which has been issued conflicts with a previous unretired store in the pipeline whose address was not known at issue time, but is later resolved to be the same as the load address.", + "EventCode": "0xC3", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "MACHINE_CLEARS.DISAMBIGUATION", + "PDIR_COUNTER": "na", + "SampleAfterValue": "20003", + "BriefDescription": "Machine clears due to memory disambiguation" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of times that the machines clears due to a page fault. Covers both I-side and D-side(Loads/Stores) page faults. A page fault occurs when either page is not present, or an access violation", + "EventCode": "0xC3", + "Counter": "0,1,2,3", + "UMask": "0x20", + "PEBScounters": "0,1,2,3", + "EventName": "MACHINE_CLEARS.PAGE_FAULT", + "PDIR_COUNTER": "na", + "SampleAfterValue": "20003", + "BriefDescription": "Machines clear due to a page fault" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts branch instructions retired for all branch types. This is an architectural performance event.", + "EventCode": "0xC4", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "BR_INST_RETIRED.ALL_BRANCHES", + "SampleAfterValue": "200003", + "BriefDescription": "Retired branch instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts retired Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired, including both when the branch was taken and when it was not taken.", + "EventCode": "0xC4", + "Counter": "0,1,2,3", + "UMask": "0x7e", + "PEBScounters": "0,1,2,3", + "EventName": "BR_INST_RETIRED.JCC", + "SampleAfterValue": "200003", + "BriefDescription": "Retired conditional branch instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts the number of taken branch instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3", + "UMask": "0x80", + "PEBScounters": "0,1,2,3", + "EventName": "BR_INST_RETIRED.ALL_TAKEN_BRANCHES", + "SampleAfterValue": "200003", + "BriefDescription": "Retired taken branch instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts far branch instructions retired. This includes far jump, far call and return, and Interrupt call and return.", + "EventCode": "0xC4", + "Counter": "0,1,2,3", + "UMask": "0xbf", + "PEBScounters": "0,1,2,3", + "EventName": "BR_INST_RETIRED.FAR_BRANCH", + "SampleAfterValue": "200003", + "BriefDescription": "Retired far branch instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts near indirect call or near indirect jmp branch instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3", + "UMask": "0xeb", + "PEBScounters": "0,1,2,3", + "EventName": "BR_INST_RETIRED.NON_RETURN_IND", + "SampleAfterValue": "200003", + "BriefDescription": "Retired instructions of near indirect Jmp or call (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts near return branch instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3", + "UMask": "0xf7", + "PEBScounters": "0,1,2,3", + "EventName": "BR_INST_RETIRED.RETURN", + "SampleAfterValue": "200003", + "BriefDescription": "Retired near return instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts near CALL branch instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3", + "UMask": "0xf9", + "PEBScounters": "0,1,2,3", + "EventName": "BR_INST_RETIRED.CALL", + "SampleAfterValue": "200003", + "BriefDescription": "Retired near call instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts near indirect CALL branch instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3", + "UMask": "0xfb", + "PEBScounters": "0,1,2,3", + "EventName": "BR_INST_RETIRED.IND_CALL", + "SampleAfterValue": "200003", + "BriefDescription": "Retired near indirect call instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts near relative CALL branch instructions retired.", + "EventCode": "0xC4", + "Counter": "0,1,2,3", + "UMask": "0xfd", + "PEBScounters": "0,1,2,3", + "EventName": "BR_INST_RETIRED.REL_CALL", + "SampleAfterValue": "200003", + "BriefDescription": "Retired near relative call instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired that were taken and does not count when the Jcc branch instruction were not taken.", + "EventCode": "0xC4", + "Counter": "0,1,2,3", + "UMask": "0xfe", + "PEBScounters": "0,1,2,3", + "EventName": "BR_INST_RETIRED.TAKEN_JCC", + "SampleAfterValue": "200003", + "BriefDescription": "Retired conditional branch instructions that were taken (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts mispredicted branch instructions retired including all branch types.", + "EventCode": "0xC5", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "BR_MISP_RETIRED.ALL_BRANCHES", + "SampleAfterValue": "200003", + "BriefDescription": "Retired mispredicted branch instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts mispredicted retired Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired, including both when the branch was supposed to be taken and when it was not supposed to be taken (but the processor predicted the opposite condition).", + "EventCode": "0xC5", + "Counter": "0,1,2,3", + "UMask": "0x7e", + "PEBScounters": "0,1,2,3", + "EventName": "BR_MISP_RETIRED.JCC", + "SampleAfterValue": "200003", + "BriefDescription": "Retired mispredicted conditional branch instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts mispredicted branch instructions retired that were near indirect call or near indirect jmp, where the target address taken was not what the processor predicted.", + "EventCode": "0xC5", + "Counter": "0,1,2,3", + "UMask": "0xeb", + "PEBScounters": "0,1,2,3", + "EventName": "BR_MISP_RETIRED.NON_RETURN_IND", + "SampleAfterValue": "200003", + "BriefDescription": "Retired mispredicted instructions of near indirect Jmp or near indirect call (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts mispredicted near RET branch instructions retired, where the return address taken was not what the processor predicted.", + "EventCode": "0xC5", + "Counter": "0,1,2,3", + "UMask": "0xf7", + "PEBScounters": "0,1,2,3", + "EventName": "BR_MISP_RETIRED.RETURN", + "SampleAfterValue": "200003", + "BriefDescription": "Retired mispredicted near return instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts mispredicted near indirect CALL branch instructions retired, where the target address taken was not what the processor predicted.", + "EventCode": "0xC5", + "Counter": "0,1,2,3", + "UMask": "0xfb", + "PEBScounters": "0,1,2,3", + "EventName": "BR_MISP_RETIRED.IND_CALL", + "SampleAfterValue": "200003", + "BriefDescription": "Retired mispredicted near indirect call instructions (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts mispredicted retired Jcc (Jump on Conditional Code/Jump if Condition is Met) branch instructions retired that were supposed to be taken but the processor predicted that it would not be taken.", + "EventCode": "0xC5", + "Counter": "0,1,2,3", + "UMask": "0xfe", + "PEBScounters": "0,1,2,3", + "EventName": "BR_MISP_RETIRED.TAKEN_JCC", + "SampleAfterValue": "200003", + "BriefDescription": "Retired mispredicted conditional branch instructions that were taken (Precise event capable)" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts core cycles if either divide unit is busy.", + "EventCode": "0xCD", + "Counter": "0,1,2,3", + "UMask": "0x0", + "PEBScounters": "0,1,2,3", + "EventName": "CYCLES_DIV_BUSY.ALL", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Cycles a divider is busy" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts core cycles the integer divide unit is busy.", + "EventCode": "0xCD", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "CYCLES_DIV_BUSY.IDIV", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Cycles the integer divide unit is busy" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts core cycles the floating point divide unit is busy.", + "EventCode": "0xCD", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "CYCLES_DIV_BUSY.FPDIV", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Cycles the FP divide unit is busy" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of times a BACLEAR is signaled for any reason, including, but not limited to indirect branch/call, Jcc (Jump on Conditional Code/Jump if Condition is Met) branch, unconditional branch/call, and returns.", + "EventCode": "0xE6", + "Counter": "0,1,2,3", + "UMask": "0x1", + "PEBScounters": "0,1,2,3", + "EventName": "BACLEARS.ALL", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "BACLEARs asserted for any branch type" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts BACLEARS on return instructions.", + "EventCode": "0xE6", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "BACLEARS.RETURN", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "BACLEARs asserted for return branch" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts BACLEARS on Jcc (Jump on Conditional Code/Jump if Condition is Met) branches.", + "EventCode": "0xE6", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "BACLEARS.COND", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "BACLEARs asserted for conditional branch" + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/goldmontplus/virtual-memory.json b/tools/perf/pmu-events/arch/x86/goldmontplus/virtual-memory.json new file mode 100644 index 000000000000..0b53a3b0dfb8 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/goldmontplus/virtual-memory.json @@ -0,0 +1,218 @@ +[ + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts page walks completed due to demand data loads (including SW prefetches) whose address translations missed in all TLB levels and were mapped to 4K pages. The page walks can end with or without a page fault.", + "EventCode": "0x08", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Page walk completed due to a demand load to a 4K page" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts page walks completed due to demand data loads (including SW prefetches) whose address translations missed in all TLB levels and were mapped to 2M or 4M pages. The page walks can end with or without a page fault.", + "EventCode": "0x08", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Page walk completed due to a demand load to a 2M or 4M page" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts page walks completed due to demand data loads (including SW prefetches) whose address translations missed in all TLB levels and were mapped to 1GB pages. The page walks can end with or without a page fault.", + "EventCode": "0x08", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1GB", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Page walk completed due to a demand load to a 1GB page" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts once per cycle for each page walk occurring due to a load (demand data loads or SW prefetches). Includes cycles spent traversing the Extended Page Table (EPT). Average cycles per walk can be calculated by dividing by the number of walks.", + "EventCode": "0x08", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_LOAD_MISSES.WALK_PENDING", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Page walks outstanding due to a demand load every cycle." + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.", + "EventCode": "0x49", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Page walk completed due to a demand data store to a 4K page" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 2M or 4M pages. The page walks can end with or without a page fault.", + "EventCode": "0x49", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Page walk completed due to a demand data store to a 2M or 4M page" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts page walks completed due to demand data stores whose address translations missed in the TLB and were mapped to 1GB pages. The page walks can end with or without a page fault.", + "EventCode": "0x49", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1GB", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Page walk completed due to a demand data store to a 1GB page" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts once per cycle for each page walk occurring due to a demand data store. Includes cycles spent traversing the Extended Page Table (EPT). Average cycles per walk can be calculated by dividing by the number of walks.", + "EventCode": "0x49", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "DTLB_STORE_MISSES.WALK_PENDING", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Page walks outstanding due to a demand data store every cycle." + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts once per cycle for each page walk only while traversing the Extended Page Table (EPT), and does not count during the rest of the translation. The EPT is used for translating Guest-Physical Addresses to Physical Addresses for Virtual Machine Monitors (VMMs). Average cycles per walk can be calculated by dividing the count by number of walks.", + "EventCode": "0x4F", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "EPT.WALK_PENDING", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Page walks outstanding due to walking the EPT every cycle" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts the number of times the machine was unable to find a translation in the Instruction Translation Lookaside Buffer (ITLB) for a linear address of an instruction fetch. It counts when new translation are filled into the ITLB. The event is speculative in nature, but will not count translations (page walks) that are begun and not finished, or translations that are finished but not filled into the ITLB.", + "EventCode": "0x81", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB.MISS", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "ITLB misses" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts page walks completed due to instruction fetches whose address translations missed in the TLB and were mapped to 4K pages. The page walks can end with or without a page fault.", + "EventCode": "0x85", + "Counter": "0,1,2,3", + "UMask": "0x2", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB_MISSES.WALK_COMPLETED_4K", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Page walk completed due to an instruction fetch in a 4K page" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts page walks completed due to instruction fetches whose address translations missed in the TLB and were mapped to 2M or 4M pages. The page walks can end with or without a page fault.", + "EventCode": "0x85", + "Counter": "0,1,2,3", + "UMask": "0x4", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Page walk completed due to an instruction fetch in a 2M or 4M page" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts page walks completed due to instruction fetches whose address translations missed in the TLB and were mapped to 1GB pages. The page walks can end with or without a page fault.", + "EventCode": "0x85", + "Counter": "0,1,2,3", + "UMask": "0x8", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB_MISSES.WALK_COMPLETED_1GB", + "PDIR_COUNTER": "na", + "SampleAfterValue": "2000003", + "BriefDescription": "Page walk completed due to an instruction fetch in a 1GB page" + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts once per cycle for each page walk occurring due to an instruction fetch. Includes cycles spent traversing the Extended Page Table (EPT). Average cycles per walk can be calculated by dividing by the number of walks.", + "EventCode": "0x85", + "Counter": "0,1,2,3", + "UMask": "0x10", + "PEBScounters": "0,1,2,3", + "EventName": "ITLB_MISSES.WALK_PENDING", + "PDIR_COUNTER": "na", + "SampleAfterValue": "200003", + "BriefDescription": "Page walks outstanding due to an instruction fetch every cycle." + }, + { + "CollectPEBSRecord": "1", + "PublicDescription": "Counts STLB flushes. The TLBs are flushed on instructions like INVLPG and MOV to CR3.", + "EventCode": "0xBD", + "Counter": "0,1,2,3", + "UMask": "0x20", + "PEBScounters": "0,1,2,3", + "EventName": "TLB_FLUSHES.STLB_ANY", + "PDIR_COUNTER": "na", + "SampleAfterValue": "20003", + "BriefDescription": "STLB flushes" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts load uops retired that caused a DTLB miss.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x11", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_LOADS", + "SampleAfterValue": "200003", + "BriefDescription": "Load uops retired that missed the DTLB (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts store uops retired that caused a DTLB miss.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x12", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_STORES", + "SampleAfterValue": "200003", + "BriefDescription": "Store uops retired that missed the DTLB (Precise event capable)" + }, + { + "PEBS": "2", + "CollectPEBSRecord": "2", + "PublicDescription": "Counts uops retired that had a DTLB miss on load, store or either. Note that when two distinct memory operations to the same page miss the DTLB, only one of them will be recorded as a DTLB miss.", + "EventCode": "0xD0", + "Counter": "0,1,2,3", + "UMask": "0x13", + "PEBScounters": "0,1,2,3", + "EventName": "MEM_UOPS_RETIRED.DTLB_MISS", + "SampleAfterValue": "200003", + "BriefDescription": "Memory uops retired that missed the DTLB (Precise event capable)" + } +] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 4ea068366c3e..fe1a2c47cabf 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -9,6 +9,7 @@ GenuineIntel-6-27,v4,bonnell,core GenuineIntel-6-36,v4,bonnell,core GenuineIntel-6-35,v4,bonnell,core GenuineIntel-6-5C,v8,goldmont,core +GenuineIntel-6-7A,v1,goldmontplus,core GenuineIntel-6-3C,v24,haswell,core GenuineIntel-6-45,v24,haswell,core GenuineIntel-6-46,v24,haswell,core -- GitLab From 3564366d550960865c273e8ce90130f6e1929aaa Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Tue, 14 Nov 2017 06:06:40 -0800 Subject: [PATCH 1147/1299] perf/x86/intel/uncore: Add event constraint for BDX PCU commit bb9fbe1b57503f790dbbf9f06e72cb0fb9e60740 upstream. Event select bit 7 'Use Occupancy' in PCU Box is not available for counter 0 on BDX Add a constraint to fix it. Reported-by: Stephane Eranian Signed-off-by: Kan Liang Signed-off-by: Thomas Gleixner Tested-by: Stephane Eranian Cc: peterz@infradead.org Cc: ak@linux.intel.com Link: https://lkml.kernel.org/r/1510668400-301000-1-git-send-email-kan.liang@intel.com Cc: "Jin, Yao" Signed-off-by: Greg Kroah-Hartman --- arch/x86/events/intel/uncore_snbep.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c index 8243fdbb9b9c..2dae3f585c01 100644 --- a/arch/x86/events/intel/uncore_snbep.c +++ b/arch/x86/events/intel/uncore_snbep.c @@ -3035,11 +3035,19 @@ static struct intel_uncore_type *bdx_msr_uncores[] = { NULL, }; +/* Bit 7 'Use Occupancy' is not available for counter 0 on BDX */ +static struct event_constraint bdx_uncore_pcu_constraints[] = { + EVENT_CONSTRAINT(0x80, 0xe, 0x80), + EVENT_CONSTRAINT_END +}; + void bdx_uncore_cpu_init(void) { if (bdx_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores) bdx_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores; uncore_msr_uncores = bdx_msr_uncores; + + hswep_uncore_pcu.constraints = bdx_uncore_pcu_constraints; } static struct intel_uncore_type bdx_uncore_ha = { -- GitLab From b28f53169c0f4947f6745a993fe655c7c7a9ff8a Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Fri, 18 May 2018 16:41:54 -0400 Subject: [PATCH 1148/1299] media: vsp1: Release buffers for each video node commit 83967993f2320575c0ab27a80bf1d7535909c2f4 upstream. Commit 372b2b0399fc ("media: v4l: vsp1: Release buffers in start_streaming error path") introduced a helper to clean up buffers on error paths, but inadvertently changed the code such that only the output WPF buffers were cleaned, rather than the video node being operated on. Since then vsp1_video_cleanup_pipeline() has grown to perform both video node cleanup, as well as pipeline cleanup. Split the implementation into two distinct functions that perform the required work, so that each video node can release its buffers correctly on streamoff. The pipe cleanup that was performed in the vsp1_video_stop_streaming() (releasing the pipe->dl) is moved to the function for clarity. Fixes: 372b2b0399fc ("media: v4l: vsp1: Release buffers in start_streaming error path") Cc: stable@vger.kernel.org # v4.14+ Signed-off-by: Kieran Bingham Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/vsp1/vsp1_video.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index c2d3b8f0f487..93f69b3ac911 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -849,9 +849,8 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe) return 0; } -static void vsp1_video_cleanup_pipeline(struct vsp1_pipeline *pipe) +static void vsp1_video_release_buffers(struct vsp1_video *video) { - struct vsp1_video *video = pipe->output->video; struct vsp1_vb2_buffer *buffer; unsigned long flags; @@ -861,12 +860,18 @@ static void vsp1_video_cleanup_pipeline(struct vsp1_pipeline *pipe) vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR); INIT_LIST_HEAD(&video->irqqueue); spin_unlock_irqrestore(&video->irqlock, flags); +} + +static void vsp1_video_cleanup_pipeline(struct vsp1_pipeline *pipe) +{ + lockdep_assert_held(&pipe->lock); /* Release our partition table allocation */ - mutex_lock(&pipe->lock); kfree(pipe->part_table); pipe->part_table = NULL; - mutex_unlock(&pipe->lock); + + vsp1_dl_list_put(pipe->dl); + pipe->dl = NULL; } static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) @@ -881,8 +886,9 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) if (pipe->stream_count == pipe->num_inputs) { ret = vsp1_video_setup_pipeline(pipe); if (ret < 0) { - mutex_unlock(&pipe->lock); + vsp1_video_release_buffers(video); vsp1_video_cleanup_pipeline(pipe); + mutex_unlock(&pipe->lock); return ret; } @@ -932,13 +938,12 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq) if (ret == -ETIMEDOUT) dev_err(video->vsp1->dev, "pipeline stop timeout\n"); - vsp1_dl_list_put(pipe->dl); - pipe->dl = NULL; + vsp1_video_cleanup_pipeline(pipe); } mutex_unlock(&pipe->lock); media_pipeline_stop(&video->video.entity); - vsp1_video_cleanup_pipeline(pipe); + vsp1_video_release_buffers(video); vsp1_video_pipeline_put(pipe); } -- GitLab From 06b846486668e1de1d350f8adc86c3d36f01a4ac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Apr 2018 11:47:32 -0400 Subject: [PATCH 1149/1299] media: v4l2-compat-ioctl32: prevent go past max size commit ea72fbf588ac9c017224dcdaa2019ff52ca56fee upstream. As warned by smatch: drivers/media/v4l2-core/v4l2-compat-ioctl32.c:879 put_v4l2_ext_controls32() warn: check for integer overflow 'count' The access_ok() logic should check for too big arrays too. Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 6730fd08ef03..e159dfc21279 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -871,7 +871,7 @@ static int put_v4l2_ext_controls32(struct file *file, get_user(kcontrols, &kp->controls)) return -EFAULT; - if (!count) + if (!count || count > (U32_MAX/sizeof(*ucontrols))) return 0; if (get_user(p, &up->controls)) return -EFAULT; -- GitLab From 2c40fa51428b50343e7964faea0aae2810750bc2 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Mon, 26 Mar 2018 02:06:16 -0400 Subject: [PATCH 1150/1299] media: cx231xx: Add support for AverMedia DVD EZMaker 7 commit 29e61d6ef061b012d320327af7dbb3990e75be45 upstream. User reports AverMedia DVD EZMaker 7 can be driven by VIDEO_GRABBER. Add the device to the id_table to make it work. BugLink: https://bugs.launchpad.net/bugs/1620762 Cc: stable@vger.kernel.org Signed-off-by: Kai-Heng Feng Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/cx231xx/cx231xx-cards.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 9b742d569fb5..c30cb0fb165d 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -918,6 +918,9 @@ struct usb_device_id cx231xx_id_table[] = { .driver_info = CX231XX_BOARD_CNXT_RDE_250}, {USB_DEVICE(0x0572, 0x58A0), .driver_info = CX231XX_BOARD_CNXT_RDU_250}, + /* AverMedia DVD EZMaker 7 */ + {USB_DEVICE(0x07ca, 0xc039), + .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER}, {USB_DEVICE(0x2040, 0xb110), .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL}, {USB_DEVICE(0x2040, 0xb111), -- GitLab From c508ed236c8b2dab6f19a6727704cc77ffe5dc1e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Apr 2018 05:30:52 -0400 Subject: [PATCH 1151/1299] media: dvb_frontend: fix locking issues at dvb_frontend_get_event() commit 76d81243a487c09619822ef8e7201a756e58a87d upstream. As warned by smatch: drivers/media/dvb-core/dvb_frontend.c:314 dvb_frontend_get_event() warn: inconsistent returns 'sem:&fepriv->sem'. Locked on: line 288 line 295 line 306 line 314 Unlocked on: line 303 The lock implementation for get event is wrong, as, if an interrupt occurs, down_interruptible() will fail, and the routine will call up() twice when userspace calls the ioctl again. The bad code is there since when Linux migrated to git, in 2005. Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb-core/dvb_frontend.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 33d844fe2e70..f7d4ec37fdbc 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -275,8 +275,20 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, wake_up_interruptible (&events->wait_queue); } +static int dvb_frontend_test_event(struct dvb_frontend_private *fepriv, + struct dvb_fe_events *events) +{ + int ret; + + up(&fepriv->sem); + ret = events->eventw != events->eventr; + down(&fepriv->sem); + + return ret; +} + static int dvb_frontend_get_event(struct dvb_frontend *fe, - struct dvb_frontend_event *event, int flags) + struct dvb_frontend_event *event, int flags) { struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_fe_events *events = &fepriv->events; @@ -294,13 +306,8 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe, if (flags & O_NONBLOCK) return -EWOULDBLOCK; - up(&fepriv->sem); - - ret = wait_event_interruptible (events->wait_queue, - events->eventw != events->eventr); - - if (down_interruptible (&fepriv->sem)) - return -ERESTARTSYS; + ret = wait_event_interruptible(events->wait_queue, + dvb_frontend_test_event(fepriv, events)); if (ret < 0) return ret; -- GitLab From 89864c2e7506ff0b5d62734b31872a5b6ddfb3ab Mon Sep 17 00:00:00 2001 From: Scott Mayhew Date: Mon, 7 May 2018 09:01:08 -0400 Subject: [PATCH 1152/1299] nfsd: restrict rd_maxcount to svc_max_payload in nfsd_encode_readdir commit 9c2ece6ef67e9d376f32823086169b489c422ed0 upstream. nfsd4_readdir_rsize restricts rd_maxcount to svc_max_payload when estimating the size of the readdir reply, but nfsd_encode_readdir restricts it to INT_MAX when encoding the reply. This can result in log messages like "kernel: RPC request reserved 32896 but used 1049444". Restrict rd_dircount similarly (no reason it should be larger than svc_max_payload). Signed-off-by: Scott Mayhew Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4xdr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index df2b8849a63b..f6588cc6816c 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3645,7 +3645,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 nfserr = nfserr_resource; goto err_no_verf; } - maxcount = min_t(u32, readdir->rd_maxcount, INT_MAX); + maxcount = svc_max_payload(resp->rqstp); + maxcount = min_t(u32, readdir->rd_maxcount, maxcount); /* * Note the rfc defines rd_maxcount as the size of the * READDIR4resok structure, which includes the verifier above @@ -3659,7 +3660,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 /* RFC 3530 14.2.24 allows us to ignore dircount when it's 0: */ if (!readdir->rd_dircount) - readdir->rd_dircount = INT_MAX; + readdir->rd_dircount = svc_max_payload(resp->rqstp); readdir->xdr = xdr; readdir->rd_maxcount = maxcount; -- GitLab From c92d800fc9c408d09526e6651154743cd6c23c29 Mon Sep 17 00:00:00 2001 From: Dave Wysochanski Date: Tue, 29 May 2018 17:47:30 -0400 Subject: [PATCH 1153/1299] NFSv4: Fix possible 1-byte stack overflow in nfs_idmap_read_and_verify_message commit d68894800ec5712d7ddf042356f11e36f87d7f78 upstream. In nfs_idmap_read_and_verify_message there is an incorrect sprintf '%d' that converts the __u32 'im_id' from struct idmap_msg to 'id_str', which is a stack char array variable of length NFS_UINT_MAXLEN == 11. If a uid or gid value is > 2147483647 = 0x7fffffff, the conversion overflows into a negative value, for example: crash> p (unsigned) (0x80000000) $1 = 2147483648 crash> p (signed) (0x80000000) $2 = -2147483648 The '-' sign is written to the buffer and this causes a 1 byte overflow when the NULL byte is written, which corrupts kernel stack memory. If CONFIG_CC_STACKPROTECTOR_STRONG is set we see a stack-protector panic: [11558053.616565] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffffa05b8a8c [11558053.639063] CPU: 6 PID: 9423 Comm: rpc.idmapd Tainted: G W ------------ T 3.10.0-514.el7.x86_64 #1 [11558053.641990] Hardware name: Red Hat OpenStack Compute, BIOS 1.10.2-3.el7_4.1 04/01/2014 [11558053.644462] ffffffff818c7bc0 00000000b1f3aec1 ffff880de0f9bd48 ffffffff81685eac [11558053.646430] ffff880de0f9bdc8 ffffffff8167f2b3 ffffffff00000010 ffff880de0f9bdd8 [11558053.648313] ffff880de0f9bd78 00000000b1f3aec1 ffffffff811dcb03 ffffffffa05b8a8c [11558053.650107] Call Trace: [11558053.651347] [] dump_stack+0x19/0x1b [11558053.653013] [] panic+0xe3/0x1f2 [11558053.666240] [] ? kfree+0x103/0x140 [11558053.682589] [] ? idmap_pipe_downcall+0x1cc/0x1e0 [nfsv4] [11558053.689710] [] __stack_chk_fail+0x1b/0x30 [11558053.691619] [] idmap_pipe_downcall+0x1cc/0x1e0 [nfsv4] [11558053.693867] [] rpc_pipe_write+0x56/0x70 [sunrpc] [11558053.695763] [] vfs_write+0xbd/0x1e0 [11558053.702236] [] ? task_work_run+0xac/0xe0 [11558053.704215] [] SyS_write+0x7f/0xe0 [11558053.709674] [] system_call_fastpath+0x16/0x1b Fix this by calling the internally defined nfs_map_numeric_to_string() function which properly uses '%u' to convert this __u32. For consistency, also replace the one other place where snprintf is called. Signed-off-by: Dave Wysochanski Reported-by: Stephen Johnston Fixes: cf4ab538f1516 ("NFSv4: Fix the string length returned by the idmapper") Cc: stable@vger.kernel.org # v3.4+ Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4idmap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c index 22dc30a679a0..b6f9d84ba19b 100644 --- a/fs/nfs/nfs4idmap.c +++ b/fs/nfs/nfs4idmap.c @@ -343,7 +343,7 @@ static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, int id_len; ssize_t ret; - id_len = snprintf(id_str, sizeof(id_str), "%u", id); + id_len = nfs_map_numeric_to_string(id, id_str, sizeof(id_str)); ret = nfs_idmap_get_key(id_str, id_len, type, buf, buflen, idmap); if (ret < 0) return -EINVAL; @@ -627,7 +627,8 @@ static int nfs_idmap_read_and_verify_message(struct idmap_msg *im, if (strcmp(upcall->im_name, im->im_name) != 0) break; /* Note: here we store the NUL terminator too */ - len = sprintf(id_str, "%d", im->im_id) + 1; + len = 1 + nfs_map_numeric_to_string(im->im_id, id_str, + sizeof(id_str)); ret = nfs_idmap_instantiate(key, authkey, id_str, len); break; case IDMAP_CONV_IDTONAME: -- GitLab From 63715ead82c5d784798427ba5e5d21b9bc7717e2 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 9 Jun 2018 12:43:06 -0400 Subject: [PATCH 1154/1299] NFSv4: Revert commit 5f83d86cf531d ("NFSv4.x: Fix wraparound issues..") commit fc40724fc6731d90cc7fb6d62d66135f85a33dd2 upstream. The correct behaviour for NFSv4 sequence IDs is to wrap around to the value 0 after 0xffffffff. See https://tools.ietf.org/html/rfc5661#section-2.10.6.1 Fixes: 5f83d86cf531d ("NFSv4.x: Fix wraparound issues when validing...") Cc: stable@vger.kernel.org # 4.6+ Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/callback_proc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 19151f6c0e97..516b2248cafe 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -420,11 +420,8 @@ validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot, return htonl(NFS4ERR_SEQ_FALSE_RETRY); } - /* Wraparound */ - if (unlikely(slot->seq_nr == 0xFFFFFFFFU)) { - if (args->csa_sequenceid == 1) - return htonl(NFS4_OK); - } else if (likely(args->csa_sequenceid == slot->seq_nr + 1)) + /* Note: wraparound relies on seq_nr being of type u32 */ + if (likely(args->csa_sequenceid == slot->seq_nr + 1)) return htonl(NFS4_OK); /* Misordered request */ -- GitLab From fb7fecb4d90fd0808b45f50befa7a07917b3ff9e Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 9 Jun 2018 12:50:50 -0400 Subject: [PATCH 1155/1299] NFSv4: Fix a typo in nfs41_sequence_process commit 995891006ccbb73c0c9c3923cf9d25c4d07ec16b upstream. We want to compare the slot_id to the highest slot number advertised by the server. Fixes: 3be0f80b5fe9c ("NFSv4.1: Fix up replays of interrupted requests") Cc: stable@vger.kernel.org # 4.15+ Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8ff98bbe479b..928bbc397818 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -750,7 +750,7 @@ static int nfs41_sequence_process(struct rpc_task *task, * The slot id we used was probably retired. Try again * using a different slot id. */ - if (slot->seq_nr < slot->table->target_highest_slotid) + if (slot->slot_nr < slot->table->target_highest_slotid) goto session_recover; goto retry_nowait; case -NFS4ERR_SEQ_MISORDERED: -- GitLab From 9aa818d42bf5f5477f66dbc941b4daddfcae290d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 11 May 2018 18:24:12 +1000 Subject: [PATCH 1156/1299] video: uvesafb: Fix integer overflow in allocation commit 9f645bcc566a1e9f921bdae7528a01ced5bc3713 upstream. cmap->len can get close to INT_MAX/2, allowing for an integer overflow in allocation. This uses kmalloc_array() instead to catch the condition. Reported-by: Dr Silvio Cesare of InfoSect Fixes: 8bdb3a2d7df48 ("uvesafb: the driver core") Cc: stable@vger.kernel.org Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/video/fbdev/uvesafb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c index 73676eb0244a..c592ca513115 100644 --- a/drivers/video/fbdev/uvesafb.c +++ b/drivers/video/fbdev/uvesafb.c @@ -1044,7 +1044,8 @@ static int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info) info->cmap.len || cmap->start < info->cmap.start) return -EINVAL; - entries = kmalloc(sizeof(*entries) * cmap->len, GFP_KERNEL); + entries = kmalloc_array(cmap->len, sizeof(*entries), + GFP_KERNEL); if (!entries) return -ENOMEM; -- GitLab From a7f3c0abac1dbba0581904ef9c9643efb0415154 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 26 Apr 2018 14:10:24 +0200 Subject: [PATCH 1157/1299] ACPI / LPSS: Add missing prv_offset setting for byt/cht PWM devices commit fdcb613d49321b5bf5d5a1bd0fba8e7c241dcc70 upstream. The LPSS PWM device on on Bay Trail and Cherry Trail devices has a set of private registers at offset 0x800, the current lpss_device_desc for them already sets the LPSS_SAVE_CTX flag to have these saved/restored over device-suspend, but the current lpss_device_desc was not setting the prv_offset field, leading to the regular device registers getting saved/restored instead. This is causing the PWM controller to no longer work, resulting in a black screen, after a suspend/resume on systems where the firmware clears the APB clock and reset bits at offset 0x804. This commit fixes this by properly setting prv_offset to 0x800 for the PWM devices. Cc: stable@vger.kernel.org Fixes: e1c748179754 ("ACPI / LPSS: Add Intel BayTrail ACPI mode PWM") Fixes: 1bfbd8eb8a7f ("ACPI / LPSS: Add ACPI IDs for Intel Braswell") Signed-off-by: Hans de Goede Acked-by: Rafael J . Wysocki Signed-off-by: Thierry Reding Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/acpi_lpss.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index a2be3fd2c72b..602ae58ee2d8 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -229,11 +229,13 @@ static const struct lpss_device_desc lpt_sdio_dev_desc = { static const struct lpss_device_desc byt_pwm_dev_desc = { .flags = LPSS_SAVE_CTX, + .prv_offset = 0x800, .setup = byt_pwm_setup, }; static const struct lpss_device_desc bsw_pwm_dev_desc = { .flags = LPSS_SAVE_CTX | LPSS_NO_D3_DELAY, + .prv_offset = 0x800, .setup = bsw_pwm_setup, }; -- GitLab From 24ab6e6858e762ade66aebf80ba02f6c4f2311b9 Mon Sep 17 00:00:00 2001 From: Alexandr Savca Date: Thu, 21 Jun 2018 17:12:54 -0700 Subject: [PATCH 1158/1299] Input: elan_i2c - add ELAN0618 (Lenovo v330 15IKB) ACPI ID commit 8938fc7b8fe9ccfa11751ead502a8d385b607967 upstream. Add ELAN0618 to the list of supported touchpads; this ID is used in Lenovo v330 15IKB devices. Signed-off-by: Alexandr Savca Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/elan_i2c_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index c4926645c779..665935b4692e 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1261,6 +1261,7 @@ static const struct acpi_device_id elan_acpi_id[] = { { "ELAN060C", 0 }, { "ELAN0611", 0 }, { "ELAN0612", 0 }, + { "ELAN0618", 0 }, { "ELAN1000", 0 }, { } }; -- GitLab From 3c718460f5a3adc0e1363e37430330295477b108 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 26 Apr 2018 14:10:23 +0200 Subject: [PATCH 1159/1299] pwm: lpss: platform: Save/restore the ctrl register over a suspend/resume commit 1d375b58c12f08d8570b30b865def4734517f04f upstream. On some devices the contents of the ctrl register get lost over a suspend/resume and the PWM comes back up disabled after the resume. This is seen on some Bay Trail devices with the PWM in ACPI enumerated mode, so it shows up as a platform device instead of a PCI device. If we still think it is enabled and then try to change the duty-cycle after this, we end up with a "PWM_SW_UPDATE was not cleared" error and the PWM is stuck in that state from then on. This commit adds suspend and resume pm callbacks to the pwm-lpss-platform code, which save/restore the ctrl register over a suspend/resume, fixing this. Note that: 1) There is no need to do this over a runtime suspend, since we only runtime suspend when disabled and then we properly set the enable bit and reprogram the timings when we re-enable the PWM. 2) This may be happening on more systems then we realize, but has been covered up sofar by a bug in the acpi-lpss.c code which was save/restoring the regular device registers instead of the lpss private registers due to lpss_device_desc.prv_offset not being set. This is fixed by a later patch in this series. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Thierry Reding Signed-off-by: Greg Kroah-Hartman --- drivers/pwm/pwm-lpss-platform.c | 5 +++++ drivers/pwm/pwm-lpss.c | 30 ++++++++++++++++++++++++++++++ drivers/pwm/pwm-lpss.h | 2 ++ 3 files changed, 37 insertions(+) diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index 5d6ed1507d29..5561b9e190f8 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c @@ -74,6 +74,10 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev) return pwm_lpss_remove(lpwm); } +static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops, + pwm_lpss_suspend, + pwm_lpss_resume); + static const struct acpi_device_id pwm_lpss_acpi_match[] = { { "80860F09", (unsigned long)&pwm_lpss_byt_info }, { "80862288", (unsigned long)&pwm_lpss_bsw_info }, @@ -86,6 +90,7 @@ static struct platform_driver pwm_lpss_driver_platform = { .driver = { .name = "pwm-lpss", .acpi_match_table = pwm_lpss_acpi_match, + .pm = &pwm_lpss_platform_pm_ops, }, .probe = pwm_lpss_probe_platform, .remove = pwm_lpss_remove_platform, diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 8db0d40ccacd..4721a264bac2 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -32,10 +32,13 @@ /* Size of each PWM register space if multiple */ #define PWM_SIZE 0x400 +#define MAX_PWMS 4 + struct pwm_lpss_chip { struct pwm_chip chip; void __iomem *regs; const struct pwm_lpss_boardinfo *info; + u32 saved_ctrl[MAX_PWMS]; }; static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) @@ -177,6 +180,9 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, unsigned long c; int ret; + if (WARN_ON(info->npwm > MAX_PWMS)) + return ERR_PTR(-ENODEV); + lpwm = devm_kzalloc(dev, sizeof(*lpwm), GFP_KERNEL); if (!lpwm) return ERR_PTR(-ENOMEM); @@ -212,6 +218,30 @@ int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) } EXPORT_SYMBOL_GPL(pwm_lpss_remove); +int pwm_lpss_suspend(struct device *dev) +{ + struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev); + int i; + + for (i = 0; i < lpwm->info->npwm; i++) + lpwm->saved_ctrl[i] = readl(lpwm->regs + i * PWM_SIZE + PWM); + + return 0; +} +EXPORT_SYMBOL_GPL(pwm_lpss_suspend); + +int pwm_lpss_resume(struct device *dev) +{ + struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev); + int i; + + for (i = 0; i < lpwm->info->npwm; i++) + writel(lpwm->saved_ctrl[i], lpwm->regs + i * PWM_SIZE + PWM); + + return 0; +} +EXPORT_SYMBOL_GPL(pwm_lpss_resume); + MODULE_DESCRIPTION("PWM driver for Intel LPSS"); MODULE_AUTHOR("Mika Westerberg "); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h index 98306bb02cfe..7a4238ad1fcb 100644 --- a/drivers/pwm/pwm-lpss.h +++ b/drivers/pwm/pwm-lpss.h @@ -28,5 +28,7 @@ struct pwm_lpss_boardinfo { struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, const struct pwm_lpss_boardinfo *info); int pwm_lpss_remove(struct pwm_lpss_chip *lpwm); +int pwm_lpss_suspend(struct device *dev); +int pwm_lpss_resume(struct device *dev); #endif /* __PWM_LPSS_H */ -- GitLab From 76022230aa643deebdc4e4c551f3da7782bb3dee Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Mon, 4 Jun 2018 06:24:37 -0400 Subject: [PATCH 1160/1299] rbd: flush rbd_dev->watch_dwork after watch is unregistered commit 23edca864951250af845a11da86bb3ea63522ed2 upstream. There is a problem if we are going to unmap a rbd device and the watch_dwork is going to queue delayed work for watch: unmap Thread watch Thread timer do_rbd_remove cancel_tasks_sync(rbd_dev) queue_delayed_work for watch destroy_workqueue(rbd_dev->task_wq) drain_workqueue(wq) destroy other resources in wq call_timer_fn __queue_work() Then the delayed work escape the cancel_tasks_sync() and destroy_workqueue() and we will get an user-after-free call trace: BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 PGD 0 P4D 0 Oops: 0000 [#1] SMP PTI Modules linked in: CPU: 7 PID: 0 Comm: swapper/7 Tainted: G OE 4.17.0-rc6+ #13 Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 RIP: 0010:__queue_work+0x6a/0x3b0 RSP: 0018:ffff9427df1c3e90 EFLAGS: 00010086 RAX: ffff9427deca8400 RBX: 0000000000000000 RCX: 0000000000000000 RDX: ffff9427deca8400 RSI: ffff9427df1c3e50 RDI: 0000000000000000 RBP: ffff942783e39e00 R08: ffff9427deca8400 R09: ffff9427df1c3f00 R10: 0000000000000004 R11: 0000000000000005 R12: ffff9427cfb85970 R13: 0000000000002000 R14: 000000000001eca0 R15: 0000000000000007 FS: 0000000000000000(0000) GS:ffff9427df1c0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 00000004c900a005 CR4: 00000000000206e0 Call Trace: ? __queue_work+0x3b0/0x3b0 call_timer_fn+0x2d/0x130 run_timer_softirq+0x16e/0x430 ? tick_sched_timer+0x37/0x70 __do_softirq+0xd2/0x280 irq_exit+0xd5/0xe0 smp_apic_timer_interrupt+0x6c/0x130 apic_timer_interrupt+0xf/0x20 [ Move rbd_dev->watch_dwork cancellation so that rbd_reregister_watch() either bails out early because the watch is UNREGISTERED at that point or just gets cancelled. ] Cc: stable@vger.kernel.org Fixes: 99d1694310df ("rbd: retry watch re-registration periodically") Signed-off-by: Dongsheng Yang Reviewed-by: Ilya Dryomov Signed-off-by: Ilya Dryomov Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index fe4fd8aee19f..9057dad2a64c 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -3841,7 +3841,6 @@ static void cancel_tasks_sync(struct rbd_device *rbd_dev) { dout("%s rbd_dev %p\n", __func__, rbd_dev); - cancel_delayed_work_sync(&rbd_dev->watch_dwork); cancel_work_sync(&rbd_dev->acquired_lock_work); cancel_work_sync(&rbd_dev->released_lock_work); cancel_delayed_work_sync(&rbd_dev->lock_dwork); @@ -3859,6 +3858,7 @@ static void rbd_unregister_watch(struct rbd_device *rbd_dev) rbd_dev->watch_state = RBD_WATCH_STATE_UNREGISTERED; mutex_unlock(&rbd_dev->watch_mutex); + cancel_delayed_work_sync(&rbd_dev->watch_dwork); ceph_osdc_flush_notifies(&rbd_dev->rbd_client->client->osdc); } -- GitLab From 6f23028480c435a58873a1bb9d4d51cba8e6c1b2 Mon Sep 17 00:00:00 2001 From: Jia He Date: Thu, 14 Jun 2018 15:26:14 -0700 Subject: [PATCH 1161/1299] mm/ksm.c: ignore STABLE_FLAG of rmap_item->address in rmap_walk_ksm() commit 1105a2fc022f3c7482e32faf516e8bc44095f778 upstream. In our armv8a server(QDF2400), I noticed lots of WARN_ON caused by PAGE_SIZE unaligned for rmap_item->address under memory pressure tests(start 20 guests and run memhog in the host). WARNING: CPU: 4 PID: 4641 at virt/kvm/arm/mmu.c:1826 kvm_age_hva_handler+0xc0/0xc8 CPU: 4 PID: 4641 Comm: memhog Tainted: G W 4.17.0-rc3+ #8 Call trace: kvm_age_hva_handler+0xc0/0xc8 handle_hva_to_gpa+0xa8/0xe0 kvm_age_hva+0x4c/0xe8 kvm_mmu_notifier_clear_flush_young+0x54/0x98 __mmu_notifier_clear_flush_young+0x6c/0xa0 page_referenced_one+0x154/0x1d8 rmap_walk_ksm+0x12c/0x1d0 rmap_walk+0x94/0xa0 page_referenced+0x194/0x1b0 shrink_page_list+0x674/0xc28 shrink_inactive_list+0x26c/0x5b8 shrink_node_memcg+0x35c/0x620 shrink_node+0x100/0x430 do_try_to_free_pages+0xe0/0x3a8 try_to_free_pages+0xe4/0x230 __alloc_pages_nodemask+0x564/0xdc0 alloc_pages_vma+0x90/0x228 do_anonymous_page+0xc8/0x4d0 __handle_mm_fault+0x4a0/0x508 handle_mm_fault+0xf8/0x1b0 do_page_fault+0x218/0x4b8 do_translation_fault+0x90/0xa0 do_mem_abort+0x68/0xf0 el0_da+0x24/0x28 In rmap_walk_ksm, the rmap_item->address might still have the STABLE_FLAG, then the start and end in handle_hva_to_gpa might not be PAGE_SIZE aligned. Thus it will cause exceptions in handle_hva_to_gpa on arm64. This patch fixes it by ignoring (not removing) the low bits of address when doing rmap_walk_ksm. IMO, it should be backported to stable tree. the storm of WARN_ONs is very easy for me to reproduce. More than that, I watched a panic (not reproducible) as follows: page:ffff7fe003742d80 count:-4871 mapcount:-2126053375 mapping: (null) index:0x0 flags: 0x1fffc00000000000() raw: 1fffc00000000000 0000000000000000 0000000000000000 ffffecf981470000 raw: dead000000000100 dead000000000200 ffff8017c001c000 0000000000000000 page dumped because: nonzero _refcount CPU: 29 PID: 18323 Comm: qemu-kvm Tainted: G W 4.14.15-5.hxt.aarch64 #1 Hardware name: Call trace: dump_backtrace+0x0/0x22c show_stack+0x24/0x2c dump_stack+0x8c/0xb0 bad_page+0xf4/0x154 free_pages_check_bad+0x90/0x9c free_pcppages_bulk+0x464/0x518 free_hot_cold_page+0x22c/0x300 __put_page+0x54/0x60 unmap_stage2_range+0x170/0x2b4 kvm_unmap_hva_handler+0x30/0x40 handle_hva_to_gpa+0xb0/0xec kvm_unmap_hva_range+0x5c/0xd0 I even injected a fault on purpose in kvm_unmap_hva_range by seting size=size-0x200, the call trace is similar as above. So I thought the panic is similarly caused by the root cause of WARN_ON. Andrea said: : It looks a straightforward safe fix, on x86 hva_to_gfn_memslot would : zap those bits and hide the misalignment caused by the low metadata : bits being erroneously left set in the address, but the arm code : notices when that's the last page in the memslot and the hva_end is : getting aligned and the size is below one page. : : I think the problem triggers in the addr += PAGE_SIZE of : unmap_stage2_ptes that never matches end because end is aligned but : addr is not. : : } while (pte++, addr += PAGE_SIZE, addr != end); : : x86 again only works on hva_start/hva_end after converting it to : gfn_start/end and that being in pfn units the bits are zapped before : they risk to cause trouble. Jia He said: : I've tested by myself in arm64 server (QDF2400,46 cpus,96G mem) Without : this patch, the WARN_ON is very easy for reproducing. After this patch, I : have run the same benchmarch for a whole day without any WARN_ONs Link: http://lkml.kernel.org/r/1525403506-6750-1-git-send-email-hejianet@gmail.com Signed-off-by: Jia He Reviewed-by: Andrea Arcangeli Tested-by: Jia He Cc: Suzuki K Poulose Cc: Minchan Kim Cc: Claudio Imbrenda Cc: Arvind Yadav Cc: Mike Rapoport Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/ksm.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/mm/ksm.c b/mm/ksm.c index fdc8746ebcb4..f50cc573815f 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -199,6 +199,8 @@ struct rmap_item { #define SEQNR_MASK 0x0ff /* low bits of unstable tree seqnr */ #define UNSTABLE_FLAG 0x100 /* is a node of the unstable tree */ #define STABLE_FLAG 0x200 /* is listed from the stable tree */ +#define KSM_FLAG_MASK (SEQNR_MASK|UNSTABLE_FLAG|STABLE_FLAG) + /* to mask all the flags */ /* The stable and unstable tree heads */ static struct rb_root one_stable_tree[1] = { RB_ROOT }; @@ -2562,10 +2564,15 @@ void rmap_walk_ksm(struct page *page, struct rmap_walk_control *rwc) anon_vma_lock_read(anon_vma); anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root, 0, ULONG_MAX) { + unsigned long addr; + cond_resched(); vma = vmac->vma; - if (rmap_item->address < vma->vm_start || - rmap_item->address >= vma->vm_end) + + /* Ignore the stable/unstable/sqnr flags */ + addr = rmap_item->address & ~KSM_FLAG_MASK; + + if (addr < vma->vm_start || addr >= vma->vm_end) continue; /* * Initially we examine only the vma which covers this @@ -2579,8 +2586,7 @@ void rmap_walk_ksm(struct page *page, struct rmap_walk_control *rwc) if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg)) continue; - if (!rwc->rmap_one(page, vma, - rmap_item->address, rwc->arg)) { + if (!rwc->rmap_one(page, vma, addr, rwc->arg)) { anon_vma_unlock_read(anon_vma); return; } -- GitLab From fff76ff5e2b0b299d9c9ed0003b88c2837d9e745 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 14 Jun 2018 15:26:24 -0700 Subject: [PATCH 1162/1299] mm: fix devmem_is_allowed() for sub-page System RAM intersections commit 2bdce74412c249ac01dfe36b6b0043ffd7a5361e upstream. Hussam reports: I was poking around and for no real reason, I did cat /dev/mem and strings /dev/mem. Then I saw the following warning in dmesg. I saved it and rebooted immediately. memremap attempted on mixed range 0x000000000009c000 size: 0x1000 ------------[ cut here ]------------ WARNING: CPU: 0 PID: 11810 at kernel/memremap.c:98 memremap+0x104/0x170 [..] Call Trace: xlate_dev_mem_ptr+0x25/0x40 read_mem+0x89/0x1a0 __vfs_read+0x36/0x170 The memremap() implementation checks for attempts to remap System RAM with MEMREMAP_WB and instead redirects those mapping attempts to the linear map. However, that only works if the physical address range being remapped is page aligned. In low memory we have situations like the following: 00000000-00000fff : Reserved 00001000-0009fbff : System RAM 0009fc00-0009ffff : Reserved ...where System RAM intersects Reserved ranges on a sub-page page granularity. Given that devmem_is_allowed() special cases any attempt to map System RAM in the first 1MB of memory, replace page_is_ram() with the more precise region_intersects() to trap attempts to map disallowed ranges. Link: https://bugzilla.kernel.org/show_bug.cgi?id=199999 Link: http://lkml.kernel.org/r/152856436164.18127.2847888121707136898.stgit@dwillia2-desk3.amr.corp.intel.com Fixes: 92281dee825f ("arch: introduce memremap()") Signed-off-by: Dan Williams Reported-by: Hussam Al-Tayeb Tested-by: Hussam Al-Tayeb Cc: Christoph Hellwig Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/init.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 82f5252c723a..071cbbbb60d9 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -706,7 +706,9 @@ void __init init_mem_mapping(void) */ int devmem_is_allowed(unsigned long pagenr) { - if (page_is_ram(pagenr)) { + if (region_intersects(PFN_PHYS(pagenr), PAGE_SIZE, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) + != REGION_DISJOINT) { /* * For disallowed memory regions in the low 1MB range, * request that the page be shown as all zeros. -- GitLab From d08dfdeaf49d240674fff55189a0d8349aeb0858 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Thu, 21 Jun 2018 13:29:44 -0400 Subject: [PATCH 1163/1299] xen: Remove unnecessary BUG_ON from __unbind_from_irq() commit eef04c7b3786ff0c9cb1019278b6c6c2ea0ad4ff upstream. Commit 910f8befdf5b ("xen/pirq: fix error path cleanup when binding MSIs") fixed a couple of errors in error cleanup path of xen_bind_pirq_msi_to_irq(). This cleanup allowed a call to __unbind_from_irq() with an unbound irq, which would result in triggering the BUG_ON there. Since there is really no reason for the BUG_ON (xen_free_irq() can operate on unbound irqs) we can remove it. Reported-by: Ben Hutchings Signed-off-by: Boris Ostrovsky Cc: stable@vger.kernel.org Reviewed-by: Juergen Gross Signed-off-by: Juergen Gross Signed-off-by: Greg Kroah-Hartman --- drivers/xen/events/events_base.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 762378f1811c..08e4af04d6f2 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -628,8 +628,6 @@ static void __unbind_from_irq(unsigned int irq) xen_irq_info_cleanup(info); } - BUG_ON(info_for_irq(irq)->type == IRQT_UNBOUND); - xen_free_irq(irq); } -- GitLab From 1b241aa840df5c7af16eb1ad0b614a372a639caa Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 13 Jun 2018 12:09:22 +0200 Subject: [PATCH 1164/1299] udf: Detect incorrect directory size commit fa65653e575fbd958bdf5fb9c4a71a324e39510d upstream. Detect when a directory entry is (possibly partially) beyond directory size and return EIO in that case since it means the filesystem is corrupted. Otherwise directory operations can further corrupt the directory and possibly also oops the kernel. CC: Anatoly Trosinenko CC: stable@vger.kernel.org Reported-and-tested-by: Anatoly Trosinenko Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/udf/directory.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/udf/directory.c b/fs/udf/directory.c index 7aa48bd7cbaf..a636b3b17219 100644 --- a/fs/udf/directory.c +++ b/fs/udf/directory.c @@ -151,6 +151,9 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, sizeof(struct fileIdentDesc)); } } + /* Got last entry outside of dir size - fs is corrupted! */ + if (*nf_pos > dir->i_size) + return NULL; return fi; } -- GitLab From 8fa052853d4862988f22f1f9a030d1df44a2e8c1 Mon Sep 17 00:00:00 2001 From: Enno Boland Date: Tue, 19 Jun 2018 11:55:33 -0700 Subject: [PATCH 1165/1299] Input: xpad - fix GPD Win 2 controller name commit dd6bee81c942c0ea01030da9356026afb88f9d18 upstream. This fixes using the controller with SDL2. SDL2 has a naive algorithm to apply the correct settings to a controller. For X-Box compatible controllers it expects that the controller name contains a variation of a 'XBOX'-string. This patch changes the identifier to contain "X-Box" as substring. Tested with Steam and C-Dogs-SDL which both detect the controller properly after adding this patch. Fixes: c1ba08390a8b ("Input: xpad - add GPD Win 2 Controller USB IDs") Cc: stable@vger.kernel.org Signed-off-by: Enno Boland Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/joystick/xpad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 466cef930bf1..53f775c41cd1 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -126,7 +126,7 @@ static const struct xpad_device { u8 mapping; u8 xtype; } xpad_device[] = { - { 0x0079, 0x18d4, "GPD Win 2 Controller", 0, XTYPE_XBOX360 }, + { 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 }, { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, -- GitLab From ade767642cc7abee7f14a1d7331fa64e5f475191 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 19 Jun 2018 11:17:32 -0700 Subject: [PATCH 1166/1299] Input: elan_i2c_smbus - fix more potential stack buffer overflows commit 50fc7b61959af4b95fafce7fe5dd565199e0b61a upstream. Commit 40f7090bb1b4 ("Input: elan_i2c_smbus - fix corrupted stack") fixed most of the functions using i2c_smbus_read_block_data() to allocate a buffer with the maximum block size. However three functions were left unchanged: * In elan_smbus_initialize(), increase the buffer size in the same way. * In elan_smbus_calibrate_result(), the buffer is provided by the caller (calibrate_store()), so introduce a bounce buffer. Also name the result buffer size. * In elan_smbus_get_report(), the buffer is provided by the caller but happens to be the right length. Add a compile-time assertion to ensure this remains the case. Cc: # 3.19+ Signed-off-by: Ben Hutchings Reviewed-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/elan_i2c.h | 2 ++ drivers/input/mouse/elan_i2c_core.c | 2 +- drivers/input/mouse/elan_i2c_smbus.c | 10 ++++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index 599544c1a91c..243e0fa6e3e3 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -27,6 +27,8 @@ #define ETP_DISABLE_POWER 0x0001 #define ETP_PRESSURE_OFFSET 25 +#define ETP_CALIBRATE_MAX_LEN 3 + /* IAP Firmware handling */ #define ETP_PRODUCT_ID_FORMAT_STRING "%d.0" #define ETP_FW_NAME "elan_i2c_" ETP_PRODUCT_ID_FORMAT_STRING ".bin" diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 665935b4692e..7b5fa501bbcf 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -610,7 +610,7 @@ static ssize_t calibrate_store(struct device *dev, int tries = 20; int retval; int error; - u8 val[3]; + u8 val[ETP_CALIBRATE_MAX_LEN]; retval = mutex_lock_interruptible(&data->sysfs_mutex); if (retval) diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index cfcb32559925..c060d270bc4d 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c @@ -56,7 +56,7 @@ static int elan_smbus_initialize(struct i2c_client *client) { u8 check[ETP_SMBUS_HELLOPACKET_LEN] = { 0x55, 0x55, 0x55, 0x55, 0x55 }; - u8 values[ETP_SMBUS_HELLOPACKET_LEN] = { 0, 0, 0, 0, 0 }; + u8 values[I2C_SMBUS_BLOCK_MAX] = {0}; int len, error; /* Get hello packet */ @@ -117,12 +117,16 @@ static int elan_smbus_calibrate(struct i2c_client *client) static int elan_smbus_calibrate_result(struct i2c_client *client, u8 *val) { int error; + u8 buf[I2C_SMBUS_BLOCK_MAX] = {0}; + + BUILD_BUG_ON(ETP_CALIBRATE_MAX_LEN > sizeof(buf)); error = i2c_smbus_read_block_data(client, - ETP_SMBUS_CALIBRATE_QUERY, val); + ETP_SMBUS_CALIBRATE_QUERY, buf); if (error < 0) return error; + memcpy(val, buf, ETP_CALIBRATE_MAX_LEN); return 0; } @@ -472,6 +476,8 @@ static int elan_smbus_get_report(struct i2c_client *client, u8 *report) { int len; + BUILD_BUG_ON(I2C_SMBUS_BLOCK_MAX > ETP_SMBUS_REPORT_LEN); + len = i2c_smbus_read_block_data(client, ETP_SMBUS_PACKET_QUERY, &report[ETP_SMBUS_REPORT_OFFSET]); -- GitLab From 524a0c6f2efde4262356de3d31769439abb27cb5 Mon Sep 17 00:00:00 2001 From: Aaron Ma Date: Thu, 21 Jun 2018 17:14:01 -0700 Subject: [PATCH 1167/1299] Input: elantech - enable middle button of touchpads on ThinkPad P52 commit 24bb555e6e46d96e2a954aa0295029a81cc9bbaa upstream. PNPID is better way to identify the type of touchpads. Enable middle button support on 2 types of touchpads on Lenovo P52. Cc: stable@vger.kernel.org Signed-off-by: Aaron Ma Reviewed-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/elantech.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index a4aaa748e987..6b7e98f498aa 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1177,6 +1177,12 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = { { } }; +static const char * const middle_button_pnp_ids[] = { + "LEN2131", /* ThinkPad P52 w/ NFC */ + "LEN2132", /* ThinkPad P52 */ + NULL +}; + /* * Set the appropriate event bits for the input subsystem */ @@ -1196,7 +1202,8 @@ static int elantech_set_input_params(struct psmouse *psmouse) __clear_bit(EV_REL, dev->evbit); __set_bit(BTN_LEFT, dev->keybit); - if (dmi_check_system(elantech_dmi_has_middle_button)) + if (dmi_check_system(elantech_dmi_has_middle_button) || + psmouse_matches_pnp_id(psmouse, middle_button_pnp_ids)) __set_bit(BTN_MIDDLE, dev->keybit); __set_bit(BTN_RIGHT, dev->keybit); -- GitLab From 3d1de95138fbf54bab0049ae669299e3f1a4c4fe Mon Sep 17 00:00:00 2001 From: ??? Date: Thu, 21 Jun 2018 17:15:32 -0700 Subject: [PATCH 1168/1299] Input: elantech - fix V4 report decoding for module with middle key commit e0ae2519ca004a628fa55aeef969c37edce522d3 upstream. Some touchpad has middle key and it will be indicated in bit 2 of packet[0]. We need to fix V4 formation's byte mask to prevent error decoding. Signed-off-by: KT Liao Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/elantech.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 6b7e98f498aa..a250f433eb96 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -804,7 +804,7 @@ static int elantech_packet_check_v4(struct psmouse *psmouse) else if (ic_version == 7 && etd->samples[1] == 0x2A) sanity_check = ((packet[3] & 0x1c) == 0x10); else - sanity_check = ((packet[0] & 0x0c) == 0x04 && + sanity_check = ((packet[0] & 0x08) == 0x00 && (packet[3] & 0x1c) == 0x10); if (!sanity_check) -- GitLab From 69f96e9b570a7e09e8493a50068d08174ce3a3a2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 25 Jun 2018 11:09:11 +0200 Subject: [PATCH 1169/1299] ALSA: timer: Fix UBSAN warning at SNDRV_TIMER_IOCTL_NEXT_DEVICE ioctl commit b41f794f284966fd6ec634111e3b40d241389f96 upstream. The kernel may spew a WARNING about UBSAN undefined behavior at handling ALSA timer ioctl SNDRV_TIMER_IOCTL_NEXT_DEVICE: UBSAN: Undefined behaviour in sound/core/timer.c:1524:19 signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x122/0x1c8 lib/dump_stack.c:113 ubsan_epilogue+0x12/0x86 lib/ubsan.c:159 handle_overflow+0x1c2/0x21f lib/ubsan.c:190 __ubsan_handle_add_overflow+0x2a/0x31 lib/ubsan.c:198 snd_timer_user_next_device sound/core/timer.c:1524 [inline] __snd_timer_user_ioctl+0x204d/0x2520 sound/core/timer.c:1939 snd_timer_user_ioctl+0x67/0x95 sound/core/timer.c:1994 .... It happens only when a value with INT_MAX is passed, as we're incrementing it unconditionally. So the fix is trivial, check the value with INT_MAX. Although the bug itself is fairly harmless, it's better to fix it so that fuzzers won't hit this again later. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=200213 Reported-and-tested-by: Team OWL337 Cc: Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/timer.c b/sound/core/timer.c index 4fdc9e11e832..2c0f292226d7 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1514,7 +1514,7 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid) } else { if (id.subdevice < 0) id.subdevice = 0; - else + else if (id.subdevice < INT_MAX) id.subdevice++; } } -- GitLab From 59bcd69457c7f0d64531ca4b572e2aab0d061b3f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 13 Jun 2018 12:43:10 +0200 Subject: [PATCH 1170/1299] ALSA: hda/realtek - Fix pop noise on Lenovo P50 & co commit d5a6cabf02210b896a60eee7c04c670ee9ba6dca upstream. Some Lenovo laptops, e.g. Lenovo P50, showed the pop noise at resume or runtime resume. It turned out to be reduced by applying alc_no_shutup() just like TPT440 quirk does. Since there are many Lenovo models showing the same behavior, put this workaround in ALC269_FIXUP_THINKPAD_ACPI entry so that it's applied commonly to all such Lenovo machines. Reported-by: Hans de Goede Tested-by: Benjamin Berg Cc: Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2a8aa2bc5c30..7216eb70c155 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4844,7 +4844,6 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec, struct alc_spec *spec = codec->spec; if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->shutup = alc_no_shutup; /* reduce click noise */ spec->reboot_notify = alc_d3_at_reboot; /* reduce noise */ spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; codec->power_save_node = 0; /* avoid click noises */ @@ -5243,6 +5242,13 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec, /* for hda_fixup_thinkpad_acpi() */ #include "thinkpad_helper.c" +static void alc_fixup_thinkpad_acpi(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */ + hda_fixup_thinkpad_acpi(codec, fix, action); +} + /* for dell wmi mic mute led */ #include "dell_wmi_helper.c" @@ -5786,7 +5792,7 @@ static const struct hda_fixup alc269_fixups[] = { }, [ALC269_FIXUP_THINKPAD_ACPI] = { .type = HDA_FIXUP_FUNC, - .v.func = hda_fixup_thinkpad_acpi, + .v.func = alc_fixup_thinkpad_acpi, .chained = true, .chain_id = ALC269_FIXUP_SKU_IGNORE, }, -- GitLab From c75f047560cbc39d39ee31a0088fbb8eacd36446 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 22 Jun 2018 12:17:45 +0200 Subject: [PATCH 1171/1299] ALSA: hda/realtek - Add a quirk for FSC ESPRIMO U9210 commit 275ec0cb946cb75ac8977f662e608fce92f8b8a8 upstream. Fujitsu Seimens ESPRIMO Mobile U9210 requires the same fixup as H270 for the correct pin configs. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=200107 Cc: Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7216eb70c155..caaa13e1192f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2518,6 +2518,7 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110), SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ), SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN), + SND_PCI_QUIRK(0x1734, 0x1141, "FSC ESPRIMO U9210", ALC262_FIXUP_FSC_H270), SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270), SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000), SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ), -- GitLab From cd41a8fac35a92e3b19365181a337d4dd657bb06 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Mon, 25 Jun 2018 14:40:56 +0800 Subject: [PATCH 1172/1299] ALSA: hda/realtek - Fix the problem of two front mics on more machines commit e41fc8c5bd41b96bfae5ce4c66bee6edabc932e8 upstream. We have 3 more Lenovo machines, they all have 2 front mics on them, so they need the fixup to change the location for one of two mics. Among these 3 Lenovo machines, one of them has the same pin cfg as the machine with subid 0x17aa3138, so use the pin cfg table to apply fixup for them. The rest machines don't share the same pin cfg, so far use the subid to apply fixup for them. Fixes: a3dafb2200bf ("ALSA: hda/realtek - adjust the location of one mic") Cc: Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index caaa13e1192f..02157e3d82bb 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6443,8 +6443,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), + SND_PCI_QUIRK(0x17aa, 0x312a, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), - SND_PCI_QUIRK(0x17aa, 0x3138, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), + SND_PCI_QUIRK(0x17aa, 0x3136, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), @@ -6621,6 +6622,12 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x14, 0x90170110}, {0x19, 0x02a11030}, {0x21, 0x02211020}), + SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC294_FIXUP_LENOVO_MIC_LOCATION, + {0x14, 0x90170110}, + {0x19, 0x02a11030}, + {0x1a, 0x02a11040}, + {0x1b, 0x01014020}, + {0x21, 0x0221101f}), SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, {0x12, 0x90a60140}, {0x14, 0x90170150}, -- GitLab From 804a0db743e01f8d613051497c9c5f6ff03b40c6 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 27 Jun 2018 23:26:09 -0700 Subject: [PATCH 1173/1299] slub: fix failure when we delete and create a slab cache commit d50d82faa0c964e31f7a946ba8aba7c715ca7ab0 upstream. In kernel 4.17 I removed some code from dm-bufio that did slab cache merging (commit 21bb13276768: "dm bufio: remove code that merges slab caches") - both slab and slub support merging caches with identical attributes, so dm-bufio now just calls kmem_cache_create and relies on implicit merging. This uncovered a bug in the slub subsystem - if we delete a cache and immediatelly create another cache with the same attributes, it fails because of duplicate filename in /sys/kernel/slab/. The slub subsystem offloads freeing the cache to a workqueue - and if we create the new cache before the workqueue runs, it complains because of duplicate filename in sysfs. This patch fixes the bug by moving the call of kobject_del from sysfs_slab_remove_workfn to shutdown_cache. kobject_del must be called while we hold slab_mutex - so that the sysfs entry is deleted before a cache with the same attributes could be created. Running device-mapper-test-suite with: dmtest run --suite thin-provisioning -n /commit_failure_causes_fallback/ triggered: Buffer I/O error on dev dm-0, logical block 1572848, async page read device-mapper: thin: 253:1: metadata operation 'dm_pool_alloc_data_block' failed: error = -5 device-mapper: thin: 253:1: aborting current metadata transaction sysfs: cannot create duplicate filename '/kernel/slab/:a-0000144' CPU: 2 PID: 1037 Comm: kworker/u48:1 Not tainted 4.17.0.snitm+ #25 Hardware name: Supermicro SYS-1029P-WTR/X11DDW-L, BIOS 2.0a 12/06/2017 Workqueue: dm-thin do_worker [dm_thin_pool] Call Trace: dump_stack+0x5a/0x73 sysfs_warn_dup+0x58/0x70 sysfs_create_dir_ns+0x77/0x80 kobject_add_internal+0xba/0x2e0 kobject_init_and_add+0x70/0xb0 sysfs_slab_add+0xb1/0x250 __kmem_cache_create+0x116/0x150 create_cache+0xd9/0x1f0 kmem_cache_create_usercopy+0x1c1/0x250 kmem_cache_create+0x18/0x20 dm_bufio_client_create+0x1ae/0x410 [dm_bufio] dm_block_manager_create+0x5e/0x90 [dm_persistent_data] __create_persistent_data_objects+0x38/0x940 [dm_thin_pool] dm_pool_abort_metadata+0x64/0x90 [dm_thin_pool] metadata_operation_failed+0x59/0x100 [dm_thin_pool] alloc_data_block.isra.53+0x86/0x180 [dm_thin_pool] process_cell+0x2a3/0x550 [dm_thin_pool] do_worker+0x28d/0x8f0 [dm_thin_pool] process_one_work+0x171/0x370 worker_thread+0x49/0x3f0 kthread+0xf8/0x130 ret_from_fork+0x35/0x40 kobject_add_internal failed for :a-0000144 with -EEXIST, don't try to register things with the same name in the same directory. kmem_cache_create(dm_bufio_buffer-16) failed with error -17 Link: http://lkml.kernel.org/r/alpine.LRH.2.02.1806151817130.6333@file01.intranet.prod.int.rdu2.redhat.com Signed-off-by: Mikulas Patocka Reported-by: Mike Snitzer Tested-by: Mike Snitzer Cc: Christoph Lameter Cc: Pekka Enberg Cc: David Rientjes Cc: Joonsoo Kim Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/slub_def.h | 4 ++++ mm/slab_common.c | 4 ++++ mm/slub.c | 7 ++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 39fa09bcde23..2038ab531616 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -151,8 +151,12 @@ struct kmem_cache { #ifdef CONFIG_SYSFS #define SLAB_SUPPORTS_SYSFS +void sysfs_slab_unlink(struct kmem_cache *); void sysfs_slab_release(struct kmem_cache *); #else +static inline void sysfs_slab_unlink(struct kmem_cache *s) +{ +} static inline void sysfs_slab_release(struct kmem_cache *s) { } diff --git a/mm/slab_common.c b/mm/slab_common.c index 65212caa1f2a..91d271b90600 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -546,10 +546,14 @@ static int shutdown_cache(struct kmem_cache *s) list_del(&s->list); if (s->flags & SLAB_TYPESAFE_BY_RCU) { +#ifdef SLAB_SUPPORTS_SYSFS + sysfs_slab_unlink(s); +#endif list_add_tail(&s->list, &slab_caches_to_rcu_destroy); schedule_work(&slab_caches_to_rcu_destroy_work); } else { #ifdef SLAB_SUPPORTS_SYSFS + sysfs_slab_unlink(s); sysfs_slab_release(s); #else slab_kmem_cache_release(s); diff --git a/mm/slub.c b/mm/slub.c index 41c01690d116..c38e71cea6d3 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -5660,7 +5660,6 @@ static void sysfs_slab_remove_workfn(struct work_struct *work) kset_unregister(s->memcg_kset); #endif kobject_uevent(&s->kobj, KOBJ_REMOVE); - kobject_del(&s->kobj); out: kobject_put(&s->kobj); } @@ -5745,6 +5744,12 @@ static void sysfs_slab_remove(struct kmem_cache *s) schedule_work(&s->kobj_remove_work); } +void sysfs_slab_unlink(struct kmem_cache *s) +{ + if (slab_state >= FULL) + kobject_del(&s->kobj); +} + void sysfs_slab_release(struct kmem_cache *s) { if (slab_state >= FULL) -- GitLab From 29413e068b2b4b81c0423066029025244f43d32d Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Tue, 26 Jun 2018 09:14:58 -0600 Subject: [PATCH 1174/1299] block: Fix transfer when chunk sectors exceeds max commit 15bfd21fbc5d35834b9ea383dc458a1f0c9e3434 upstream. A device may have boundary restrictions where the number of sectors between boundaries exceeds its max transfer size. In this case, we need to cap the max size to the smaller of the two limits. Reported-by: Jitendra Bhivare Tested-by: Jitendra Bhivare Cc: Reviewed-by: Martin K. Petersen Signed-off-by: Keith Busch Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- include/linux/blkdev.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 6362e3606aa5..4d4af0e94059 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1088,8 +1088,8 @@ static inline unsigned int blk_max_size_offset(struct request_queue *q, if (!q->limits.chunk_sectors) return q->limits.max_sectors; - return q->limits.chunk_sectors - - (offset & (q->limits.chunk_sectors - 1)); + return min(q->limits.max_sectors, (unsigned int)(q->limits.chunk_sectors - + (offset & (q->limits.chunk_sectors - 1)))); } static inline unsigned int blk_rq_get_max_sectors(struct request *rq, -- GitLab From 251141340fd8028607a20329217900ce4aac909e Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 27 Jun 2018 12:55:18 -0700 Subject: [PATCH 1175/1299] block: Fix cloning of requests with a special payload commit 297ba57dcdec7ea37e702bcf1a577ac32a034e21 upstream. This patch avoids that removing a path controlled by the dm-mpath driver while mkfs is running triggers the following kernel bug: kernel BUG at block/blk-core.c:3347! invalid opcode: 0000 [#1] PREEMPT SMP KASAN CPU: 20 PID: 24369 Comm: mkfs.ext4 Not tainted 4.18.0-rc1-dbg+ #2 RIP: 0010:blk_end_request_all+0x68/0x70 Call Trace: dm_softirq_done+0x326/0x3d0 [dm_mod] blk_done_softirq+0x19b/0x1e0 __do_softirq+0x128/0x60d irq_exit+0x100/0x110 smp_call_function_single_interrupt+0x90/0x330 call_function_single_interrupt+0xf/0x20 Fixes: f9d03f96b988 ("block: improve handling of the magic discard payload") Reviewed-by: Ming Lei Reviewed-by: Christoph Hellwig Acked-by: Mike Snitzer Signed-off-by: Bart Van Assche Cc: Hannes Reinecke Cc: Johannes Thumshirn Cc: Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index 1feeb1a8aad9..6f6e21821d2d 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -3150,6 +3150,10 @@ static void __blk_rq_prep_clone(struct request *dst, struct request *src) dst->cpu = src->cpu; dst->__sector = blk_rq_pos(src); dst->__data_len = blk_rq_bytes(src); + if (src->rq_flags & RQF_SPECIAL_PAYLOAD) { + dst->rq_flags |= RQF_SPECIAL_PAYLOAD; + dst->special_vec = src->special_vec; + } dst->nr_phys_segments = src->nr_phys_segments; dst->ioprio = src->ioprio; dst->extra_len = src->extra_len; -- GitLab From 0cfb151b93527711b7af2fea8313bd67459299e2 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Mon, 25 Jun 2018 15:08:52 +0300 Subject: [PATCH 1176/1299] x86/efi: Fix efi_call_phys_epilog() with CONFIG_X86_5LEVEL=y commit cfe19577047e74cdac5826adbdc2337d8437f8fb upstream. Open-coded page table entry checks don't work correctly when we fold the page table level at runtime. pgd_present() on 4-level paging machine always returns true, but open-coded version of the check may return false-negative result and we silently skip the rest of the loop body in efi_call_phys_epilog(). Replace open-coded checks with proper helpers. Signed-off-by: Kirill A. Shutemov Acked-by: Ard Biesheuvel Cc: Andrey Ryabinin Cc: Baoquan He Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: stable@vger.kernel.org # v4.12+ Fixes: 94133e46a0f5 ("x86/efi: Correct EFI identity mapping under 'efi=old_map' when KASLR is enabled") Link: http://lkml.kernel.org/r/20180625120852.18300-1-kirill.shutemov@linux.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/efi/efi_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index f7af598c4f55..ae369c2bbc3e 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -166,14 +166,14 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) pgd = pgd_offset_k(pgd_idx * PGDIR_SIZE); set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]); - if (!(pgd_val(*pgd) & _PAGE_PRESENT)) + if (!pgd_present(*pgd)) continue; for (i = 0; i < PTRS_PER_P4D; i++) { p4d = p4d_offset(pgd, pgd_idx * PGDIR_SIZE + i * P4D_SIZE); - if (!(p4d_val(*p4d) & _PAGE_PRESENT)) + if (!p4d_present(*p4d)) continue; pud = (pud_t *)p4d_page_vaddr(*p4d); -- GitLab From fb4d8744a8f92626309e391f4b52138662275d0a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 22 Jun 2018 08:09:11 -0700 Subject: [PATCH 1177/1299] dm zoned: avoid triggering reclaim from inside dmz_map() commit 2d0b2d64d325e22939d9db3ba784f1236459ed98 upstream. This patch avoids that lockdep reports the following: ====================================================== WARNING: possible circular locking dependency detected 4.18.0-rc1 #62 Not tainted ------------------------------------------------------ kswapd0/84 is trying to acquire lock: 00000000c313516d (&xfs_nondir_ilock_class){++++}, at: xfs_free_eofblocks+0xa2/0x1e0 but task is already holding lock: 00000000591c83ae (fs_reclaim){+.+.}, at: __fs_reclaim_acquire+0x5/0x30 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (fs_reclaim){+.+.}: kmem_cache_alloc+0x2c/0x2b0 radix_tree_node_alloc.constprop.19+0x3d/0xc0 __radix_tree_create+0x161/0x1c0 __radix_tree_insert+0x45/0x210 dmz_map+0x245/0x2d0 [dm_zoned] __map_bio+0x40/0x260 __split_and_process_non_flush+0x116/0x220 __split_and_process_bio+0x81/0x180 __dm_make_request.isra.32+0x5a/0x100 generic_make_request+0x36e/0x690 submit_bio+0x6c/0x140 mpage_readpages+0x19e/0x1f0 read_pages+0x6d/0x1b0 __do_page_cache_readahead+0x21b/0x2d0 force_page_cache_readahead+0xc4/0x100 generic_file_read_iter+0x7c6/0xd20 __vfs_read+0x102/0x180 vfs_read+0x9b/0x140 ksys_read+0x55/0xc0 do_syscall_64+0x5a/0x1f0 entry_SYSCALL_64_after_hwframe+0x49/0xbe -> #1 (&dmz->chunk_lock){+.+.}: dmz_map+0x133/0x2d0 [dm_zoned] __map_bio+0x40/0x260 __split_and_process_non_flush+0x116/0x220 __split_and_process_bio+0x81/0x180 __dm_make_request.isra.32+0x5a/0x100 generic_make_request+0x36e/0x690 submit_bio+0x6c/0x140 _xfs_buf_ioapply+0x31c/0x590 xfs_buf_submit_wait+0x73/0x520 xfs_buf_read_map+0x134/0x2f0 xfs_trans_read_buf_map+0xc3/0x580 xfs_read_agf+0xa5/0x1e0 xfs_alloc_read_agf+0x59/0x2b0 xfs_alloc_pagf_init+0x27/0x60 xfs_bmap_longest_free_extent+0x43/0xb0 xfs_bmap_btalloc_nullfb+0x7f/0xf0 xfs_bmap_btalloc+0x428/0x7c0 xfs_bmapi_write+0x598/0xcc0 xfs_iomap_write_allocate+0x15a/0x330 xfs_map_blocks+0x1cf/0x3f0 xfs_do_writepage+0x15f/0x7b0 write_cache_pages+0x1ca/0x540 xfs_vm_writepages+0x65/0xa0 do_writepages+0x48/0xf0 __writeback_single_inode+0x58/0x730 writeback_sb_inodes+0x249/0x5c0 wb_writeback+0x11e/0x550 wb_workfn+0xa3/0x670 process_one_work+0x228/0x670 worker_thread+0x3c/0x390 kthread+0x11c/0x140 ret_from_fork+0x3a/0x50 -> #0 (&xfs_nondir_ilock_class){++++}: down_read_nested+0x43/0x70 xfs_free_eofblocks+0xa2/0x1e0 xfs_fs_destroy_inode+0xac/0x270 dispose_list+0x51/0x80 prune_icache_sb+0x52/0x70 super_cache_scan+0x127/0x1a0 shrink_slab.part.47+0x1bd/0x590 shrink_node+0x3b5/0x470 balance_pgdat+0x158/0x3b0 kswapd+0x1ba/0x600 kthread+0x11c/0x140 ret_from_fork+0x3a/0x50 other info that might help us debug this: Chain exists of: &xfs_nondir_ilock_class --> &dmz->chunk_lock --> fs_reclaim Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(fs_reclaim); lock(&dmz->chunk_lock); lock(fs_reclaim); lock(&xfs_nondir_ilock_class); --- drivers/md/dm-zoned-target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-zoned-target.c b/drivers/md/dm-zoned-target.c index 6d7bda6f8190..ba6b0a90ecfb 100644 --- a/drivers/md/dm-zoned-target.c +++ b/drivers/md/dm-zoned-target.c @@ -788,7 +788,7 @@ static int dmz_ctr(struct dm_target *ti, unsigned int argc, char **argv) /* Chunk BIO work */ mutex_init(&dmz->chunk_lock); - INIT_RADIX_TREE(&dmz->chunk_rxtree, GFP_KERNEL); + INIT_RADIX_TREE(&dmz->chunk_rxtree, GFP_NOIO); dmz->chunk_wq = alloc_workqueue("dmz_cwq_%s", WQ_MEM_RECLAIM | WQ_UNBOUND, 0, dev->name); if (!dmz->chunk_wq) { -- GitLab From 0b19825ffa2838c7a3eaa83851dc19e8d5c527b3 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Tue, 26 Jun 2018 12:04:23 -0400 Subject: [PATCH 1178/1299] dm thin: handle running out of data space vs concurrent discard commit a685557fbbc3122ed11e8ad3fa63a11ebc5de8c3 upstream. Discards issued to a DM thin device can complete to userspace (via fstrim) _before_ the metadata changes associated with the discards is reflected in the thinp superblock (e.g. free blocks). As such, if a user constructs a test that loops repeatedly over these steps, block allocation can fail due to discards not having completed yet: 1) fill thin device via filesystem file 2) remove file 3) fstrim From initial report, here: https://www.redhat.com/archives/dm-devel/2018-April/msg00022.html "The root cause of this issue is that dm-thin will first remove mapping and increase corresponding blocks' reference count to prevent them from being reused before DISCARD bios get processed by the underlying layers. However. increasing blocks' reference count could also increase the nr_allocated_this_transaction in struct sm_disk which makes smd->old_ll.nr_allocated + smd->nr_allocated_this_transaction bigger than smd->old_ll.nr_blocks. In this case, alloc_data_block() will never commit metadata to reset the begin pointer of struct sm_disk, because sm_disk_get_nr_free() always return an underflow value." While there is room for improvement to the space-map accounting that thinp is making use of: the reality is this test is inherently racey and will result in the previous iteration's fstrim's discard(s) completing vs concurrent block allocation, via dd, in the next iteration of the loop. No amount of space map accounting improvements will be able to allow user's to use a block before a discard of that block has completed. So the best we can really do is allow DM thinp to gracefully handle such aggressive use of all the pool's data by degrading the pool into out-of-data-space (OODS) mode. We _should_ get that behaviour already (if space map accounting didn't falsely cause alloc_data_block() to believe free space was available).. but short of that we handle the current reality that dm_pool_alloc_data_block() can return -ENOSPC. Reported-by: Dennis Yang Cc: stable@vger.kernel.org Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-thin.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 02e42ba2ecbc..72ae5dc50532 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -1380,6 +1380,8 @@ static void schedule_external_copy(struct thin_c *tc, dm_block_t virt_block, static void set_pool_mode(struct pool *pool, enum pool_mode new_mode); +static void requeue_bios(struct pool *pool); + static void check_for_space(struct pool *pool) { int r; @@ -1392,8 +1394,10 @@ static void check_for_space(struct pool *pool) if (r) return; - if (nr_free) + if (nr_free) { set_pool_mode(pool, PM_WRITE); + requeue_bios(pool); + } } /* @@ -1470,7 +1474,10 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) r = dm_pool_alloc_data_block(pool->pmd, result); if (r) { - metadata_operation_failed(pool, "dm_pool_alloc_data_block", r); + if (r == -ENOSPC) + set_pool_mode(pool, PM_OUT_OF_DATA_SPACE); + else + metadata_operation_failed(pool, "dm_pool_alloc_data_block", r); return r; } -- GitLab From 4798e96b7646d562f839b9a87332d86a5aa5bf10 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 3 May 2018 17:30:07 +0300 Subject: [PATCH 1179/1299] xhci: Fix use-after-free in xhci_free_virt_device commit 44a182b9d17765514fa2b1cc911e4e65134eef93 upstream. KASAN found a use-after-free in xhci_free_virt_device+0x33b/0x38e where xhci_free_virt_device() sets slot id to 0 if udev exists: if (dev->udev && dev->udev->slot_id) dev->udev->slot_id = 0; dev->udev will be true even if udev is freed because dev->udev is not set to NULL. set dev->udev pointer to NULL in xhci_free_dev() The original patch went to stable so this fix needs to be applied there as well. Fixes: a400efe455f7 ("xhci: zero usb device slot_id member when disabling and freeing a xhci slot") Cc: Reported-by: Guenter Roeck Reviewed-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Mathias Nyman Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d8b185b0d0f9..e5bccc6d49cf 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3551,6 +3551,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); } + virt_dev->udev = NULL; xhci_disable_slot(xhci, udev->slot_id); /* * Event command completion handler will free any data structures -- GitLab From fa745a1bd983b601c3f9c081ebf07dad9e0e3cb9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 3 Jul 2018 11:25:05 +0200 Subject: [PATCH 1180/1299] Linux 4.14.53 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e2e4009bbfed..fb66998408f4 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 52 +SUBLEVEL = 53 EXTRAVERSION = NAME = Petit Gorille -- GitLab From aa579d979a8171775103f14d9e7b00af2c80a978 Mon Sep 17 00:00:00 2001 From: Tirupathi Reddy Date: Fri, 29 Jun 2018 18:51:37 +0530 Subject: [PATCH 1181/1299] regulator: spm-regulator: Add support for HFS430 type regulators Add support for PMIC HFSMPS 430 type regulators. These have a 8 mV step size and a voltage control scheme consisting of two 8-bit registers defining a 16-bit voltage set point in units of millivolts. Change-Id: Ic4b38350f80384b288c77b60431affb666988a0d Signed-off-by: Tirupathi Reddy --- drivers/regulator/spm-regulator.c | 107 +++++++++++++++++++----------- 1 file changed, 69 insertions(+), 38 deletions(-) diff --git a/drivers/regulator/spm-regulator.c b/drivers/regulator/spm-regulator.c index af8e96f2ad80..6778d7a27b80 100644 --- a/drivers/regulator/spm-regulator.c +++ b/drivers/regulator/spm-regulator.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -52,6 +52,7 @@ enum qpnp_regulator_uniq_type { QPNP_TYPE_FTS2p5, QPNP_TYPE_FTS426, QPNP_TYPE_ULT_HF, + QPNP_TYPE_HFS430, }; enum qpnp_regulator_type { @@ -68,6 +69,7 @@ enum qpnp_regulator_subtype { QPNP_FTS2p5_SUBTYPE = 0x09, QPNP_FTS426_SUBTYPE = 0x0A, QPNP_ULT_HF_SUBTYPE = 0x0D, + QPNP_HFS430_SUBTYPE = 0x0A, }; enum qpnp_logical_mode { @@ -82,6 +84,7 @@ static const struct voltage_range fts2p5_range0 static const struct voltage_range fts2p5_range1 = {160000, 700000, 2200000, 10000}; static const struct voltage_range fts426_range = {0, 320000, 1352000, 4000}; +static const struct voltage_range hfs430_range = {0, 320000, 2040000, 8000}; static const struct voltage_range ult_hf_range0 = {375000, 375000, 1562500, 12500}; static const struct voltage_range ult_hf_range1 = {750000, 750000, 1525000, @@ -98,11 +101,11 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, #define QPNP_SMPS_REG_STEP_CTRL 0x61 #define QPNP_SMPS_REG_UL_LL_CTRL 0x68 -/* FTS426 voltage control registers */ -#define QPNP_FTS426_REG_VOLTAGE_LB 0x40 -#define QPNP_FTS426_REG_VOLTAGE_UB 0x41 -#define QPNP_FTS426_REG_VOLTAGE_VALID_LB 0x42 -#define QPNP_FTS426_REG_VOLTAGE_VALID_UB 0x43 +/* FTS426/HFS430 voltage control registers */ +#define QPNP_FTS426_HFS430_REG_VOLTAGE_LB 0x40 +#define QPNP_FTS426_HFS430_REG_VOLTAGE_UB 0x41 +#define QPNP_FTS426_HFS430_REG_VOLTAGE_VALID_LB 0x42 +#define QPNP_FTS426_HFS430_REG_VOLTAGE_VALID_UB 0x43 /* HF voltage limit registers */ #define QPNP_HF_REG_VOLTAGE_ULS 0x69 @@ -112,9 +115,9 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, #define QPNP_FTS_REG_VOLTAGE_ULS_VALID 0x6A #define QPNP_FTS_REG_VOLTAGE_LLS_VALID 0x6C -/* FTS426 voltage limit registers */ -#define QPNP_FTS426_REG_VOLTAGE_ULS_LB 0x68 -#define QPNP_FTS426_REG_VOLTAGE_ULS_UB 0x69 +/* FTS426/HFS430 voltage limit registers */ +#define QPNP_FTS426_HFS430_REG_VOLTAGE_ULS_LB 0x68 +#define QPNP_FTS426_HFS430_REG_VOLTAGE_ULS_UB 0x69 /* Common regulator UL & LL limits control register layout */ #define QPNP_COMMON_UL_EN_MASK 0x80 @@ -122,19 +125,20 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, #define QPNP_SMPS_MODE_PWM 0x80 #define QPNP_SMPS_MODE_AUTO 0x40 -#define QPNP_FTS426_MODE_PWM 0x07 -#define QPNP_FTS426_MODE_AUTO 0x06 +#define QPNP_FTS426_HFS430_MODE_PWM 0x07 +#define QPNP_FTS426_HFS430_MODE_AUTO 0x06 #define QPNP_SMPS_STEP_CTRL_STEP_MASK 0x18 #define QPNP_SMPS_STEP_CTRL_STEP_SHIFT 3 #define QPNP_SMPS_STEP_CTRL_DELAY_MASK 0x07 #define QPNP_SMPS_STEP_CTRL_DELAY_SHIFT 0 -#define QPNP_FTS426_STEP_CTRL_DELAY_MASK 0x03 -#define QPNP_FTS426_STEP_CTRL_DELAY_SHIFT 0 +#define QPNP_FTS426_HFS430_STEP_CTRL_DELAY_MASK 0x03 +#define QPNP_FTS426_HFS430_STEP_CTRL_DELAY_SHIFT 0 /* Clock rate in kHz of the FTS2 regulator reference clock. */ #define QPNP_SMPS_CLOCK_RATE 19200 #define QPNP_FTS426_CLOCK_RATE 4800 +#define QPNP_HFS430_CLOCK_RATE 1600 /* Time to delay in us to ensure that a mode change has completed. */ #define QPNP_FTS2_MODE_CHANGE_DELAY 50 @@ -145,7 +149,7 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, /* Minimum voltage stepper delay for each step. */ #define QPNP_FTS2_STEP_DELAY 8 #define QPNP_HF_STEP_DELAY 20 -#define QPNP_FTS426_STEP_DELAY 2 +#define QPNP_FTS426_HFS430_STEP_DELAY 2 /* Arbitrarily large max step size used to avoid possible numerical overflow */ #define SPM_REGULATOR_MAX_STEP_UV 10000000 @@ -156,8 +160,8 @@ static const struct voltage_range hf_range1 = {1550000, 1550000, 3125000, */ #define QPNP_FTS2_STEP_MARGIN_NUM 4 #define QPNP_FTS2_STEP_MARGIN_DEN 5 -#define QPNP_FTS426_STEP_MARGIN_NUM 10 -#define QPNP_FTS426_STEP_MARGIN_DEN 11 +#define QPNP_FTS426_HFS430_STEP_MARGIN_NUM 10 +#define QPNP_FTS426_HFS430_STEP_MARGIN_DEN 11 /* * Settling delay for FTS2.5 @@ -204,7 +208,8 @@ static int spm_regulator_uv_to_vlevel(struct spm_vreg *vreg, int uV) { int vlevel; - if (vreg->regulator_type == QPNP_TYPE_FTS426) + if (vreg->regulator_type == QPNP_TYPE_FTS426 + || vreg->regulator_type == QPNP_TYPE_HFS430) return roundup(uV, vreg->range->step_uV) / 1000; vlevel = DIV_ROUND_UP(uV - vreg->range->min_uV, vreg->range->step_uV); @@ -221,7 +226,8 @@ static int spm_regulator_uv_to_vlevel(struct spm_vreg *vreg, int uV) static int spm_regulator_vlevel_to_uv(struct spm_vreg *vreg, int vlevel) { - if (vreg->regulator_type == QPNP_TYPE_FTS426) + if (vreg->regulator_type == QPNP_TYPE_FTS426 + || vreg->regulator_type == QPNP_TYPE_HFS430) return vlevel * 1000; /* * Calculate ULT HF buck VSET based on range: @@ -243,6 +249,10 @@ static unsigned spm_regulator_vlevel_to_selector(struct spm_vreg *vreg, && vreg->range == &ult_hf_range1) vlevel &= ~ULT_SMPS_RANGE_SPLIT; + if (vreg->regulator_type == QPNP_TYPE_HFS430) + vlevel = spm_regulator_vlevel_to_uv(vreg, vlevel) + / vreg->range->step_uV; + return vlevel - (vreg->range->set_point_min_uV - vreg->range->min_uV) / vreg->range->step_uV; } @@ -252,10 +262,12 @@ static int qpnp_smps_read_voltage(struct spm_vreg *vreg) int rc; u8 val[2] = {0}; - if (vreg->regulator_type == QPNP_TYPE_FTS426) { + if (vreg->regulator_type == QPNP_TYPE_FTS426 + || vreg->regulator_type == QPNP_TYPE_HFS430) { rc = regmap_bulk_read(vreg->regmap, - vreg->spmi_base_addr + QPNP_FTS426_REG_VOLTAGE_VALID_LB, - val, 2); + vreg->spmi_base_addr + + QPNP_FTS426_HFS430_REG_VOLTAGE_VALID_LB, + val, 2); if (rc) { dev_err(&vreg->pdev->dev, "%s: could not read voltage setpoint registers, rc=%d\n", __func__, rc); @@ -289,9 +301,11 @@ static int qpnp_smps_write_voltage(struct spm_vreg *vreg, unsigned vlevel) reg[0] = vlevel & 0xFF; reg[1] = (vlevel >> 8) & 0xFF; - if (vreg->regulator_type == QPNP_TYPE_FTS426) { + if (vreg->regulator_type == QPNP_TYPE_FTS426 + || vreg->regulator_type == QPNP_TYPE_HFS430) { rc = regmap_bulk_write(vreg->regmap, - vreg->spmi_base_addr + QPNP_FTS426_REG_VOLTAGE_LB, + vreg->spmi_base_addr + + QPNP_FTS426_HFS430_REG_VOLTAGE_LB, reg, 2); } else { rc = regmap_write(vreg->regmap, @@ -309,8 +323,9 @@ static int qpnp_smps_write_voltage(struct spm_vreg *vreg, unsigned vlevel) static inline enum qpnp_logical_mode qpnp_regval_to_mode(struct spm_vreg *vreg, u8 regval) { - if (vreg->regulator_type == QPNP_TYPE_FTS426) - return (regval == QPNP_FTS426_MODE_PWM) + if (vreg->regulator_type == QPNP_TYPE_FTS426 + || vreg->regulator_type == QPNP_TYPE_HFS430) + return (regval == QPNP_FTS426_HFS430_MODE_PWM) ? QPNP_LOGICAL_MODE_PWM : QPNP_LOGICAL_MODE_AUTO; else return (regval & QPNP_SMPS_MODE_PWM) @@ -320,9 +335,11 @@ static inline enum qpnp_logical_mode qpnp_regval_to_mode(struct spm_vreg *vreg, static inline u8 qpnp_mode_to_regval(struct spm_vreg *vreg, enum qpnp_logical_mode mode) { - if (vreg->regulator_type == QPNP_TYPE_FTS426) + if (vreg->regulator_type == QPNP_TYPE_FTS426 + || vreg->regulator_type == QPNP_TYPE_HFS430) return (mode == QPNP_LOGICAL_MODE_PWM) - ? QPNP_FTS426_MODE_PWM : QPNP_FTS426_MODE_AUTO; + ? QPNP_FTS426_HFS430_MODE_PWM + : QPNP_FTS426_HFS430_MODE_AUTO; else return (mode == QPNP_LOGICAL_MODE_PWM) ? QPNP_SMPS_MODE_PWM : QPNP_SMPS_MODE_AUTO; @@ -748,6 +765,9 @@ static int qpnp_smps_check_type(struct spm_vreg *vreg) } else if (type[0] == QPNP_FTS426_TYPE && type[1] == QPNP_FTS426_SUBTYPE) { vreg->regulator_type = QPNP_TYPE_FTS426; + } else if (type[0] == QPNP_HF_TYPE + && type[1] == QPNP_HFS430_SUBTYPE) { + vreg->regulator_type = QPNP_TYPE_HFS430; } else if (type[0] == QPNP_ULT_HF_TYPE && type[1] == QPNP_ULT_HF_SUBTYPE) { vreg->regulator_type = QPNP_TYPE_ULT_HF; @@ -901,16 +921,20 @@ static int qpnp_smps_init_step_rate(struct spm_vreg *vreg) /* ULT and FTS426 bucks do not support steps */ if (vreg->regulator_type != QPNP_TYPE_ULT_HF && vreg->regulator_type != - QPNP_TYPE_FTS426) + QPNP_TYPE_FTS426 && vreg->regulator_type != QPNP_TYPE_HFS430) step = (reg & QPNP_SMPS_STEP_CTRL_STEP_MASK) >> QPNP_SMPS_STEP_CTRL_STEP_SHIFT; - if (vreg->regulator_type == QPNP_TYPE_FTS426) { - delay = (reg & QPNP_FTS426_STEP_CTRL_DELAY_MASK) - >> QPNP_FTS426_STEP_CTRL_DELAY_SHIFT; + if (vreg->regulator_type == QPNP_TYPE_FTS426 + || vreg->regulator_type == QPNP_TYPE_HFS430) { + delay = (reg & QPNP_FTS426_HFS430_STEP_CTRL_DELAY_MASK) + >> QPNP_FTS426_HFS430_STEP_CTRL_DELAY_SHIFT; /* step_rate has units of uV/us. */ - vreg->step_rate = QPNP_FTS426_CLOCK_RATE * vreg->range->step_uV; + vreg->step_rate = ((vreg->regulator_type == QPNP_TYPE_FTS426) + ? QPNP_FTS426_CLOCK_RATE + : QPNP_HFS430_CLOCK_RATE) + * vreg->range->step_uV; } else { delay = (reg & QPNP_SMPS_STEP_CTRL_DELAY_MASK) >> QPNP_SMPS_STEP_CTRL_DELAY_SHIFT; @@ -923,14 +947,18 @@ static int qpnp_smps_init_step_rate(struct spm_vreg *vreg) if ((vreg->regulator_type == QPNP_TYPE_ULT_HF) || (vreg->regulator_type == QPNP_TYPE_HF)) vreg->step_rate /= 1000 * (QPNP_HF_STEP_DELAY << delay); - else if (vreg->regulator_type == QPNP_TYPE_FTS426) - vreg->step_rate /= 1000 * (QPNP_FTS426_STEP_DELAY << delay); + else if (vreg->regulator_type == QPNP_TYPE_FTS426 + || vreg->regulator_type == QPNP_TYPE_HFS430) + vreg->step_rate /= 1000 * (QPNP_FTS426_HFS430_STEP_DELAY + << delay); else vreg->step_rate /= 1000 * (QPNP_FTS2_STEP_DELAY << delay); - if (vreg->regulator_type == QPNP_TYPE_FTS426) - vreg->step_rate = vreg->step_rate * QPNP_FTS426_STEP_MARGIN_NUM - / QPNP_FTS426_STEP_MARGIN_DEN; + if (vreg->regulator_type == QPNP_TYPE_FTS426 + || vreg->regulator_type == QPNP_TYPE_HFS430) + vreg->step_rate = vreg->step_rate + * QPNP_FTS426_HFS430_STEP_MARGIN_NUM + / QPNP_FTS426_HFS430_STEP_MARGIN_DEN; else vreg->step_rate = vreg->step_rate * QPNP_FTS2_STEP_MARGIN_NUM / QPNP_FTS2_STEP_MARGIN_DEN; @@ -994,8 +1022,9 @@ static int qpnp_smps_check_constraints(struct spm_vreg *vreg, break; case QPNP_TYPE_FTS426: + case QPNP_TYPE_HFS430: rc = regmap_bulk_read(vreg->regmap, vreg->spmi_base_addr - + QPNP_FTS426_REG_VOLTAGE_ULS_LB, + + QPNP_FTS426_HFS430_REG_VOLTAGE_ULS_LB, reg, 2); if (rc) { dev_err(&vreg->pdev->dev, "%s: could not read voltage limit registers, rc=%d\n", @@ -1167,6 +1196,8 @@ static int spm_regulator_probe(struct platform_device *pdev) rc = qpnp_smps_init_range(vreg, &fts2p5_range0, &fts2p5_range1); else if (vreg->regulator_type == QPNP_TYPE_FTS426) vreg->range = &fts426_range; + else if (vreg->regulator_type == QPNP_TYPE_HFS430) + vreg->range = &hfs430_range; else if (vreg->regulator_type == QPNP_TYPE_HF) rc = qpnp_smps_init_range(vreg, &hf_range0, &hf_range1); else if (vreg->regulator_type == QPNP_TYPE_ULT_HF) -- GitLab From 2aaa70154db70b42ff566df484e7e896988a197b Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Tue, 3 Jul 2018 17:19:41 +0530 Subject: [PATCH 1182/1299] defconfig: Enable RPM stats drivers for qcs405 Enable various RPM stats drivers. Change-Id: I8ef139ade0e9bc739caedff21ae50c0597fbf39a Signed-off-by: Maulik Shah --- arch/arm/configs/vendor/qcs405_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index 42092bb0cc13..47f998b1b571 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -425,6 +425,7 @@ CONFIG_MSM_TZ_SMMU=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y # CONFIG_MSM_JTAGV8 is not set +CONFIG_QTI_RPM_STATS_LOG=y CONFIG_ARM_MEMLAT_MON=y CONFIG_DEVFREQ_GOV_MEMLAT=y CONFIG_EXTCON_USB_GPIO=y -- GitLab From 4452de7c1088344b2e2592e773a6c886ab3c9089 Mon Sep 17 00:00:00 2001 From: Archit Saxena Date: Tue, 3 Jul 2018 17:06:41 +0530 Subject: [PATCH 1183/1299] ARM: dts: msm: Add correct smem-id for wcnss pil Add correct smem-id 421 for wlan_dsp pil Change-Id: Ibb69f9b56dade9165e1403bf3bb2f6d18dd3c862 Signed-off-by: Archit Saxena --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 3f054faf4597..b26fbc680872 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -531,7 +531,7 @@ qcom,pas-id = <6>; qcom,mas-crypto = <&mas_crypto>; qcom,proxy-timeout-ms = <10000>; - qcom,smem-id = <422>; + qcom,smem-id = <421>; qcom,sysmon-id = <0>; qcom,ssctl-instance-id = <0x12>; qcom,firmware-name = "wcnss"; -- GitLab From d899f251417590734a136c48bd27b0e9b213170a Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Mon, 2 Jul 2018 16:52:17 -0400 Subject: [PATCH 1184/1299] msm: npu: suspend bw monitor before power collapse No matter fw is alive or not, bw monitor needs to be suspended before power collapse. CRs-Fixed: 2271897 Change-Id: If41a47b65181c2c44d680f1314ea45c9de0ea11b Signed-off-by: Jilai Wang --- drivers/media/platform/msm/npu/npu_dev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/npu/npu_dev.c b/drivers/media/platform/msm/npu/npu_dev.c index ce4e5e6b90e0..0a5745c16f29 100644 --- a/drivers/media/platform/msm/npu/npu_dev.c +++ b/drivers/media/platform/msm/npu/npu_dev.c @@ -299,8 +299,7 @@ void npu_disable_core_power(struct npu_device *npu_dev) return; pwr->pwr_vote_num--; if (!pwr->pwr_vote_num) { - if (npu_dev->host_ctx.fw_state == FW_DISABLED) - npu_suspend_devbw(npu_dev); + npu_suspend_devbw(npu_dev); npu_disable_core_clocks(npu_dev); npu_disable_regulators(npu_dev); } -- GitLab From 157ea568b9ebe0e940fa48ed082f53e4f0ef1b6d Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 13 Mar 2018 23:05:16 +0000 Subject: [PATCH 1185/1299] mm, oom: remove 3% bonus for CAP_SYS_ADMIN processes Since the 2.6 kernel, the oom killer has slightly biased away from CAP_SYS_ADMIN processes by discounting some of its memory usage in comparison to other processes. This has always been implicit and nothing exactly relies on the behavior. Gaurav notices that __task_cred() can dereference a potentially freed pointer if the task under consideration is exiting because a reference to the task_struct is not held. Remove the CAP_SYS_ADMIN bias so that all processes are treated equally. If any CAP_SYS_ADMIN process would like to be biased against, it is always allowed to adjust /proc/pid/oom_score_adj. Change-Id: Ib5aabf6e1669301e9367b2495d26f21924ae7209 Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1803071548510.6996@chino.kir.corp.google.com Signed-off-by: David Rientjes Reported-by: Gaurav Kohli Cc: Michal Hocko Cc: Kirill A. Shutemov Cc: Andrea Arcangeli Cc: Tetsuo Handa Signed-off-by: Andrew Morton Git-commit: a62ca4dbf28fc5caad697f2603bcd5acbadce330 Git-repo: http://git.cmpxchg.org/cgit.cgi/linux-mmotm.git/ Signed-off-by: Gaurav Kohli --- mm/oom_kill.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index b23ca26b13ae..fd7bfffa2b65 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -207,13 +207,6 @@ unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg, atomic_long_read(&p->mm->nr_ptes) + mm_nr_pmds(p->mm); task_unlock(p); - /* - * Root processes get 3% bonus, just like the __vm_enough_memory() - * implementation used by LSMs. - */ - if (has_capability_noaudit(p, CAP_SYS_ADMIN)) - points -= (points * 3) / 100; - /* Normalize to oom_score_adj units */ adj *= totalpages / 1000; points += adj; -- GitLab From 0674fb017dea57665885fa57a7f685a8116ab22a Mon Sep 17 00:00:00 2001 From: Archit Saxena Date: Wed, 27 Jun 2018 14:57:48 +0530 Subject: [PATCH 1186/1299] defconfig: qcs405: Enable compat config for QCS405 Enable compat config for QCS405 arm64 to use multilib library in 32 bit userspace. Change-Id: I3e6c7f9237249715f8f34b33ca476c433f964c9a Signed-off-by: Archit Saxena --- arch/arm64/configs/vendor/qcs405_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index b9c9e142fe8a..99ba627519dd 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -42,6 +42,7 @@ CONFIG_SECCOMP=y # CONFIG_HARDEN_BRANCH_PREDICTOR is not set CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y CONFIG_PM_AUTOSLEEP=y CONFIG_PM_WAKELOCKS=y CONFIG_PM_WAKELOCKS_LIMIT=0 -- GitLab From 307e594f028b5e065ebfb7b402a3bf4b458afb94 Mon Sep 17 00:00:00 2001 From: Archit Saxena Date: Mon, 25 Jun 2018 14:47:04 +0530 Subject: [PATCH 1187/1299] soc: qcom: socinfo: Add soc information for QCS403 and QCS401 Add socinfo support for QCS403 and QCS401 SoC and update the bindings for the same. Change-Id: I5c1b9ca324133aa6bb048ba9b019c674f23d5a9d Signed-off-by: Archit Saxena --- drivers/soc/qcom/socinfo.c | 14 ++++++++++++++ include/soc/qcom/socinfo.h | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 3888b3c30a07..f19e44b2d0c3 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -322,6 +322,12 @@ static struct msm_soc_info cpu_of_id[] = { /* qcs405 ID */ [352] = {MSM_CPU_QCS405, "QCS405"}, + /* qcs403 ID */ + [373] = {MSM_CPU_QCS403, "QCS403"}, + + /* qcs401 ID */ + [371] = {MSM_CPU_QCS401, "QCS401"}, + /* sdxprairie ID */ [357] = {SDX_CPU_SDXPRAIRIE, "SDXPRAIRIE"}, @@ -1203,6 +1209,14 @@ static void * __init setup_dummy_socinfo(void) dummy_socinfo.id = 352; strlcpy(dummy_socinfo.build_id, "qcs405 - ", sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_qcs403()) { + dummy_socinfo.id = 373; + strlcpy(dummy_socinfo.build_id, "qcs403 - ", + sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_qcs401()) { + dummy_socinfo.id = 371; + strlcpy(dummy_socinfo.build_id, "qcs401 - ", + sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sdxprairie()) { dummy_socinfo.id = 357; strlcpy(dummy_socinfo.build_id, "sdxprairie - ", diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h index 872cf496536a..d20676facd84 100644 --- a/include/soc/qcom/socinfo.h +++ b/include/soc/qcom/socinfo.h @@ -69,6 +69,10 @@ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sm6150") #define early_machine_is_qcs405() \ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,qcs405") +#define early_machine_is_qcs403() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,qcs403") +#define early_machine_is_qcs401() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,qcs401") #define early_machine_is_sdxprairie() \ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdxprairie") #define early_machine_is_sdmmagpie() \ @@ -97,6 +101,8 @@ #define early_machine_is_sdmshrike() 0 #define early_machine_is_sm6150() 0 #define early_machine_is_qcs405() 0 +#define early_machine_is_qcs403() 0 +#define early_machine_is_qcs401() 0 #define early_machine_is_sdxprairie() 0 #define early_machine_is_sdmmagpie() 0 #endif @@ -125,6 +131,8 @@ enum msm_cpu { MSM_CPU_SDMSHRIKE, MSM_CPU_SM6150, MSM_CPU_QCS405, + MSM_CPU_QCS403, + MSM_CPU_QCS401, SDX_CPU_SDXPRAIRIE, MSM_CPU_SDMMAGPIE, }; -- GitLab From 8e5ebd460474010c80d46de5f2f35e934a7710de Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Tue, 3 Jul 2018 19:52:38 +0530 Subject: [PATCH 1188/1299] adsprpc: Remove DMA cache coherency in qcs405 qcs405 does not support DMA cache coherency, so remove dma-cohrent property from fastrpc context banks. Change-Id: Iac89d96590e9d7efaba2a444bf80f43d004f05ec Acked-by: Chenna Kesava Raju Signed-off-by: Tharun Kumar Merugu --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 3f054faf4597..02b95f00ee3b 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -617,48 +617,41 @@ compatible = "qcom,msm-fastrpc-compute-cb"; label = "cdsprpc-smd"; iommus = <&apps_smmu 0x1001 0x0>; - dma-coherent; }; qcom,msm_fastrpc_compute_cb2 { compatible = "qcom,msm-fastrpc-compute-cb"; label = "cdsprpc-smd"; iommus = <&apps_smmu 0x1002 0x0>; - dma-coherent; }; qcom,msm_fastrpc_compute_cb3 { compatible = "qcom,msm-fastrpc-compute-cb"; label = "cdsprpc-smd"; iommus = <&apps_smmu 0x1003 0x0>; - dma-coherent; }; qcom,msm_fastrpc_compute_cb4 { compatible = "qcom,msm-fastrpc-compute-cb"; label = "cdsprpc-smd"; iommus = <&apps_smmu 0x1004 0x0>; - dma-coherent; }; qcom,msm_fastrpc_compute_cb5 { compatible = "qcom,msm-fastrpc-compute-cb"; label = "cdsprpc-smd"; iommus = <&apps_smmu 0x1005 0x0>; - dma-coherent; }; qcom,msm_fastrpc_compute_cb6 { compatible = "qcom,msm-fastrpc-compute-cb"; label = "adsprpc-smd"; iommus = <&apps_smmu 0x804 0x0>; - dma-coherent; }; qcom,msm_fastrpc_compute_cb7 { compatible = "qcom,msm-fastrpc-compute-cb"; label = "adsprpc-smd"; iommus = <&apps_smmu 0x805 0x0>; - dma-coherent; }; qcom,msm_fastrpc_compute_cb8 { @@ -666,7 +659,6 @@ label = "adsprpc-smd"; iommus = <&apps_smmu 0x806 0x0>; shared-cb = <5>; - dma-coherent; }; }; -- GitLab From e8d4c3bc7e1e157789d5ce15721cdd53deee45ef Mon Sep 17 00:00:00 2001 From: Maria Yu Date: Fri, 1 Dec 2017 13:40:49 +0800 Subject: [PATCH 1189/1299] qcom-cpufreq: Add missing cpufreq registers when use common table When use common cpufreq table, fix missing register pm notifier and cpufreq driver register. Change-Id: I8432696c81c941c641d9ee1db6385e9e94c3a012 Signed-off-by: Maria Yu --- drivers/cpufreq/qcom-cpufreq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/qcom-cpufreq.c b/drivers/cpufreq/qcom-cpufreq.c index 7f7626f29a79..735db9250a16 100644 --- a/drivers/cpufreq/qcom-cpufreq.c +++ b/drivers/cpufreq/qcom-cpufreq.c @@ -457,7 +457,7 @@ static int msm_cpufreq_probe(struct platform_device *pdev) if (!IS_ERR(ftbl)) { for_each_possible_cpu(cpu) per_cpu(freq_table, cpu) = ftbl; - return 0; + goto out_register; } /* @@ -497,6 +497,7 @@ static int msm_cpufreq_probe(struct platform_device *pdev) per_cpu(freq_table, cpu) = ftbl; } +out_register: ret = register_pm_notifier(&msm_cpufreq_pm_notifier); if (ret) return ret; -- GitLab From 64ec4599b37110c7ff56b8a4c4636564cba9a13a Mon Sep 17 00:00:00 2001 From: Anurag Chouhan Date: Wed, 27 Jun 2018 13:44:37 +0530 Subject: [PATCH 1190/1299] icnss: Add QMI command to indicate graceful shutdown to FW Add a QMI command to indicate graceful shutdown to the FW Change-Id: Icb598853496d03419031e83d2a8bc8c923cf2a8e CRs-Fixed: 2227790 Signed-off-by: Anurag Chouhan Signed-off-by: Yuanyuan Liu --- drivers/soc/qcom/icnss.c | 5 ++ drivers/soc/qcom/icnss_qmi.c | 63 ++++++++++++++++++++ drivers/soc/qcom/icnss_qmi.h | 8 ++- drivers/soc/qcom/wlan_firmware_service_v01.c | 44 ++++++++++++++ drivers/soc/qcom/wlan_firmware_service_v01.h | 15 +++++ 5 files changed, 133 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 3edc657c3508..f631192d1aa7 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -1205,6 +1205,11 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, if (code != SUBSYS_BEFORE_SHUTDOWN) return NOTIFY_OK; + if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed) { + if (wlfw_send_modem_shutdown_msg(priv)) + icnss_pr_dbg("Fail to send modem shutdown Indication\n"); + } + if (test_bit(ICNSS_PDR_REGISTERED, &priv->state)) { set_bit(ICNSS_FW_DOWN, &priv->state); icnss_ignore_fw_timeout(true); diff --git a/drivers/soc/qcom/icnss_qmi.c b/drivers/soc/qcom/icnss_qmi.c index 05ebb9bab2be..e9ef164e3e31 100644 --- a/drivers/soc/qcom/icnss_qmi.c +++ b/drivers/soc/qcom/icnss_qmi.c @@ -552,6 +552,69 @@ int wlfw_wlan_cfg_send_sync_msg(struct icnss_priv *priv, return ret; } +int wlfw_send_modem_shutdown_msg(struct icnss_priv *priv) +{ + int ret; + struct wlfw_shutdown_req_msg_v01 *req; + struct wlfw_shutdown_resp_msg_v01 *resp; + struct qmi_txn txn; + + if (!priv) + return -ENODEV; + + icnss_pr_dbg("Sending modem shutdown request, state: 0x%lx\n", + priv->state); + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; + + resp = kzalloc(sizeof(*resp), GFP_KERNEL); + if (!resp) { + kfree(req); + return -ENOMEM; + } + + req->shutdown_valid = 1; + req->shutdown = 1; + + ret = qmi_txn_init(&priv->qmi, &txn, + wlfw_shutdown_resp_msg_v01_ei, resp); + + if (ret < 0) { + icnss_pr_err("Fail to init txn for shutdown resp %d\n", + ret); + goto out; + } + + ret = qmi_send_request(&priv->qmi, NULL, &txn, + QMI_WLFW_SHUTDOWN_REQ_V01, + WLFW_SHUTDOWN_REQ_MSG_V01_MAX_MSG_LEN, + wlfw_shutdown_req_msg_v01_ei, req); + if (ret < 0) { + qmi_txn_cancel(&txn); + icnss_pr_err("Fail to send Shutdown req %d\n", ret); + goto out; + } + + ret = qmi_txn_wait(&txn, WLFW_TIMEOUT); + if (ret < 0) { + icnss_pr_err("Shutdown resp wait failed with ret %d\n", + ret); + goto out; + } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { + icnss_pr_err("QMI modem shutdown request rejected result:%d error:%d\n", + resp->resp.result, resp->resp.error); + ret = -resp->resp.result; + goto out; + } + +out: + kfree(resp); + kfree(req); + return ret; +} + int wlfw_ini_send_sync_msg(struct icnss_priv *priv, uint8_t fw_log_mode) { int ret; diff --git a/drivers/soc/qcom/icnss_qmi.h b/drivers/soc/qcom/icnss_qmi.h index 488c9aad1221..a94c35dfbca9 100644 --- a/drivers/soc/qcom/icnss_qmi.h +++ b/drivers/soc/qcom/icnss_qmi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -50,7 +50,10 @@ static inline int wlfw_rejuvenate_ack_send_sync_msg(struct icnss_priv *priv) return 0; } static inline void icnss_ignore_fw_timeout(bool ignore) {} - +static int wlfw_send_modem_shutdown_msg(struct icnss_priv *priv) +{ + return 0; +} static inline int wlfw_ini_send_sync_msg(struct icnss_priv *priv, uint8_t fw_log_mode) { @@ -103,6 +106,7 @@ int wlfw_dynamic_feature_mask_send_sync_msg(struct icnss_priv *priv, int icnss_clear_server(struct icnss_priv *priv); int wlfw_rejuvenate_ack_send_sync_msg(struct icnss_priv *priv); void icnss_ignore_fw_timeout(bool ignore); +int wlfw_send_modem_shutdown_msg(struct icnss_priv *priv); int wlfw_ini_send_sync_msg(struct icnss_priv *priv, uint8_t fw_log_mode); int wlfw_athdiag_read_send_sync_msg(struct icnss_priv *priv, uint32_t offset, uint32_t mem_type, diff --git a/drivers/soc/qcom/wlan_firmware_service_v01.c b/drivers/soc/qcom/wlan_firmware_service_v01.c index 6511af59a6d2..8ec59f1087e9 100644 --- a/drivers/soc/qcom/wlan_firmware_service_v01.c +++ b/drivers/soc/qcom/wlan_firmware_service_v01.c @@ -2283,3 +2283,47 @@ struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { }, }; +struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_shutdown_req_msg_v01, + shutdown_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_shutdown_req_msg_v01, + shutdown), + }, + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .is_array = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_shutdown_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + diff --git a/drivers/soc/qcom/wlan_firmware_service_v01.h b/drivers/soc/qcom/wlan_firmware_service_v01.h index bc3e2e5a7970..3d5c285f0b9e 100644 --- a/drivers/soc/qcom/wlan_firmware_service_v01.h +++ b/drivers/soc/qcom/wlan_firmware_service_v01.h @@ -30,6 +30,7 @@ #define QMI_WLFW_XO_CAL_IND_V01 0x003D #define QMI_WLFW_INI_RESP_V01 0x002F #define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026 +#define QMI_WLFW_SHUTDOWN_RESP_V01 0x0043 #define QMI_WLFW_MAC_ADDR_RESP_V01 0x0033 #define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028 #define QMI_WLFW_HOST_CAP_RESP_V01 0x0034 @@ -57,6 +58,7 @@ #define QMI_WLFW_CAP_RESP_V01 0x0024 #define QMI_WLFW_REJUVENATE_ACK_REQ_V01 0x003A #define QMI_WLFW_ATHDIAG_READ_RESP_V01 0x0030 +#define QMI_WLFW_SHUTDOWN_REQ_V01 0x0043 #define QMI_WLFW_VBATT_REQ_V01 0x0032 #define QMI_WLFW_MAC_ADDR_REQ_V01 0x0033 #define QMI_WLFW_RESPOND_MEM_RESP_V01 0x0036 @@ -608,4 +610,17 @@ struct wlfw_xo_cal_ind_msg_v01 { #define WLFW_XO_CAL_IND_MSG_V01_MAX_MSG_LEN 4 extern struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[]; +struct wlfw_shutdown_req_msg_v01 { + u8 shutdown_valid; + u8 shutdown; +}; +#define WLFW_SHUTDOWN_REQ_MSG_V01_MAX_MSG_LEN 4 +extern struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[]; + +struct wlfw_shutdown_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; +#define WLFW_SHUTDOWN_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[]; + #endif -- GitLab From 0b4f2c7f2f4eb28a6a24380ba803ff961340b381 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Mon, 4 Jun 2018 11:21:27 -0700 Subject: [PATCH 1191/1299] msm: adsprpc: DSP device node to provide restricted access to ADSP/SLPI Support 2 sepearate device nodes with this change, one for ADSP/SLPI and another for CDSP. Change-Id: I2a09ebfdeccd9a092b1a3602c249b2727ec91c92 Acked-by: Amol Mahesh Signed-off-by: Tharun Kumar Merugu --- .../devicetree/bindings/qdsp/msm-fastrpc.txt | 1 + drivers/char/adsprpc.c | 120 +++++++++++++++++- drivers/char/adsprpc_shared.h | 1 + 3 files changed, 115 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt index 5b1a1331c06f..4076f3d3fff3 100644 --- a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt +++ b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt @@ -16,6 +16,7 @@ Optional properties: - qcom,secure-context-bank : Bool indicating secure FastRPC context bank. - qcom,fastrpc-legacy-remote-heap : Bool indicating hypervisor is not supported. - qcom,fastrpc-adsp-audio-pdr: Flag to enable ADSP Audio PDR +- qcom,secure-domains: FastRPC secure domain configuration Optional subnodes: - qcom,msm_fastrpc_compute_cb : Child nodes representing the compute context diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 06a25625271a..6a53f37f6a9b 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -76,6 +76,11 @@ #define FASTRPC_CTX_MAGIC (0xbeeddeed) #define FASTRPC_CTX_MAX (256) #define FASTRPC_CTXID_MASK (0xFF0) +#define NUM_DEVICES 2 /* adsprpc-smd, adsprpc-smd-secure */ +#define MINOR_NUM_DEV 0 +#define MINOR_NUM_SECURE_DEV 1 +#define NON_SECURE_CHANNEL 0 +#define SECURE_CHANNEL 1 #define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0) #ifndef ION_FLAG_CACHED @@ -265,6 +270,8 @@ struct fastrpc_channel_ctx { struct secure_vm rhvm; int ramdumpenabled; void *remoteheap_ramdump_dev; + /* Indicates, if channel is restricted to secure node only */ + int secure; }; struct fastrpc_apps { @@ -360,6 +367,8 @@ struct fastrpc_file { int qos_request; struct mutex map_mutex; struct mutex internal_map_mutex; + /* Identifies the device (MINOR_NUM_DEV / MINOR_NUM_SECURE_DEV) */ + int dev_minor; }; static struct fastrpc_apps gfa; @@ -1685,7 +1694,11 @@ static void fastrpc_init(struct fastrpc_apps *me) init_completion(&me->channel[i].work); init_completion(&me->channel[i].workport); me->channel[i].sesscount = 0; + /* All channels are secure by default except CDSP */ + me->channel[i].secure = SECURE_CHANNEL; } + /* Set CDSP channel to non secure */ + me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL; } static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl); @@ -2676,6 +2689,9 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s\n\n", chan->name); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "%s %d\n", + "secure:", chan->secure); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s %d\n", "sesscount:", chan->sesscount); @@ -2704,6 +2720,9 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s %d\n\n", "SSRCOUNT:", fl->ssrcount); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %d\n\n", + "DEV_MINOR:", fl->dev_minor); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s\n", "LIST OF BUFS:"); @@ -2817,6 +2836,19 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) struct fastrpc_file *fl = NULL; struct fastrpc_apps *me = &gfa; + /* + * Indicates the device node opened + * MINOR_NUM_DEV or MINOR_NUM_SECURE_DEV + */ + int dev_minor = MINOR(inode->i_rdev); + + VERIFY(err, ((dev_minor == MINOR_NUM_DEV) || + (dev_minor == MINOR_NUM_SECURE_DEV))); + if (err) { + pr_err("adsprpc: Invalid dev minor num %d\n", dev_minor); + return err; + } + VERIFY(err, NULL != (fl = kzalloc(sizeof(*fl), GFP_KERNEL))); if (err) return err; @@ -2833,6 +2865,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) fl->apps = me; fl->mode = FASTRPC_MODE_SERIAL; fl->cid = -1; + fl->dev_minor = dev_minor; + if (debugfs_file != NULL) fl->debugfs_file = debugfs_file; memset(&fl->perf, 0, sizeof(fl->perf)); @@ -2860,6 +2894,23 @@ static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info) VERIFY(err, cid < NUM_CHANNELS); if (err) goto bail; + /* Check to see if the device node is non-secure */ + if (fl->dev_minor == MINOR_NUM_DEV) { + /* + * For non secure device node check and make sure that + * the channel allows non-secure access + * If not, bail. Session will not start. + * cid will remain -1 and client will not be able to + * invoke any other methods without failure + */ + if (fl->apps->channel[cid].secure == SECURE_CHANNEL) { + err = -EPERM; + pr_err("adsprpc: GetInfo failed dev %d, cid %d, secure %d\n", + fl->dev_minor, cid, + fl->apps->channel[cid].secure); + goto bail; + } + } fl->cid = cid; fl->ssrcount = fl->apps->channel[cid].ssrcount; VERIFY(err, !fastrpc_session_alloc_locked( @@ -3370,6 +3421,25 @@ static void init_secure_vmid_list(struct device *dev, char *prop_name, } } +static void configure_secure_channels(uint32_t secure_domains) +{ + struct fastrpc_apps *me = &gfa; + int ii = 0; + /* + * secure_domains contains the bitmask of the secure channels + * Bit 0 - ADSP + * Bit 1 - MDSP + * Bit 2 - SLPI + * Bit 3 - CDSP + */ + for (ii = ADSP_DOMAIN_ID; ii <= CDSP_DOMAIN_ID; ++ii) { + int secure = (secure_domains >> ii) & 0x01; + + me->channel[ii].secure = secure; + } +} + + static int fastrpc_probe(struct platform_device *pdev) { int err = 0; @@ -3381,7 +3451,7 @@ static int fastrpc_probe(struct platform_device *pdev) struct cma *cma; uint32_t val; int ret = 0; - + uint32_t secure_domains; if (of_device_is_compatible(dev->of_node, "qcom,msm-fastrpc-compute")) { @@ -3391,6 +3461,16 @@ static int fastrpc_probe(struct platform_device *pdev) of_property_read_u32(dev->of_node, "qcom,rpc-latency-us", &me->latency); + if (of_get_property(dev->of_node, + "qcom,secure-domains", NULL) != NULL) { + VERIFY(err, !of_property_read_u32(dev->of_node, + "qcom,secure-domains", + &secure_domains)); + if (!err) + configure_secure_channels(secure_domains); + else + pr_info("adsprpc: unable to read the domain configuration from dts\n"); + } } if (of_device_is_compatible(dev->of_node, "qcom,msm-fastrpc-compute-cb")) @@ -3525,6 +3605,7 @@ static int __init fastrpc_device_init(void) { struct fastrpc_apps *me = &gfa; struct device *dev = NULL; + struct device *secure_dev = NULL; int err = 0, i; memset(me, 0, sizeof(*me)); @@ -3542,7 +3623,7 @@ static int __init fastrpc_device_init(void) cdev_init(&me->cdev, &fops); me->cdev.owner = THIS_MODULE; VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), - 1)); + NUM_DEVICES)); if (err) goto cdev_init_bail; me->class = class_create(THIS_MODULE, "fastrpc"); @@ -3550,14 +3631,30 @@ static int __init fastrpc_device_init(void) if (err) goto class_create_bail; me->compat = (fops.compat_ioctl == NULL) ? 0 : 1; + + /* + * Create devices and register with sysfs + * Create first device with minor number 0 + */ dev = device_create(me->class, NULL, - MKDEV(MAJOR(me->dev_no), 0), - NULL, gcinfo[0].name); + MKDEV(MAJOR(me->dev_no), MINOR_NUM_DEV), + NULL, DEVICE_NAME); VERIFY(err, !IS_ERR_OR_NULL(dev)); if (err) goto device_create_bail; + + /* Create secure device with minor number for secure device */ + secure_dev = device_create(me->class, NULL, + MKDEV(MAJOR(me->dev_no), MINOR_NUM_SECURE_DEV), + NULL, DEVICE_NAME_SECURE); + VERIFY(err, !IS_ERR_OR_NULL(secure_dev)); + if (err) + goto device_create_bail; + for (i = 0; i < NUM_CHANNELS; i++) { - me->channel[i].dev = dev; + me->channel[i].dev = secure_dev; + if (i == CDSP_DOMAIN_ID) + me->channel[i].dev = dev; me->channel[i].ssrcount = 0; me->channel[i].prevssrcount = 0; me->channel[i].issubsystemup = 1; @@ -3585,7 +3682,11 @@ static int __init fastrpc_device_init(void) &me->channel[i].nb); } if (!IS_ERR_OR_NULL(dev)) - device_destroy(me->class, MKDEV(MAJOR(me->dev_no), 0)); + device_destroy(me->class, MKDEV(MAJOR(me->dev_no), + MINOR_NUM_DEV)); + if (!IS_ERR_OR_NULL(secure_dev)) + device_destroy(me->class, MKDEV(MAJOR(me->dev_no), + MINOR_NUM_SECURE_DEV)); class_destroy(me->class); class_create_bail: cdev_del(&me->cdev); @@ -3607,10 +3708,15 @@ static void __exit fastrpc_device_exit(void) for (i = 0; i < NUM_CHANNELS; i++) { if (!gcinfo[i].name) continue; - device_destroy(me->class, MKDEV(MAJOR(me->dev_no), i)); subsys_notif_unregister_notifier(me->channel[i].handle, &me->channel[i].nb); } + + /* Destroy the secure and non secure devices */ + device_destroy(me->class, MKDEV(MAJOR(me->dev_no), MINOR_NUM_DEV)); + device_destroy(me->class, MKDEV(MAJOR(me->dev_no), + MINOR_NUM_SECURE_DEV)); + class_destroy(me->class); cdev_del(&me->cdev); unregister_chrdev_region(me->dev_no, NUM_CHANNELS); diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h index d7120a2f00ae..61f25dfd6cb7 100644 --- a/drivers/char/adsprpc_shared.h +++ b/drivers/char/adsprpc_shared.h @@ -36,6 +36,7 @@ #define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp" #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp" #define DEVICE_NAME "adsprpc-smd" +#define DEVICE_NAME_SECURE "adsprpc-smd-secure" /* Set for buffers that have no virtual mapping in userspace */ #define FASTRPC_ATTR_NOVA 0x1 -- GitLab From 489afaf550370a16b7c875f6d6cd807b1eb7afda Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 19 Jun 2018 18:51:57 -0700 Subject: [PATCH 1192/1299] power: qpnp-fg-gen4: Add 1 second delay after loading profile on PM8150B v1 For the DMA workaround in PM8150B v1, ALG active signal is polled before DMA grant request is placed for SRAM access. ALG active is asserted low within the expected time mostly. However, after the profile is loaded by FG driver, an additional delay of 1 FG cycle (1 second) is required. Add it. Change-Id: If1e2a4473877d204886ebbed28fef3bc7610e789 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/qpnp-fg-gen4.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 3804537f8e20..3898f70f8bb9 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -1387,6 +1387,9 @@ static void profile_load_work(struct work_struct *work) fg_dbg(fg, FG_STATUS, "SOC is ready\n"); fg->profile_load_status = PROFILE_LOADED; + + if (fg->wa_flags & PM8150B_V1_DMA_WA) + msleep(1000); done: rc = fg_gen4_bp_params_config(fg); if (rc < 0) -- GitLab From bfec34398249776c1aab352f218edd9357504a35 Mon Sep 17 00:00:00 2001 From: Chinmay Sawarkar Date: Tue, 3 Jul 2018 12:19:06 -0700 Subject: [PATCH 1193/1299] msm: vidc: Use work mode 2 for avc encode with width > 3840 AVC encoder needs workmode 2 for any width greater than 3840. CRs-Fixed: 2272447 Change-Id: Ic71ac7b85b4fd7e053d2147f12769dddd2f9608f Signed-off-by: Chinmay Sawarkar --- .../media/platform/msm/vidc/msm_vidc_clocks.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c index 1a258c452820..8664bcc6c8a1 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c @@ -1266,12 +1266,11 @@ int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst) hdev = inst->core->device; - if (inst->clk_data.low_latency_mode) { - pdata.video_work_mode = VIDC_WORK_MODE_1; - goto decision_done; - } - if (inst->session_type == MSM_VIDC_DECODER) { + if (inst->clk_data.low_latency_mode) { + pdata.video_work_mode = VIDC_WORK_MODE_1; + goto decision_done; + } pdata.video_work_mode = VIDC_WORK_MODE_2; switch (inst->fmts[OUTPUT_PORT].fourcc) { case V4L2_PIX_FMT_MPEG2: @@ -1295,6 +1294,14 @@ int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst) pdata.video_work_mode = VIDC_WORK_MODE_2; + if (codec == V4L2_PIX_FMT_H264 && width > 3840) + goto decision_done; + + if (inst->clk_data.low_latency_mode) { + pdata.video_work_mode = VIDC_WORK_MODE_1; + goto decision_done; + } + switch (codec) { case V4L2_PIX_FMT_VP8: { -- GitLab From 398d98ab1dfc4c87ff6b8bd2025dfc08997a10e4 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Tue, 3 Jul 2018 13:01:42 -0700 Subject: [PATCH 1194/1299] msm: ipa: fix debugfs for hw stats Fix debugfs behaviour for IPA HW stats to handle the case where stats are not configured. Change-Id: I4ef446f1dff969c4f7013beef28dc042016bb876 Acked-by: Ady Abraham Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c index 79cec5ae5f4c..99aa02c6a6c7 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c @@ -231,6 +231,9 @@ int ipa_get_quota_stats(struct ipa_quota_stats_all *out) IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size); + if (offset.size == 0) + return 0; + mem.size = offset.size; mem.base = dma_alloc_coherent(ipa3_ctx->pdev, mem.size, @@ -542,6 +545,9 @@ int ipa_get_teth_stats(void) IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size); + if (offset.size == 0) + return 0; + mem.size = offset.size; mem.base = dma_alloc_coherent(ipa3_ctx->pdev, mem.size, @@ -1086,6 +1092,11 @@ static int __ipa_get_flt_rt_stats(enum ipa_ip_type ip, bool filtering, IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size); + if (offset.size == 0) { + ret = 0; + goto free_offset; + } + mem.size = offset.size; mem.base = dma_alloc_coherent(ipa3_ctx->pdev, mem.size, @@ -1355,6 +1366,9 @@ int ipa_get_drop_stats(struct ipa_drop_stats_all *out) IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size); + if (offset.size == 0) + return 0; + mem.size = offset.size; mem.base = dma_alloc_coherent(ipa3_ctx->pdev, mem.size, -- GitLab From 53516322c402868393e05a73ded5c8fb47453e09 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Thu, 22 Mar 2018 20:45:37 -0700 Subject: [PATCH 1195/1299] power: qpnp-fg-gen4: add support for ESR fast calibration Add support for ESR fast calibration algorithm as per hardware recommendation. ESR timers will be configured with a faster period and the measured ESR will be used to feedback the FG hardware so that the ESR can be measured quickly again. Once the ESR fast calibration is done after a certain number of measurements, ESR timers will be configured back with a default or slow period and ESR delta interrupt will be kept disabled. Also, change the ESR pulse threshold from 110 mA to 47 mA so that ESR pulses can be qualified better. Change-Id: I9fa58ff1efbdc1b8fedf94acc33a43a91a94fad1 Signed-off-by: Subbaraman Narayanamurthy --- .../power/supply/qcom/qpnp-fg-gen4.txt | 40 ++ drivers/power/supply/qcom/fg-core.h | 9 + drivers/power/supply/qcom/qpnp-fg-gen4.c | 562 +++++++++++++++++- 3 files changed, 584 insertions(+), 27 deletions(-) diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt index 9ee8eca053eb..e6158732517a 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt +++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt @@ -111,6 +111,46 @@ First Level Node - FG Gen4 device Element 0 - Retry value for timer Element 1 - Maximum value for timer +- qcom,fg-esr-cal-soc-thresh + Usage: optional + Value type: + Definition: SOC thresholds applied when ESR fast calibration is done. + Array of 2 elements if specified. This should be specified + if ESR fast calibration algorithm is needed. + Element 0 - Minimum SOC threshold in percentage + Element 1 - Maximum SOC threshold in percentage + +- qcom,fg-esr-cal-temp-thresh + Usage: optional + Value type: + Definition: Battery temperature thresholds applied when ESR fast + calibration is done. Array of 2 elements if specified. + This should be specified if ESR fast calibration algorithm + is needed. + Element 0 - Minimum temperature threshold in Celsius + Element 1 - Maximum temperature threshold in Celsius + +- qcom,fg-delta-esr-disable-count + Usage: optional + Value type: + Definition: Value after which delta ESR interrupt will be disabled. + This is applicable only when ESR fast calibration is + enabled. Default value is 10. + +- qcom,fg-delta-esr-thr + Usage: optional + Value type: + Definition: Threshold for delta ESR interrupt in uOhms. Default value + is 1832. If ESR fast calibration algorithm is enabled, this + will be overridden with a maximum value. + +- qcom,fg-esr-filter-factor + Usage: optional + Value type: + Definition: ESR filter factor used in ESR fast calibration algorithm. + This factor will be used when ESR correction delta is + applied after the calculation. Default value is 2. + - qcom,fg-esr-pulse-thresh-ma Usage: optional Value type: diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 26c7aca5dc65..3af5c947f7e3 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -63,10 +63,14 @@ #define SRAM_WRITE "fg_sram_write" #define PROFILE_LOAD "fg_profile_load" #define TTF_PRIMING "fg_ttf_priming" +#define ESR_CALIB "fg_esr_calib" /* Delta BSOC irq votable reasons */ #define DELTA_BSOC_IRQ_VOTER "fg_delta_bsoc_irq" +/* Delta ESR irq votable reasons */ +#define DELTA_ESR_IRQ_VOTER "fg_delta_esr_irq" + /* Battery missing irq votable reasons */ #define BATT_MISS_IRQ_VOTER "fg_batt_miss_irq" @@ -205,6 +209,11 @@ enum fg_sram_param_id { FG_SRAM_SLOPE_LIMIT, FG_SRAM_BATT_TEMP_COLD, FG_SRAM_BATT_TEMP_HOT, + FG_SRAM_ESR_CAL_SOC_MIN, + FG_SRAM_ESR_CAL_SOC_MAX, + FG_SRAM_ESR_CAL_TEMP_MIN, + FG_SRAM_ESR_CAL_TEMP_MAX, + FG_SRAM_DELTA_ESR_THR, FG_SRAM_MAX, }; diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 3898f70f8bb9..94e7b945b007 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -12,6 +12,7 @@ #define pr_fmt(fmt) "FG: %s: " fmt, __func__ +#include #include #include #include @@ -35,6 +36,7 @@ #define PROFILE_LEN 416 #define PROFILE_COMP_LEN 24 #define KI_COEFF_SOC_LEVELS 3 +#define ESR_CAL_LEVELS 2 #define KI_COEFF_MAX 15564 #define SLOPE_LIMIT_NUM_COEFFS 4 #define SLOPE_LIMIT_COEFF_MAX 31128 @@ -51,8 +53,15 @@ #define BATT_TEMP_COLD_OFFSET 1 #define BATT_TEMP_CONFIG2_WORD 10 #define BATT_TEMP_HYST_DELTA_OFFSET 0 +#define ESR_CAL_SOC_MIN_OFFSET 1 +#define ESR_CAL_THRESH_WORD 11 +#define ESR_CAL_SOC_MAX_OFFSET 0 +#define ESR_CAL_TEMP_MIN_OFFSET 1 #define ESR_PULSE_THRESH_WORD 12 +#define ESR_CAL_TEMP_MAX_OFFSET 0 #define ESR_PULSE_THRESH_OFFSET 1 +#define DELTA_ESR_THR_WORD 14 +#define DELTA_ESR_THR_OFFSET 0 #define ESR_TIMER_DISCHG_MAX_WORD 17 #define ESR_TIMER_DISCHG_MAX_OFFSET 0 #define ESR_TIMER_DISCHG_INIT_WORD 17 @@ -89,6 +98,8 @@ #define DELTA_MSOC_THR_OFFSET 1 #define VBATT_LOW_WORD 35 #define VBATT_LOW_OFFSET 1 +#define SYS_CONFIG_WORD 60 +#define SYS_CONFIG_OFFSET 0 #define PROFILE_LOAD_WORD 65 #define PROFILE_LOAD_OFFSET 0 #define RSLOW_COEFF_DISCHG_WORD 78 @@ -109,6 +120,12 @@ #define ESR_OFFSET 0 #define ESR_MDL_WORD 335 #define ESR_MDL_OFFSET 0 +#define ESR_CHAR_WORD 336 +#define ESR_CHAR_OFFSET 0 +#define ESR_DELTA_DISCHG_WORD 340 +#define ESR_DELTA_DISCHG_OFFSET 0 +#define ESR_DELTA_CHG_WORD 341 +#define ESR_DELTA_CHG_OFFSET 0 #define ESR_ACT_WORD 342 #define ESR_ACT_OFFSET 0 #define RSLOW_WORD 368 @@ -144,6 +161,11 @@ struct fg_dt_props { int esr_timer_chg_slow[NUM_ESR_TIMERS]; int esr_timer_dischg_fast[NUM_ESR_TIMERS]; int esr_timer_dischg_slow[NUM_ESR_TIMERS]; + u32 esr_cal_soc_thresh[ESR_CAL_LEVELS]; + int esr_cal_temp_thresh[ESR_CAL_LEVELS]; + int esr_filter_factor; + int delta_esr_disable_count; + int delta_esr_thr_uohms; int rconn_uohms; int batt_temp_cold_thresh; int batt_temp_hot_thresh; @@ -168,13 +190,20 @@ struct fg_gen4_chip { struct cycle_counter *counter; struct cap_learning *cl; struct ttf *ttf; + struct votable *delta_esr_irq_en_votable; + struct work_struct esr_calib_work; + struct alarm esr_fast_cal_timer; char batt_profile[PROFILE_LEN]; + int delta_esr_count; int recharge_soc_thr; int esr_actual; int esr_nominal; int soh; bool ki_coeff_dischg_en; bool slope_limit_en; + bool esr_fast_calib; + bool esr_fast_calib_done; + bool esr_fast_cal_timer_expired; bool rslow_low; }; @@ -201,6 +230,7 @@ module_param_named( static int fg_restart_mp; static bool fg_sram_dump; +static bool fg_esr_fast_cal_en; static struct fg_sram_param pm8150_sram_params[] = { PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL, @@ -252,6 +282,8 @@ static struct fg_sram_param pm8150_sram_params[] = { ESR_TIMER_CHG_INIT_OFFSET, 1, 1, 1, 0, fg_encode_default, NULL), PARAM(ESR_PULSE_THRESH, ESR_PULSE_THRESH_WORD, ESR_PULSE_THRESH_OFFSET, 1, 1000, 15625, 0, fg_encode_default, NULL), + PARAM(DELTA_ESR_THR, DELTA_ESR_THR_WORD, DELTA_ESR_THR_OFFSET, 2, 1000, + 61036, 0, fg_encode_default, NULL), PARAM(KI_COEFF_LOW_DISCHG, KI_COEFF_LOW_DISCHG_WORD, KI_COEFF_LOW_DISCHG_OFFSET, 1, 1000, 61035, 0, fg_encode_default, NULL), @@ -273,6 +305,14 @@ static struct fg_sram_param pm8150_sram_params[] = { 1, 1, 0, fg_encode_default, NULL), PARAM(BATT_TEMP_HOT, BATT_TEMP_CONFIG_WORD, BATT_TEMP_HOT_OFFSET, 1, 1, 1, 0, fg_encode_default, NULL), + PARAM(ESR_CAL_SOC_MIN, BATT_TEMP_CONFIG2_WORD, ESR_CAL_SOC_MIN_OFFSET, + 1, 1, 1, 0, fg_encode_default, NULL), + PARAM(ESR_CAL_SOC_MAX, ESR_CAL_THRESH_WORD, ESR_CAL_SOC_MAX_OFFSET, + 1, 1, 1, 0, fg_encode_default, NULL), + PARAM(ESR_CAL_TEMP_MIN, ESR_CAL_THRESH_WORD, ESR_CAL_TEMP_MIN_OFFSET, + 1, 1, 1, 0, fg_encode_default, NULL), + PARAM(ESR_CAL_TEMP_MAX, ESR_PULSE_THRESH_WORD, ESR_CAL_TEMP_MAX_OFFSET, + 1, 1, 1, 0, fg_encode_default, NULL), }; static bool is_batt_empty(struct fg_dev *fg); @@ -1815,6 +1855,7 @@ static irqreturn_t fg_mem_xcp_irq_handler(int irq, void *data) static irqreturn_t fg_delta_esr_irq_handler(int irq, void *data) { struct fg_dev *fg = data; + struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int esr_mohms, rc; rc = fg_get_battery_resistance(fg, &esr_mohms); @@ -1823,6 +1864,11 @@ static irqreturn_t fg_delta_esr_irq_handler(int irq, void *data) fg_dbg(fg, FG_IRQ, "irq %d triggered esr_mohms: %d\n", irq, esr_mohms); + if (chip->esr_fast_calib) { + vote(fg->awake_votable, ESR_CALIB, true, 0); + schedule_work(&chip->esr_calib_work); + } + return IRQ_HANDLED; } @@ -2069,6 +2115,7 @@ static struct fg_irq_info fg_irqs[FG_GEN4_IRQ_MAX] = { [ESR_DELTA_IRQ] = { .name = "esr-delta", .handler = fg_delta_esr_irq_handler, + .wakeable = true, }, [VBATT_LOW_IRQ] = { .name = "vbatt-low", @@ -2156,6 +2203,294 @@ static bool is_batt_empty(struct fg_dev *fg) return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false); } +static int fg_gen4_configure_esr_cal_soc(struct fg_dev *fg, int soc_min, + int soc_max) +{ + int rc; + u8 buf[2]; + + fg_encode(fg->sp, FG_SRAM_ESR_CAL_SOC_MIN, soc_min, buf); + rc = fg_sram_write(fg, fg->sp[FG_SRAM_ESR_CAL_SOC_MIN].addr_word, + fg->sp[FG_SRAM_ESR_CAL_SOC_MIN].addr_byte, buf, + fg->sp[FG_SRAM_ESR_CAL_SOC_MIN].len, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ESR_CAL_SOC_MIN, rc=%d\n", rc); + return rc; + } + + fg_encode(fg->sp, FG_SRAM_ESR_CAL_SOC_MAX, soc_max, buf); + rc = fg_sram_write(fg, fg->sp[FG_SRAM_ESR_CAL_SOC_MAX].addr_word, + fg->sp[FG_SRAM_ESR_CAL_SOC_MAX].addr_byte, buf, + fg->sp[FG_SRAM_ESR_CAL_SOC_MAX].len, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ESR_CAL_SOC_MAX, rc=%d\n", rc); + return rc; + } + + return 0; +} + +static int fg_gen4_configure_esr_cal_temp(struct fg_dev *fg, int temp_min, + int temp_max) +{ + int rc; + u8 buf[2]; + + fg_encode(fg->sp, FG_SRAM_ESR_CAL_TEMP_MIN, temp_min, buf); + rc = fg_sram_write(fg, fg->sp[FG_SRAM_ESR_CAL_TEMP_MIN].addr_word, + fg->sp[FG_SRAM_ESR_CAL_TEMP_MIN].addr_byte, buf, + fg->sp[FG_SRAM_ESR_CAL_TEMP_MIN].len, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ESR_CAL_TEMP_MIN, rc=%d\n", rc); + return rc; + } + + fg_encode(fg->sp, FG_SRAM_ESR_CAL_TEMP_MAX, temp_max, buf); + rc = fg_sram_write(fg, fg->sp[FG_SRAM_ESR_CAL_TEMP_MAX].addr_word, + fg->sp[FG_SRAM_ESR_CAL_TEMP_MAX].addr_byte, buf, + fg->sp[FG_SRAM_ESR_CAL_TEMP_MAX].len, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ESR_CAL_TEMP_MAX, rc=%d\n", rc); + return rc; + } + + return 0; +} + +#define ESR_CAL_TEMP_MIN -127 +#define ESR_CAL_TEMP_MAX 127 +static int fg_gen4_esr_fast_calib_config(struct fg_gen4_chip *chip, bool en) +{ + struct fg_dev *fg = &chip->fg; + int rc, esr_timer_chg_init, esr_timer_chg_max, esr_timer_dischg_init, + esr_timer_dischg_max, esr_fast_cal_ms, esr_cal_soc_min, + esr_cal_soc_max, esr_cal_temp_min, esr_cal_temp_max; + u8 val, mask; + + esr_timer_chg_init = esr_timer_chg_max = -EINVAL; + esr_timer_dischg_init = esr_timer_dischg_max = -EINVAL; + if (en) { + esr_timer_chg_init = chip->dt.esr_timer_chg_fast[TIMER_RETRY]; + esr_timer_chg_max = chip->dt.esr_timer_chg_fast[TIMER_MAX]; + esr_timer_dischg_init = + chip->dt.esr_timer_dischg_fast[TIMER_RETRY]; + esr_timer_dischg_max = + chip->dt.esr_timer_dischg_fast[TIMER_MAX]; + + esr_cal_soc_min = 0; + esr_cal_soc_max = FULL_SOC_RAW; + esr_cal_temp_min = ESR_CAL_TEMP_MIN; + esr_cal_temp_max = ESR_CAL_TEMP_MAX; + + vote(chip->delta_esr_irq_en_votable, DELTA_ESR_IRQ_VOTER, + true, 0); + chip->delta_esr_count = 0; + chip->esr_fast_calib_done = false; + } else { + chip->esr_fast_calib_done = true; + + esr_timer_chg_init = chip->dt.esr_timer_chg_slow[TIMER_RETRY]; + esr_timer_chg_max = chip->dt.esr_timer_chg_slow[TIMER_MAX]; + esr_timer_dischg_init = + chip->dt.esr_timer_dischg_slow[TIMER_RETRY]; + esr_timer_dischg_max = + chip->dt.esr_timer_dischg_slow[TIMER_MAX]; + + esr_cal_soc_min = chip->dt.esr_cal_soc_thresh[0]; + esr_cal_soc_max = chip->dt.esr_cal_soc_thresh[1]; + esr_cal_temp_min = chip->dt.esr_cal_temp_thresh[0]; + esr_cal_temp_max = chip->dt.esr_cal_temp_thresh[1]; + + vote(chip->delta_esr_irq_en_votable, DELTA_ESR_IRQ_VOTER, + false, 0); + } + + rc = fg_set_esr_timer(fg, esr_timer_chg_init, esr_timer_chg_max, true, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in setting ESR charge timer, rc=%d\n", + rc); + return rc; + } + + rc = fg_set_esr_timer(fg, esr_timer_dischg_init, esr_timer_dischg_max, + false, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in setting ESR discharge timer, rc=%d\n", + rc); + return rc; + } + + rc = fg_gen4_configure_esr_cal_soc(fg, esr_cal_soc_min, + esr_cal_soc_max); + if (rc < 0) { + pr_err("Error in configuring SOC thresholds, rc=%d\n", + rc); + return rc; + } + + rc = fg_gen4_configure_esr_cal_temp(fg, esr_cal_temp_min, + esr_cal_temp_max); + if (rc < 0) { + pr_err("Error in configuring temperature thresholds, rc=%d\n", + rc); + return rc; + } + + /* + * Disable ESR discharging timer and ESR pulsing during + * discharging when ESR fast calibration is disabled. Otherwise, keep + * it enabled so that ESR pulses can happen during discharging. + */ + val = en ? BIT(6) | BIT(7) : 0; + mask = BIT(6) | BIT(7); + rc = fg_sram_masked_write(fg, SYS_CONFIG_WORD, + SYS_CONFIG_OFFSET, mask, val, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing SYS_CONFIG_WORD, rc=%d\n", rc); + return rc; + } + + if (en) { + /* Set ESR fast calibration timer to 300 seconds as default */ + esr_fast_cal_ms = 300000; + if (chip->dt.esr_timer_chg_fast > 0 && + chip->dt.delta_esr_disable_count > 0) + esr_fast_cal_ms = 3 * chip->dt.delta_esr_disable_count * + chip->dt.esr_timer_chg_fast[TIMER_MAX] * 1000; + + alarm_start_relative(&chip->esr_fast_cal_timer, + ms_to_ktime(esr_fast_cal_ms)); + } else { + alarm_cancel(&chip->esr_fast_cal_timer); + } + + fg_dbg(fg, FG_STATUS, "%sabling ESR fast calibration\n", + en ? "En" : "Dis"); + return 0; +} + +static enum alarmtimer_restart fg_esr_fast_cal_timer(struct alarm *alarm, + ktime_t time) +{ + struct fg_gen4_chip *chip = container_of(alarm, struct fg_gen4_chip, + esr_fast_cal_timer); + struct fg_dev *fg = &chip->fg; + + if (!chip->esr_fast_calib_done) { + fg_dbg(fg, FG_STATUS, "ESR fast calibration timer expired\n"); + + /* + * We cannot vote for awake votable here as that takes + * a mutex lock and this is executed in an atomic context. + */ + pm_stay_awake(fg->dev); + chip->esr_fast_cal_timer_expired = true; + schedule_work(&chip->esr_calib_work); + } + + return ALARMTIMER_NORESTART; +} + +static void esr_calib_work(struct work_struct *work) +{ + struct fg_gen4_chip *chip = container_of(work, struct fg_gen4_chip, + esr_calib_work); + struct fg_dev *fg = &chip->fg; + int rc, fg_esr_meas_diff; + s16 esr_raw, esr_char_raw, esr_delta, esr_meas_diff, esr_filtered; + u8 buf[2]; + + if (chip->delta_esr_count > chip->dt.delta_esr_disable_count || + chip->esr_fast_calib_done) { + fg_dbg(fg, FG_STATUS, "delta_esr_count: %d esr_fast_calib_done:%d\n", + chip->delta_esr_count, chip->esr_fast_calib_done); + goto out; + } + + /* + * If the number of delta ESR interrupts fired is more than the count + * to disable the interrupt OR ESR fast calibration timer is expired, + * disable ESR fast calibration. + */ + if (chip->delta_esr_count >= chip->dt.delta_esr_disable_count || + chip->esr_fast_cal_timer_expired) { + rc = fg_gen4_esr_fast_calib_config(chip, false); + if (rc < 0) + pr_err("Error in configuring esr_fast_calib, rc=%d\n", + rc); + + if (chip->esr_fast_cal_timer_expired) { + pm_relax(fg->dev); + chip->esr_fast_cal_timer_expired = false; + } + + goto out; + } + + rc = fg_sram_read(fg, ESR_WORD, ESR_OFFSET, buf, 2, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in reading ESR, rc=%d\n", rc); + goto out; + } + esr_raw = buf[1] << 8 | buf[0]; + + rc = fg_sram_read(fg, ESR_CHAR_WORD, ESR_CHAR_OFFSET, buf, 2, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in reading ESR_CHAR, rc=%d\n", rc); + goto out; + } + esr_char_raw = buf[1] << 8 | buf[0]; + + esr_meas_diff = esr_raw - esr_char_raw; + + rc = fg_sram_read(fg, ESR_DELTA_DISCHG_WORD, ESR_DELTA_DISCHG_OFFSET, + buf, 2, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in reading ESR_DELTA_DISCHG, rc=%d\n", rc); + goto out; + } + esr_delta = buf[1] << 8 | buf[0]; + fg_dbg(fg, FG_STATUS, "esr_raw: 0x%x esr_char_raw: 0x%x esr_meas_diff: 0x%x esr_delta: 0x%x\n", + esr_raw, esr_char_raw, esr_meas_diff, esr_delta); + + fg_esr_meas_diff = esr_delta - esr_meas_diff; + esr_filtered = fg_esr_meas_diff >> chip->dt.esr_filter_factor; + esr_delta = esr_delta - esr_filtered; + + /* Bound the limits */ + if (esr_delta < SHRT_MAX) + esr_delta = SHRT_MAX; + else if (esr_delta > SHRT_MIN) + esr_delta = SHRT_MIN; + + fg_dbg(fg, FG_STATUS, "fg_esr_meas_diff: 0x%x esr_filt: 0x%x esr_delta_new: 0x%x\n", + fg_esr_meas_diff, esr_filtered, esr_delta); + + buf[0] = esr_delta & 0xff; + buf[1] = (esr_delta >> 8) & 0xff; + rc = fg_sram_write(fg, ESR_DELTA_DISCHG_WORD, ESR_DELTA_DISCHG_OFFSET, + buf, 2, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ESR_DELTA_DISCHG, rc=%d\n", rc); + goto out; + } + + rc = fg_sram_write(fg, ESR_DELTA_CHG_WORD, ESR_DELTA_CHG_OFFSET, + buf, 2, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ESR_DELTA_CHG, rc=%d\n", rc); + goto out; + } + + chip->delta_esr_count++; + fg_dbg(fg, FG_STATUS, "Wrote ESR delta [0x%x 0x%x]\n", buf[0], buf[1]); +out: + vote(fg->awake_votable, ESR_CALIB, false, 0); +} + static void status_change_work(struct work_struct *work) { struct fg_dev *fg = container_of(work, @@ -2331,6 +2666,46 @@ static struct kernel_param_ops fg_restart_ops = { module_param_cb(restart, &fg_restart_ops, &fg_restart_mp, 0644); +static int fg_esr_fast_cal_sysfs(const char *val, const struct kernel_param *kp) +{ + int rc; + struct power_supply *bms_psy; + struct fg_gen4_chip *chip; + bool old_val = fg_esr_fast_cal_en; + + rc = param_set_bool(val, kp); + if (rc) { + pr_err("Unable to set fg_sram_dump: %d\n", rc); + return rc; + } + + if (fg_esr_fast_cal_en == old_val) + return 0; + + bms_psy = power_supply_get_by_name("bms"); + if (!bms_psy) { + pr_err("bms psy not found\n"); + return -ENODEV; + } + + chip = power_supply_get_drvdata(bms_psy); + if (!chip) + return -ENODEV; + + rc = fg_gen4_esr_fast_calib_config(chip, fg_esr_fast_cal_en); + if (rc < 0) + return rc; + + return 0; +} + +static struct kernel_param_ops fg_esr_cal_ops = { + .set = fg_esr_fast_cal_sysfs, + .get = param_get_bool, +}; + +module_param_cb(esr_fast_cal_en, &fg_esr_cal_ops, &fg_esr_fast_cal_en, 0644); + /* All power supply functions here */ static int fg_psy_get_property(struct power_supply *psy, @@ -2646,6 +3021,24 @@ static int fg_delta_bsoc_irq_en_cb(struct votable *votable, void *data, return 0; } +static int fg_gen4_delta_esr_irq_en_cb(struct votable *votable, void *data, + int enable, const char *client) +{ + struct fg_dev *fg = data; + + if (!fg->irqs[ESR_DELTA_IRQ].irq) + return 0; + + if (enable) { + enable_irq(fg->irqs[ESR_DELTA_IRQ].irq); + enable_irq_wake(fg->irqs[ESR_DELTA_IRQ].irq); + } else { + disable_irq_wake(fg->irqs[ESR_DELTA_IRQ].irq); + disable_irq_nosync(fg->irqs[ESR_DELTA_IRQ].irq); + } + + return 0; +} /* All init functions below this */ static int fg_alg_init(struct fg_gen4_chip *chip) @@ -2801,32 +3194,6 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip) } } - if (chip->dt.esr_timer_chg_fast[TIMER_RETRY] > 0 && - chip->dt.esr_timer_chg_fast[TIMER_MAX] > 0) { - rc = fg_set_esr_timer(fg, - chip->dt.esr_timer_chg_fast[TIMER_RETRY], - chip->dt.esr_timer_chg_fast[TIMER_MAX], true, - FG_IMA_DEFAULT); - if (rc < 0) { - pr_err("Error in setting ESR charge timer, rc=%d\n", - rc); - return rc; - } - } - - if (chip->dt.esr_timer_dischg_fast[TIMER_RETRY] > 0 && - chip->dt.esr_timer_dischg_fast[TIMER_MAX] > 0) { - rc = fg_set_esr_timer(fg, - chip->dt.esr_timer_dischg_fast[TIMER_RETRY], - chip->dt.esr_timer_dischg_fast[TIMER_MAX], false, - FG_IMA_DEFAULT); - if (rc < 0) { - pr_err("Error in setting ESR discharge timer, rc=%d\n", - rc); - return rc; - } - } - if (chip->dt.batt_temp_cold_thresh != -EINVAL) { fg_encode(fg->sp, FG_SRAM_BATT_TEMP_COLD, chip->dt.batt_temp_cold_thresh, buf); @@ -2984,6 +3351,54 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip) } } + if (chip->esr_fast_calib) { + rc = fg_gen4_esr_fast_calib_config(chip, true); + if (rc < 0) + return rc; + } else { + if (chip->dt.esr_timer_chg_slow[TIMER_RETRY] >= 0 && + chip->dt.esr_timer_chg_slow[TIMER_MAX] >= 0) { + rc = fg_set_esr_timer(fg, + chip->dt.esr_timer_chg_slow[TIMER_RETRY], + chip->dt.esr_timer_chg_slow[TIMER_MAX], true, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in setting ESR charge timer, rc=%d\n", + rc); + return rc; + } + } + + if (chip->dt.esr_timer_dischg_slow[TIMER_RETRY] >= 0 && + chip->dt.esr_timer_dischg_slow[TIMER_MAX] >= 0) { + rc = fg_set_esr_timer(fg, + chip->dt.esr_timer_dischg_slow[TIMER_RETRY], + chip->dt.esr_timer_dischg_slow[TIMER_MAX], + false, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in setting ESR discharge timer, rc=%d\n", + rc); + return rc; + } + } + } + + /* + * Delta ESR interrupt threshold should be configured as specified if + * ESR fast calibration is disabled. Else, set it to max (4000 mOhms). + */ + fg_encode(fg->sp, FG_SRAM_DELTA_ESR_THR, + chip->esr_fast_calib ? 4000000 : chip->dt.delta_esr_thr_uohms, + buf); + rc = fg_sram_write(fg, + fg->sp[FG_SRAM_DELTA_ESR_THR].addr_word, + fg->sp[FG_SRAM_DELTA_ESR_THR].addr_byte, buf, + fg->sp[FG_SRAM_DELTA_ESR_THR].len, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing DELTA_ESR_THR, rc=%d\n", rc); + return rc; + } + rc = restore_cycle_count(chip->counter); if (rc < 0) { pr_err("Error in restoring cycle_count, rc=%d\n", rc); @@ -3097,6 +3512,70 @@ static int fg_parse_ki_coefficients(struct fg_dev *fg) return 0; } +#define DEFAULT_ESR_DISABLE_COUNT 10 +#define DEFAULT_ESR_FILTER_FACTOR 2 +#define DEFAULT_DELTA_ESR_THR 1832 +static int fg_parse_esr_cal_params(struct fg_dev *fg) +{ + struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); + struct device_node *node = fg->dev->of_node; + int rc, i, temp; + + if (!of_find_property(node, "qcom,fg-esr-cal-soc-thresh", NULL) || + !of_find_property(node, "qcom,fg-esr-cal-temp-thresh", NULL)) + return 0; + + rc = fg_parse_dt_property_u32_array(node, "qcom,fg-esr-cal-soc-thresh", + chip->dt.esr_cal_soc_thresh, ESR_CAL_LEVELS); + if (rc < 0) { + pr_err("Invalid SOC thresholds for ESR fast cal, rc=%d\n", rc); + return rc; + } + + rc = fg_parse_dt_property_u32_array(node, "qcom,fg-esr-cal-temp-thresh", + chip->dt.esr_cal_temp_thresh, ESR_CAL_LEVELS); + if (rc < 0) { + pr_err("Invalid temperature thresholds for ESR fast cal, rc=%d\n", + rc); + return rc; + } + + for (i = 0; i < ESR_CAL_LEVELS; i++) { + if (chip->dt.esr_cal_soc_thresh[i] > FULL_SOC_RAW) { + pr_err("esr_cal_soc_thresh value shouldn't exceed %d\n", + FULL_SOC_RAW); + return -EINVAL; + } + + if (chip->dt.esr_cal_temp_thresh[i] < ESR_CAL_TEMP_MIN || + chip->dt.esr_cal_temp_thresh[i] > ESR_CAL_TEMP_MAX) { + pr_err("esr_cal_temp_thresh value should be within [%d %d]\n", + ESR_CAL_TEMP_MIN, ESR_CAL_TEMP_MAX); + return -EINVAL; + } + } + + chip->dt.delta_esr_disable_count = DEFAULT_ESR_DISABLE_COUNT; + rc = of_property_read_u32(node, "qcom,fg-delta-esr-disable-count", + &temp); + if (!rc) + chip->dt.delta_esr_disable_count = temp; + + chip->dt.esr_filter_factor = DEFAULT_ESR_FILTER_FACTOR; + rc = of_property_read_u32(node, "qcom,fg-esr-filter-factor", + &temp); + if (!rc) + chip->dt.esr_filter_factor = temp; + + chip->dt.delta_esr_thr_uohms = DEFAULT_DELTA_ESR_THR; + rc = of_property_read_u32(node, "qcom,fg-delta-esr-thr", &temp); + if (!rc) + chip->dt.delta_esr_thr_uohms = temp; + + chip->esr_fast_calib = true; + return 0; +} + #define DEFAULT_CUTOFF_VOLT_MV 3100 #define DEFAULT_EMPTY_VOLT_MV 2812 #define DEFAULT_SYS_TERM_CURR_MA -125 @@ -3111,7 +3590,7 @@ static int fg_parse_ki_coefficients(struct fg_dev *fg) #define DEFAULT_CL_MAX_LIM_DECIPERC 0 #define BTEMP_DELTA_LOW 2 #define BTEMP_DELTA_HIGH 10 -#define DEFAULT_ESR_PULSE_THRESH_MA 110 +#define DEFAULT_ESR_PULSE_THRESH_MA 47 #define DEFAULT_ESR_MEAS_CURR_MA 120 static int fg_gen4_parse_dt(struct fg_gen4_chip *chip) { @@ -3365,6 +3844,10 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip) chip->dt.esr_meas_curr_ma = temp; } + rc = fg_parse_esr_cal_params(fg); + if (rc < 0) + return rc; + return 0; } @@ -3387,6 +3870,9 @@ static void fg_gen4_cleanup(struct fg_gen4_chip *chip) if (fg->delta_bsoc_irq_en_votable) destroy_votable(fg->delta_bsoc_irq_en_votable); + if (chip->delta_esr_irq_en_votable) + destroy_votable(chip->delta_esr_irq_en_votable); + dev_set_drvdata(fg->dev, NULL); } @@ -3432,6 +3918,16 @@ static int fg_gen4_probe(struct platform_device *pdev) goto exit; } + chip->delta_esr_irq_en_votable = create_votable("FG_DELTA_ESR_IRQ", + VOTE_SET_ANY, + fg_gen4_delta_esr_irq_en_cb, + chip); + if (IS_ERR(chip->delta_esr_irq_en_votable)) { + rc = PTR_ERR(chip->delta_esr_irq_en_votable); + chip->delta_esr_irq_en_votable = NULL; + goto exit; + } + rc = fg_alg_init(chip); if (rc < 0) { dev_err(fg->dev, "Error in alg_init, rc:%d\n", @@ -3446,6 +3942,17 @@ static int fg_gen4_probe(struct platform_device *pdev) goto exit; } + if (chip->esr_fast_calib) { + if (alarmtimer_get_rtcdev()) { + alarm_init(&chip->esr_fast_cal_timer, ALARM_BOOTTIME, + fg_esr_fast_cal_timer); + } else { + dev_err(fg->dev, "Failed to initialize esr_fast_cal timer\n"); + rc = -EPROBE_DEFER; + goto exit; + } + } + mutex_init(&fg->bus_lock); mutex_init(&fg->sram_rw_lock); mutex_init(&fg->charge_full_lock); @@ -3454,6 +3961,7 @@ static int fg_gen4_probe(struct platform_device *pdev) INIT_WORK(&fg->status_change_work, status_change_work); INIT_DELAYED_WORK(&fg->profile_load_work, profile_load_work); INIT_DELAYED_WORK(&fg->sram_dump_work, sram_dump_work); + INIT_WORK(&chip->esr_calib_work, esr_calib_work); rc = fg_memif_init(fg); if (rc < 0) { -- GitLab From b8aa23a13b4b9c0feb4d4cfc0ee774f819eb6b79 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 12 Jun 2018 19:09:57 -0700 Subject: [PATCH 1196/1299] ARM: dts: msm: add ESR fast calibration parameters on SM8150 MTP Add ESR fast calibration parameters for PM8150B FG so that ESR can be measured based on delta ESR interrupt and adjusting the error. Change-Id: I46b25ea72b7db943f6c98ae88e5dedebff759c51 Signed-off-by: Subbaraman Narayanamurthy --- arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi index c1864ffac427..6cf59bad3626 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi @@ -293,6 +293,13 @@ qcom,battery-data = <&mtp_batterydata>; qcom,hold-soc-while-full; qcom,linearize-soc; + /* ESR fast calibration */ + qcom,fg-esr-timer-chg-fast = <0 10>; + qcom,fg-esr-timer-dischg-fast = <0 10>; + qcom,fg-esr-timer-chg-slow = <0 96>; + qcom,fg-esr-timer-dischg-slow = <0 96>; + qcom,fg-esr-cal-soc-thresh = <26 230>; + qcom,fg-esr-cal-temp-thresh = <10 40>; }; &sdhc_2 { -- GitLab From d8e40bbfc2be38b1988276f4bb2df3919e7c90ea Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Wed, 27 Jun 2018 16:43:48 -0700 Subject: [PATCH 1197/1299] power: qpnp-fg-gen4: Add support for PM8150B v2 FG SRAM PM8150B v2 FG SRAM memory map got changed. Add support for it. Change-Id: I4cab8947b5bdb1ca785e3270b10e765671f53c5b Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-core.h | 1 + drivers/power/supply/qcom/fg-memif.c | 4 +- drivers/power/supply/qcom/qpnp-fg-gen4.c | 131 +++++++++++++++++++++-- 3 files changed, 124 insertions(+), 12 deletions(-) diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 3af5c947f7e3..571a995a31d0 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -167,6 +167,7 @@ enum fg_irq_index { enum fg_sram_param_id { FG_SRAM_BATT_SOC = 0, FG_SRAM_FULL_SOC, + FG_SRAM_MONOTONIC_SOC, FG_SRAM_VOLTAGE_PRED, FG_SRAM_OCV, FG_SRAM_ESR, diff --git a/drivers/power/supply/qcom/fg-memif.c b/drivers/power/supply/qcom/fg-memif.c index 5f44934d57b6..08e803818dae 100644 --- a/drivers/power/supply/qcom/fg-memif.c +++ b/drivers/power/supply/qcom/fg-memif.c @@ -1200,7 +1200,7 @@ static struct fg_dma_address fg_gen4_addr_map[6] = { /* wk/scratch pad partition continued */ { .partition_start = 406, - .partition_end = 480, + .partition_end = 486, .spmi_addr_base = GEN4_FG_DMA5_BASE + SRAM_ADDR_OFFSET, }, }; @@ -1219,7 +1219,7 @@ static int fg_dma_init(struct fg_dev *fg) fg->sram.addr_map = fg_gen4_addr_map; fg->sram.num_partitions = 6; fg->sram.num_bytes_per_word = 2; - fg->sram.address_max = 479; + fg->sram.address_max = 485; } else { pr_err("Unknown FG version %d\n", fg->version); return -ENXIO; diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 94e7b945b007..1fd5badf85e5 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -142,9 +142,29 @@ #define CC_SOC_SW_OFFSET 0 #define CC_SOC_WORD 460 #define CC_SOC_OFFSET 0 -#define MONOTONIC_SOC_WORD 455 +#define MONOTONIC_SOC_WORD 463 #define MONOTONIC_SOC_OFFSET 0 +/* v2 SRAM address and offset in ascending order */ +#define ACT_BATT_CAP_v2_WORD 287 +#define ACT_BATT_CAP_v2_OFFSET 0 +#define RSLOW_v2_WORD 371 +#define RSLOW_v2_OFFSET 0 +#define OCV_v2_WORD 425 +#define OCV_v2_OFFSET 0 +#define VOLTAGE_PRED_v2_WORD 440 +#define VOLTAGE_PRED_v2_OFFSET 0 +#define BATT_SOC_v2_WORD 455 +#define BATT_SOC_v2_OFFSET 0 +#define FULL_SOC_v2_WORD 461 +#define FULL_SOC_v2_OFFSET 0 +#define CC_SOC_SW_v2_WORD 464 +#define CC_SOC_SW_v2_OFFSET 0 +#define CC_SOC_v2_WORD 466 +#define CC_SOC_v2_OFFSET 0 +#define MONOTONIC_SOC_v2_WORD 469 +#define MONOTONIC_SOC_v2_OFFSET 0 + static struct fg_irq_info fg_irqs[FG_GEN4_IRQ_MAX]; /* DT parameters for FG device */ @@ -232,11 +252,13 @@ static int fg_restart_mp; static bool fg_sram_dump; static bool fg_esr_fast_cal_en; -static struct fg_sram_param pm8150_sram_params[] = { +static struct fg_sram_param pm8150b_v1_sram_params[] = { PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL, fg_decode_default), - PARAM(FULL_SOC, FULL_SOC_WORD, FULL_SOC_OFFSET, 2, 1, 1, 0, NULL, - fg_decode_default), + PARAM(FULL_SOC, FULL_SOC_WORD, FULL_SOC_OFFSET, 2, 1, 1, 0, + fg_encode_default, fg_decode_default), + PARAM(MONOTONIC_SOC, MONOTONIC_SOC_WORD, MONOTONIC_SOC_OFFSET, 2, 1, 1, + 0, NULL, fg_decode_default), PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 1000, 244141, 0, NULL, fg_decode_voltage_15b), PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 1000, 244141, 0, NULL, @@ -315,6 +337,91 @@ static struct fg_sram_param pm8150_sram_params[] = { 1, 1, 1, 0, fg_encode_default, NULL), }; +static struct fg_sram_param pm8150b_v2_sram_params[] = { + PARAM(BATT_SOC, BATT_SOC_v2_WORD, BATT_SOC_v2_OFFSET, 4, 1, 1, 0, NULL, + fg_decode_default), + PARAM(FULL_SOC, FULL_SOC_v2_WORD, FULL_SOC_v2_OFFSET, 2, 1, 1, 0, NULL, + fg_decode_default), + PARAM(MONOTONIC_SOC, MONOTONIC_SOC_v2_WORD, MONOTONIC_SOC_v2_OFFSET, 2, + 1, 1, 0, NULL, fg_decode_default), + PARAM(VOLTAGE_PRED, VOLTAGE_PRED_v2_WORD, VOLTAGE_PRED_v2_OFFSET, 2, + 1000, 244141, 0, NULL, fg_decode_voltage_15b), + PARAM(OCV, OCV_v2_WORD, OCV_v2_OFFSET, 2, 1000, 244141, 0, NULL, + fg_decode_voltage_15b), + PARAM(ESR, ESR_WORD, ESR_OFFSET, 2, 1000, 244141, 0, fg_encode_default, + fg_decode_value_16b), + PARAM(ESR_MDL, ESR_MDL_WORD, ESR_MDL_OFFSET, 2, 1000, 244141, 0, + fg_encode_default, fg_decode_value_16b), + PARAM(ESR_ACT, ESR_ACT_WORD, ESR_ACT_OFFSET, 2, 1000, 244141, 0, + fg_encode_default, fg_decode_value_16b), + PARAM(RSLOW, RSLOW_v2_WORD, RSLOW_v2_OFFSET, 2, 1000, 244141, 0, NULL, + fg_decode_value_16b), + PARAM(CC_SOC, CC_SOC_v2_WORD, CC_SOC_v2_OFFSET, 4, 1, 1, 0, NULL, + fg_decode_cc_soc), + PARAM(CC_SOC_SW, CC_SOC_SW_v2_WORD, CC_SOC_SW_v2_OFFSET, 4, 1, 1, 0, + NULL, fg_decode_cc_soc), + PARAM(ACT_BATT_CAP, ACT_BATT_CAP_v2_WORD, ACT_BATT_CAP_v2_OFFSET, 2, + 1, 1, 0, NULL, fg_decode_default), + /* Entries below here are configurable during initialization */ + PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000, + 244141, 0, fg_encode_voltage, NULL), + PARAM(VBATT_LOW, VBATT_LOW_WORD, VBATT_LOW_OFFSET, 1, 1000, + 15625, -2000, fg_encode_voltage, NULL), + PARAM(VBATT_FULL, VBATT_FULL_WORD, VBATT_FULL_OFFSET, 2, 1000, + 244141, 0, fg_encode_voltage, fg_decode_voltage_15b), + PARAM(CUTOFF_CURR, CUTOFF_CURR_WORD, CUTOFF_CURR_OFFSET, 2, + 100000, 48828, 0, fg_encode_current, NULL), + PARAM(SYS_TERM_CURR, SYS_TERM_CURR_WORD, SYS_TERM_CURR_OFFSET, 2, + 100000, 48828, 0, fg_encode_current, NULL), + PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_WORD, DELTA_MSOC_THR_OFFSET, + 1, 2048, 100, 0, fg_encode_default, NULL), + PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_WORD, DELTA_BSOC_THR_OFFSET, + 1, 2048, 100, 0, fg_encode_default, NULL), + PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD, + ESR_TIMER_DISCHG_MAX_OFFSET, 1, 1, 1, 0, fg_encode_default, + NULL), + PARAM(ESR_TIMER_DISCHG_INIT, ESR_TIMER_DISCHG_INIT_WORD, + ESR_TIMER_DISCHG_INIT_OFFSET, 1, 1, 1, 0, fg_encode_default, + NULL), + PARAM(ESR_TIMER_CHG_MAX, ESR_TIMER_CHG_MAX_WORD, + ESR_TIMER_CHG_MAX_OFFSET, 1, 1, 1, 0, fg_encode_default, NULL), + PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD, + ESR_TIMER_CHG_INIT_OFFSET, 1, 1, 1, 0, fg_encode_default, NULL), + PARAM(ESR_PULSE_THRESH, ESR_PULSE_THRESH_WORD, ESR_PULSE_THRESH_OFFSET, + 1, 1000, 15625, 0, fg_encode_default, NULL), + PARAM(DELTA_ESR_THR, DELTA_ESR_THR_WORD, DELTA_ESR_THR_OFFSET, 2, 1000, + 61036, 0, fg_encode_default, NULL), + PARAM(KI_COEFF_LOW_DISCHG, KI_COEFF_LOW_DISCHG_WORD, + KI_COEFF_LOW_DISCHG_OFFSET, 1, 1000, 61035, 0, + fg_encode_default, NULL), + PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_WORD, + KI_COEFF_MED_DISCHG_OFFSET, 1, 1000, 61035, 0, + fg_encode_default, NULL), + PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_WORD, + KI_COEFF_HI_DISCHG_OFFSET, 1, 1000, 61035, 0, + fg_encode_default, NULL), + PARAM(KI_COEFF_LOW_CHG, KI_COEFF_LOW_CHG_WORD, KI_COEFF_LOW_CHG_OFFSET, + 1, 1000, 61035, 0, fg_encode_default, NULL), + PARAM(KI_COEFF_MED_CHG, KI_COEFF_MED_CHG_WORD, KI_COEFF_MED_CHG_OFFSET, + 1, 1000, 61035, 0, fg_encode_default, NULL), + PARAM(KI_COEFF_HI_CHG, KI_COEFF_HI_CHG_WORD, KI_COEFF_HI_CHG_OFFSET, 1, + 1000, 61035, 0, fg_encode_default, NULL), + PARAM(SLOPE_LIMIT, SLOPE_LIMIT_WORD, SLOPE_LIMIT_OFFSET, 1, 8192, + 1000000, 0, fg_encode_default, NULL), + PARAM(BATT_TEMP_COLD, BATT_TEMP_CONFIG_WORD, BATT_TEMP_COLD_OFFSET, 1, + 1, 1, 0, fg_encode_default, NULL), + PARAM(BATT_TEMP_HOT, BATT_TEMP_CONFIG_WORD, BATT_TEMP_HOT_OFFSET, 1, + 1, 1, 0, fg_encode_default, NULL), + PARAM(ESR_CAL_SOC_MIN, BATT_TEMP_CONFIG2_WORD, ESR_CAL_SOC_MIN_OFFSET, + 1, 1, 1, 0, fg_encode_default, NULL), + PARAM(ESR_CAL_SOC_MAX, ESR_CAL_THRESH_WORD, ESR_CAL_SOC_MAX_OFFSET, + 1, 1, 1, 0, fg_encode_default, NULL), + PARAM(ESR_CAL_TEMP_MIN, ESR_CAL_THRESH_WORD, ESR_CAL_TEMP_MIN_OFFSET, + 1, 1, 1, 0, fg_encode_default, NULL), + PARAM(ESR_CAL_TEMP_MAX, ESR_PULSE_THRESH_WORD, ESR_CAL_TEMP_MAX_OFFSET, + 1, 1, 1, 0, fg_encode_default, NULL), +}; + static bool is_batt_empty(struct fg_dev *fg); /* All get functions below */ @@ -1612,22 +1719,25 @@ static int fg_gen4_update_maint_soc(struct fg_dev *fg) static int fg_gen4_configure_full_soc(struct fg_dev *fg, int bsoc) { int rc; - u8 full_soc[2] = {0xFF, 0xFF}; + u8 full_soc[2] = {0xFF, 0xFF}, buf[2]; /* * Once SOC masking condition is cleared, FULL_SOC and MONOTONIC_SOC * needs to be updated to reflect the same. Write battery SOC to * FULL_SOC and write a full value to MONOTONIC_SOC. */ - rc = fg_sram_write(fg, FULL_SOC_WORD, FULL_SOC_OFFSET, - (u8 *)&bsoc, 2, FG_IMA_ATOMIC); + fg_encode(fg->sp, FG_SRAM_FULL_SOC, bsoc, buf); + rc = fg_sram_write(fg, fg->sp[FG_SRAM_FULL_SOC].addr_word, + fg->sp[FG_SRAM_FULL_SOC].addr_byte, buf, + fg->sp[FG_SRAM_FULL_SOC].len, FG_IMA_ATOMIC); if (rc < 0) { pr_err("failed to write full_soc rc=%d\n", rc); return rc; } - rc = fg_sram_write(fg, MONOTONIC_SOC_WORD, MONOTONIC_SOC_OFFSET, - full_soc, 2, FG_IMA_ATOMIC); + rc = fg_sram_write(fg, fg->sp[FG_SRAM_MONOTONIC_SOC].addr_word, + fg->sp[FG_SRAM_MONOTONIC_SOC].addr_byte, full_soc, + fg->sp[FG_SRAM_MONOTONIC_SOC].len, FG_IMA_ATOMIC); if (rc < 0) { pr_err("failed to write monotonic_soc rc=%d\n", rc); return rc; @@ -3631,8 +3741,9 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip) case PM8150B_SUBTYPE: fg->version = GEN4_FG; fg->use_dma = true; - fg->sp = pm8150_sram_params; + fg->sp = pm8150b_v2_sram_params; if (fg->pmic_rev_id->rev4 == PM8150B_V1P0_REV4) { + fg->sp = pm8150b_v1_sram_params; fg->wa_flags |= PM8150B_V1_DMA_WA; fg->wa_flags |= PM8150B_V1_RSLOW_COMP_WA; } -- GitLab From 0c1b63de733081cb1d2f6f6a59d40f2861739416 Mon Sep 17 00:00:00 2001 From: Kyle Piefer Date: Fri, 8 Jun 2018 13:53:28 -0700 Subject: [PATCH 1198/1299] Revert "msm: kgsl: Enable IFPC on A640 GPUs" Disable IFPC because it could cause system instability. This reverts commit b449aa80b24a36a5fe3b66ffc63bb34d0c60b3ac. Change-Id: I6b25a70ee741de18541763fdf65d0ab50e8019fc Signed-off-by: Kyle Piefer --- drivers/gpu/msm/adreno-gpulist.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index 5cd4d92fcec4..e84ee9a2b727 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -386,7 +386,7 @@ static const struct adreno_gpu_core adreno_gpulist[] = { .minor = 0, .patchid = 0, .features = ADRENO_64BIT | ADRENO_RPMH | ADRENO_GPMU | - ADRENO_IFPC | ADRENO_CONTENT_PROTECTION, + ADRENO_CONTENT_PROTECTION, .sqefw_name = "a630_sqe.fw", .zap_name = "a640_zap", .gpudev = &adreno_a6xx_gpudev, @@ -407,7 +407,7 @@ static const struct adreno_gpu_core adreno_gpulist[] = { .minor = 0, .patchid = ANY_ID, .features = ADRENO_64BIT | ADRENO_RPMH | ADRENO_GPMU | - ADRENO_IFPC | ADRENO_CONTENT_PROTECTION, + ADRENO_CONTENT_PROTECTION, .sqefw_name = "a630_sqe.fw", .zap_name = "a640_zap", .gpudev = &adreno_a6xx_gpudev, -- GitLab From 89556e9d71b02cc61b95cf7fc99b7071773e995d Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 26 Jun 2018 18:08:19 -0700 Subject: [PATCH 1199/1299] power: step-chg-jeita: Clip voltages higher than max allowed Currently, if the current battery voltage is out of bounds of the Step Charge ranges, the step charging voter is disabled. In tapered charging situations where Vbatt sometimes exceeds the highest allowed voltage, this leads to a sudden change in the charging current due to the MIN voter mechanism selecting the next minimum value out of all the votes, which is undesirable. Fix this by choosing highest possible range value for battery voltage when the observed value exceeds the range of acceptable values. This results in the step charge voter remaining enabled and retaining its vote, which, in turn, ensures that the charging current remains the same even when the battery voltage exceeds the maximum allowed value (assuming battery temperature is unchanged). The current behaviour is retained for those situations where the observed value is lesser than the minimum acceptable range value. Also enable this behaviour for JEITA functionality as well. CRs-Fixed: 2255514 Change-Id: I3c33c76306f0290005fe9bbe0345c76b284c56e6 Signed-off-by: Guru Das Srinagesh --- drivers/power/supply/qcom/step-chg-jeita.c | 39 +++++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/drivers/power/supply/qcom/step-chg-jeita.c b/drivers/power/supply/qcom/step-chg-jeita.c index b0e62d32f188..b87e19ca11e8 100644 --- a/drivers/power/supply/qcom/step-chg-jeita.c +++ b/drivers/power/supply/qcom/step-chg-jeita.c @@ -347,17 +347,46 @@ static int get_val(struct range_data *range, int hysteresis, int current_index, int i; *new_index = -EINVAL; - /* first find the matching index without hysteresis */ - for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++) + + /* + * If the threshold is lesser than the minimum allowed range, + * return -ENODATA. + */ + if (threshold < range[0].low_threshold) + return -ENODATA; + + /* First try to find the matching index without hysteresis */ + for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++) { + if (!range[i].high_threshold && !range[i].low_threshold) { + /* First invalid table entry; exit loop */ + break; + } + if (is_between(range[i].low_threshold, range[i].high_threshold, threshold)) { *new_index = i; *val = range[i].value; + break; } + } + + /* + * If nothing was found, the threshold exceeds the max range for sure + * as the other case where it is lesser than the min range is handled + * at the very beginning of this function. Therefore, clip it to the + * max allowed range value, which is the one corresponding to the last + * valid entry in the battery profile data array. + */ + if (*new_index == -EINVAL) { + if (i == 0) { + /* Battery profile data array is completely invalid */ + return -ENODATA; + } + + *new_index = (i - 1); + *val = range[*new_index].value; + } - /* if nothing was found, return -ENODATA */ - if (*new_index == -EINVAL) - return -ENODATA; /* * If we don't have a current_index return this * newfound value. There is no hysterisis from out of range -- GitLab From d5382b05dc7775c9f528112e611d3f1a416a8c80 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Tue, 5 Jun 2018 16:30:36 -0700 Subject: [PATCH 1200/1299] Revert "staging, android: remove lowmemory killer from the tree" This reverts commit 915e70f9263d56fbf103742265025f7a492aa625. Restore the kernel low memory killer as an alternative implementation to the android userspace low memory killer. Change-Id: I2b1e91a7bc4261cd1a8a23ae69b128d113069441 Signed-off-by: Patrick Daly --- drivers/staging/android/Kconfig | 10 + drivers/staging/android/Makefile | 1 + drivers/staging/android/lowmemorykiller.c | 213 ++++++++++++++++++++++ include/linux/sched.h | 5 + 4 files changed, 229 insertions(+) create mode 100644 drivers/staging/android/lowmemorykiller.c diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 4630dc85634e..5db9d25a4fe9 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -23,6 +23,16 @@ config ANDROID_VSOC a 'cuttlefish' Android image inside QEmu. The driver interacts with a QEmu ivshmem device. If built as a module, it will be called vsoc. +config ANDROID_LOW_MEMORY_KILLER + bool "Android Low Memory Killer" + ---help--- + Registers processes to be killed when low memory conditions, this is useful + as there is no particular swap space on android. + + The registered process will kill according to the priorities in android init + scripts (/init.rc), and it defines priority values with minimum free memory size + for each priority. + source "drivers/staging/android/ion/Kconfig" source "drivers/staging/android/fiq_debugger/Kconfig" diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 2638b4a23df4..191ac4bdefa3 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger/ obj-$(CONFIG_ASHMEM) += ashmem.o obj-$(CONFIG_ANDROID_VSOC) += vsoc.o +obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c new file mode 100644 index 000000000000..2a4a497d6dff --- /dev/null +++ b/drivers/staging/android/lowmemorykiller.c @@ -0,0 +1,213 @@ +/* drivers/misc/lowmemorykiller.c + * + * The lowmemorykiller driver lets user-space specify a set of memory thresholds + * where processes with a range of oom_score_adj values will get killed. Specify + * the minimum oom_score_adj values in + * /sys/module/lowmemorykiller/parameters/adj and the number of free pages in + * /sys/module/lowmemorykiller/parameters/minfree. Both files take a comma + * separated list of numbers in ascending order. + * + * For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and + * "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill + * processes with a oom_score_adj value of 8 or higher when the free memory + * drops below 4096 pages and kill processes with a oom_score_adj value of 0 or + * higher when the free memory drops below 1024 pages. + * + * The driver considers memory used for caches to be free, but if a large + * percentage of the cached memory is locked this can be very inaccurate + * and processes may not get killed until the normal oom killer is triggered. + * + * Copyright (C) 2007-2008 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static u32 lowmem_debug_level = 1; +static short lowmem_adj[6] = { + 0, + 1, + 6, + 12, +}; + +static int lowmem_adj_size = 4; +static int lowmem_minfree[6] = { + 3 * 512, /* 6MB */ + 2 * 1024, /* 8MB */ + 4 * 1024, /* 16MB */ + 16 * 1024, /* 64MB */ +}; + +static int lowmem_minfree_size = 4; + +static unsigned long lowmem_deathpending_timeout; + +#define lowmem_print(level, x...) \ + do { \ + if (lowmem_debug_level >= (level)) \ + pr_info(x); \ + } while (0) + +static unsigned long lowmem_count(struct shrinker *s, + struct shrink_control *sc) +{ + return global_node_page_state(NR_ACTIVE_ANON) + + global_node_page_state(NR_ACTIVE_FILE) + + global_node_page_state(NR_INACTIVE_ANON) + + global_node_page_state(NR_INACTIVE_FILE); +} + +static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) +{ + struct task_struct *tsk; + struct task_struct *selected = NULL; + unsigned long rem = 0; + int tasksize; + int i; + short min_score_adj = OOM_SCORE_ADJ_MAX + 1; + int minfree = 0; + int selected_tasksize = 0; + short selected_oom_score_adj; + int array_size = ARRAY_SIZE(lowmem_adj); + int other_free = global_zone_page_state(NR_FREE_PAGES) - + totalreserve_pages; + int other_file = global_node_page_state(NR_FILE_PAGES) - + global_node_page_state(NR_SHMEM) - + total_swapcache_pages(); + + if (lowmem_adj_size < array_size) + array_size = lowmem_adj_size; + if (lowmem_minfree_size < array_size) + array_size = lowmem_minfree_size; + for (i = 0; i < array_size; i++) { + minfree = lowmem_minfree[i]; + if (other_free < minfree && other_file < minfree) { + min_score_adj = lowmem_adj[i]; + break; + } + } + + lowmem_print(3, "%s %lu, %x, ofree %d %d, ma %hd\n", + __func__, sc->nr_to_scan, sc->gfp_mask, other_free, + other_file, min_score_adj); + + if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) { + lowmem_print(5, "%s %lu, %x, return 0\n", + __func__, sc->nr_to_scan, sc->gfp_mask); + return 0; + } + + selected_oom_score_adj = min_score_adj; + + rcu_read_lock(); + for_each_process(tsk) { + struct task_struct *p; + short oom_score_adj; + + if (tsk->flags & PF_KTHREAD) + continue; + + p = find_lock_task_mm(tsk); + if (!p) + continue; + + if (task_lmk_waiting(p) && + time_before_eq(jiffies, lowmem_deathpending_timeout)) { + task_unlock(p); + rcu_read_unlock(); + return 0; + } + oom_score_adj = p->signal->oom_score_adj; + if (oom_score_adj < min_score_adj) { + task_unlock(p); + continue; + } + tasksize = get_mm_rss(p->mm); + task_unlock(p); + if (tasksize <= 0) + continue; + if (selected) { + if (oom_score_adj < selected_oom_score_adj) + continue; + if (oom_score_adj == selected_oom_score_adj && + tasksize <= selected_tasksize) + continue; + } + selected = p; + selected_tasksize = tasksize; + selected_oom_score_adj = oom_score_adj; + lowmem_print(2, "select '%s' (%d), adj %hd, size %d, to kill\n", + p->comm, p->pid, oom_score_adj, tasksize); + } + if (selected) { + task_lock(selected); + send_sig(SIGKILL, selected, 0); + if (selected->mm) + task_set_lmk_waiting(selected); + task_unlock(selected); + lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" + " to free %ldkB on behalf of '%s' (%d) because\n" + " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" + " Free memory is %ldkB above reserved\n", + selected->comm, selected->pid, + selected_oom_score_adj, + selected_tasksize * (long)(PAGE_SIZE / 1024), + current->comm, current->pid, + other_file * (long)(PAGE_SIZE / 1024), + minfree * (long)(PAGE_SIZE / 1024), + min_score_adj, + other_free * (long)(PAGE_SIZE / 1024)); + lowmem_deathpending_timeout = jiffies + HZ; + rem += selected_tasksize; + } + + lowmem_print(4, "%s %lu, %x, return %lu\n", + __func__, sc->nr_to_scan, sc->gfp_mask, rem); + rcu_read_unlock(); + return rem; +} + +static struct shrinker lowmem_shrinker = { + .scan_objects = lowmem_scan, + .count_objects = lowmem_count, + .seeks = DEFAULT_SEEKS * 16 +}; + +static int __init lowmem_init(void) +{ + register_shrinker(&lowmem_shrinker); + return 0; +} +device_initcall(lowmem_init); + +/* + * not really modular, but the easiest way to keep compat with existing + * bootargs behaviour is to continue using module_param here. + */ +module_param_named(cost, lowmem_shrinker.seeks, int, 0644); +module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, 0644); +module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, + 0644); +module_param_named(debug_level, lowmem_debug_level, uint, 0644); + diff --git a/include/linux/sched.h b/include/linux/sched.h index 88da0bb5ece3..8814051c5a8e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1570,6 +1570,8 @@ static inline bool is_percpu_thread(void) #define PFA_SPREAD_SLAB 2 /* Spread some slab caches over cpuset */ #define PFA_SPEC_SSB_DISABLE 3 /* Speculative Store Bypass disabled */ #define PFA_SPEC_SSB_FORCE_DISABLE 4 /* Speculative Store Bypass force disabled*/ +#define PFA_LMK_WAITING 5 /* Lowmemorykiller is waiting */ + #define TASK_PFA_TEST(name, func) \ static inline bool task_##func(struct task_struct *p) \ @@ -1601,6 +1603,9 @@ TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ssb_disable) TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) +TASK_PFA_TEST(LMK_WAITING, lmk_waiting) +TASK_PFA_SET(LMK_WAITING, lmk_waiting) + static inline void current_restore_flags(unsigned long orig_flags, unsigned long flags) { -- GitLab From 34c217eebbe39d50c61fab01abb8921e2e24e072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Tue, 25 Sep 2012 17:37:14 -0700 Subject: [PATCH 1201/1299] ANDROID: staging: lowmemorykiller: Add config option to support oom_adj values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The conversion to use oom_score_adj instead of the deprecated oom_adj values breaks existing user-space code. Add a config option to convert oom_adj values written to oom_score_adj values if they appear to be valid oom_adj values. Change-Id: I72512ade5e68c1eeb4f382dfc9ce4f123cb622b8 Signed-off-by: Arve Hjønnevåg Git-Commit: 73f1dd691f22d58c9bfb970cb8b5a3b25fb4f3c3 Git-Repo: https://android.googlesource.com/kernel/common Signed-off-by: Patrick Daly --- drivers/staging/android/Kconfig | 9 +++ drivers/staging/android/lowmemorykiller.c | 85 +++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 5db9d25a4fe9..1d233d01ec1f 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -33,6 +33,15 @@ config ANDROID_LOW_MEMORY_KILLER scripts (/init.rc), and it defines priority values with minimum free memory size for each priority. +config ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES + bool "Android Low Memory Killer: detect oom_adj values" + depends on ANDROID_LOW_MEMORY_KILLER + default y + ---help--- + Detect oom_adj values written to + /sys/module/lowmemorykiller/parameters/adj and convert them + to oom_score_adj values. + source "drivers/staging/android/ion/Kconfig" source "drivers/staging/android/fiq_debugger/Kconfig" diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 2a4a497d6dff..b27bd3097c85 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -201,12 +201,97 @@ static int __init lowmem_init(void) } device_initcall(lowmem_init); +#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES +static short lowmem_oom_adj_to_oom_score_adj(short oom_adj) +{ + if (oom_adj == OOM_ADJUST_MAX) + return OOM_SCORE_ADJ_MAX; + else + return (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; +} + +static void lowmem_autodetect_oom_adj_values(void) +{ + int i; + short oom_adj; + short oom_score_adj; + int array_size = ARRAY_SIZE(lowmem_adj); + + if (lowmem_adj_size < array_size) + array_size = lowmem_adj_size; + + if (array_size <= 0) + return; + + oom_adj = lowmem_adj[array_size - 1]; + if (oom_adj > OOM_ADJUST_MAX) + return; + + oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj); + if (oom_score_adj <= OOM_ADJUST_MAX) + return; + + lowmem_print(1, "lowmem_shrink: convert oom_adj to oom_score_adj:\n"); + for (i = 0; i < array_size; i++) { + oom_adj = lowmem_adj[i]; + oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj); + lowmem_adj[i] = oom_score_adj; + lowmem_print(1, "oom_adj %d => oom_score_adj %d\n", + oom_adj, oom_score_adj); + } +} + +static int lowmem_adj_array_set(const char *val, const struct kernel_param *kp) +{ + int ret; + + ret = param_array_ops.set(val, kp); + + /* HACK: Autodetect oom_adj values in lowmem_adj array */ + lowmem_autodetect_oom_adj_values(); + + return ret; +} + +static int lowmem_adj_array_get(char *buffer, const struct kernel_param *kp) +{ + return param_array_ops.get(buffer, kp); +} + +static void lowmem_adj_array_free(void *arg) +{ + param_array_ops.free(arg); +} + +static struct kernel_param_ops lowmem_adj_array_ops = { + .set = lowmem_adj_array_set, + .get = lowmem_adj_array_get, + .free = lowmem_adj_array_free, +}; + +static const struct kparam_array __param_arr_adj = { + .max = ARRAY_SIZE(lowmem_adj), + .num = &lowmem_adj_size, + .ops = ¶m_ops_short, + .elemsize = sizeof(lowmem_adj[0]), + .elem = lowmem_adj, +}; +#endif + /* * not really modular, but the easiest way to keep compat with existing * bootargs behaviour is to continue using module_param here. */ module_param_named(cost, lowmem_shrinker.seeks, int, 0644); +#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES +__module_param_call(MODULE_PARAM_PREFIX, adj, + &lowmem_adj_array_ops, + .arr = &__param_arr_adj, + 0644, -1); +__MODULE_PARM_TYPE(adj, "array of short"); +#else module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, 0644); +#endif module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, 0644); module_param_named(debug_level, lowmem_debug_level, uint, 0644); -- GitLab From 47f26a14246e6ab77a6f292768cbb5dc1fe19a8e Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Tue, 26 May 2015 11:28:47 +0200 Subject: [PATCH 1202/1299] ANDROID: lowmemorykiller: trace kill events. Allows for capturing lmk kill events and their rationale. Change-Id: I74404e1a7e390a8a34fdd8020c25e5554d9e053d Signed-off-by: Martijn Coenen Git-Commit: cbd47bd62399911c7e95ce82314c660e44a05e61 Git-Repo: https://android.googlesource.com/kernel/common Signed-off-by: Patrick Daly --- drivers/staging/android/lowmemorykiller.c | 12 ++++-- .../staging/android/trace/lowmemorykiller.h | 41 +++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 drivers/staging/android/trace/lowmemorykiller.h diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index b27bd3097c85..8240b4b8a30d 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -43,6 +43,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include "trace/lowmemorykiller.h" + static u32 lowmem_debug_level = 1; static short lowmem_adj[6] = { 0, @@ -166,6 +169,10 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (selected->mm) task_set_lmk_waiting(selected); task_unlock(selected); + long cache_size = other_file * (long)(PAGE_SIZE / 1024); + long cache_limit = minfree * (long)(PAGE_SIZE / 1024); + long free = other_free * (long)(PAGE_SIZE / 1024); + trace_lowmemory_kill(selected, cache_size, cache_limit, free); lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" " to free %ldkB on behalf of '%s' (%d) because\n" " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" @@ -174,10 +181,9 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) selected_oom_score_adj, selected_tasksize * (long)(PAGE_SIZE / 1024), current->comm, current->pid, - other_file * (long)(PAGE_SIZE / 1024), - minfree * (long)(PAGE_SIZE / 1024), + cache_size, cache_limit, min_score_adj, - other_free * (long)(PAGE_SIZE / 1024)); + free); lowmem_deathpending_timeout = jiffies + HZ; rem += selected_tasksize; } diff --git a/drivers/staging/android/trace/lowmemorykiller.h b/drivers/staging/android/trace/lowmemorykiller.h new file mode 100644 index 000000000000..f43d3fae75ee --- /dev/null +++ b/drivers/staging/android/trace/lowmemorykiller.h @@ -0,0 +1,41 @@ +#undef TRACE_SYSTEM +#define TRACE_INCLUDE_PATH ../../drivers/staging/android/trace +#define TRACE_SYSTEM lowmemorykiller + +#if !defined(_TRACE_LOWMEMORYKILLER_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_LOWMEMORYKILLER_H + +#include + +TRACE_EVENT(lowmemory_kill, + TP_PROTO(struct task_struct *killed_task, long cache_size, \ + long cache_limit, long free), + + TP_ARGS(killed_task, cache_size, cache_limit, free), + + TP_STRUCT__entry( + __array(char, comm, TASK_COMM_LEN) + __field(pid_t, pid) + __field(long, pagecache_size) + __field(long, pagecache_limit) + __field(long, free) + ), + + TP_fast_assign( + memcpy(__entry->comm, killed_task->comm, TASK_COMM_LEN); + __entry->pid = killed_task->pid; + __entry->pagecache_size = cache_size; + __entry->pagecache_limit = cache_limit; + __entry->free = free; + ), + + TP_printk("%s (%d), page cache %ldkB (limit %ldkB), free %ldKb", + __entry->comm, __entry->pid, __entry->pagecache_size, + __entry->pagecache_limit, __entry->free) +); + + +#endif /* if !defined(_TRACE_LOWMEMORYKILLER_H) || defined(TRACE_HEADER_MULTI_READ) */ + +/* This part must be outside protection */ +#include -- GitLab From 2367a7742aabeaecb92ac4627f3ea76e20237426 Mon Sep 17 00:00:00 2001 From: Amit Pundir Date: Fri, 30 Oct 2015 01:16:29 +0530 Subject: [PATCH 1203/1299] ANDROID: lowmemorykiller: use module_param_cb instead of __module_param_call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use module_param_cb helper routine instead of __module_param_call otherwise we run into following build error: CC drivers/staging/android/lowmemorykiller.o drivers/staging/android/lowmemorykiller.c:293:28: error: macro "__module_param_call" requires 7 arguments, but only 6 given S_IRUGO | S_IWUSR, -1); ^ drivers/staging/android/lowmemorykiller.c:290:1: warning: data definition has no type or storage class [enabled by default] __module_param_call(MODULE_PARAM_PREFIX, adj, ^ drivers/staging/android/lowmemorykiller.c:290:1: error: type defaults to ‘int’ in declaration of ‘__module_param_call’ [-Werror=implicit-int] drivers/staging/android/lowmemorykiller.c:273:32: warning: ‘lowmem_adj_array_ops’ defined but not used [-Wunused-variable] static struct kernel_param_ops lowmem_adj_array_ops = { ^ cc1: some warnings being treated as errors make[3]: *** [drivers/staging/android/lowmemorykiller.o] Error 1 Change-Id: Ib2249f1f8c28d5678f127d0c8d3028555bf6f4e7 Signed-off-by: Amit Pundir Git-Commit: 092be1d02aca34d5347b90375956ddca076df605 Git-Repo: https://android.googlesource.com/kernel/common Signed-off-by: Patrick Daly --- drivers/staging/android/lowmemorykiller.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 8240b4b8a30d..57862d9fb625 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -290,10 +290,9 @@ static const struct kparam_array __param_arr_adj = { */ module_param_named(cost, lowmem_shrinker.seeks, int, 0644); #ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES -__module_param_call(MODULE_PARAM_PREFIX, adj, - &lowmem_adj_array_ops, - .arr = &__param_arr_adj, - 0644, -1); +module_param_cb(adj, &lowmem_adj_array_ops, + .arr = &__param_arr_adj, + 0644); __MODULE_PARM_TYPE(adj, "array of short"); #else module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, 0644); -- GitLab From 2e78ad25816d63041609ad176706102e774344bc Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 29 Feb 2016 17:40:05 -0800 Subject: [PATCH 1204/1299] ANDROID: lowmemorykiller: fix declaration order warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/staging/android/lowmemorykiller.c: In function ‘lowmem_scan’: drivers/staging/android/lowmemorykiller.c:174:3: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] Change-Id: I7164a1316ed379c9c887f82cd16e7bb91e9dfcd6 Signed-off-by: Brian Norris Git-Commit: 5fb1ae07029fdaf8b9ea00f07344d1e8f7d419af Git-Repo: https://android.googlesource.com/kernel/common Signed-off-by: Patrick Daly --- drivers/staging/android/lowmemorykiller.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 57862d9fb625..d44f974015cd 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -164,14 +164,15 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) p->comm, p->pid, oom_score_adj, tasksize); } if (selected) { + long cache_size = other_file * (long)(PAGE_SIZE / 1024); + long cache_limit = minfree * (long)(PAGE_SIZE / 1024); + long free = other_free * (long)(PAGE_SIZE / 1024); + task_lock(selected); send_sig(SIGKILL, selected, 0); if (selected->mm) task_set_lmk_waiting(selected); task_unlock(selected); - long cache_size = other_file * (long)(PAGE_SIZE / 1024); - long cache_limit = minfree * (long)(PAGE_SIZE / 1024); - long free = other_free * (long)(PAGE_SIZE / 1024); trace_lowmemory_kill(selected, cache_size, cache_limit, free); lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" " to free %ldkB on behalf of '%s' (%d) because\n" -- GitLab From 664a65c9909f4c06a97cec735ee10e11304e763f Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Fri, 2 Sep 2016 16:04:41 -0700 Subject: [PATCH 1205/1299] ANDROID: lowmemorykiller: account for unevictable pages lowmemorykiller was not taking into account unevictable pages when deciding what level to kill. If significant amounts of memory were pinned, this caused lowmemorykiller to effectively stop at a much higher level than it should. bug 31255977 Change-Id: If68b4bc31ed5364fd6e8cae9bec0659f6b114903 Signed-off-by: Tim Murray Git-Commit: 15a97d3c46c78589db87083fb07d7262df99b1dc Git-Repo: https://android.googlesource.com/kernel/common Signed-off-by: Patrick Daly --- drivers/staging/android/lowmemorykiller.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index d44f974015cd..18f739277e8c 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -97,6 +97,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) totalreserve_pages; int other_file = global_node_page_state(NR_FILE_PAGES) - global_node_page_state(NR_SHMEM) - + global_node_page_state(NR_UNEVICTABLE) - total_swapcache_pages(); if (lowmem_adj_size < array_size) -- GitLab From 226c186be4c22e08b941635ca35eebcb5c705d3a Mon Sep 17 00:00:00 2001 From: Joel Fernandes Date: Fri, 21 Jul 2017 09:41:06 -0700 Subject: [PATCH 1206/1299] ANDROID: lowmemorykiller: Add tgid to kill message Bug: 33346201 Test: trigger LMK and verify tgid is there Change-Id: I579f388d7fe04592ce567737f5a3720f7f7f5ab1 Signed-off-by: Joel Fernandes Git-Commit: f44842e559d2cab58d0a7c312e09e73ff6c2d3e0 Git-Repo: https://android.googlesource.com/kernel/common Signed-off-by: Patrick Daly --- drivers/staging/android/lowmemorykiller.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 18f739277e8c..e89683583bcf 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -175,11 +175,11 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) task_set_lmk_waiting(selected); task_unlock(selected); trace_lowmemory_kill(selected, cache_size, cache_limit, free); - lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" + lowmem_print(1, "Killing '%s' (%d) (tgid %d), adj %hd,\n" " to free %ldkB on behalf of '%s' (%d) because\n" " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" " Free memory is %ldkB above reserved\n", - selected->comm, selected->pid, + selected->comm, selected->pid, selected->tgid, selected_oom_score_adj, selected_tasksize * (long)(PAGE_SIZE / 1024), current->comm, current->pid, -- GitLab From 32f800c63edbf60b28b1fd7fdc7cbfa4a43d2d99 Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Thu, 20 Sep 2012 14:42:28 -0700 Subject: [PATCH 1207/1299] android/lowmemorykiller: Check all tasks for death pending The lowmemorykiller uses the TIF_MEMDIE flag to help ensure it doesn't kill another task until the memory from the previously killed task has been returned to the system. However the lowmemorykiller does not currently look at tasks who do not have a tasks->mm, but just because a process doesn't have a tasks->mm does not mean that the task's memory has been fully returned to the system yet. In order to prevent the lowmemorykiller from unnecessarily killing multiple applications in a row the lowmemorykiller has been changed to ensure that previous killed tasks are no longer in the process list before attempting to kill another task. Change-Id: I7d8a8fd39ca5625e6448ed2efebfb621f6e93845 Signed-off-by: Liam Mark [vinmenon@codeaurora.org: Use task_lmk_waiting instead of TIF_MEMDIE as it is no more set for tasks killed my LMK] Signed-off-by: Vinayak Menon --- drivers/staging/android/lowmemorykiller.c | 29 ++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index e89683583bcf..5dc13e690285 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -81,6 +81,22 @@ static unsigned long lowmem_count(struct shrinker *s, global_node_page_state(NR_INACTIVE_FILE); } +static int test_task_lmk_waiting(struct task_struct *p) +{ + struct task_struct *t = p; + + do { + task_lock(t); + if (task_lmk_waiting(t)) { + task_unlock(t); + return 1; + } + task_unlock(t); + } while_each_thread(p, t); + + return 0; +} + static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) { struct task_struct *tsk; @@ -132,16 +148,17 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (tsk->flags & PF_KTHREAD) continue; + if (time_before_eq(jiffies, lowmem_deathpending_timeout)) { + if (test_task_lmk_waiting(tsk)) { + rcu_read_unlock(); + return 0; + } + } + p = find_lock_task_mm(tsk); if (!p) continue; - if (task_lmk_waiting(p) && - time_before_eq(jiffies, lowmem_deathpending_timeout)) { - task_unlock(p); - rcu_read_unlock(); - return 0; - } oom_score_adj = p->signal->oom_score_adj; if (oom_score_adj < min_score_adj) { task_unlock(p); -- GitLab From fb8a8ce2d889bbcbf264cbcadd031c7972e7f460 Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Fri, 25 Jan 2013 12:40:18 -0800 Subject: [PATCH 1208/1299] android/lowmemorykiller: Wait for memory to be freed The memory reclaim code needs to give time to the system to return the memory from a killed process otherwise the memory reclaim code could run continuously, in multiple threads, which could starve both the watchdog thread and the thread which is responsible for returning the memory from the killed process. Change-Id: Ieded4bfe038ca936247fa4b638070e979b02eaa1 Signed-off-by: Liam Mark Signed-off-by: Vinayak Menon --- drivers/staging/android/lowmemorykiller.c | 28 ++++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 5dc13e690285..a76aed5fe12b 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -42,6 +42,8 @@ #include #include #include +#include +#include #define CREATE_TRACE_POINTS #include "trace/lowmemorykiller.h" @@ -97,6 +99,8 @@ static int test_task_lmk_waiting(struct task_struct *p) return 0; } +static DEFINE_MUTEX(scan_mutex); + static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) { struct task_struct *tsk; @@ -109,12 +113,17 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) int selected_tasksize = 0; short selected_oom_score_adj; int array_size = ARRAY_SIZE(lowmem_adj); - int other_free = global_zone_page_state(NR_FREE_PAGES) - - totalreserve_pages; - int other_file = global_node_page_state(NR_FILE_PAGES) - - global_node_page_state(NR_SHMEM) - - global_node_page_state(NR_UNEVICTABLE) - - total_swapcache_pages(); + int other_free; + int other_file; + + if (mutex_lock_interruptible(&scan_mutex) < 0) + return 0; + + other_free = global_zone_page_state(NR_FREE_PAGES) - totalreserve_pages; + other_file = global_node_page_state(NR_FILE_PAGES) - + global_node_page_state(NR_SHMEM) - + global_node_page_state(NR_UNEVICTABLE) - + total_swapcache_pages(); if (lowmem_adj_size < array_size) array_size = lowmem_adj_size; @@ -135,6 +144,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) { lowmem_print(5, "%s %lu, %x, return 0\n", __func__, sc->nr_to_scan, sc->gfp_mask); + mutex_unlock(&scan_mutex); return 0; } @@ -151,6 +161,9 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (time_before_eq(jiffies, lowmem_deathpending_timeout)) { if (test_task_lmk_waiting(tsk)) { rcu_read_unlock(); + /* give the system time to free up the memory */ + msleep_interruptible(20); + mutex_unlock(&scan_mutex); return 0; } } @@ -205,11 +218,14 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) free); lowmem_deathpending_timeout = jiffies + HZ; rem += selected_tasksize; + /* give the system time to free up the memory */ + msleep_interruptible(20); } lowmem_print(4, "%s %lu, %x, return %lu\n", __func__, sc->nr_to_scan, sc->gfp_mask, rem); rcu_read_unlock(); + mutex_unlock(&scan_mutex); return rem; } -- GitLab From 32acddacf38225d2dcecd6b7fdf5bdda57667568 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 3 Jul 2018 17:39:29 -0700 Subject: [PATCH 1209/1299] power: qpnp-fg-gen4: Update actual capacity when the profile is loaded Whenever the battery profile is loaded, actual or aged battery capacity should be updated with the nominal capacity. This is because it is outside the profile region and might contain OTP values. Change-Id: I11cc63d698289691df5ce2ab9ada1d32e48fe97c Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/qpnp-fg-gen4.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index 1fd5badf85e5..d34b8470d216 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -1474,7 +1474,7 @@ static void profile_load_work(struct work_struct *work) struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int64_t nom_cap_uah; - u8 val; + u8 val, buf[2]; int rc; vote(fg->awake_votable, PROFILE_LOAD, true, 0); @@ -1537,6 +1537,24 @@ static void profile_load_work(struct work_struct *work) if (fg->wa_flags & PM8150B_V1_DMA_WA) msleep(1000); + + /* + * Whenever battery profile is loaded, read nominal capacity and write + * it to actual (or aged) capacity as it is outside the profile region + * and might contain OTP values. + */ + rc = fg_sram_read(fg, NOM_CAP_WORD, NOM_CAP_OFFSET, buf, 2, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in reading %04x[%d] rc=%d\n", NOM_CAP_WORD, + NOM_CAP_OFFSET, rc); + } else { + rc = fg_sram_write(fg, fg->sp[FG_SRAM_ACT_BATT_CAP].addr_word, + fg->sp[FG_SRAM_ACT_BATT_CAP].addr_byte, buf, + fg->sp[FG_SRAM_ACT_BATT_CAP].len, FG_IMA_DEFAULT); + if (rc < 0) + pr_err("Error in writing to ACT_BATT_CAP rc=%d\n", rc); + } done: rc = fg_gen4_bp_params_config(fg); if (rc < 0) -- GitLab From 17dec66cf827ab1822bad47c74aa2cdde8b5f527 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Tue, 26 Jun 2018 10:39:00 -0700 Subject: [PATCH 1210/1299] net: qrtr: Change node mutex to a rw_semaphore There is a chance for a remote processor to become unresponsive while QRTR is trying to broadcast a control message. This results in the node lock being held for an extended period of time and prevents node lookup which is needed to send messages. Change the mutex to a rw_semaphore to allow concurrency during node lookups and broadcasts. Change-Id: I2e3fdde22edaac64f164cf08900e9d09b16c380d Signed-off-by: Chris Lew --- net/qrtr/qrtr.c | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 6bcbe6ee149c..4794353968c4 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -16,6 +16,7 @@ #include #include /* For TIOCINQ/OUTQ */ #include +#include #include @@ -115,7 +116,7 @@ static RADIX_TREE(qrtr_nodes, GFP_KERNEL); /* broadcast list */ static LIST_HEAD(qrtr_all_epts); /* lock for qrtr_nodes, qrtr_all_epts and node reference */ -static DEFINE_MUTEX(qrtr_node_lock); +static DECLARE_RWSEM(qrtr_node_lock); /* local port allocation management */ static DEFINE_IDR(qrtr_ports); @@ -163,6 +164,32 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, int type, struct sockaddr_qrtr *from, struct sockaddr_qrtr *to); +static bool refcount_dec_and_rwsem_lock(refcount_t *r, + struct rw_semaphore *sem) +{ + if (refcount_dec_not_one(r)) + return false; + + down_write(sem); + if (!refcount_dec_and_test(r)) { + up_write(sem); + return false; + } + + return true; +} + +static inline int kref_put_rwsem_lock(struct kref *kref, + void (*release)(struct kref *kref), + struct rw_semaphore *sem) +{ + if (refcount_dec_and_rwsem_lock(&kref->refcount, sem)) { + release(kref); + return 1; + } + return 0; +} + /* Release node resources and free the node. * * Do not call directly, use qrtr_node_release. To be used with @@ -182,7 +209,7 @@ static void __qrtr_node_release(struct kref *kref) } list_del(&node->item); - mutex_unlock(&qrtr_node_lock); + up_write(&qrtr_node_lock); /* Free tx flow counters */ radix_tree_for_each_slot(slot, &node->qrtr_tx_flow, &iter, 0) { @@ -207,7 +234,7 @@ static void qrtr_node_release(struct qrtr_node *node) { if (!node) return; - kref_put_mutex(&node->ref, __qrtr_node_release, &qrtr_node_lock); + kref_put_rwsem_lock(&node->ref, __qrtr_node_release, &qrtr_node_lock); } /** @@ -351,10 +378,10 @@ static struct qrtr_node *qrtr_node_lookup(unsigned int nid) { struct qrtr_node *node; - mutex_lock(&qrtr_node_lock); + down_read(&qrtr_node_lock); node = radix_tree_lookup(&qrtr_nodes, nid); node = qrtr_node_acquire(node); - mutex_unlock(&qrtr_node_lock); + up_read(&qrtr_node_lock); return node; } @@ -369,13 +396,13 @@ static void qrtr_node_assign(struct qrtr_node *node, unsigned int nid) if (nid == QRTR_EP_NID_AUTO) return; - mutex_lock(&qrtr_node_lock); + down_write(&qrtr_node_lock); if (!radix_tree_lookup(&qrtr_nodes, nid)) radix_tree_insert(&qrtr_nodes, nid, node); if (node->nid == QRTR_EP_NID_AUTO) node->nid = nid; - mutex_unlock(&qrtr_node_lock); + up_write(&qrtr_node_lock); } /** @@ -559,9 +586,9 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid) qrtr_node_assign(node, nid); - mutex_lock(&qrtr_node_lock); + down_write(&qrtr_node_lock); list_add(&node->item, &qrtr_all_epts); - mutex_unlock(&qrtr_node_lock); + up_write(&qrtr_node_lock); ep->node = node; return 0; @@ -862,7 +889,7 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, { struct sk_buff *skbn; - mutex_lock(&qrtr_node_lock); + down_read(&qrtr_node_lock); list_for_each_entry(node, &qrtr_all_epts, item) { if (node->nid == QRTR_EP_NID_AUTO) continue; @@ -872,7 +899,7 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, skb_set_owner_w(skbn, skb->sk); qrtr_node_enqueue(node, skbn, type, from, to); } - mutex_unlock(&qrtr_node_lock); + up_read(&qrtr_node_lock); qrtr_local_enqueue(node, skb, type, from, to); -- GitLab From 05cc45488555a71ccfee1c6f8279a9df78c3db65 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Wed, 27 Jun 2018 19:41:41 -0700 Subject: [PATCH 1211/1299] net: qrtr: Flush work during release The work struct to route packets to the appropriate port may sbe active when the endpoint unregister occurs. Flush the work struct before freeing the node structure. This change assumes that data will not be posted on the endpointed after getting an unregister call. Change-Id: Ia44dff6ca339dffa3e793d1545594da960240f8e Signed-off-by: Chris Lew --- net/qrtr/qrtr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 4794353968c4..9b6cd1ef83c9 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -217,6 +217,7 @@ static void __qrtr_node_release(struct kref *kref) kfree(*slot); } + flush_work(&node->work); skb_queue_purge(&node->rx_queue); kfree(node); } -- GitLab From 39dbfdd173e27455b9df9cca80798e2949eb2997 Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Thu, 7 Feb 2013 14:31:36 -0800 Subject: [PATCH 1212/1299] android/lowmemorykiller: Ignore tasks with freed mm A killed task can stay in the task list long after its memory has been returned to the system, therefore ignore any tasks whose mm struct has been freed. Change-Id: I76394b203b4ab2312437c839976f0ecb7b6dde4e Signed-off-by: Liam Mark Signed-off-by: Vinayak Menon --- arch/arm/include/asm/thread_info.h | 1 + arch/um/include/asm/thread_info.h | 1 + drivers/staging/android/lowmemorykiller.c | 24 ++++++++++++++++++++++- include/linux/sched/mm.h | 2 +- kernel/exit.c | 6 +++++- kernel/fork.c | 9 +++++++-- 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 776757d1604a..f23454db246f 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -148,6 +148,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, #define TIF_USING_IWMMXT 17 #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ #define TIF_RESTORE_SIGMASK 20 +#define TIF_MM_RELEASED 21 /* task MM has been released */ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index 9300f7630d2a..efe075a04533 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h @@ -66,6 +66,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_RESTORE_SIGMASK 7 #define TIF_NOTIFY_RESUME 8 #define TIF_SECCOMP 9 /* secure computing */ +#define TIF_MM_RELEASED 10 /* task MM has been released */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index a76aed5fe12b..56aa4debfdc0 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -83,6 +83,22 @@ static unsigned long lowmem_count(struct shrinker *s, global_node_page_state(NR_INACTIVE_FILE); } +static int test_task_flag(struct task_struct *p, int flag) +{ + struct task_struct *t = p; + + do { + task_lock(t); + if (test_tsk_thread_flag(t, flag)) { + task_unlock(t); + return 1; + } + task_unlock(t); + } while_each_thread(p, t); + + return 0; +} + static int test_task_lmk_waiting(struct task_struct *p) { struct task_struct *t = p; @@ -158,6 +174,10 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (tsk->flags & PF_KTHREAD) continue; + /* if task no longer has any memory ignore it */ + if (test_task_flag(tsk, TIF_MM_RELEASED)) + continue; + if (time_before_eq(jiffies, lowmem_deathpending_timeout)) { if (test_task_lmk_waiting(tsk)) { rcu_read_unlock(); @@ -218,13 +238,15 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) free); lowmem_deathpending_timeout = jiffies + HZ; rem += selected_tasksize; + rcu_read_unlock(); /* give the system time to free up the memory */ msleep_interruptible(20); + } else { + rcu_read_unlock(); } lowmem_print(4, "%s %lu, %x, return %lu\n", __func__, sc->nr_to_scan, sc->gfp_mask, rem); - rcu_read_unlock(); mutex_unlock(&scan_mutex); return rem; } diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h index 3d49b91b674d..c0ae94910277 100644 --- a/include/linux/sched/mm.h +++ b/include/linux/sched/mm.h @@ -84,7 +84,7 @@ static inline bool mmget_not_zero(struct mm_struct *mm) } /* mmput gets rid of the mappings and all user-space */ -extern void mmput(struct mm_struct *); +extern int mmput(struct mm_struct *mm); #ifdef CONFIG_MMU /* same as above but performs the slow path from the async context. Can * be called from the atomic context as well diff --git a/kernel/exit.c b/kernel/exit.c index 129005ce76ae..840a7851a4ae 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -499,6 +499,7 @@ static void exit_mm(void) { struct mm_struct *mm = current->mm; struct core_state *core_state; + int mm_released; mm_release(current, mm); if (!mm) @@ -545,9 +546,12 @@ static void exit_mm(void) enter_lazy_tlb(mm, current); task_unlock(current); mm_update_next_owner(mm); - mmput(mm); + + mm_released = mmput(mm); if (test_thread_flag(TIF_MEMDIE)) exit_oom_victim(); + if (mm_released) + set_tsk_thread_flag(current, TIF_MM_RELEASED); } static struct task_struct *find_alive_thread(struct task_struct *p) diff --git a/kernel/fork.c b/kernel/fork.c index d323550d6c14..93537008aa35 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -943,12 +943,17 @@ static inline void __mmput(struct mm_struct *mm) /* * Decrement the use count and release all resources for an mm. */ -void mmput(struct mm_struct *mm) +int mmput(struct mm_struct *mm) { + int mm_freed = 0; might_sleep(); - if (atomic_dec_and_test(&mm->mm_users)) + if (atomic_dec_and_test(&mm->mm_users)) { __mmput(mm); + mm_freed = 1; + } + + return mm_freed; } EXPORT_SYMBOL_GPL(mmput); -- GitLab From 51ae2f58a1d9cf87b36d4a7c1816b9fe7168e1e5 Mon Sep 17 00:00:00 2001 From: "seungho1.park" Date: Tue, 24 Jul 2012 10:20:44 +0900 Subject: [PATCH 1213/1299] android: lowmemorykiller: add lmk parameters tunning code. There are cases that LMK doesn't run, even when it must run. It is due to LMK shrinker not considering memory status per zone. So add LMK parameters(other_free, other_file) tunnig code to consider target zone of LMK shrinker. Change-Id: I6f1f8660d5da920a0e3af45a160499965032081d Git-commit: 22d990a58fc17b3f0155e15eb2dc3efa037bea1c Git-repo: https://android.googlesource.com/kernel/common/ [ohaugan@codeaurora.org: Fix compilation issues] Signed-off-by: Olav Haugan Signed-off-by: Liam Mark [vinmenon@codeaurora.org: change for movement of lrus from zone to node. KSWAPD_BALANCE_GAP_RATIO is no more available, but use its value so as to not break the code] Signed-off-by: Vinayak Menon Signed-off-by: Patrick Daly --- drivers/staging/android/lowmemorykiller.c | 94 ++++++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 56aa4debfdc0..c558ab092445 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -44,6 +44,13 @@ #include #include #include +#include + +#ifdef CONFIG_HIGHMEM +#define _ZONE ZONE_HIGHMEM +#else +#define _ZONE ZONE_NORMAL +#endif #define CREATE_TRACE_POINTS #include "trace/lowmemorykiller.h" @@ -65,6 +72,7 @@ static int lowmem_minfree[6] = { }; static int lowmem_minfree_size = 4; +static int lmk_fast_run = 1; static unsigned long lowmem_deathpending_timeout; @@ -117,6 +125,85 @@ static int test_task_lmk_waiting(struct task_struct *p) static DEFINE_MUTEX(scan_mutex); +void tune_lmk_zone_param(struct zonelist *zonelist, int classzone_idx, + int *other_free, int *other_file) +{ + struct zone *zone; + struct zoneref *zoneref; + int zone_idx; + + for_each_zone_zonelist(zone, zoneref, zonelist, MAX_NR_ZONES) { + if ((zone_idx = zonelist_zone_idx(zoneref)) == ZONE_MOVABLE) + continue; + + if (zone_idx > classzone_idx) { + if (other_free != NULL) + *other_free -= zone_page_state(zone, + NR_FREE_PAGES); + if (other_file != NULL) + *other_file -= zone_page_state(zone, + NR_ZONE_INACTIVE_FILE) + + zone_page_state(zone, + NR_ZONE_ACTIVE_FILE); + } else if ((zone_idx < classzone_idx) && other_free) { + if (zone_watermark_ok(zone, 0, 0, classzone_idx, 0)) + *other_free -= + zone->lowmem_reserve[classzone_idx]; + else + *other_free -= + zone_page_state(zone, NR_FREE_PAGES); + } + } +} + +void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc) +{ + gfp_t gfp_mask; + struct zone *preferred_zone; + struct zoneref *zref; + struct zonelist *zonelist; + enum zone_type high_zoneidx, classzone_idx; + unsigned long balance_gap; + + gfp_mask = sc->gfp_mask; + zonelist = node_zonelist(0, gfp_mask); + high_zoneidx = gfp_zone(gfp_mask); + zref = first_zones_zonelist(zonelist, high_zoneidx, NULL); + preferred_zone = zref->zone; + classzone_idx = zone_idx(preferred_zone); + + balance_gap = min(low_wmark_pages(preferred_zone), + (preferred_zone->present_pages + + 100-1) / + 100); + + if (likely(current_is_kswapd() && zone_watermark_ok(preferred_zone, 0, + high_wmark_pages(preferred_zone) + SWAP_CLUSTER_MAX + + balance_gap, 0, 0))) { + if (lmk_fast_run) + tune_lmk_zone_param(zonelist, classzone_idx, other_free, + other_file); + else + tune_lmk_zone_param(zonelist, classzone_idx, other_free, + NULL); + + if (zone_watermark_ok(preferred_zone, 0, 0, _ZONE, 0)) + *other_free -= + preferred_zone->lowmem_reserve[_ZONE]; + else + *other_free -= zone_page_state(preferred_zone, + NR_FREE_PAGES); + lowmem_print(4, "lowmem_shrink of kswapd tunning for highmem " + "ofree %d, %d\n", *other_free, *other_file); + } else { + tune_lmk_zone_param(zonelist, classzone_idx, other_free, + other_file); + + lowmem_print(4, "lowmem_shrink tunning for others ofree %d, " + "%d\n", *other_free, *other_file); + } +} + static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) { struct task_struct *tsk; @@ -141,6 +228,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) global_node_page_state(NR_UNEVICTABLE) - total_swapcache_pages(); + tune_lmk_param(&other_free, &other_file, sc); + if (lowmem_adj_size < array_size) array_size = lowmem_adj_size; if (lowmem_minfree_size < array_size) @@ -355,6 +444,7 @@ __MODULE_PARM_TYPE(adj, "array of short"); module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, 0644); #endif module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, - 0644); -module_param_named(debug_level, lowmem_debug_level, uint, 0644); + S_IRUGO | S_IWUSR); +module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR); +module_param_named(lmk_fast_run, lmk_fast_run, int, S_IRUGO | S_IWUSR); -- GitLab From 8df57cb4fa3206d67a591c70327ba7e14a3dc8f9 Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Wed, 27 Mar 2013 12:34:51 -0700 Subject: [PATCH 1214/1299] android/lowmemorykiller: Selectively count free CMA pages In certain memory configurations there can be a large number of CMA pages which are not suitable to satisfy certain memory requests. This large number of unsuitable pages can cause the lowmemorykiller to not kill any tasks because the lowmemorykiller counts all free pages. In order to ensure the lowmemorykiller properly evaluates the free memory only count the free CMA pages if they are suitable for satisfying the memory request. Change-Id: I7f06d53e2d8cfe7439e5561fe6e5209ce73b1c90 Signed-off-by: Liam Mark Signed-off-by: Vinayak Menon --- drivers/staging/android/lowmemorykiller.c | 89 +++++++++++++++++++---- include/linux/mmzone.h | 7 ++ mm/page_alloc.c | 5 ++ 3 files changed, 86 insertions(+), 15 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index c558ab092445..99ed6aabcc0b 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -125,16 +125,47 @@ static int test_task_lmk_waiting(struct task_struct *p) static DEFINE_MUTEX(scan_mutex); +static int can_use_cma_pages(gfp_t gfp_mask) +{ + int can_use = 0; + int mtype = gfpflags_to_migratetype(gfp_mask); + int i = 0; + int *mtype_fallbacks = get_migratetype_fallbacks(mtype); + + if (is_migrate_cma(mtype)) { + can_use = 1; + } else { + for (i = 0;; i++) { + int fallbacktype = mtype_fallbacks[i]; + + if (is_migrate_cma(fallbacktype)) { + can_use = 1; + break; + } + + if (fallbacktype == MIGRATE_TYPES) + break; + } + } + return can_use; +} + void tune_lmk_zone_param(struct zonelist *zonelist, int classzone_idx, - int *other_free, int *other_file) + int *other_free, int *other_file, + int use_cma_pages) { struct zone *zone; struct zoneref *zoneref; int zone_idx; for_each_zone_zonelist(zone, zoneref, zonelist, MAX_NR_ZONES) { - if ((zone_idx = zonelist_zone_idx(zoneref)) == ZONE_MOVABLE) + zone_idx = zonelist_zone_idx(zoneref); + if (zone_idx == ZONE_MOVABLE) { + if (!use_cma_pages && other_free) + *other_free -= + zone_page_state(zone, NR_FREE_CMA_PAGES); continue; + } if (zone_idx > classzone_idx) { if (other_free != NULL) @@ -146,12 +177,22 @@ void tune_lmk_zone_param(struct zonelist *zonelist, int classzone_idx, zone_page_state(zone, NR_ZONE_ACTIVE_FILE); } else if ((zone_idx < classzone_idx) && other_free) { - if (zone_watermark_ok(zone, 0, 0, classzone_idx, 0)) + if (zone_watermark_ok(zone, 0, 0, classzone_idx, 0)) { + if (!use_cma_pages) { + *other_free -= min( + zone->lowmem_reserve[classzone_idx] + + zone_page_state( + zone, NR_FREE_CMA_PAGES), + zone_page_state( + zone, NR_FREE_PAGES)); + } else { + *other_free -= + zone->lowmem_reserve[classzone_idx]; + } + } else { *other_free -= - zone->lowmem_reserve[classzone_idx]; - else - *other_free -= - zone_page_state(zone, NR_FREE_PAGES); + zone_page_state(zone, NR_FREE_PAGES); + } } } } @@ -164,6 +205,7 @@ void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc) struct zonelist *zonelist; enum zone_type high_zoneidx, classzone_idx; unsigned long balance_gap; + int use_cma_pages; gfp_mask = sc->gfp_mask; zonelist = node_zonelist(0, gfp_mask); @@ -171,6 +213,7 @@ void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc) zref = first_zones_zonelist(zonelist, high_zoneidx, NULL); preferred_zone = zref->zone; classzone_idx = zone_idx(preferred_zone); + use_cma_pages = can_use_cma_pages(gfp_mask); balance_gap = min(low_wmark_pages(preferred_zone), (preferred_zone->present_pages + @@ -182,22 +225,38 @@ void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc) balance_gap, 0, 0))) { if (lmk_fast_run) tune_lmk_zone_param(zonelist, classzone_idx, other_free, - other_file); + other_file, use_cma_pages); else tune_lmk_zone_param(zonelist, classzone_idx, other_free, - NULL); - - if (zone_watermark_ok(preferred_zone, 0, 0, _ZONE, 0)) - *other_free -= - preferred_zone->lowmem_reserve[_ZONE]; - else + NULL, use_cma_pages); + + if (zone_watermark_ok(preferred_zone, 0, 0, _ZONE, 0)) { + if (!use_cma_pages) { + *other_free -= min( + preferred_zone->lowmem_reserve[_ZONE] + + zone_page_state( + preferred_zone, NR_FREE_CMA_PAGES), + zone_page_state( + preferred_zone, NR_FREE_PAGES)); + } else { + *other_free -= + preferred_zone->lowmem_reserve[_ZONE]; + } + } else { *other_free -= zone_page_state(preferred_zone, NR_FREE_PAGES); + } + lowmem_print(4, "lowmem_shrink of kswapd tunning for highmem " "ofree %d, %d\n", *other_free, *other_file); } else { tune_lmk_zone_param(zonelist, classzone_idx, other_free, - other_file); + other_file, use_cma_pages); + + if (!use_cma_pages) { + *other_free -= + zone_page_state(preferred_zone, NR_FREE_CMA_PAGES); + } lowmem_print(4, "lowmem_shrink tunning for others ofree %d, " "%d\n", *other_free, *other_file); diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index f679f5268467..da6bb5bb3658 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -66,6 +66,13 @@ enum migratetype { /* In mm/page_alloc.c; keep in sync also with show_migration_types() there */ extern char * const migratetype_names[MIGRATE_TYPES]; +/* + * Returns a list which contains the migrate types on to which + * an allocation falls back when the free list for the migrate + * type mtype is depleted. + * The end of the list is delimited by the type MIGRATE_TYPES. + */ +extern int *get_migratetype_fallbacks(int mtype); #ifdef CONFIG_CMA # define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 1d8e455e0266..d9ac316e3043 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1854,6 +1854,11 @@ static int fallbacks[MIGRATE_TYPES][4] = { #endif }; +int *get_migratetype_fallbacks(int mtype) +{ + return fallbacks[mtype]; +} + #ifdef CONFIG_CMA static struct page *__rmqueue_cma_fallback(struct zone *zone, unsigned int order) -- GitLab From e6497c5a731973511aa32f3442ff03870f01fdcd Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Fri, 30 Aug 2013 12:10:39 -0700 Subject: [PATCH 1215/1299] android/lowmemorykiller: Account for total_swapcache_pages The lowmemorykiller relies on NR_FILE_PAGES when measuring the amount of reclaimable memory in the system. However when swap is enabled swap cache pages are counted in NR_FILE_PAGES, and swap cache pages aren't as reclaimable in low memory as file cache pages. Therefore a large swap cache can result in the lowmemorykiller not running and an OOM occurring. In order to ensure the lowmemorykiller properly evaluates the amount of reclaimable memory don't count the swap cache pages. Change-Id: I38239283e572f814b277c718eaf6be7f92abacbb Signed-off-by: Liam Mark Signed-off-by: Vinayak Menon --- drivers/staging/android/lowmemorykiller.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 99ed6aabcc0b..aee5318ea622 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -45,6 +45,7 @@ #include #include #include +#include #ifdef CONFIG_HIGHMEM #define _ZONE ZONE_HIGHMEM @@ -282,10 +283,16 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) return 0; other_free = global_zone_page_state(NR_FREE_PAGES) - totalreserve_pages; - other_file = global_node_page_state(NR_FILE_PAGES) - + + if (global_node_page_state(NR_SHMEM) + total_swapcache_pages() + + global_node_page_state(NR_UNEVICTABLE) < + global_node_page_state(NR_FILE_PAGES)) + other_file = global_node_page_state(NR_FILE_PAGES) - global_node_page_state(NR_SHMEM) - global_node_page_state(NR_UNEVICTABLE) - total_swapcache_pages(); + else + other_file = 0; tune_lmk_param(&other_free, &other_file, sc); -- GitLab From e4bd0a3a97ab2429c46c340a1cb311a9b2bccc2c Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Mon, 10 Mar 2014 16:06:39 -0700 Subject: [PATCH 1216/1299] lowmemorykiller: Account for highmem during kswapd reclaim Currenlty most memory reclaim is done through kswapd. Since kswapd uses a gfp mask of GFP_KERNEL, and because the lowmemorykiller is zone aware, the lowmemorykiller will ignore highmem most of the time. This results in the lowmemorykiller being overly aggressive. The fix to this issue is to allow the lowmemorykiller to count highmem when being called by the kswapd if the lowmem watermarks are satisfied. Change-Id: I938644584f374763d10d429d835e74daa4854a38 Signed-off-by: Liam Mark Signed-off-by: Vinayak Menon --- drivers/staging/android/lowmemorykiller.c | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index aee5318ea622..e589ad7a60b1 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -198,6 +198,37 @@ void tune_lmk_zone_param(struct zonelist *zonelist, int classzone_idx, } } +#ifdef CONFIG_HIGHMEM +static void adjust_gfp_mask(gfp_t *gfp_mask) +{ + struct zone *preferred_zone; + struct zoneref *zref; + struct zonelist *zonelist; + enum zone_type high_zoneidx; + + if (current_is_kswapd()) { + zonelist = node_zonelist(0, *gfp_mask); + high_zoneidx = gfp_zone(*gfp_mask); + zref = first_zones_zonelist(zonelist, high_zoneidx, NULL); + preferred_zone = zref->zone; + + if (high_zoneidx == ZONE_NORMAL) { + if (zone_watermark_ok_safe( + preferred_zone, 0, + high_wmark_pages(preferred_zone), 0, + 0)) + *gfp_mask |= __GFP_HIGHMEM; + } else if (high_zoneidx == ZONE_HIGHMEM) { + *gfp_mask |= __GFP_HIGHMEM; + } + } +} +#else +static void adjust_gfp_mask(gfp_t *unused) +{ +} +#endif + void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc) { gfp_t gfp_mask; @@ -209,6 +240,8 @@ void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc) int use_cma_pages; gfp_mask = sc->gfp_mask; + adjust_gfp_mask(&gfp_mask); + zonelist = node_zonelist(0, gfp_mask); high_zoneidx = gfp_zone(gfp_mask); zref = first_zones_zonelist(zonelist, high_zoneidx, NULL); -- GitLab From e962892d82aa1acd7b9223f51d195436c3d3f5f8 Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Tue, 3 Jun 2014 13:57:47 -0700 Subject: [PATCH 1217/1299] lowmemorykiller: enhance debug information Add extra debug information to make it easier to both determine why the lowmemorykiller killed a process and to help find the source of memory leaks. Also increase the debug level for "select" statements to help prevent flooding the log. Change-Id: I3b6876c5ecdf192ecc271aed3f37579f66d47a08 Signed-off-by: Liam Mark [vinmenon@codeaurora.org: fix checkpatch warnings] Signed-off-by: Vinayak Menon --- drivers/staging/android/lowmemorykiller.c | 42 +++++++++++++++++------ 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index e589ad7a60b1..94480efd5c97 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -46,6 +46,7 @@ #include #include #include +#include #ifdef CONFIG_HIGHMEM #define _ZONE ZONE_HIGHMEM @@ -399,7 +400,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) selected = p; selected_tasksize = tasksize; selected_oom_score_adj = oom_score_adj; - lowmem_print(2, "select '%s' (%d), adj %hd, size %d, to kill\n", + lowmem_print(3, "select '%s' (%d), adj %hd, size %d, to kill\n", p->comm, p->pid, oom_score_adj, tasksize); } if (selected) { @@ -414,16 +415,35 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) task_unlock(selected); trace_lowmemory_kill(selected, cache_size, cache_limit, free); lowmem_print(1, "Killing '%s' (%d) (tgid %d), adj %hd,\n" - " to free %ldkB on behalf of '%s' (%d) because\n" - " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" - " Free memory is %ldkB above reserved\n", - selected->comm, selected->pid, selected->tgid, - selected_oom_score_adj, - selected_tasksize * (long)(PAGE_SIZE / 1024), - current->comm, current->pid, - cache_size, cache_limit, - min_score_adj, - free); + "to free %ldkB on behalf of '%s' (%d) because\n" + "cache %ldkB is below limit %ldkB for oom score %hd\n" + "Free memory is %ldkB above reserved.\n" + "Free CMA is %ldkB\n" + "Total reserve is %ldkB\n" + "Total free pages is %ldkB\n" + "Total file cache is %ldkB\n" + "GFP mask is 0x%x\n", + selected->comm, selected->pid, selected->tgid, + selected_oom_score_adj, + selected_tasksize * (long)(PAGE_SIZE / 1024), + current->comm, current->pid, + cache_size, cache_limit, + min_score_adj, + free, + global_zone_page_state(NR_FREE_CMA_PAGES) * + (long)(PAGE_SIZE / 1024), + totalreserve_pages * (long)(PAGE_SIZE / 1024), + global_zone_page_state(NR_FREE_PAGES) * + (long)(PAGE_SIZE / 1024), + global_node_page_state(NR_FILE_PAGES) * + (long)(PAGE_SIZE / 1024), + sc->gfp_mask); + + if (lowmem_debug_level >= 2 && selected_oom_score_adj == 0) { + show_mem(SHOW_MEM_FILTER_NODES, NULL); + dump_tasks(NULL, NULL); + } + lowmem_deathpending_timeout = jiffies + HZ; rem += selected_tasksize; rcu_read_unlock(); -- GitLab From cbe635911d035db07f042f367398799e388b7b77 Mon Sep 17 00:00:00 2001 From: Susheel Khiani Date: Thu, 12 Feb 2015 19:00:15 +0530 Subject: [PATCH 1218/1299] lowmemorykiller: Do proper NULL checks Pointer other_free is getting dereferenced without performing proper NULL checks which may cause issue. Do proper NULL checks at all points before dereferencing it. Change-Id: I88515703d64730e42598ab16136dcce4c18b099c Signed-off-by: Susheel Khiani --- drivers/staging/android/lowmemorykiller.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 94480efd5c97..b336d997c493 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -178,8 +178,9 @@ void tune_lmk_zone_param(struct zonelist *zonelist, int classzone_idx, NR_ZONE_INACTIVE_FILE) + zone_page_state(zone, NR_ZONE_ACTIVE_FILE); - } else if ((zone_idx < classzone_idx) && other_free) { - if (zone_watermark_ok(zone, 0, 0, classzone_idx, 0)) { + } else if (zone_idx < classzone_idx) { + if (zone_watermark_ok(zone, 0, 0, classzone_idx, 0) && + other_free) { if (!use_cma_pages) { *other_free -= min( zone->lowmem_reserve[classzone_idx] + @@ -192,8 +193,9 @@ void tune_lmk_zone_param(struct zonelist *zonelist, int classzone_idx, zone->lowmem_reserve[classzone_idx]; } } else { - *other_free -= - zone_page_state(zone, NR_FREE_PAGES); + if (other_free) + *other_free -= + zone_page_state(zone, NR_FREE_PAGES); } } } -- GitLab From ebea3f9b130d18543c839ee06dc551574bc64643 Mon Sep 17 00:00:00 2001 From: Tirupathi Reddy Date: Fri, 29 Jun 2018 21:30:09 +0530 Subject: [PATCH 1219/1299] ARM: dts: msm: Update the PMIC related DT configuration for QCS405 Change the below PMIC configurations for QCS405 1. enable SMB1351 only for SKU1 2. MX and LPI_CX resource-id 3. APC CPR fused-voltage step-size to 8mV 4. PON interrupt configuration Change-Id: Idd4564828982525372aa55d17be136f398f2e414 Signed-off-by: Tirupathi Reddy --- arch/arm64/boot/dts/qcom/pms405-rpm-regulator.dtsi | 4 ++-- arch/arm64/boot/dts/qcom/pms405.dtsi | 2 +- arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts | 8 ++++++++ arch/arm64/boot/dts/qcom/qcs405-regulator.dtsi | 2 +- arch/arm64/boot/dts/qcom/qcs405.dtsi | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/pms405-rpm-regulator.dtsi b/arch/arm64/boot/dts/qcom/pms405-rpm-regulator.dtsi index dd0200ef5027..5b5c9d76cf4c 100644 --- a/arch/arm64/boot/dts/qcom/pms405-rpm-regulator.dtsi +++ b/arch/arm64/boot/dts/qcom/pms405-rpm-regulator.dtsi @@ -15,7 +15,7 @@ rpm-regulator-smpa1 { compatible = "qcom,rpm-smd-regulator-resource"; qcom,resource-name = "rwmx"; - qcom,resource-id = <1>; + qcom,resource-id = <0>; qcom,regulator-type = <1>; qcom,hpm-min-load = <100000>; status = "disabled"; @@ -32,7 +32,7 @@ rpm-regulator-smpa2 { compatible = "qcom,rpm-smd-regulator-resource"; qcom,resource-name = "rwlc"; - qcom,resource-id = <2>; + qcom,resource-id = <0>; qcom,regulator-type = <1>; qcom,hpm-min-load = <100000>; status = "disabled"; diff --git a/arch/arm64/boot/dts/qcom/pms405.dtsi b/arch/arm64/boot/dts/qcom/pms405.dtsi index 3717e39aa861..7149c9b1f5b1 100644 --- a/arch/arm64/boot/dts/qcom/pms405.dtsi +++ b/arch/arm64/boot/dts/qcom/pms405.dtsi @@ -87,7 +87,7 @@ pms405_pon: qcom,power-on@800 { compatible = "qcom,qpnp-power-on"; reg = <0x800 0x100>; - interrupts = <0x0 0x8 0x0>; + interrupts = <0x0 0x8 0x0 IRQ_TYPE_NONE>; interrupt-names = "kpdpwr"; qcom,pon-dbc-delay = <15625>; diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts index b90cde09f737..b450ced5cf2e 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts +++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku1.dts @@ -21,3 +21,11 @@ compatible = "qcom,qcs405-iot", "qcom,qcs405", "qcom,iot"; qcom,board-id = <0x010020 0>; }; + +&i2c_5 { + status = "ok"; +}; + +&smb1351_otg_supply { + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405-regulator.dtsi b/arch/arm64/boot/dts/qcom/qcs405-regulator.dtsi index 74f0a257332b..ecaccdccf65c 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-regulator.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-regulator.dtsi @@ -339,7 +339,7 @@ <70 19 7 0>, <70 26 7 0>; qcom,cpr-fuse-quot-offset-scale = <5 5 5>; - qcom,cpr-init-voltage-step = <10000>; + qcom,cpr-init-voltage-step = <8000>; qcom,cpr-corner-map = <1 2 3>; qcom,mem-acc-corner-map = <1 2 2>; qcom,cpr-corner-frequency-map = diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 3f054faf4597..8933719bc620 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -995,8 +995,8 @@ #include "qcs405-usb.dtsi" &i2c_5 { - status = "ok"; smb1351_otg_supply: smb1351-charger@55 { + status = "disabled"; compatible = "qcom,smb1351-charger"; reg = <0x55>; interrupt-parent = <&tlmm>; -- GitLab From 72d03d4746ab59d58d7e080dacd9058697b47027 Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Mon, 2 Jul 2018 22:39:45 +0530 Subject: [PATCH 1220/1299] drivers: pinctrl: qcom: Forward all tlmm interrupt calls to parent TLMM interrupt controller is child to mpm interrupt controller. Add changes to forward all interrupt calls to parent mpm. Change-Id: Iae5f91328125150aa67d7a505609d94682f836c2 Signed-off-by: Raghavendra Kakarla --- drivers/pinctrl/qcom/pinctrl-msm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 9bea154ffff1..2569bc7d5920 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -885,16 +885,21 @@ static int msm_gpio_domain_translate(struct irq_domain *d, static int msm_gpio_domain_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, void *arg) { - int ret; + int ret = 0; irq_hw_number_t hwirq; - struct irq_fwspec *fwspec = arg; + struct irq_fwspec *fwspec = arg, parent_fwspec; ret = msm_gpio_domain_translate(domain, fwspec, &hwirq, NULL); if (ret) return ret; msm_gpio_domain_set_info(domain, virq, hwirq); - return ret; + + parent_fwspec = *fwspec; + parent_fwspec.fwnode = domain->parent->fwnode; + + return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, + &parent_fwspec); } static const struct irq_domain_ops msm_gpio_domain_ops = { @@ -1339,11 +1344,6 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) chip->parent = pctrl->dev; chip->owner = THIS_MODULE; chip->of_node = pctrl->dev->of_node; - chip->irqchip = &msm_gpio_irq_chip; - chip->irq_handler = handle_fasteoi_irq; - chip->irq_default_type = IRQ_TYPE_NONE; - chip->to_irq = msm_gpiochip_to_irq; - chip->lock_key = NULL; ret = gpiochip_add_data(&pctrl->chip, pctrl); if (ret) { -- GitLab From 230e0a7d40842a3a2c34b7e1603454bfd5491d8a Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Tue, 3 Jul 2018 00:23:46 +0530 Subject: [PATCH 1221/1299] ARM: dts: msm: Support 16bit vlevel setting from SAW for qcs405 Update pvc port configuration for sending upper byte of 16bit vlevel for qcs405. Change-Id: I85087c459e7cc04c10295a36524ce361714a21ae Signed-off-by: Raghavendra Kakarla --- arch/arm64/boot/dts/qcom/qcs405-pm.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405-pm.dtsi b/arch/arm64/boot/dts/qcom/qcs405-pm.dtsi index 85a2e9fe566e..36b8d2cdcef3 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-pm.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-pm.dtsi @@ -26,6 +26,8 @@ qcom,cpu-vctl-list = <&CPU0 &CPU1 &CPU2 &CPU3>; qcom,vctl-timeout-us = <500>; qcom,vctl-port = <0x0>; + qcom,vctl-port-ub = <0x1>; + qcom,pfm-port = <0x02>; }; qcom,lpm-levels { -- GitLab From f64cd7345eb3cb471b3650a8332746b1c564f1fc Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Fri, 29 Jun 2018 14:34:22 +0530 Subject: [PATCH 1222/1299] clk: qcom: Kconfig: Add support to select GDSC flag Select GDSC flag whenever we select flag for global clock controlller so that all the gdsc also get registered along with GCC. Change-Id: I7cffc5252c45e2e0c10325037794b9a4263a58f4 Signed-off-by: Shefali Jain --- drivers/clk/qcom/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 768a462dfb3d..61ed49c4eaa9 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -318,6 +318,7 @@ config MSM_CAMCC_SDMSHRIKE config MDM_GCC_QCS405 tristate "QCS405 Global Clock Controller" + select QCOM_GDSC depends on COMMON_CLK_QCOM help Support for the global clock controller on Qualcomm Technologies, Inc -- GitLab From 770ececf950a175c4c4c1ad3663dfe301e36f4eb Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Fri, 29 Jun 2018 15:28:00 +0530 Subject: [PATCH 1223/1299] drivers: rpmsg: rpm-smd: populate the rpm-bus child devices populate rpm-bus child devices in rpm-smd. Change-Id: Ib57467509c02a826446f9bef51aec19c11e1f2f6 Signed-off-by: Raghavendra Kakarla --- drivers/rpmsg/rpm-smd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/rpmsg/rpm-smd.c b/drivers/rpmsg/rpm-smd.c index 65f2fbb9d4fc..be2e69dcdc03 100644 --- a/drivers/rpmsg/rpm-smd.c +++ b/drivers/rpmsg/rpm-smd.c @@ -1608,8 +1608,7 @@ static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev) spin_lock_init(&msm_rpm_data.smd_lock_read); skip_init: - probe_status = of_platform_populate(rpdev->dev.of_node, - NULL, NULL, &rpdev->dev); + probe_status = of_platform_populate(p, NULL, NULL, &rpdev->dev); if (standalone) pr_info("RPM running in standalone mode\n"); -- GitLab From 7964b3ce47f0d87fbbb1cfdd1fb4aadb620133dd Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Fri, 20 Mar 2015 14:15:39 +0530 Subject: [PATCH 1224/1299] mm: process reclaim: vmpressure based process reclaim With this patch, anon pages of inactive tasks can be reclaimed, depending on memory pressure. Memory pressure is detected using vmpressure events. 'N' best tasks in terms of anon size is selected and pages proportional to their tasksize is reclaimed. The total number of pages reclaimed at each run of the swap work, can be tuned from userspace, the default being SWAP_CLUSTER_MAX * 32. The patch also adds tracepoints to debug and tune the feature. echo 1 > /sys/module/process_reclaim/parameters/enable_process_reclaim to enable the feature. echo > /sys/module/process_reclaim/parameters/per_swap_size, to set the number of pages reclaimed in each scan. /sys/module/process_reclaim/parameters/reclaim_avg_efficiency, provides the average efficiency (scan to reclaim ratio) of the algorithm. /sys/module/process_reclaim/parameters/swap_eff_win, to set the window period (in unit of number of times reclaim is triggered) to detect low efficiency runs. /sys/module/process_reclaim/parameters/swap_opt_eff, to set the optimal efficiency threshold for low efficiency detection. Change-Id: I895986f10c997d1715761eaaadc4bbbee60db9d2 Signed-off-by: Vinayak Menon --- fs/proc/task_mmu.c | 71 ++++++- include/linux/mm.h | 14 ++ include/trace/events/process_reclaim.h | 85 +++++++++ mm/Makefile | 1 + mm/process_reclaim.c | 251 +++++++++++++++++++++++++ 5 files changed, 415 insertions(+), 7 deletions(-) create mode 100644 include/trace/events/process_reclaim.h create mode 100644 mm/process_reclaim.c diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 2f7e1e90a9e6..cb3ad7e47df0 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1648,15 +1648,17 @@ const struct file_operations proc_pagemap_operations = { static int reclaim_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, struct mm_walk *walk) { - struct vm_area_struct *vma = walk->private; + struct reclaim_param *rp = walk->private; + struct vm_area_struct *vma = rp->vma; pte_t *pte, ptent; spinlock_t *ptl; struct page *page; LIST_HEAD(page_list); int isolated; + int reclaimed; split_huge_pmd(vma, addr, pmd); - if (pmd_trans_unstable(pmd)) + if (pmd_trans_unstable(pmd) || !rp->nr_to_reclaim) return 0; cont: isolated = 0; @@ -1677,12 +1679,18 @@ static int reclaim_pte_range(pmd_t *pmd, unsigned long addr, inc_node_page_state(page, NR_ISOLATED_ANON + page_is_file_cache(page)); isolated++; - if (isolated >= SWAP_CLUSTER_MAX) + rp->nr_scanned++; + if ((isolated >= SWAP_CLUSTER_MAX) || !rp->nr_to_reclaim) break; } pte_unmap_unlock(pte - 1, ptl); - reclaim_pages_from_list(&page_list, vma); - if (addr != end) + reclaimed = reclaim_pages_from_list(&page_list, vma); + rp->nr_reclaimed += reclaimed; + rp->nr_to_reclaim -= reclaimed; + if (rp->nr_to_reclaim < 0) + rp->nr_to_reclaim = 0; + + if (rp->nr_to_reclaim && (addr != end)) goto cont; cond_resched(); @@ -1696,6 +1704,50 @@ enum reclaim_type { RECLAIM_RANGE, }; +struct reclaim_param reclaim_task_anon(struct task_struct *task, + int nr_to_reclaim) +{ + struct mm_struct *mm; + struct vm_area_struct *vma; + struct mm_walk reclaim_walk = {}; + struct reclaim_param rp = { + .nr_to_reclaim = nr_to_reclaim, + }; + + get_task_struct(task); + mm = get_task_mm(task); + if (!mm) + goto out; + + reclaim_walk.mm = mm; + reclaim_walk.pmd_entry = reclaim_pte_range; + + reclaim_walk.private = &rp; + + down_read(&mm->mmap_sem); + for (vma = mm->mmap; vma; vma = vma->vm_next) { + if (is_vm_hugetlb_page(vma)) + continue; + + if (vma->vm_file) + continue; + + if (!rp.nr_to_reclaim) + break; + + rp.vma = vma; + walk_page_range(vma->vm_start, vma->vm_end, + &reclaim_walk); + } + + flush_tlb_mm(mm); + up_read(&mm->mmap_sem); + mmput(mm); +out: + put_task_struct(task); + return rp; +} + static ssize_t reclaim_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { @@ -1708,6 +1760,7 @@ static ssize_t reclaim_write(struct file *file, const char __user *buf, struct mm_walk reclaim_walk = {}; unsigned long start = 0; unsigned long end = 0; + struct reclaim_param rp; memset(buffer, 0, sizeof(buffer)); if (count > sizeof(buffer) - 1) @@ -1770,6 +1823,10 @@ static ssize_t reclaim_write(struct file *file, const char __user *buf, reclaim_walk.mm = mm; reclaim_walk.pmd_entry = reclaim_pte_range; + rp.nr_to_reclaim = INT_MAX; + rp.nr_reclaimed = 0; + reclaim_walk.private = &rp; + down_read(&mm->mmap_sem); if (type == RECLAIM_RANGE) { vma = find_vma(mm, start); @@ -1779,7 +1836,7 @@ static ssize_t reclaim_write(struct file *file, const char __user *buf, if (is_vm_hugetlb_page(vma)) continue; - reclaim_walk.private = vma; + rp.vma = vma; walk_page_range(max(vma->vm_start, start), min(vma->vm_end, end), &reclaim_walk); @@ -1796,7 +1853,7 @@ static ssize_t reclaim_write(struct file *file, const char __user *buf, if (type == RECLAIM_FILE && !vma->vm_file) continue; - reclaim_walk.private = vma; + rp.vma = vma; walk_page_range(vma->vm_start, vma->vm_end, &reclaim_walk); } diff --git a/include/linux/mm.h b/include/linux/mm.h index 21385142e63a..f1b0668551e9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2749,5 +2749,19 @@ static inline void setup_nr_node_ids(void) {} extern int want_old_faultaround_pte; +#ifdef CONFIG_PROCESS_RECLAIM +struct reclaim_param { + struct vm_area_struct *vma; + /* Number of pages scanned */ + int nr_scanned; + /* max pages to reclaim */ + int nr_to_reclaim; + /* pages reclaimed */ + int nr_reclaimed; +}; +extern struct reclaim_param reclaim_task_anon(struct task_struct *task, + int nr_to_reclaim); +#endif + #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/include/trace/events/process_reclaim.h b/include/trace/events/process_reclaim.h new file mode 100644 index 000000000000..d79327ee4969 --- /dev/null +++ b/include/trace/events/process_reclaim.h @@ -0,0 +1,85 @@ +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM process_reclaim + +#if !defined(_TRACE_EVENT_PROCESSRECLAIM_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_EVENT_PROCESSRECLAIM_H + +#include +#include +#include + +TRACE_EVENT(process_reclaim, + + TP_PROTO(int tasksize, + short oom_score_adj, + int nr_scanned, int nr_reclaimed, + int per_swap_size, int total_sz, + int nr_to_reclaim), + + TP_ARGS(tasksize, oom_score_adj, nr_scanned, + nr_reclaimed, per_swap_size, + total_sz, nr_to_reclaim), + + TP_STRUCT__entry( + __field(int, tasksize) + __field(short, oom_score_adj) + __field(int, nr_scanned) + __field(int, nr_reclaimed) + __field(int, per_swap_size) + __field(int, total_sz) + __field(int, nr_to_reclaim) + ), + + TP_fast_assign( + __entry->tasksize = tasksize; + __entry->oom_score_adj = oom_score_adj; + __entry->nr_scanned = nr_scanned; + __entry->nr_reclaimed = nr_reclaimed; + __entry->per_swap_size = per_swap_size; + __entry->total_sz = total_sz; + __entry->nr_to_reclaim = nr_to_reclaim; + ), + + TP_printk("%d, %hd, %d, %d, %d, %d, %d", + __entry->tasksize, __entry->oom_score_adj, + __entry->nr_scanned, __entry->nr_reclaimed, + __entry->per_swap_size, __entry->total_sz, + __entry->nr_to_reclaim) +); + +TRACE_EVENT(process_reclaim_eff, + + TP_PROTO(int efficiency, int reclaim_avg_efficiency), + + TP_ARGS(efficiency, reclaim_avg_efficiency), + + TP_STRUCT__entry( + __field(int, efficiency) + __field(int, reclaim_avg_efficiency) + ), + + TP_fast_assign( + __entry->efficiency = efficiency; + __entry->reclaim_avg_efficiency = reclaim_avg_efficiency; + ), + + TP_printk("%d, %d", __entry->efficiency, + __entry->reclaim_avg_efficiency) +); + +#endif + +#include + diff --git a/mm/Makefile b/mm/Makefile index 3243322fb58f..61e1aac6a150 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -104,3 +104,4 @@ obj-$(CONFIG_DEBUG_PAGE_REF) += debug_page_ref.o obj-$(CONFIG_HARDENED_USERCOPY) += usercopy.o obj-$(CONFIG_PERCPU_STATS) += percpu-stats.o obj-$(CONFIG_HMM) += hmm.o +obj-$(CONFIG_PROCESS_RECLAIM) += process_reclaim.o diff --git a/mm/process_reclaim.c b/mm/process_reclaim.c new file mode 100644 index 000000000000..92ce0a5c105c --- /dev/null +++ b/mm/process_reclaim.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CREATE_TRACE_POINTS +#include + +#define MAX_SWAP_TASKS SWAP_CLUSTER_MAX + +static void swap_fn(struct work_struct *work); +DECLARE_WORK(swap_work, swap_fn); + +/* User knob to enable/disable process reclaim feature */ +static int enable_process_reclaim; +module_param_named(enable_process_reclaim, enable_process_reclaim, int, 0644); + +/* The max number of pages tried to be reclaimed in a single run */ +int per_swap_size = SWAP_CLUSTER_MAX * 32; +module_param_named(per_swap_size, per_swap_size, int, 0644); + +int reclaim_avg_efficiency; +module_param_named(reclaim_avg_efficiency, reclaim_avg_efficiency, int, 0444); + +/* The vmpressure region where process reclaim operates */ +static unsigned long pressure_min = 50; +static unsigned long pressure_max = 90; +module_param_named(pressure_min, pressure_min, ulong, 0644); +module_param_named(pressure_max, pressure_max, ulong, 0644); + +/* + * Scheduling process reclaim workqueue unecessarily + * when the reclaim efficiency is low does not make + * sense. We try to detect a drop in efficiency and + * disable reclaim for a time period. This period and the + * period for which we monitor a drop in efficiency is + * defined by swap_eff_win. swap_opt_eff is the optimal + * efficincy used as theshold for this. + */ +static int swap_eff_win = 2; +module_param_named(swap_eff_win, swap_eff_win, int, 0644); + +static int swap_opt_eff = 50; +module_param_named(swap_opt_eff, swap_opt_eff, int, 0644); + +static atomic_t skip_reclaim = ATOMIC_INIT(0); +/* Not atomic since only a single instance of swap_fn run at a time */ +static int monitor_eff; + +struct selected_task { + struct task_struct *p; + int tasksize; + short oom_score_adj; +}; + +int selected_cmp(const void *a, const void *b) +{ + const struct selected_task *x = a; + const struct selected_task *y = b; + int ret; + + ret = x->tasksize < y->tasksize ? -1 : 1; + + return ret; +} + +static int test_task_flag(struct task_struct *p, int flag) +{ + struct task_struct *t = p; + + rcu_read_lock(); + for_each_thread(p, t) { + task_lock(t); + if (test_tsk_thread_flag(t, flag)) { + task_unlock(t); + rcu_read_unlock(); + return 1; + } + task_unlock(t); + } + rcu_read_unlock(); + + return 0; +} + +static void swap_fn(struct work_struct *work) +{ + struct task_struct *tsk; + struct reclaim_param rp; + + /* Pick the best MAX_SWAP_TASKS tasks in terms of anon size */ + struct selected_task selected[MAX_SWAP_TASKS] = {{0, 0, 0},}; + int si = 0; + int i; + int tasksize; + int total_sz = 0; + short min_score_adj = 360; + int total_scan = 0; + int total_reclaimed = 0; + int nr_to_reclaim; + int efficiency; + + rcu_read_lock(); + for_each_process(tsk) { + struct task_struct *p; + short oom_score_adj; + + if (tsk->flags & PF_KTHREAD) + continue; + + if (test_task_flag(tsk, TIF_MEMDIE)) + continue; + + p = find_lock_task_mm(tsk); + if (!p) + continue; + + oom_score_adj = p->signal->oom_score_adj; + if (oom_score_adj < min_score_adj) { + task_unlock(p); + continue; + } + + tasksize = get_mm_counter(p->mm, MM_ANONPAGES); + task_unlock(p); + + if (tasksize <= 0) + continue; + + if (si == MAX_SWAP_TASKS) { + sort(&selected[0], MAX_SWAP_TASKS, + sizeof(struct selected_task), + &selected_cmp, NULL); + if (tasksize < selected[0].tasksize) + continue; + selected[0].p = p; + selected[0].oom_score_adj = oom_score_adj; + selected[0].tasksize = tasksize; + } else { + selected[si].p = p; + selected[si].oom_score_adj = oom_score_adj; + selected[si].tasksize = tasksize; + si++; + } + } + + for (i = 0; i < si; i++) + total_sz += selected[i].tasksize; + + /* Skip reclaim if total size is too less */ + if (total_sz < SWAP_CLUSTER_MAX) { + rcu_read_unlock(); + return; + } + + for (i = 0; i < si; i++) + get_task_struct(selected[i].p); + + rcu_read_unlock(); + + while (si--) { + nr_to_reclaim = + (selected[si].tasksize * per_swap_size) / total_sz; + /* scan atleast a page */ + if (!nr_to_reclaim) + nr_to_reclaim = 1; + + rp = reclaim_task_anon(selected[si].p, nr_to_reclaim); + + trace_process_reclaim(selected[si].tasksize, + selected[si].oom_score_adj, rp.nr_scanned, + rp.nr_reclaimed, per_swap_size, total_sz, + nr_to_reclaim); + total_scan += rp.nr_scanned; + total_reclaimed += rp.nr_reclaimed; + put_task_struct(selected[si].p); + } + + if (total_scan) { + efficiency = (total_reclaimed * 100) / total_scan; + + if (efficiency < swap_opt_eff) { + if (++monitor_eff == swap_eff_win) { + atomic_set(&skip_reclaim, swap_eff_win); + monitor_eff = 0; + } + } else { + monitor_eff = 0; + } + + reclaim_avg_efficiency = + (efficiency + reclaim_avg_efficiency) / 2; + trace_process_reclaim_eff(efficiency, reclaim_avg_efficiency); + } +} + +static int vmpressure_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + unsigned long pressure = action; + + if (!enable_process_reclaim) + return 0; + + if (!current_is_kswapd()) + return 0; + + if (atomic_dec_if_positive(&skip_reclaim) >= 0) + return 0; + + if ((pressure >= pressure_min) && (pressure < pressure_max)) + if (!work_pending(&swap_work)) + queue_work(system_unbound_wq, &swap_work); + return 0; +} + +static struct notifier_block vmpr_nb = { + .notifier_call = vmpressure_notifier, +}; + +static int __init process_reclaim_init(void) +{ + vmpressure_notifier_register(&vmpr_nb); + return 0; +} + +static void __exit process_reclaim_exit(void) +{ + vmpressure_notifier_unregister(&vmpr_nb); +} + +module_init(process_reclaim_init); +module_exit(process_reclaim_exit); -- GitLab From 2493065a6926bc80d110c8a4856a7cd16311f5d3 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Wed, 19 Aug 2015 16:16:39 +0530 Subject: [PATCH 1225/1299] mm: vmpressure: account allocstalls only on higher pressures At present any vmpressure value is scaled up if the pages are reclaimed through direct reclaim. This can result in false vmpressure values. Consider a case where a device is booted up and most of the memory is occuppied by file pages. kswapd will make sure that high watermark is maintained. Now when a sudden huge allocation request comes in, the system will definitely have to get into direct reclaims. The vmpressures can be very low, but because of allocstall accounting logic even these low values will be scaled to values nearing 100. This can result in unnecessary LMK kills for example. So define a tunable threshold for vmpressure above which the allocstalls will be accounted. Change-Id: Idd7c6724264ac89f1f68f2e9d70a32390ffca3e5 Signed-off-by: Vinayak Menon --- mm/vmpressure.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/mm/vmpressure.c b/mm/vmpressure.c index e3098a56fafc..027db670268e 100644 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c @@ -56,6 +56,11 @@ static unsigned long vmpressure_scale_max = 100; module_param_named(vmpressure_scale_max, vmpressure_scale_max, ulong, 0644); +/* vmpressure values >= this will be scaled based on allocstalls */ +static unsigned long allocstall_threshold = 70; +module_param_named(allocstall_threshold, allocstall_threshold, + ulong, 0644); + static struct vmpressure global_vmpressure; static BLOCKING_NOTIFIER_HEAD(vmpressure_notifier); @@ -186,8 +191,12 @@ static unsigned long vmpressure_calc_pressure(unsigned long scanned, static unsigned long vmpressure_account_stall(unsigned long pressure, unsigned long stall, unsigned long scanned) { - unsigned long scale = - ((vmpressure_scale_max - pressure) * stall) / scanned; + unsigned long scale; + + if (pressure < allocstall_threshold) + return pressure; + + scale = ((vmpressure_scale_max - pressure) * stall) / scanned; return pressure + scale; } -- GitLab From 68ce3bbbaa34947f01458be6a70ec7873ff9ed6c Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Tue, 31 Mar 2015 11:06:29 +0530 Subject: [PATCH 1226/1299] mm: vmpressure: scale pressure based on reclaim context The existing calculation of vmpressure takes into account only the ratio of reclaimed to scanned pages, but not the time spent or the difficulty in reclaiming those pages. For e.g. when there are quite a number of file pages in the system, an allocation request can be satisfied by reclaiming the file pages alone. If such a reclaim is successful, the vmpressure value will remain low irrespective of the time spent by the reclaim code to free up the file pages. With a feature like lowmemorykiller, killing a task can be faster than reclaiming the file pages alone. So if the vmpressure values reflect the reclaim difficulty level, clients can make a decision based on that, for e.g. to kill a task early. This patch monitors the number of pages scanned in the direct reclaim path and scales the vmpressure level according to that. Signed-off-by: Vinayak Menon Change-Id: I6e643d29a9a1aa0814309253a8b690ad86ec0b13 --- include/linux/vmpressure.h | 1 + mm/vmpressure.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/linux/vmpressure.h b/include/linux/vmpressure.h index 1b8a21c3757a..de86c6b946c7 100644 --- a/include/linux/vmpressure.h +++ b/include/linux/vmpressure.h @@ -16,6 +16,7 @@ struct vmpressure { unsigned long tree_scanned; unsigned long tree_reclaimed; + unsigned long stall; /* The lock is used to keep the scanned/reclaimed above in sync. */ struct spinlock sr_lock; diff --git a/mm/vmpressure.c b/mm/vmpressure.c index d3b694a89271..e3098a56fafc 100644 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c @@ -24,6 +24,7 @@ #include #include #include +#include #include /* @@ -51,6 +52,10 @@ static const unsigned long vmpressure_win = SWAP_CLUSTER_MAX * 16; static const unsigned int vmpressure_level_med = 60; static const unsigned int vmpressure_level_critical = 95; +static unsigned long vmpressure_scale_max = 100; +module_param_named(vmpressure_scale_max, vmpressure_scale_max, + ulong, 0644); + static struct vmpressure global_vmpressure; static BLOCKING_NOTIFIER_HEAD(vmpressure_notifier); @@ -178,6 +183,15 @@ static unsigned long vmpressure_calc_pressure(unsigned long scanned, return pressure; } +static unsigned long vmpressure_account_stall(unsigned long pressure, + unsigned long stall, unsigned long scanned) +{ + unsigned long scale = + ((vmpressure_scale_max - pressure) * stall) / scanned; + + return pressure + scale; +} + struct vmpressure_event { struct eventfd_ctx *efd; enum vmpressure_levels level; @@ -334,6 +348,7 @@ static void vmpressure_global(gfp_t gfp, unsigned long scanned, { struct vmpressure *vmpr = &global_vmpressure; unsigned long pressure; + unsigned long stall; if (!(gfp & (__GFP_HIGHMEM | __GFP_MOVABLE | __GFP_IO | __GFP_FS))) return; @@ -344,6 +359,11 @@ static void vmpressure_global(gfp_t gfp, unsigned long scanned, spin_lock(&vmpr->sr_lock); vmpr->scanned += scanned; vmpr->reclaimed += reclaimed; + + if (!current_is_kswapd()) + vmpr->stall += scanned; + + stall = vmpr->stall; scanned = vmpr->scanned; reclaimed = vmpr->reclaimed; spin_unlock(&vmpr->sr_lock); @@ -354,9 +374,11 @@ static void vmpressure_global(gfp_t gfp, unsigned long scanned, spin_lock(&vmpr->sr_lock); vmpr->scanned = 0; vmpr->reclaimed = 0; + vmpr->stall = 0; spin_unlock(&vmpr->sr_lock); pressure = vmpressure_calc_pressure(scanned, reclaimed); + pressure = vmpressure_account_stall(pressure, stall, scanned); vmpressure_notify(pressure); } -- GitLab From 59906b3de3168b5922b56183cf4fb14869039686 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Mon, 19 Sep 2016 12:44:15 +0530 Subject: [PATCH 1227/1299] mm: vmpressure: make vmpressure window variable Right now the vmpressure window is of constant size 2MB, which works well with the following exceptions. 1) False vmpressure triggers are seen when the RAM size is greater than 3GB. This results in lowmemorykiller, which uses vmpressure events, killing tasks unnecessarily. 2) Vmpressure events are received late under memory pressure. This behaviour is seen prominently in <=2GB RAM targets. This results in lowmemorykiller kicking in late to kill tasks resulting in avoidable page cache reclaim. The problem analysis shows that the issue is with the constant size of the vmpressure window which does not adapt to the varying memory conditions. This patch recalculates the vmpressure window size at the end of each window. The chosen window size is proportional to the total of free and cached memory at that point. Change-Id: I7e9ef4ddd82e2c2dd04ce09ec8d58a8829cfb64d Signed-off-by: Vinayak Menon --- mm/vmpressure.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/mm/vmpressure.c b/mm/vmpressure.c index 027db670268e..679fe3020b77 100644 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c @@ -41,7 +41,7 @@ * TODO: Make the window size depend on machine size, as we do for vmstat * thresholds. Currently we set it to 512 pages (2MB for 4KB pages). */ -static const unsigned long vmpressure_win = SWAP_CLUSTER_MAX * 16; +static unsigned long vmpressure_win = SWAP_CLUSTER_MAX * 16; /* * These thresholds are used when we account memory pressure through @@ -352,6 +352,29 @@ static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree, } #endif +static void calculate_vmpressure_win(void) +{ + long x; + + x = global_node_page_state(NR_FILE_PAGES) - + global_node_page_state(NR_SHMEM) - + total_swapcache_pages() + + global_zone_page_state(NR_FREE_PAGES); + if (x < 1) + x = 1; + /* + * For low (free + cached), vmpressure window should be + * small, and high for higher values of (free + cached). + * But it should not be linear as well. This ensures + * timely vmpressure notifications when system is under + * memory pressure, and optimal number of events when + * cached is high. The sqaure root function is empirically + * found to serve the purpose. + */ + x = int_sqrt(x); + vmpressure_win = x; +} + static void vmpressure_global(gfp_t gfp, unsigned long scanned, unsigned long reclaimed) { @@ -366,6 +389,9 @@ static void vmpressure_global(gfp_t gfp, unsigned long scanned, return; spin_lock(&vmpr->sr_lock); + if (!vmpr->scanned) + calculate_vmpressure_win(); + vmpr->scanned += scanned; vmpr->reclaimed += reclaimed; -- GitLab From 0aea8a5de64a6601941bbdbe875d76b5613f91ae Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Wed, 10 May 2017 15:43:57 +0530 Subject: [PATCH 1228/1299] drivers: soc: qcom: spm: Add support for 16bit vlevel SPM regulator driver can send 16bit voltage levels to be sent to pmic arbiter for certain PMICs. SAW VCTL can have max pmic data width as 8bit. Update spm driver to send lower 8bit of voltage level first and then send upper 8bit to PVC port. Voltage change happens when upper 8bit is written to PMIC registers. Change-Id: Iff1d1976adfe75058f6c64d4212c78d88422278c Signed-off-by: Maulik Shah Signed-off-by: Srinivas Rao L Signed-off-by: Chinkit Kumar,Kirti Kumar Parmar --- .../devicetree/bindings/arm/msm/spm-v2.txt | 4 + drivers/soc/qcom/msm-spm.c | 114 ++++++++++++------ drivers/soc/qcom/spm_devices.c | 6 +- drivers/soc/qcom/spm_driver.h | 4 +- 4 files changed, 92 insertions(+), 36 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt index 194059c39c68..d44ab56b9f48 100644 --- a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt +++ b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt @@ -45,6 +45,8 @@ Optional properties for only Non-PSCI targets index to send the PMIC data to - qcom,vctl-port: The PVC (PMIC Virtual Channel) port used for changing voltage +- qcom,vctl-port-ub: The PVC (PMIC Virtual Channel) port used for changing + voltage - qcom,phase-port: The PVC port used for changing the number of phases - qcom,pfm-port: The PVC port used for enabling PWM/PFM modes - qcom,cpu-vctl-mask: Mask of cpus, whose voltage the spm device can control. @@ -105,6 +107,8 @@ Optional properties for only PSCI targets: between AVS controller requests - qcom,vctl-port: The PVC (PMIC Virtual Channel) port used for changing voltage +- qcom,vctl-port-ub: The PVC (PMIC Virtual Channel) port used for changing + voltage - qcom,phase-port: The PVC port used for changing the number of phases - qcom,pfm-port: The PVC port used for enabling PWM/PFM modes - qcom,cpu-vctl-list: List of cpu node phandles, whose voltage the spm device diff --git a/drivers/soc/qcom/msm-spm.c b/drivers/soc/qcom/msm-spm.c index abaa1aef2479..cad99d7ce355 100644 --- a/drivers/soc/qcom/msm-spm.c +++ b/drivers/soc/qcom/msm-spm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -189,21 +189,12 @@ static inline bool msm_spm_pmic_arb_present(struct msm_spm_driver_data *dev) } static inline void msm_spm_drv_set_vctl2(struct msm_spm_driver_data *dev, - uint32_t vlevel) + uint32_t vlevel, uint32_t vctl_port) { unsigned int pmic_data = 0; - /** - * VCTL_PORT has to be 0, for PMIC_STS register to be updated. - * Ensure that vctl_port is always set to 0. - */ - if (dev->vctl_port) { - __WARN(); - return; - } - pmic_data |= vlevel; - pmic_data |= (dev->vctl_port & 0x7) << 16; + pmic_data |= (vctl_port & 0x7) << 16; dev->reg_shadow[MSM_SPM_REG_SAW_VCTL] &= ~0x700FF; dev->reg_shadow[MSM_SPM_REG_SAW_VCTL] |= pmic_data; @@ -512,10 +503,46 @@ static void msm_spm_drv_set_avs_vlevel(struct msm_spm_driver_data *dev, } #endif +static inline int msm_spm_drv_validate_data(struct msm_spm_driver_data *dev, + unsigned int vlevel, int vctl_port) +{ + int timeout_us = dev->vctl_timeout_us; + uint32_t new_level; + + /* Confirm the voltage we set was what hardware sent and + * FSM is idle. + */ + do { + udelay(1); + new_level = msm_spm_drv_get_sts_curr_pmic_data(dev); + + /** + * VCTL_PORT has to be 0, for vlevel to be updated. + * If port is not 0, check for PMIC_STATE only. + */ + + if (((new_level & 0x30000) == MSM_SPM_PMIC_STATE_IDLE) && + (vctl_port || ((new_level & 0xFF) == vlevel))) + break; + } while (--timeout_us); + + if (!timeout_us) { + pr_err("Wrong level %#x\n", new_level); + return -EIO; + } + + if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL) + pr_info("%s: done, remaining timeout %u us\n", + __func__, timeout_us); + + return 0; +} + int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev, unsigned int vlevel) { - uint32_t timeout_us, new_level; + uint32_t vlevel_set = vlevel; bool avs_enabled; + int ret = 0; if (!dev) return -EINVAL; @@ -531,45 +558,63 @@ int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev, unsigned int vlevel) if (avs_enabled) msm_spm_drv_disable_avs(dev); + if (dev->vctl_port_ub >= 0) { + /** + * VCTL can send 8bit voltage level at once. + * Send lower 8bit first, vlevel change happens + * when upper 8bit is sent. + */ + vlevel = vlevel_set & 0xFF; + } + /* Kick the state machine back to idle */ dev->reg_shadow[MSM_SPM_REG_SAW_RST] = 1; msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW_RST); - msm_spm_drv_set_vctl2(dev, vlevel); + msm_spm_drv_set_vctl2(dev, vlevel, dev->vctl_port); - timeout_us = dev->vctl_timeout_us; - /* Confirm the voltage we set was what hardware sent */ - do { - udelay(1); - new_level = msm_spm_drv_get_sts_curr_pmic_data(dev); - /* FSM is idle */ - if (((new_level & 0x30000) == 0) && - ((new_level & 0xFF) == vlevel)) - break; - } while (--timeout_us); - if (!timeout_us) { - pr_info("Wrong level %#x\n", new_level); + ret = msm_spm_drv_validate_data(dev, vlevel, dev->vctl_port); + if (ret) goto set_vdd_bail; - } - if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL) - pr_info("%s: done, remaining timeout %u us\n", - __func__, timeout_us); + if (dev->vctl_port_ub >= 0) { + /* Send upper 8bit of voltage level */ + vlevel = (vlevel_set >> 8) & 0xFF; + + /* Kick the state machine back to idle */ + dev->reg_shadow[MSM_SPM_REG_SAW_RST] = 1; + msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW_RST); + + /* + * Steps for sending for vctl port other than '0' + * Write VCTL register with pmic data and address index + * Perform system barrier + * Wait for 1us + * Read PMIC_STS register to make sure operation is complete + */ + msm_spm_drv_set_vctl2(dev, vlevel, dev->vctl_port_ub); + + mb(); /* To make sure data is sent before checking status */ + + ret = msm_spm_drv_validate_data(dev, vlevel, dev->vctl_port_ub); + if (ret) + goto set_vdd_bail; + } /* Set AVS min/max */ if (avs_enabled) { - msm_spm_drv_set_avs_vlevel(dev, vlevel); + msm_spm_drv_set_avs_vlevel(dev, vlevel_set); msm_spm_drv_enable_avs(dev); } - return 0; + return ret; set_vdd_bail: if (avs_enabled) msm_spm_drv_enable_avs(dev); - pr_err("%s: failed %#x, remaining timeout %uus, vlevel %#x\n", - __func__, vlevel, timeout_us, new_level); + pr_err("%s: failed %#x vlevel setting in timeout %uus\n", + __func__, vlevel_set, dev->vctl_timeout_us); return -EIO; } @@ -699,6 +744,7 @@ int msm_spm_drv_init(struct msm_spm_driver_data *dev, return -ENODEV; dev->vctl_port = data->vctl_port; + dev->vctl_port_ub = data->vctl_port_ub; dev->phase_port = data->phase_port; dev->pfm_port = data->pfm_port; dev->reg_base_addr = data->reg_base_addr; diff --git a/drivers/soc/qcom/spm_devices.c b/drivers/soc/qcom/spm_devices.c index 44c0c55e278f..620da5eb06e8 100644 --- a/drivers/soc/qcom/spm_devices.c +++ b/drivers/soc/qcom/spm_devices.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -782,12 +782,16 @@ static int msm_spm_dev_probe(struct platform_device *pdev) } spm_data.vctl_port = -1; + spm_data.vctl_port_ub = -1; spm_data.phase_port = -1; spm_data.pfm_port = -1; key = "qcom,vctl-port"; of_property_read_u32(node, key, &spm_data.vctl_port); + key = "qcom,vctl-port-ub"; + of_property_read_u32(node, key, &spm_data.vctl_port_ub); + key = "qcom,phase-port"; of_property_read_u32(node, key, &spm_data.phase_port); diff --git a/drivers/soc/qcom/spm_driver.h b/drivers/soc/qcom/spm_driver.h index a6458135c548..198267a4012a 100644 --- a/drivers/soc/qcom/spm_driver.h +++ b/drivers/soc/qcom/spm_driver.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -62,6 +62,7 @@ struct msm_spm_platform_data { uint32_t ver_reg; uint32_t vctl_port; + int vctl_port_ub; uint32_t phase_port; uint32_t pfm_port; @@ -84,6 +85,7 @@ struct msm_spm_driver_data { uint32_t minor; uint32_t ver_reg; uint32_t vctl_port; + int vctl_port_ub; uint32_t phase_port; uint32_t pfm_port; void __iomem *reg_base_addr; -- GitLab From dab6a1c7c7d53eb7851a056346135aba5fb9554a Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Wed, 4 Jul 2018 10:31:01 +0300 Subject: [PATCH 1229/1299] msm: ipa: Enable IPA compilation for sdxprairie Enable all IPA modules except rmnet_ipa3 for compilation. rmnet_ipa3 will be enabled later once QCOM_QMI_HELPERS dependency will be enabled. CRs-Fixed: 2272805 Change-Id: I209de020090a7d0bb940b4ecec34f1e6928ce053 Signed-off-by: Ghanim Fodi --- arch/arm/configs/vendor/sdxprairie-perf_defconfig | 5 +++++ arch/arm/configs/vendor/sdxprairie_defconfig | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/configs/vendor/sdxprairie-perf_defconfig b/arch/arm/configs/vendor/sdxprairie-perf_defconfig index b7a0d8e8f518..c4f409d24d54 100644 --- a/arch/arm/configs/vendor/sdxprairie-perf_defconfig +++ b/arch/arm/configs/vendor/sdxprairie-perf_defconfig @@ -245,6 +245,11 @@ CONFIG_STAGING=y CONFIG_SPS=y CONFIG_SPS_SUPPORT_NDP_BAM=y CONFIG_USB_BAM=y +CONFIG_IPA3=y +CONFIG_IPA_WDI_UNIFIED_API=y +CONFIG_ECM_IPA=y +CONFIG_RNDIS_IPA=y +CONFIG_IPA_UT=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_IOMMU_IO_PGTABLE_FAST=y diff --git a/arch/arm/configs/vendor/sdxprairie_defconfig b/arch/arm/configs/vendor/sdxprairie_defconfig index 5f9bd5c32f18..090d5983b41e 100644 --- a/arch/arm/configs/vendor/sdxprairie_defconfig +++ b/arch/arm/configs/vendor/sdxprairie_defconfig @@ -234,6 +234,11 @@ CONFIG_UIO=y CONFIG_STAGING=y CONFIG_SPS=y CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_IPA3=y +CONFIG_IPA_WDI_UNIFIED_API=y +CONFIG_ECM_IPA=y +CONFIG_RNDIS_IPA=y +CONFIG_IPA_UT=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_IOMMU_IO_PGTABLE_FAST=y -- GitLab From 3a7604c06a5a7ed9c1f4994895c8dea8b25649e9 Mon Sep 17 00:00:00 2001 From: Saranya Chidura Date: Tue, 3 Jul 2018 17:11:31 +0530 Subject: [PATCH 1230/1299] ARM: dts: msm: fix the STM stimulus base address of qcs405 HLOS uses only particular STM channels, Update the STM stimulus base address with correct channel base address in QCS405. Change-Id: Ia4c94de406ef33ce41217ccfe5be182f92d5522e Signed-off-by: Saranya Chidura --- arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi b/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi index 9cb4826f6eb1..ddb3896cc986 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi @@ -340,7 +340,7 @@ arm,primecell-periphid = <0x0003b962>; reg = <0x6002000 0x1000>, - <0x09000000 0x1000000>; + <0x09280000 0x180000>; reg-names = "stm-base", "stm-stimulus-base"; coresight-name = "coresight-stm"; -- GitLab From 815e2bf788d5dfd15715ca10813ee8be234be7d6 Mon Sep 17 00:00:00 2001 From: Umang Agrawal Date: Mon, 16 Apr 2018 17:42:21 +0530 Subject: [PATCH 1231/1299] power: smb1390: Configure SMB1390 to improve ILIM accuracy Configure WIN_OV to 10V and VOUT tracking value to 1V to improve the accuracy of ILIM IRQ trigger. Change-Id: Ifadda6faea6acfbf4fe283aebb25fb4c5118087a Signed-off-by: Umang Agrawal --- drivers/power/supply/qcom/smb1390-charger.c | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/power/supply/qcom/smb1390-charger.c b/drivers/power/supply/qcom/smb1390-charger.c index 6ba5fffee615..a5ea43bf3f6d 100644 --- a/drivers/power/supply/qcom/smb1390-charger.c +++ b/drivers/power/supply/qcom/smb1390-charger.c @@ -67,6 +67,15 @@ #define CORE_FTRIM_ILIM_REG 0x1030 #define CFG_ILIM_MASK GENMASK(4, 0) +#define CORE_FTRIM_LVL_REG 0x1033 +#define CFG_WIN_HI_MASK GENMASK(3, 2) +#define WIN_OV_LVL_1000MV 0x08 + +#define CORE_FTRIM_MISC_REG 0x1034 +#define TR_WIN_1P5X_BIT BIT(0) +#define WINDOW_DETECTION_DELTA_X1P0 0 +#define WINDOW_DETECTION_DELTA_X1P5 1 + #define CP_VOTER "CP_VOTER" #define USER_VOTER "USER_VOTER" #define ILIM_VOTER "ILIM_VOTER" @@ -550,11 +559,30 @@ static void smb1390_destroy_votables(struct smb1390 *chip) static int smb1390_init_hw(struct smb1390 *chip) { + int rc; + /* * charge pump is initially disabled; this indirectly votes to allow * traditional parallel charging if present */ vote(chip->disable_votable, USER_VOTER, true, 0); + + /* + * Improve ILIM accuracy: + * - Configure window (Vin - 2Vout) OV level to 1000mV + * - Configure VOUT tracking value to 1.0 + */ + rc = smb1390_masked_write(chip, CORE_FTRIM_LVL_REG, + CFG_WIN_HI_MASK, WIN_OV_LVL_1000MV); + if (rc < 0) + return rc; + + rc = smb1390_masked_write(chip, CORE_FTRIM_MISC_REG, + TR_WIN_1P5X_BIT, WINDOW_DETECTION_DELTA_X1P0); + if (rc < 0) + return rc; + + return 0; } -- GitLab From ba75c204afc6ba5fbd770e05a833be88262d6544 Mon Sep 17 00:00:00 2001 From: Sumatheendra Raghavendrachar Date: Tue, 26 Jun 2018 15:00:40 +0530 Subject: [PATCH 1232/1299] defconfig: arm: qcs405: Enable NTAG driver Enable NTAG driver for QCS405 platform. Change-Id: I5b675f56f2a535158432a2b709dbd10825e9d315 Signed-off-by: Sumatheendra Raghavendrachar --- arch/arm/configs/vendor/qcs405_defconfig | 1 + arch/arm64/configs/vendor/qcs405_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index 47f998b1b571..dda9bac15146 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -193,6 +193,7 @@ CONFIG_BT_HIDP=y CONFIG_CFG80211=y CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_RFKILL=y +CONFIG_NTAG_NQ=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index b9c9e142fe8a..4ca566bd7fb4 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -190,6 +190,7 @@ CONFIG_BT_HIDP=y CONFIG_CFG80211=y CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_RFKILL=y +CONFIG_NTAG_NQ=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y CONFIG_DMA_CMA=y -- GitLab From 58754e235c80e18b42828810ad2775cdde83cde5 Mon Sep 17 00:00:00 2001 From: Sumatheendra Raghavendrachar Date: Tue, 19 Jun 2018 12:19:52 +0530 Subject: [PATCH 1233/1299] ARM: dts: msm: Add NTAG device node for QCS405 Add NTAG device tree node and associated GPIO configurations for QCS405 platform. Change-Id: I5724bfc784a4b09348fd80c195c4f7b7deabf6a2 Signed-off-by: Sumatheendra Raghavendrachar --- arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi | 33 ++++++++++++++++++++ arch/arm64/boot/dts/qcom/qcs405.dtsi | 16 ++++++++++ 2 files changed, 49 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi index a4a9f5bb5f87..6582cd025fac 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi @@ -645,6 +645,39 @@ }; }; + ntag { + ntag_int_active: ntag_int_active { + /* active state */ + mux { + /* GPIO 53 Field Detect Interrupt */ + pins = "gpio53"; + function = "gpio"; + }; + + config { + pins = "gpio53"; + drive-strength = <2>; /* 2 MA */ + bias-pull-up; + }; + }; + + ntag_int_suspend: ntag_int_suspend { + /* sleep state */ + mux { + /* GPIO 53 Field Detect Interrupt */ + pins = "gpio53"; + function = "gpio"; + }; + + config { + pins = "gpio53"; + drive-strength = <2>; /* 2 MA */ + bias-pull-up; + }; + }; + + }; + /* SDC pin type */ sdc1_clk_on: sdc1_clk_on { config { diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 3f054faf4597..5cb5d6fee1fa 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -121,6 +121,22 @@ #include "qcs405-gpu.dtsi" #include "qcs405-mdss-pll.dtsi" +&i2c_5 { /* BLSP (NTAG) */ + status = "ok"; + nq@55 { + compatible = "qcom,nq-ntag"; + reg = <0x55>; + qcom,nq-ntagfd = <&tlmm 53 GPIO_ACTIVE_LOW>; + interrupt-parent = <&tlmm>; + interrupts = <53 0>; + interrupt-names = "ntag_fd"; + pinctrl-names = "ntag_active", "ntag_suspend"; + pinctrl-0 = <&ntag_int_active>; + pinctrl-1 = <&ntag_int_suspend>; + }; +}; + + &soc { #address-cells = <1>; #size-cells = <1>; -- GitLab From c8e9d1cb9b9e81c2ba6e400152a61a3c4dda6b6c Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Wed, 4 Jul 2018 13:58:55 +0530 Subject: [PATCH 1234/1299] ARM: dts: msm: Enable UTMI bridge for HS PHY on QCS405 SNPS HS PHY can communicate over ULPI or UTMI bridge, SNPS DWC3 controller uses UTMI whereas the default is ULPI for HS PHY. So, enable UTMI by setting the TCSR_CTRL register. Change-Id: I9d4a4dcb8a941ff7066abc101d064d7ce1e96366 Signed-off-by: Sriharsha Allenki --- arch/arm64/boot/dts/qcom/qcs405-usb.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi index e6fb5e0620fc..0024bc58bd10 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi @@ -86,6 +86,7 @@ reset-names = "phy_reset", "phy_por_reset"; qcom,snps-hs-phy-init-seq = + <0xc0 0x01 0>, <0xe8 0x0d 0>, <0x74 0x12 0>, <0x98 0x63 0>, @@ -190,6 +191,7 @@ reset-names = "phy_reset", "phy_por_reset"; qcom,snps-hs-phy-init-seq = + <0xc0 0x01 0>, <0xe8 0x0d 0>, <0x74 0x12 0>, <0x98 0x63 0>, -- GitLab From 2a07cd824554857949df56c483832a43ec8dd626 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Wed, 4 Jul 2018 14:14:19 +0530 Subject: [PATCH 1235/1299] ARM: dts: Enable PCNOC_USB3_CLK for QCS405 USB30_MASTER_CLK has a dependency on PCNOC_USB3_CLK and it needs to be enabled for master clock to be turned on. So, enable PCNOC_USB3_CLK before enabling the core clock. Change-Id: I983b61646d35cd612fb97145190f25cffc6d7ad8 Signed-off-by: Sriharsha Allenki --- arch/arm64/boot/dts/qcom/qcs405-usb.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi index e6fb5e0620fc..f976d60b8f3a 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi @@ -30,9 +30,10 @@ <&clock_gcc GCC_SYS_NOC_USB3_CLK>, <&clock_gcc GCC_USB30_SLEEP_CLK>, <&clock_gcc GCC_USB30_MOCK_UTMI_CLK>, - <&clock_rpmcc CXO_SMD_OTG_CLK>; + <&clock_rpmcc CXO_SMD_OTG_CLK>, + <&clock_gcc GCC_PCNOC_USB3_CLK>; clock-names = "core_clk", "iface_clk", "sleep_clk", - "utmi_clk", "xo"; + "utmi_clk", "xo", "noc_aggr_clk"; qcom,core-clk-rate = <200000000>; qcom,core-clk-rate-hs = <10000000>; -- GitLab From 881d4e147a96fa1bfeaa0cbcb74c077c7eeca365 Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Tue, 26 Jun 2018 13:00:09 +0530 Subject: [PATCH 1236/1299] ARM: dts: msm: Add USB DLOAD cookie device node on SM6150 Linux USB DIAG driver needs to update PID and serial number with IMEM memory to avoid DIAG port hopping while performing RAMDUMP collection over USB. Hence add device node entry with IMEM driver for USB dload cookie imem start address and size. Change-Id: I486e9f4272134767918e2385f9acc4fe7168d899 Signed-off-by: Pratham Pratap --- arch/arm64/boot/dts/qcom/sm6150.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi index f35441c022d7..eb18da4b7916 100644 --- a/arch/arm64/boot/dts/qcom/sm6150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi @@ -715,6 +715,11 @@ compatible = "qcom,msm-imem-pil"; reg = <0x94c 200>; }; + + diag_dload@c8 { + compatible = "qcom,msm-imem-diag-dload"; + reg = <0xc8 200>; + }; }; restart@c264000 { -- GitLab From 7ffb763e7f7ce63e9902b52c5f93fb61837a4914 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Wed, 4 Jul 2018 13:25:50 +0530 Subject: [PATCH 1237/1299] msm: kgsl: Enable GPU core memory and periphery retention for A308 Set CLKFLAG_RETAIN_PERIPH and CLKFLAG_RETAIN_MEM flags for GPU core clock to make sure GPU core memory is retained during GPU NAP state. Change-Id: I7a2ce2ba0f883baf9d54a0104d6229551210bd2e Signed-off-by: Deepak Kumar --- drivers/gpu/msm/adreno_a3xx.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 4f9891278118..25909776d4b0 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "kgsl.h" #include "adreno.h" @@ -1904,6 +1905,29 @@ int a3xx_microcode_load(struct adreno_device *adreno_dev, return 0; } +static void a3xx_clk_set_options(struct adreno_device *adreno_dev, + const char *name, struct clk *clk, bool on) +{ + if (!adreno_is_a306a(adreno_dev)) + return; + + /* Handle clock settings for GFX PSCBCs */ + if (on) { + if (!strcmp(name, "mem_iface_clk")) { + clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH); + clk_set_flags(clk, CLKFLAG_NORETAIN_MEM); + } else if (!strcmp(name, "core_clk")) { + clk_set_flags(clk, CLKFLAG_RETAIN_PERIPH); + clk_set_flags(clk, CLKFLAG_RETAIN_MEM); + } + } else { + if (!strcmp(name, "core_clk")) { + clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH); + clk_set_flags(clk, CLKFLAG_NORETAIN_MEM); + } + } +} + struct adreno_gpudev adreno_a3xx_gpudev = { .reg_offsets = &a3xx_reg_offsets, .int_bits = a3xx_int_bits, @@ -1924,4 +1948,5 @@ struct adreno_gpudev adreno_a3xx_gpudev = { .start = a3xx_start, .snapshot = a3xx_snapshot, .coresight = {&a3xx_coresight}, + .clk_set_options = a3xx_clk_set_options, }; -- GitLab From f6dc66739281dc8c15e87662748d847d27156ecc Mon Sep 17 00:00:00 2001 From: Lingutla Chandrasekhar Date: Wed, 4 Jul 2018 15:24:05 +0530 Subject: [PATCH 1238/1299] ARM: dts: msm: Update cluster numbering for qcs405/403 qcs405 and 403 variants have single cluster so update proper cluster numbering, otherwise sched domain groups are not created properly. Change-Id: I72e79d07180202864fcd1a7104d56df97ca7df54 Signed-off-by: Lingutla Chandrasekhar --- arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts | 2 +- arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts | 2 +- arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts index a4d7b5526f59..f0b91c4cf7df 100644 --- a/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts +++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts @@ -26,7 +26,7 @@ /delete-node/ cpu@103; cpu-map { - cluster1 { + cluster0 { /delete-node/ core2; /delete-node/ core3; }; diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts index cfcbdcbac88b..fc6b265c4dad 100644 --- a/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts +++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts @@ -26,7 +26,7 @@ /delete-node/ cpu@103; cpu-map { - cluster1 { + cluster0 { /delete-node/ core2; /delete-node/ core3; }; diff --git a/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi b/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi index cc237fdeccf0..d15ea0356775 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-cpu.dtsi @@ -21,7 +21,7 @@ #address-cells = <1>; #size-cells = <0>; cpu-map { - cluster1 { + cluster0 { core0 { cpu = <&CPU0>; }; -- GitLab From aa0cc58daf198b2852ab12c50a1aedb02defa4d0 Mon Sep 17 00:00:00 2001 From: Hardik Arya Date: Mon, 28 May 2018 12:25:35 +0530 Subject: [PATCH 1239/1299] ARM: dts: msm: Add MPROC device nodes for sdmmagpie Add SMEM, TCSR Mutex, Glink and SMP2P devices for enabling interprocessor communication with MPSS, LPASS and CDSP. Change-Id: I5dfcc8a64e422945f574b1224af7b7f1274404b5 Signed-off-by: Hardik Arya --- arch/arm64/boot/dts/qcom/sdmmagpie.dtsi | 303 ++++++++++++++++++++++++ 1 file changed, 303 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index fca3e75fe912..6136e5dcddc5 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -1029,6 +1029,309 @@ compatible = "qcom,cmd-db"; reg = <0xc3f000c 8>; }; + + tcsr_mutex_block: syscon@1f40000 { + compatible = "syscon"; + reg = <0x1f40000 0x20000>; + }; + + tcsr_mutex: hwlock { + compatible = "qcom,tcsr-mutex"; + syscon = <&tcsr_mutex_block 0 0x1000>; + #hwlock-cells = <1>; + }; + + smem: qcom,smem { + compatible = "qcom,smem"; + memory-region = <&smem_region>; + hwlocks = <&tcsr_mutex 3>; + }; + + apcs: syscon@17c0000c { + compatible = "syscon"; + reg = <0x17c0000c 0x4>; + }; + + apcs_glb: mailbox@17c00000 { + compatible = "qcom,sm8150-apcs-hmss-global"; + reg = <0x17c00000 0x1000>; + + #mbox-cells = <1>; + }; + + qcom,glink { + compatible = "qcom,glink"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + glink_modem: modem { + qcom,remote-pid = <1>; + transport = "smem"; + mboxes = <&apcs_glb 12>; + mbox-names = "mpss_smem"; + interrupts = ; + + label = "modem"; + qcom,glink-label = "mpss"; + + qcom,modem_qrtr { + qcom,glink-channels = "IPCRTR"; + qcom,intents = <0x800 5 + 0x2000 3 + 0x4400 2>; + }; + + qcom,msm_fastrpc_rpmsg { + compatible = "qcom,msm-fastrpc-rpmsg"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + qcom,intents = <0x64 64>; + }; + + qcom,modem_ds { + qcom,glink-channels = "DS"; + qcom,intents = <0x4000 0x2>; + }; + + qcom,modem_glink_ssr { + qcom,glink-channels = "glink_ssr"; + qcom,notify-edges = <&glink_adsp>, + <&glink_cdsp>; + }; + }; + + glink_adsp: adsp { + qcom,remote-pid = <2>; + transport = "smem"; + mboxes = <&apcs_glb 24>; + mbox-names = "adsp_smem"; + interrupts = ; + + label = "adsp"; + qcom,glink-label = "lpass"; + + qcom,adsp_qrtr { + qcom,glink-channels = "IPCRTR"; + qcom,intents = <0x800 5 + 0x2000 3 + 0x4400 2>; + }; + + qcom,apr_tal_rpmsg { + qcom,glink-channels = "apr_audio_svc"; + qcom,intents = <0x200 20>; + }; + + qcom,msm_fastrpc_rpmsg { + compatible = "qcom,msm-fastrpc-rpmsg"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + qcom,intents = <0x64 64>; + }; + + qcom,adsp_glink_ssr { + qcom,glink-channels = "glink_ssr"; + qcom,notify-edges = <&glink_modem>, + <&glink_cdsp>; + }; + }; + + glink_cdsp: cdsp { + qcom,remote-pid = <5>; + transport = "smem"; + mboxes = <&apcs_glb 4>; + mbox-names = "cdsp_smem"; + interrupts = ; + + label = "cdsp"; + qcom,glink-label = "cdsp"; + + qcom,cdsp_qrtr { + qcom,glink-channels = "IPCRTR"; + qcom,intents = <0x800 5 + 0x2000 3 + 0x4400 2>; + }; + + qcom,msm_fastrpc_rpmsg { + compatible = "qcom,msm-fastrpc-rpmsg"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + qcom,intents = <0x64 64>; + }; + + qcom,cdsp_glink_ssr { + qcom,glink-channels = "glink_ssr"; + qcom,notify-edges = <&glink_modem>, + <&glink_adsp>; + }; + }; + + glink_spi_xprt_wdsp: wdsp { + qcom,remote-pid = <10>; + transport = "spi"; + tx-descriptors = <0x12000 0x12004>; + rx-descriptors = <0x1200c 0x12010>; + + qcom,wdsp_ctrl { + qcom,glink-channels = "g_glink_ctrl"; + qcom,intents = <0x400 1>; + }; + + qcom,wdsp_ild { + qcom,glink-channels = + "g_glink_persistent_data_ild"; + }; + + qcom,wdsp_nild { + qcom,glink-channels = + "g_glink_persistent_data_nild"; + }; + + qcom,wdsp_data { + qcom,glink-channels = "g_glink_audio_data"; + qcom,intents = <0x1000 2>; + }; + }; + }; + + qcom,glinkpkt { + compatible = "qcom,glinkpkt"; + + qcom,glinkpkt-at-mdm0 { + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DS"; + qcom,glinkpkt-dev-name = "at_mdm0"; + }; + + qcom,glinkpkt-apr-apps2 { + qcom,glinkpkt-edge = "adsp"; + qcom,glinkpkt-ch-name = "apr_apps2"; + qcom,glinkpkt-dev-name = "apr_apps2"; + }; + + qcom,glinkpkt-data40-cntl { + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA40_CNTL"; + qcom,glinkpkt-dev-name = "smdcntl8"; + }; + + qcom,glinkpkt-data1 { + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA1"; + qcom,glinkpkt-dev-name = "smd7"; + }; + + qcom,glinkpkt-data4 { + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA4"; + qcom,glinkpkt-dev-name = "smd8"; + }; + + qcom,glinkpkt-data11 { + qcom,glinkpkt-edge = "mpss"; + qcom,glinkpkt-ch-name = "DATA11"; + qcom,glinkpkt-dev-name = "smd11"; + }; + }; + + qmp_npu0: qcom,qmp-npu-low@9818000 { + compatible = "qcom,qmp-mbox"; + reg = <0x9818000 0x8000>, <0x17c00010 0x4>; + reg-names = "msgram", "irq-reg-base"; + qcom,irq-mask = <0x20>; + interrupts = ; + + label = "npu_qmp_low"; + priority = <0>; + mbox-desc-offset = <0x0>; + #mbox-cells = <1>; + }; + + qmp_npu1: qcom,qmp-npu-high@9818000 { + compatible = "qcom,qmp-mbox"; + reg = <0x9818000 0x8000>, <0x17c00010 0x4>; + reg-names = "msgram", "irq-reg-base"; + qcom,irq-mask = <0x40>; + interrupts = ; + + label = "npu_qmp_high"; + priority = <1>; + mbox-desc-offset = <0x2000>; + #mbox-cells = <1>; + }; + + qmp_aop: qcom,qmp-aop@c300000 { + compatible = "qcom,qmp-mbox"; + reg = <0xc300000 0x1000>, <0x17c0000C 0x4>; + reg-names = "msgram", "irq-reg-base"; + qcom,irq-mask = <0x1>; + interrupts = ; + + label = "aop"; + qcom,early-boot; + priority = <0>; + mbox-desc-offset = <0x0>; + #mbox-cells = <1>; + }; + + qcom,smp2p-modem { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + interrupts = ; + qcom,ipc = <&apcs 0 14>; + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + modem_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + modem_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + qcom,smp2p-adsp { + compatible = "qcom,smp2p"; + qcom,smem = <443>, <429>; + interrupts = ; + qcom,ipc = <&apcs 0 26>; + qcom,local-pid = <0>; + qcom,remote-pid = <2>; + + adsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + adsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + qcom,smp2p-cdsp { + compatible = "qcom,smp2p"; + qcom,smem = <94>, <432>; + interrupts = ; + qcom,ipc = <&apcs 0 6>; + qcom,local-pid = <0>; + qcom,remote-pid = <5>; + + cdsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + cdsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; }; #include "sdmmagpie-pinctrl.dtsi" -- GitLab From 7249d60c93759c68ec19954c5db946c3a5f08cd0 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Wed, 4 Jul 2018 17:21:54 +0530 Subject: [PATCH 1240/1299] ARM: dts: msm: Enable WLED and LCDB devices for sm6150 WLED and LCDB device nodes are needed for the display to be functional. Enable the same for sm6150 idp/mtp/cdp platforms. Change-Id: Iab1ecaf3ae9eca77210506cd2dc4c8d1d82847f0 Signed-off-by: Kiran Gunda --- arch/arm64/boot/dts/qcom/sm6150-cdp.dtsi | 9 +++++++++ arch/arm64/boot/dts/qcom/sm6150-idp.dtsi | 9 +++++++++ arch/arm64/boot/dts/qcom/sm6150-mtp.dtsi | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150-cdp.dtsi b/arch/arm64/boot/dts/qcom/sm6150-cdp.dtsi index d4db086685f5..836f84bc261b 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-cdp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-cdp.dtsi @@ -20,3 +20,12 @@ &pm6150_charger { qcom,batteryless-platform; }; + +&pm6150l_wled { + qcom,string-cfg= <7>; + status = "ok"; +}; + +&pm6150l_lcdb { + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/qcom/sm6150-idp.dtsi b/arch/arm64/boot/dts/qcom/sm6150-idp.dtsi index 83cbf89a00a7..f9f7bc31ec86 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-idp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-idp.dtsi @@ -16,3 +16,12 @@ &qupv3_se0_2uart { status = "ok"; }; + +&pm6150l_wled { + qcom,string-cfg= <7>; + status = "ok"; +}; + +&pm6150l_lcdb { + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/qcom/sm6150-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm6150-mtp.dtsi index 83cbf89a00a7..f9f7bc31ec86 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-mtp.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-mtp.dtsi @@ -16,3 +16,12 @@ &qupv3_se0_2uart { status = "ok"; }; + +&pm6150l_wled { + qcom,string-cfg= <7>; + status = "ok"; +}; + +&pm6150l_lcdb { + status = "ok"; +}; -- GitLab From 3399d409c8a50255a6af9a1db32d4b1ed8762434 Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Mon, 2 Jul 2018 20:14:03 +0530 Subject: [PATCH 1241/1299] ARM: dts: msm: enable cpufreq and devfreq nodes for qcs405 To scale cpu and ddr frequency enable cpufreq and devfreq nodes for qcs405 target. Change-Id: Ie426f34e32daa4c981eee8a1b97bd472a9f9583f Signed-off-by: Santosh Mardi --- arch/arm64/boot/dts/qcom/qcs403.dtsi | 14 +++++++ arch/arm64/boot/dts/qcom/qcs405.dtsi | 56 ++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs403.dtsi b/arch/arm64/boot/dts/qcom/qcs403.dtsi index 3cdbb7a533b2..72e417e4f493 100644 --- a/arch/arm64/boot/dts/qcom/qcs403.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs403.dtsi @@ -18,3 +18,17 @@ qcom,msm-name = "QCS403"; qcom,msm-id = <373 0x0>; }; + +&soc { + /delete-node/ qcom,cpu0-computemon; + + cpu0_computemon: qcom,cpu0-computemon { + compatible = "qcom,arm-cpu-mon"; + qcom,cpulist = <&CPU0 &CPU1>; + qcom,target-dev = <&cpu0_cpu_ddr_latfloor>; + qcom,core-dev-table = + < 1113600 MHZ_TO_MBPS( 297, 4) >, + < 1267200 MHZ_TO_MBPS( 597, 4) >, + < 1401600 MHZ_TO_MBPS( 710, 4) >; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 9af9da5f7a61..cf15499a9848 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -20,6 +20,9 @@ #include #include +#define MHZ_TO_MBPS(mhz, w) ((mhz * 1000000 * w) / (1024 * 1024)) +#define BW_OPP_ENTRY(mhz, w) opp-mhz {opp-hz = /bits/ 64 ;} + / { model = "Qualcomm Technologies, Inc. QCS405"; compatible = "qcom,qcs405"; @@ -971,6 +974,59 @@ status = "disabled"; }; + + msm_cpufreq: qcom,msm-cpufreq { + compatible = "qcom,msm-cpufreq"; + clock-names = "cpu0_clk"; + clocks = <&clock_cpu APCS_MUX_CLK>; + + qcom,cpufreq-table = + < 1113600 >, + < 1267200 >, + < 1401600 >; + }; + + ddr_bw_opp_table: ddr-bw-opp-table { + compatible = "operating-points-v2"; + BW_OPP_ENTRY( 297, 4); /* 1132 MB/s */ + BW_OPP_ENTRY( 595, 4); /* 2269 MB/s */ + BW_OPP_ENTRY( 710, 4); /* 2708 MB/s */ + }; + + cpubw: qcom,cpubw { + compatible = "qcom,devbw"; + governor = "performance"; + qcom,src-dst-ports = <1 512>; + qcom,active-only; + operating-points-v2 = <&ddr_bw_opp_table>; + }; + + qcom,cpu-bwmon { + compatible = "qcom,bimc-bwmon2"; + reg = <0x408000 0x300>, <0x401000 0x200>; + reg-names = "base", "global_base"; + interrupts = <0 183 4>; + qcom,mport = <0>; + qcom,target-dev = <&cpubw>; + }; + + cpu0_cpu_ddr_latfloor: qcom,cpu0-cpu-ddr-latfloor { + compatible = "qcom,devbw"; + governor = "performance"; + qcom,src-dst-ports = <1 512>; + qcom,active-only; + operating-points-v2 = <&ddr_bw_opp_table>; + }; + + cpu0_computemon: qcom,cpu0-computemon { + compatible = "qcom,arm-cpu-mon"; + qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>; + qcom,target-dev = <&cpu0_cpu_ddr_latfloor>; + qcom,core-dev-table = + < 1113600 MHZ_TO_MBPS( 297, 4) >, + < 1267200 MHZ_TO_MBPS( 597, 4) >, + < 1401600 MHZ_TO_MBPS( 710, 4) >; + }; }; #include "qcs405-gdsc.dtsi" -- GitLab From d504347e5833cf70ac99806f12aa86b9291a1fe0 Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Mon, 2 Jul 2018 20:14:51 +0530 Subject: [PATCH 1242/1299] defconfig: enable devfreq and cpufreq drivers for qcs405 target Enable devfreq governors and cpufreq driver to scale cpu frequency and DDR for qcs405 target. Change-Id: I7e3453b6ccc3ad451b3e393ce632a26d4491a8ff Signed-off-by: Santosh Mardi --- arch/arm64/configs/vendor/qcs405_defconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index 9e34c16fb8af..2cf412cbe731 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -50,7 +50,10 @@ CONFIG_PM_DEBUG=y CONFIG_CPU_IDLE=y CONFIG_ARM_CPUIDLE=y CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_MSM=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -426,6 +429,11 @@ CONFIG_MSM_TZ_SMMU=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y CONFIG_MSM_PM=y +CONFIG_QCOM_BIMC_BWMON=y +CONFIG_ARM_MEMLAT_MON=y +CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_MEMLAT=y +CONFIG_QCOM_DEVFREQ_DEVBW=y CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y -- GitLab From e289fb6e2d04c0aa344728a29ca5548fa39e7d86 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Wed, 4 Jul 2018 20:48:45 +0530 Subject: [PATCH 1243/1299] ARM: dts: msm: Add extcon node for USB3 on QCS405 Add GPIO based ID detection for USB3 on QCS405. Add the proper extcon for the same. Change-Id: Ib0bc9784e79f5f2c6e7febab992cd91f3c6e1218 Signed-off-by: Sriharsha Allenki --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 3f054faf4597..8d3a25db6e1a 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -1046,3 +1046,7 @@ &usb3_vbus_boost_default>; }; }; + +&usb3 { + extcon = <&usb3_extcon>; +}; -- GitLab From 32109a3f7a25be73999da6c6c4ecffec313d783b Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Tue, 3 Jul 2018 19:28:54 +0530 Subject: [PATCH 1244/1299] drivers: irqchip: qcom: Add mpm pin data for qcs405 Add mpm pin data for gic and gpio interrupts for qcs405. Change-Id: I916e4e169055c0589f6021ea2a164cb4fec56a5a Signed-off-by: Maulik Shah --- .../bindings/interrupt-controller/qti,mpm.txt | 16 +++- drivers/irqchip/qcom/Makefile | 2 +- drivers/irqchip/qcom/mpm-qcs405.c | 77 +++++++++++++++++++ drivers/irqchip/qcom/mpm.c | 8 ++ drivers/irqchip/qcom/mpm.h | 2 + 5 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 drivers/irqchip/qcom/mpm-qcs405.c diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt index 717b8901fb68..969bf6531e31 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt @@ -17,7 +17,11 @@ Properties: - compatible: Usage: required Value type: - Definition: Should contain "qcom,mpm-gic" and the respective target compatible flag. + Definition: Should contain "qcom,mpm-gic" and the respective target compatible flag + from below ones. + "qcom,mpm-gic-msm8953", + "qcom,mpm-gic-msm8937", + "qcom,mpm-gic-qcs405" - interrupts: Usage: required @@ -52,7 +56,7 @@ Properties: Example: wakegic: wake-gic@7781b8 { - compatible = "qcom,mpm-gic", "qcom,mpm-gic-msm8953", "qcom,mpm-gic-msm8937"; + compatible = "qcom,mpm-gic", "qcom,mpm-gic-msm8953"; interrupts = ; reg = <0x601d4 0x1000>, <0xb011008 0x4>; /* MSM_APCS_GCC_BASE 4K */ @@ -70,7 +74,11 @@ properties: - compatible: Usage: required Value type: - Definition: Should contain "qcom,mpm-gpio" and the respective target compatible flag. + Definition: Should contain "qcom,mpm-gpio" and the respective target compatible flag + from below ones. + "qcom,mpm-gpio-msm8953", + "qcom,mpm-gpio-msm8937", + "qcom,mpm-gpio-qcs405" - interrupt-parent: Usage: required @@ -85,7 +93,7 @@ properties: Example: wakegpio: wake-gpio { - compatible = "qcom,mpm-gpio", "qcom,mpm-gpio-msm8953", "qcom,mpm-gpio-msm8937"; + compatible = "qcom,mpm-gpio", "qcom,mpm-gpio-msm8953"; interrupt-controller; interrupt-parent = <&tlmm>; #interrupt-cells = <2>; diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile index d879a5e0eb7a..9ab6c8543f83 100644 --- a/drivers/irqchip/qcom/Makefile +++ b/drivers/irqchip/qcom/Makefile @@ -3,4 +3,4 @@ obj-$(CONFIG_QTI_PDC_SM8150) += pdc-sm8150.o obj-$(CONFIG_QTI_PDC_SM6150) += pdc-sm6150.o obj-$(CONFIG_QTI_PDC_SDMMAGPIE) += pdc-sdmmagpie.o obj-$(CONFIG_QTI_MPM) += mpm.o -obj-$(CONFIG_QTI_MPM) += mpm.o mpm-8937.o +obj-$(CONFIG_QTI_MPM) += mpm.o mpm-8937.o mpm-qcs405.o diff --git a/drivers/irqchip/qcom/mpm-qcs405.c b/drivers/irqchip/qcom/mpm-qcs405.c new file mode 100644 index 000000000000..d73cd8111fe9 --- /dev/null +++ b/drivers/irqchip/qcom/mpm-qcs405.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "mpm.h" + +const struct mpm_pin mpm_qcs405_gic_chip_data[] = { + {2, 216}, + {35, 350}, /* dmse_hv, usb20 -> hs_phy_irq */ + {36, 350}, /* dpse_hv, usb20 -> hs_phy_irq */ + {38, 351}, /* dmse_hv, usb30 -> hs_phy_irq */ + {39, 351}, /* dpse_hv, usb30 -> hs_phy_irq */ + {62, 222}, /* mpm_wake,spmi_m */ + {-1}, +}; + +const struct mpm_pin mpm_qcs405_gpio_chip_data[] = { + {3, 4}, + {4, 6}, + {5, 14}, + {6, 18}, + {7, 117}, + {8, 19}, + {9, 20}, + {10, 21}, + {11, 22}, + {12, 23}, + {13, 24}, + {14, 27}, + {15, 28}, + {16, 31}, + {17, 32}, + {18, 34}, + {19, 35}, + {20, 37}, + {21, 38}, + {22, 59}, + {23, 61}, + {24, 62}, + {25, 77}, + {26, 78}, + {27, 79}, + {28, 80}, + {29, 81}, + {30, 83}, + {31, 84}, + {32, 88}, + {33, 89}, + {34, 99}, + {42, 100}, + {43, 104}, + {47, 105}, + {48, 106}, + {49, 107}, + {52, 109}, + {53, 110}, + {54, 111}, + {55, 112}, + {56, 113}, + {57, 114}, + {58, 115}, + {64, 3}, + {65, 17}, + {66, 19}, + {67, 53}, + {68, 54}, + {-1}, +}; diff --git a/drivers/irqchip/qcom/mpm.c b/drivers/irqchip/qcom/mpm.c index c7b610f29f32..8b4f900184f9 100644 --- a/drivers/irqchip/qcom/mpm.c +++ b/drivers/irqchip/qcom/mpm.c @@ -605,6 +605,10 @@ static const struct of_device_id mpm_gic_chip_data_table[] = { .compatible = "qcom,mpm-gic-msm8937", .data = mpm_msm8937_gic_chip_data, }, + { + .compatible = "qcom,mpm-gic-qcs405", + .data = mpm_qcs405_gic_chip_data, + }, {} }; MODULE_DEVICE_TABLE(of, mpm_gic_chip_data_table); @@ -614,6 +618,10 @@ static const struct of_device_id mpm_gpio_chip_data_table[] = { .compatible = "qcom,mpm-gpio-msm8937", .data = mpm_msm8937_gpio_chip_data, }, + { + .compatible = "qcom,mpm-gpio-qcs405", + .data = mpm_qcs405_gpio_chip_data, + }, {} }; diff --git a/drivers/irqchip/qcom/mpm.h b/drivers/irqchip/qcom/mpm.h index c2d5eae179fe..7b5c3d8f4048 100644 --- a/drivers/irqchip/qcom/mpm.h +++ b/drivers/irqchip/qcom/mpm.h @@ -24,4 +24,6 @@ struct mpm_pin { extern const struct mpm_pin mpm_msm8937_gic_chip_data[]; extern const struct mpm_pin mpm_msm8937_gpio_chip_data[]; +extern const struct mpm_pin mpm_qcs405_gic_chip_data[]; +extern const struct mpm_pin mpm_qcs405_gpio_chip_data[]; #endif /* __QCOM_MPM_H__ */ -- GitLab From f5f4cdfb982a26efb477910f9bb8516e87dcf10d Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Tue, 3 Jul 2018 19:33:14 +0530 Subject: [PATCH 1245/1299] ARM: dts: msm: Update mpm node for qcs405 Update number of irqs supported by mpm and vmpm address. Also update compatible flag accordingly. Change-Id: If6400971930a97120a961ad072829ecfc5da9ded Signed-off-by: Maulik Shah --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 3f054faf4597..332ddd4ee5ba 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -137,19 +137,19 @@ }; wakegic: wake-gic { - compatible = "qcom,mpm-gic-msm8937", "qcom,mpm-gic"; + compatible = "qcom,mpm-gic-qcs405", "qcom,mpm-gic"; interrupts = ; - reg = <0x601d0 0x1000>, + reg = <0x601b8 0x1000>, <0xb011008 0x4>; /* MSM_APCS_GCC_BASE 4K */ reg-names = "vmpm", "ipc"; - qcom,num-mpm-irqs = <64>; + qcom,num-mpm-irqs = <96>; interrupt-controller; interrupt-parent = <&intc>; #interrupt-cells = <3>; }; wakegpio: wake-gpio { - compatible = "qcom,mpm-gpio-msm8937", "qcom,mpm-gpio"; + compatible = "qcom,mpm-gpio-qcs405", "qcom,mpm-gpio"; interrupt-controller; interrupt-parent = <&intc>; #interrupt-cells = <2>; -- GitLab From bd6136ed11353917d3694a3438b4219179014c92 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Wed, 4 Jul 2018 20:27:32 +0530 Subject: [PATCH 1246/1299] defconfig: Enable RPM stats drivers for qcs405 Enable various RPM stats drivers for 64 bit. Change-Id: I0f2e5c715cd4d436fb07dd0e16cf6f5afbc2d476 Signed-off-by: Maulik Shah --- arch/arm64/configs/vendor/qcs405_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index b9c9e142fe8a..cf2aa099c89b 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -427,6 +427,7 @@ CONFIG_QCOM_BUS_SCALING=y CONFIG_MSM_TZ_SMMU=y CONFIG_QCOM_GLINK=y CONFIG_QCOM_GLINK_PKT=y +CONFIG_QTI_RPM_STATS_LOG=y CONFIG_MSM_PM=y CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y -- GitLab From 6f1e145b83c2b6732e1b2a33691fb771021e34ae Mon Sep 17 00:00:00 2001 From: Amit Nischal Date: Fri, 22 Jun 2018 10:59:34 +0530 Subject: [PATCH 1247/1299] clk: qcom: Add support for gcc_usb2 ref clocks For USB2 controller operation, there is requirement to add usb2 ref clocks from gcc clock driver. Add support for the same by adding new ref clocks. Change-Id: Ie52f06c0f536cfe22df28c78f74f5034634aa335 Signed-off-by: Amit Nischal --- drivers/clk/qcom/gcc-sm6150.c | 42 +++++++++++++++++++++ include/dt-bindings/clock/qcom,gcc-sm6150.h | 3 ++ 2 files changed, 45 insertions(+) diff --git a/drivers/clk/qcom/gcc-sm6150.c b/drivers/clk/qcom/gcc-sm6150.c index 8e9b98f398c2..2a7c239375c3 100644 --- a/drivers/clk/qcom/gcc-sm6150.c +++ b/drivers/clk/qcom/gcc-sm6150.c @@ -3146,6 +3146,45 @@ static struct clk_branch gcc_wcss_vs_clk = { }, }; +static struct clk_branch gcc_rx1_usb2_clkref_clk = { + .halt_reg = 0x8c030, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8c030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_rx1_usb2_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_prim_clkref_clk = { + .halt_reg = 0x8c028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8c028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb2_prim_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_sec_clkref_clk = { + .halt_reg = 0x8c018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8c018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb2_sec_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + /* Measure-only clock for ddrss_gcc_debug_clk. */ static struct clk_dummy measure_only_bimc_clk = { .rrate = 1000, @@ -3362,6 +3401,9 @@ static struct clk_regmap *gcc_sm6150_clocks[] = { [GPLL6_OUT_MAIN] = &gpll6_out_main.clkr, [GPLL7_OUT_MAIN] = &gpll7_out_main.clkr, [GPLL8_OUT_MAIN] = &gpll8_out_main.clkr, + [GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr, + [GCC_USB2_PRIM_CLKREF_CLK] = &gcc_usb2_prim_clkref_clk.clkr, + [GCC_USB2_SEC_CLKREF_CLK] = &gcc_usb2_sec_clkref_clk.clkr, }; static const struct qcom_reset_map gcc_sm6150_resets[] = { diff --git a/include/dt-bindings/clock/qcom,gcc-sm6150.h b/include/dt-bindings/clock/qcom,gcc-sm6150.h index ed98f1450084..2b1678111e43 100644 --- a/include/dt-bindings/clock/qcom,gcc-sm6150.h +++ b/include/dt-bindings/clock/qcom,gcc-sm6150.h @@ -187,6 +187,9 @@ #define GCC_CPUSS_GNOC_CLK 167 #define GCC_DISP_XO_CLK 168 #define GCC_VIDEO_XO_CLK 169 +#define GCC_RX1_USB2_CLKREF_CLK 170 +#define GCC_USB2_PRIM_CLKREF_CLK 171 +#define GCC_USB2_SEC_CLKREF_CLK 172 /* GCC Resets */ #define GCC_QUSB2PHY_PRIM_BCR 0 -- GitLab From 206bb94089272821e1c299b91048ee684011ba36 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Thu, 5 Jul 2018 10:47:56 +0530 Subject: [PATCH 1248/1299] soc: qcom: rpm_stats: Add support to display multiple records RPM stats drivers currently displays 2 records. Add support to display multiple records using sysfs. Also remove unused code and add remove method for proper cleanup during driver unbind. Change-Id: I251fcdd3434de2125f72acd2202e7152f7937f65 Signed-off-by: Maulik Shah --- .../devicetree/bindings/arm/msm/rpm_stats.txt | 6 ++ drivers/soc/qcom/rpm_stats.c | 65 ++++++++++++++----- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt b/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt index 02dab4c8eb8d..7fe9e5ddc06a 100644 --- a/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt +++ b/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt @@ -24,10 +24,16 @@ PROPERTIES Value type: Definition: Provides labels for the reg property. +- qcom,num-records: + Usage: optional + Value type: + Definition: Specifies number of records to read from RPM RAM. + EXAMPLE: qcom,rpm-stats@c000000 { compatible = "qcom,rpm-stats"; reg = <0xC000000 0x1000>, <0x3F0000 0x4>; reg-names = "phys_addr_base", "offset_addr"; + qcom,num-records = <3>; }; diff --git a/drivers/soc/qcom/rpm_stats.c b/drivers/soc/qcom/rpm_stats.c index df3dbeb9553d..e7d9fac5e589 100644 --- a/drivers/soc/qcom/rpm_stats.c +++ b/drivers/soc/qcom/rpm_stats.c @@ -11,6 +11,8 @@ * */ +#define pr_fmt(fmt) "%s: " fmt, __func__ + #include #include #include @@ -36,6 +38,7 @@ struct msm_rpmstats_record { struct msm_rpmstats_platform_data { phys_addr_t phys_addr_base; u32 phys_size; + u32 num_records; }; struct msm_rpmstats_private_data { @@ -43,7 +46,7 @@ struct msm_rpmstats_private_data { u32 num_records; u32 read_idx; u32 len; - char buf[320]; + char buf[480]; struct msm_rpmstats_platform_data *platform_data; }; @@ -61,6 +64,7 @@ struct msm_rpm_stats_data { }; struct msm_rpmstats_kobj_attr { + struct kobject *kobj; struct kobj_attribute ka; struct msm_rpmstats_platform_data *pd; }; @@ -175,29 +179,32 @@ static ssize_t rpmstats_show(struct kobject *kobj, { struct msm_rpmstats_private_data prvdata; struct msm_rpmstats_platform_data *pdata = NULL; + ssize_t length; pdata = GET_PDATA_OF_ATTR(attr); prvdata.reg_base = ioremap_nocache(pdata->phys_addr_base, pdata->phys_size); if (!prvdata.reg_base) { - pr_err("%s: ERROR could not ioremap start=%pa, len=%u\n", - __func__, &pdata->phys_addr_base, - pdata->phys_size); + pr_err("ERROR could not ioremap start=%pa, len=%u\n", + &pdata->phys_addr_base, pdata->phys_size); return -EBUSY; } prvdata.read_idx = prvdata.len = 0; prvdata.platform_data = pdata; - prvdata.num_records = RPM_STATS_NUM_REC; + prvdata.num_records = pdata->num_records; if (prvdata.read_idx < prvdata.num_records) prvdata.len = msm_rpmstats_copy_stats(&prvdata); - return snprintf(buf, prvdata.len, "%s", prvdata.buf); + length = scnprintf(buf, prvdata.len, "%s", prvdata.buf); + iounmap(prvdata.reg_base); + return length; } -static int msm_rpmstats_create_sysfs(struct msm_rpmstats_platform_data *pd) +static int msm_rpmstats_create_sysfs(struct platform_device *pdev, + struct msm_rpmstats_platform_data *pd) { struct kobject *rpmstats_kobj = NULL; struct msm_rpmstats_kobj_attr *rpms_ka = NULL; @@ -205,7 +212,7 @@ static int msm_rpmstats_create_sysfs(struct msm_rpmstats_platform_data *pd) rpmstats_kobj = kobject_create_and_add("system_sleep", power_kobj); if (!rpmstats_kobj) { - pr_err("%s: Cannot create rpmstats kobject\n", __func__); + pr_err("Cannot create rpmstats kobject\n"); ret = -ENOMEM; goto fail; } @@ -217,6 +224,8 @@ static int msm_rpmstats_create_sysfs(struct msm_rpmstats_platform_data *pd) goto fail; } + rpms_ka->kobj = rpmstats_kobj; + sysfs_attr_init(&rpms_ka->ka.attr); rpms_ka->pd = pd; rpms_ka->ka.attr.mode = 0444; @@ -225,6 +234,7 @@ static int msm_rpmstats_create_sysfs(struct msm_rpmstats_platform_data *pd) rpms_ka->ka.store = NULL; ret = sysfs_create_file(rpmstats_kobj, &rpms_ka->ka.attr); + platform_set_drvdata(pdev, rpms_ka); fail: return ret; @@ -233,28 +243,27 @@ static int msm_rpmstats_create_sysfs(struct msm_rpmstats_platform_data *pd) static int msm_rpmstats_probe(struct platform_device *pdev) { struct msm_rpmstats_platform_data *pdata; - struct msm_rpmstats_platform_data *pd; struct resource *res = NULL, *offset = NULL; u32 offset_addr = 0; void __iomem *phys_ptr = NULL; + char *key; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "phys_addr_base"); + key = "phys_addr_base"; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, key); if (!res) return -EINVAL; - offset = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "offset_addr"); + key = "offset_addr"; + offset = platform_get_resource_byname(pdev, IORESOURCE_MEM, key); if (offset) { /* Remap the rpm-stats pointer */ phys_ptr = ioremap_nocache(offset->start, SZ_4); if (!phys_ptr) { - pr_err("%s: Failed to ioremap address: %x\n", - __func__, offset_addr); + pr_err("Failed to ioremap offset address\n"); return -ENODEV; } offset_addr = readl_relaxed(phys_ptr); @@ -264,14 +273,33 @@ static int msm_rpmstats_probe(struct platform_device *pdev) pdata->phys_addr_base = res->start + offset_addr; pdata->phys_size = resource_size(res); - if (pdev->dev.platform_data) - pd = pdev->dev.platform_data; + key = "qcom,num-records"; + if (of_property_read_u32(pdev->dev.of_node, key, &pdata->num_records)) + pdata->num_records = RPM_STATS_NUM_REC; - msm_rpmstats_create_sysfs(pdata); + msm_rpmstats_create_sysfs(pdev, pdata); return 0; } +static int msm_rpmstats_remove(struct platform_device *pdev) +{ + struct msm_rpmstats_kobj_attr *rpms_ka; + + if (!pdev) + return -EINVAL; + + rpms_ka = (struct msm_rpmstats_kobj_attr *) + platform_get_drvdata(pdev); + + sysfs_remove_file(rpms_ka->kobj, &rpms_ka->ka.attr); + kobject_put(rpms_ka->kobj); + platform_set_drvdata(pdev, NULL); + + return 0; +} + + static const struct of_device_id rpm_stats_table[] = { { .compatible = "qcom,rpm-stats" }, { }, @@ -279,6 +307,7 @@ static const struct of_device_id rpm_stats_table[] = { static struct platform_driver msm_rpmstats_driver = { .probe = msm_rpmstats_probe, + .remove = msm_rpmstats_remove, .driver = { .name = "msm_rpm_stat", .owner = THIS_MODULE, -- GitLab From 7c091086b735119317950676dcd20da1e7c76ca5 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Thu, 5 Jul 2018 10:53:43 +0530 Subject: [PATCH 1249/1299] ARM: dts: msm: Add num records for rpm stats for sm8150/sm6150/sdmmagpie Add number of records to display in rpm stats. Change-Id: I6689632fcd8160732c41f3e5faf99cc93714b404 Signed-off-by: Maulik Shah --- arch/arm64/boot/dts/qcom/sdmmagpie-pm.dtsi | 1 + arch/arm64/boot/dts/qcom/sm6150-pm.dtsi | 1 + arch/arm64/boot/dts/qcom/sm8150-pm.dtsi | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-pm.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-pm.dtsi index d12395384a45..dda1f4ec0f0e 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie-pm.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie-pm.dtsi @@ -163,6 +163,7 @@ compatible = "qcom,rpm-stats"; reg = <0xc300000 0x1000>, <0xc3f0004 0x4>; reg-names = "phys_addr_base", "offset_addr"; + qcom,num-records = <3>; }; qcom,rpmh-master-stats@b221200 { diff --git a/arch/arm64/boot/dts/qcom/sm6150-pm.dtsi b/arch/arm64/boot/dts/qcom/sm6150-pm.dtsi index 303f0634f01b..e15beb75a971 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-pm.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-pm.dtsi @@ -165,6 +165,7 @@ compatible = "qcom,rpm-stats"; reg = <0xc300000 0x1000>, <0xc3f0004 0x4>; reg-names = "phys_addr_base", "offset_addr"; + qcom,num-records = <3>; }; qcom,rpmh-master-stats@b221200 { diff --git a/arch/arm64/boot/dts/qcom/sm8150-pm.dtsi b/arch/arm64/boot/dts/qcom/sm8150-pm.dtsi index 838b17dfeba0..1a2ac061dadb 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-pm.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-pm.dtsi @@ -142,6 +142,7 @@ compatible = "qcom,rpm-stats"; reg = <0xc300000 0x1000>, <0xc3f0004 0x4>; reg-names = "phys_addr_base", "offset_addr"; + qcom,num-records = <3>; }; qcom,rpmh-master-stats@b221200 { -- GitLab From 1e37eac039b205ab21c79c14a6c56670a43f97eb Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Wed, 27 Jun 2018 16:05:57 +0530 Subject: [PATCH 1250/1299] diag: Update mask buffer after reallocation Currently, reallocated mask update buffers are not updated if the received mask range is more than the mask update buffer length. Update the reallocated buffer address before writing the mask to peripherals. CRs-Fixed: 2266693 Change-Id: I6b506ce68e17b7da61926b0f9543157812a8c555 Signed-off-by: Manoj Prabhu B --- drivers/char/diag/diag_masks.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index caf76181f228..914147a015c4 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -195,10 +195,11 @@ static void diag_send_log_mask_update(uint8_t peripheral, int equip_id) } mask_info->update_buf = temp; mask_info->update_buf_len = header_len + mask_size; + buf = temp; } memcpy(buf, &ctrl_pkt, header_len); - if (mask_size > 0) + if (mask_size > 0 && mask_size <= LOG_MASK_SIZE) memcpy(buf + header_len, mask->ptr, mask_size); mutex_unlock(&mask->lock); @@ -297,9 +298,16 @@ static void diag_send_event_mask_update(uint8_t peripheral) } else { mask_info->update_buf = temp; mask_info->update_buf_len = temp_len; + buf = temp; } } - memcpy(buf + sizeof(header), mask_info->ptr, num_bytes); + if (num_bytes > 0 && num_bytes < mask_info->mask_len) + memcpy(buf + sizeof(header), mask_info->ptr, num_bytes); + else { + pr_err("diag: num_bytes(%d) is not satisfying length condition\n", + num_bytes); + goto err; + } write_len += num_bytes; break; default: @@ -415,6 +423,7 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last) } else { mask_info->update_buf = temp; mask_info->update_buf_len = temp_len; + buf = temp; pr_debug("diag: In %s, successfully reallocated msg_mask update buffer to len: %d\n", __func__, mask_info->update_buf_len); } -- GitLab From 93ec43e66ca27a197677ec006851236ce11a54ac Mon Sep 17 00:00:00 2001 From: Lingutla Chandrasekhar Date: Thu, 5 Jul 2018 10:28:27 +0530 Subject: [PATCH 1251/1299] sched: add per CPU sched_load_boost knob Commit '858d5751bcf7b6a ("sched: introduce per CPU sched_load_boost knob")' introduce a new knob sched_load_boost that allows userspace to provide additional CPU capacity margin to work running on CPUs in msm-4.9. Userspace could increase this for exceedingly sporadic workloads in case the existing margin isn't sufficient. While porting it, sched_load_boost support is ported but missed adding procfs interface. Add it now to let user space configure the knob. Change-Id: I4277c63089f6bb5227d257ab7484d50c42827c86 Signed-off-by: Lingutla Chandrasekhar --- drivers/base/cpu.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index b56ca174f582..ff58c8efa1ef 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -209,6 +209,59 @@ static struct attribute_group cpu_isolated_attr_group = { #endif +static ssize_t show_sched_load_boost(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t rc; + unsigned int boost; + struct cpu *cpu = container_of(dev, struct cpu, dev); + int cpuid = cpu->dev.id; + + boost = per_cpu(sched_load_boost, cpuid); + rc = snprintf(buf, PAGE_SIZE-2, "%d\n", boost); + + return rc; +} + +static ssize_t __ref store_sched_load_boost(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int err; + int boost; + struct cpu *cpu = container_of(dev, struct cpu, dev); + int cpuid = cpu->dev.id; + + err = kstrtoint(strstrip((char *)buf), 0, &boost); + if (err) + return err; + + /* + * -100 is low enough to cancel out CPU's load and make it near zro. + * 1000 is close to the maximum value that cpu_util_freq_{walt,pelt} + * can take without overflow. + */ + if (boost < -100 || boost > 1000) + return -EINVAL; + + per_cpu(sched_load_boost, cpuid) = boost; + + return count; +} + +static DEVICE_ATTR(sched_load_boost, 0644, + show_sched_load_boost, + store_sched_load_boost); + +static struct attribute *sched_cpu_attrs[] = { + &dev_attr_sched_load_boost.attr, + NULL +}; + +static struct attribute_group sched_cpu_attr_group = { + .attrs = sched_cpu_attrs, +}; + static const struct attribute_group *common_cpu_attr_groups[] = { #ifdef CONFIG_KEXEC &crash_note_cpu_attr_group, @@ -216,6 +269,7 @@ static const struct attribute_group *common_cpu_attr_groups[] = { #ifdef CONFIG_HOTPLUG_CPU &cpu_isolated_attr_group, #endif + &sched_cpu_attr_group, NULL }; @@ -226,6 +280,7 @@ static const struct attribute_group *hotplugable_cpu_attr_groups[] = { #ifdef CONFIG_HOTPLUG_CPU &cpu_isolated_attr_group, #endif + &sched_cpu_attr_group, NULL }; -- GitLab From e2fb8589d3a09d4214d7c2e2599a8ab1c7d96142 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Sat, 30 Jun 2018 22:23:42 +0530 Subject: [PATCH 1252/1299] clk: qcom: Support clock misc updates for QCS405 There are clock fixes which are required for QCS405 to enable the GFX3D source to slew GPLL3 PLL. While at it also update the GCC region to be remapped in the MDSS probe for byte0/pclk0 clock. Change-Id: Iad138ef8f196ace8bd36867c032f433806cfd339 Signed-off-by: Taniya Das --- drivers/clk/qcom/gcc-qcs405.c | 53 +++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/drivers/clk/qcom/gcc-qcs405.c b/drivers/clk/qcom/gcc-qcs405.c index fdde841f3cbc..4d0f2be22e53 100644 --- a/drivers/clk/qcom/gcc-qcs405.c +++ b/drivers/clk/qcom/gcc-qcs405.c @@ -823,7 +823,7 @@ static struct clk_rcg2 byte0_clk_src = { .name = "byte0_clk_src", .parent_names = gcc_parent_names_5, .num_parents = 4, - .flags = CLK_GET_RATE_NOCACHE, + .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, .ops = &clk_byte2_ops, .vdd_class = &vdd_cx, .num_rate_max = VDD_NUM, @@ -926,17 +926,12 @@ static struct clk_rcg2 gfx3d_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_7, .freq_tbl = ftbl_gfx3d_clk_src, + .flags = FORCE_ENABLE_RCG, .clkr.hw.init = &(struct clk_init_data){ .name = "gfx3d_clk_src", .parent_names = gcc_parent_names_7, .num_parents = 6, .ops = &clk_rcg2_ops, - .vdd_class = &vdd_cx, - .num_rate_max = VDD_NUM, - .rate_max = (unsigned long[VDD_NUM]) { - [VDD_LOW] = 270000000, - [VDD_NOMINAL] = 484800000, - [VDD_HIGH] = 598000000}, }, }; @@ -1132,7 +1127,7 @@ static struct clk_rcg2 pclk0_clk_src = { .name = "pclk0_clk_src", .parent_names = gcc_parent_names_12, .num_parents = 4, - .flags = CLK_GET_RATE_NOCACHE, + .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, .ops = &clk_pixel_ops, .vdd_class = &vdd_cx, .num_rate_max = VDD_NUM, @@ -2152,8 +2147,8 @@ static struct clk_branch gcc_mdss_mdp_clk = { }, }; -static DEFINE_CLK_VOTER(mdss_mdp_vote_clk, &gcc_mdss_mdp_clk.c, 0); -static DEFINE_CLK_VOTER(mdss_rotator_vote_clk, &gcc_mdss_mdp_clk.c, 0); +static DEFINE_CLK_VOTER(mdss_mdp_vote_clk, gcc_mdss_mdp_clk, 0); +static DEFINE_CLK_VOTER(mdss_rotator_vote_clk, gcc_mdss_mdp_clk, 0); static struct clk_branch gcc_mdss_pclk0_clk = { .halt_reg = 0x4d084, @@ -2218,6 +2213,12 @@ static struct clk_branch gcc_oxili_gfx3d_clk = { .num_parents = 1, .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, + .vdd_class = &vdd_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOW] = 270000000, + [VDD_NOMINAL] = 484800000, + [VDD_HIGH] = 598000000}, }, }, }; @@ -2651,8 +2652,7 @@ static struct clk_branch gcc_usb3_phy_aux_clk = { }; static struct clk_branch gcc_usb3_phy_pipe_clk = { - .halt_reg = 0x39018, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x39018, .enable_mask = BIT(0), @@ -2958,6 +2958,8 @@ static const struct qcom_cc_desc mdss_qcs405_desc = { .config = &gcc_qcs405_regmap_config, .clks = mdss_qcs405_clocks, .num_clks = ARRAY_SIZE(mdss_qcs405_clocks), + .hwclks = mdss_qcs405_hws, + .num_hwclks = ARRAY_SIZE(mdss_qcs405_hws), }; static const struct of_device_id mdss_qcs405_match_table[] = { @@ -2970,7 +2972,10 @@ MODULE_DEVICE_TABLE(of, mdss_qcs405_match_table); static int mdss_qcs405_probe(struct platform_device *pdev) { struct clk *clk; - int ret = 0, i; + struct regmap *regmap; + struct resource *res; + void __iomem *base; + int ret = 0; clk = devm_clk_get(&pdev->dev, "pclk0_src"); if (IS_ERR(clk)) { @@ -2986,16 +2991,22 @@ static int mdss_qcs405_probe(struct platform_device *pdev) return PTR_ERR(clk); } - /* register hardware clocks */ - for (i = 0; i < ARRAY_SIZE(mdss_qcs405_hws); i++) { - clk = devm_clk_register(&pdev->dev, mdss_qcs405_hws[i]); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "Unable to register hardware clocks\n"); - return PTR_ERR(clk); - } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "Failed to get resources\n"); + return -EINVAL; } - ret = qcom_cc_probe(pdev, &mdss_qcs405_desc); + base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (IS_ERR(base)) + return PTR_ERR(base); + + regmap = devm_regmap_init_mmio(&pdev->dev, base, + mdss_qcs405_desc.config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + ret = qcom_cc_really_probe(pdev, &mdss_qcs405_desc, regmap); if (ret) { dev_err(&pdev->dev, "Failed to register MDSS clocks\n"); return ret; -- GitLab From 6c8fa26b651daea571a185d0bf83adba2d73f174 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Thu, 5 Jul 2018 13:25:06 +0530 Subject: [PATCH 1253/1299] ARM: dts: msm: Use correct interrupt number for QCS405 There are two sets of interrupts from PHY, hs_phy_irq and usb2_phy_irq. Use the usb2_phy_irq which are triggered with PHY CSR programming. Change-Id: I9eb4ae11a0d0d3df9ebfbb7535bfb0f8ced196f6 Signed-off-by: Sriharsha Allenki --- arch/arm64/boot/dts/qcom/qcs405-usb.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi index e6fb5e0620fc..6e0bb9ee40f7 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi @@ -23,7 +23,7 @@ #size-cells = <1>; ranges; - interrupts = <0 25 0>, <0 24 0>; + interrupts = <0 25 0>, <0 319 0>; interrupt-names = "pwr_event_irq", "hs_phy_irq"; clocks = <&clock_gcc GCC_USB30_MASTER_CLK>, @@ -130,7 +130,7 @@ #size-cells = <1>; ranges; - interrupts = <0 32 0>, <0 31 0>; + interrupts = <0 32 0>, <0 318 0>; interrupt-names = "pwr_event_irq", "hs_phy_irq"; clocks = <&clock_gcc GCC_USB_HS_SYSTEM_CLK>, -- GitLab From 2c1c10b2d523b54357a1b18d7a3498ac5acf874a Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Wed, 4 Jul 2018 14:14:56 +0800 Subject: [PATCH 1254/1299] ARM: dts: msm: Correct fast charging current for mlp466076 battery The property of qcom,fastchg-current-ma was set a value in uA but it actually expects a mA value. Correct it. Change-Id: I9ee5cd0606cb47cdd77aa3eecb5daebc5d8c8c32 Signed-off-by: Fenglin Wu --- .../boot/dts/qcom/fg-gen4-batterydata-mlp466076-3250mah.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-mlp466076-3250mah.dtsi b/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-mlp466076-3250mah.dtsi index 93bebb09cbc4..45975eee13e0 100644 --- a/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-mlp466076-3250mah.dtsi +++ b/arch/arm64/boot/dts/qcom/fg-gen4-batterydata-mlp466076-3250mah.dtsi @@ -14,7 +14,7 @@ qcom,mlp466076_3250mah_averaged_masterslave_mar27th2018 { /* #mlp466076_3250mAh_averaged_MasterSlave_Mar27th2018 */ qcom,max-voltage-uv = <4400000>; - qcom,fastchg-current-ma = <6000000>; + qcom,fastchg-current-ma = <6000>; qcom,jeita-fcc-ranges = <0 150 650000 151 450 4875000 451 550 1625000>; -- GitLab From bcdb609dec710a10664bc1d01ce0e70b9d0dbee9 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Thu, 5 Jul 2018 13:33:50 +0530 Subject: [PATCH 1255/1299] usb: dwc3: Fix probe failure in host only mode The commit 7681b2bac53("usb: dwc3: Change to simulate VBUS without extcon/PMI") caused a regression that in the case where the dwc3-msm driver is configured in host only mode without any extcon present results in probe failure for dwc3-msm driver. Fix the dr_mode conditional check that is causing this issue. Also remove setting vbus_active of dwc which is not needed. Change-Id: I578c2bc0056c0a14b242d98acc54a88be2c4c60a Signed-off-by: Sriharsha Allenki --- drivers/usb/dwc3/dwc3-msm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 6d899aec43d9..a4a5d7ee2686 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -2909,13 +2909,13 @@ static int dwc3_msm_extcon_register(struct dwc3_msm *mdwc) bool check_vbus_state, check_id_state, phandle_found = false; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); - if (!of_property_read_bool(node, "extcon") && - (dwc->dr_mode == USB_DR_MODE_OTG)) { - dev_dbg(mdwc->dev, "%s: no extcon, simulate vbus connect\n", + if (!of_property_read_bool(node, "extcon")) { + if (dwc->dr_mode == USB_DR_MODE_OTG) { + dev_dbg(mdwc->dev, "%s: no extcon, simulate vbus connect\n", __func__); - mdwc->vbus_active = true; - dwc->vbus_active = true; - queue_work(mdwc->dwc3_wq, &mdwc->resume_work); + mdwc->vbus_active = true; + queue_work(mdwc->dwc3_wq, &mdwc->resume_work); + } return 0; } -- GitLab From 206807374892e88374ff09329a938c1c7236d1c9 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Wed, 4 Jul 2018 14:31:03 +0530 Subject: [PATCH 1256/1299] clk: qcom: alpha: Update the setrate/enable for slew PLL Currently the slew PLL would get calibrated each time the PLL enable is requested which could result in L/Alpha values set by the PLL set rate. Avoid the above condition by calibrating the PLL in the set rate path. Change-Id: Ib83129a7f8ad5c0c8535a7f10c2e60573c06dc1f Signed-off-by: Taniya Das --- drivers/clk/qcom/clk-alpha-pll.c | 34 +++++++++++++------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index f23f88a3a116..3a115dfd6259 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -181,15 +181,10 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, { u32 val, mask; - if (config->l) - regmap_write(regmap, pll->offset + PLL_L_VAL, - config->l); - if (config->alpha) - regmap_write(regmap, pll->offset + PLL_ALPHA_VAL, - config->alpha); - if (config->alpha_u) - regmap_write(regmap, pll->offset + PLL_ALPHA_VAL_U, - config->alpha_u); + regmap_write(regmap, pll->offset + PLL_L_VAL, config->l); + regmap_write(regmap, pll->offset + PLL_ALPHA_VAL, config->alpha); + regmap_write(regmap, pll->offset + PLL_ALPHA_VAL_U, config->alpha_u); + if (config->config_ctl_val) regmap_write(regmap, pll->offset + PLL_CONFIG_CTL, config->config_ctl_val); @@ -1487,6 +1482,8 @@ static int clk_alpha_pll_slew_update(struct clk_alpha_pll *pll) return ret; } +static int clk_alpha_pll_calibrate(struct clk_hw *hw); + static int clk_alpha_pll_slew_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -1495,7 +1492,13 @@ static int clk_alpha_pll_slew_set_rate(struct clk_hw *hw, unsigned long rate, const struct pll_vco *curr_vco = NULL, *vco; u32 l, ctl; u64 a; - int i = 0; + int i = 0, rc; + + if (!clk_hw_is_enabled(hw)) { + rc = clk_alpha_pll_calibrate(hw); + if (rc) + return rc; + } freq_hz = alpha_pll_round_rate(pll, rate, parent_rate, &l, &a); if (freq_hz != rate) { @@ -1594,7 +1597,6 @@ static int clk_alpha_pll_calibrate(struct clk_hw *hw) calibration_freq = (pll->vco_table[0].min_freq + pll->vco_table[0].max_freq)/2; - freq_hz = alpha_pll_round_rate(pll, calibration_freq, clk_hw_get_rate(parent), &l, &a); if (freq_hz != calibration_freq) { @@ -1648,15 +1650,7 @@ static int clk_alpha_pll_calibrate(struct clk_hw *hw) static int clk_alpha_pll_slew_enable(struct clk_hw *hw) { - int rc; - - rc = clk_alpha_pll_calibrate(hw); - if (rc) - return rc; - - rc = clk_alpha_pll_enable(hw); - - return rc; + return clk_alpha_pll_enable(hw); } const struct clk_ops clk_alpha_pll_slew_ops = { -- GitLab From 1c2eeb1b9d673822e1295d1a8d855c3b168cde56 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Wed, 4 Jul 2018 21:36:13 +0530 Subject: [PATCH 1257/1299] clk: qcom: clk-rcg2: Introduce a cfg offset for RCGs The RCG CFG/M/N/D register base could be at a different offset than the CMD register, so introduce a cfg_offset to identify the offset with respect to the CMD register. Change-Id: I2f0d085edb24852d69def0185bfaec5d2fd290e9 Signed-off-by: Taniya Das --- drivers/clk/qcom/clk-rcg.h | 2 ++ drivers/clk/qcom/clk-rcg2.c | 37 +++++++++++++++++++++++-------------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index 1b9a5f13de18..197ba2ce6f28 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -161,6 +161,7 @@ extern const struct clk_ops clk_dyn_rcg_ops; * @current_freq: last cached frequency when using branches with shared RCGs * @enable_safe_config: When set, the RCG is parked at CXO when it's disabled * @clkr: regmap clock handle + * @cfg_off: defines the cfg register offseted from the CMD_RCGR * @flags: additional flag parameters for the RCG */ struct clk_rcg2 { @@ -172,6 +173,7 @@ struct clk_rcg2 { unsigned long current_freq; bool enable_safe_config; struct clk_regmap clkr; + u8 cfg_off; u8 flags; #define FORCE_ENABLE_RCG BIT(0) #define DFS_ENABLE_RCG BIT(1) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 866d5aaf84a5..41d40a955f98 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -92,7 +92,8 @@ static u8 clk_rcg2_get_parent(struct clk_hw *hw) u32 cfg; int i, ret; - ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg); + ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + rcg->cfg_off + + CFG_REG, &cfg); if (ret) goto err; @@ -147,13 +148,14 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index) u32 old_cfg; /* Read back the old configuration */ - regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &old_cfg); + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + rcg->cfg_off + CFG_REG, + &old_cfg); if (rcg->flags & DFS_ENABLE_RCG) return 0; - ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, - CFG_SRC_SEL_MASK, cfg); + ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + + rcg->cfg_off + CFG_REG, CFG_SRC_SEL_MASK, cfg); if (ret) return ret; @@ -272,13 +274,16 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) return rcg->current_freq; } - regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg); + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + rcg->cfg_off + CFG_REG, + &cfg); if (rcg->mnd_width) { mask = BIT(rcg->mnd_width) - 1; - regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG, &m); + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + rcg->cfg_off + + M_REG, &m); m &= mask; - regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG, &n); + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + rcg->cfg_off + + N_REG, &n); n = ~n; n &= mask; n += m; @@ -389,22 +394,26 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) return index; /* Read back the old configuration */ - regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &old_cfg); + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + rcg->cfg_off + CFG_REG, + &old_cfg); if (rcg->mnd_width && f->n) { mask = BIT(rcg->mnd_width) - 1; ret = regmap_update_bits(rcg->clkr.regmap, - rcg->cmd_rcgr + M_REG, mask, f->m); + rcg->cmd_rcgr + rcg->cfg_off + M_REG, + mask, f->m); if (ret) return ret; ret = regmap_update_bits(rcg->clkr.regmap, - rcg->cmd_rcgr + N_REG, mask, ~(f->n - f->m)); + rcg->cmd_rcgr + rcg->cfg_off + N_REG, + mask, ~(f->n - f->m)); if (ret) return ret; ret = regmap_update_bits(rcg->clkr.regmap, - rcg->cmd_rcgr + D_REG, mask, ~f->n); + rcg->cmd_rcgr + rcg->cfg_off + D_REG, + mask, ~f->n); if (ret) return ret; } @@ -416,7 +425,7 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) if (rcg->mnd_width && f->n && (f->m != f->n)) cfg |= CFG_MODE_DUAL_EDGE; ret = regmap_update_bits(rcg->clkr.regmap, - rcg->cmd_rcgr + CFG_REG, mask, cfg); + rcg->cmd_rcgr + rcg->cfg_off + CFG_REG, mask, cfg); if (ret) return ret; @@ -445,7 +454,7 @@ static void clk_rcg2_list_registers(struct seq_file *f, struct clk_hw *hw) size = ARRAY_SIZE(data1); for (i = 0; i < size; i++) { regmap_read(rcg->clkr.regmap, (rcg->cmd_rcgr + - data1[i].offset), &val); + rcg->cfg_off + data1[i].offset), &val); clock_debug_output(f, false, "%20s: 0x%.8x\n", data1[i].name, val); } @@ -453,7 +462,7 @@ static void clk_rcg2_list_registers(struct seq_file *f, struct clk_hw *hw) size = ARRAY_SIZE(data); for (i = 0; i < size; i++) { regmap_read(rcg->clkr.regmap, (rcg->cmd_rcgr + - data[i].offset), &val); + rcg->cfg_off + data[i].offset), &val); clock_debug_output(f, false, "%20s: 0x%.8x\n", data[i].name, val); } -- GitLab From 929f07f4ae476789db89cc81bceae94609553264 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Thu, 28 Jun 2018 12:47:55 +0530 Subject: [PATCH 1258/1299] ARM: dts: msm: Update thermal zone names for TSENS rules for SM6150 Update thermal zone names for gold cpu TSENS user_space governor rules with proper cpu mappings for SM6150. Change-Id: Icc643ee2e78ff107fdce3ea68b58545e1e426734 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi b/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi index 37bae76fa1e4..f73f763adcbb 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi @@ -84,7 +84,7 @@ }; }; - apc1-cpu0-usr { + cpu-1-0-usr { polling-delay-passive = <0>; polling-delay = <0>; thermal-sensors = <&tsens0 5>; @@ -98,7 +98,7 @@ }; }; - apc1-cpu1-usr { + cpu-1-1-usr { polling-delay-passive = <0>; polling-delay = <0>; thermal-sensors = <&tsens0 6>; @@ -112,7 +112,7 @@ }; }; - apc1-cpu2-usr { + cpu-1-2-usr { polling-delay-passive = <0>; polling-delay = <0>; thermal-sensors = <&tsens0 7>; @@ -126,7 +126,7 @@ }; }; - apc1-cpu3-usr { + cpu-1-3-usr { polling-delay-passive = <0>; polling-delay = <0>; thermal-sensors = <&tsens0 8>; -- GitLab From a642ec7d868abda9a286564d03cfce42f0cd218f Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Fri, 29 Jun 2018 15:54:40 +0530 Subject: [PATCH 1259/1299] ARM: dts: msm: Add QMI cooling device for SM6150 Add QMI cooling devices for SM6150. These cooling devices will be used to apply cold temperature voltage restriction and other mitigation for remote subsystems. Change-Id: I72fc50ae192aaee0717df6662b0204a5291af36c Signed-off-by: Manaf Meethalavalappu Pallikunhi --- arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi | 53 ++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi b/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi index f73f763adcbb..95a8366d4b00 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi @@ -13,6 +13,59 @@ #include +&soc { + qmi-tmd-devices { + compatible = "qcom,qmi-cooling-devices"; + + modem { + qcom,instance-id = <0x0>; + + modem_pa: modem_pa { + qcom,qmi-dev-name = "pa"; + #cooling-cells = <2>; + }; + + modem_proc: modem_proc { + qcom,qmi-dev-name = "modem"; + #cooling-cells = <2>; + }; + + modem_current: modem_current { + qcom,qmi-dev-name = "modem_current"; + #cooling-cells = <2>; + }; + + modem_skin: modem_skin { + qcom,qmi-dev-name = "modem_skin"; + #cooling-cells = <2>; + }; + + modem_vdd: modem_vdd { + qcom,qmi-dev-name = "cpuv_restriction_cold"; + #cooling-cells = <2>; + }; + }; + + adsp { + qcom,instance-id = <0x1>; + + adsp_vdd: adsp_vdd { + qcom,qmi-dev-name = "cpuv_restriction_cold"; + #cooling-cells = <2>; + }; + }; + + cdsp { + qcom,instance-id = <0x43>; + + cdsp_vdd: cdsp_vdd { + qcom,qmi-dev-name = "cpuv_restriction_cold"; + #cooling-cells = <2>; + }; + }; + }; +}; + &thermal_zones { aoss-usr { polling-delay-passive = <0>; -- GitLab From d17c078bcd5db7fada3a365200e85877a8080262 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Mon, 2 Jul 2018 12:18:37 +0530 Subject: [PATCH 1260/1299] ARM: dts: msm: Add regulator cooling device for SM6150 Add regulator cooling device for SM6150. These cooling devices will be used to place minimum voltage restriction at low temperature for CX and MX rails. Change-Id: I20ac938c79c4bc31499afdfdf03d0e588ee28b06 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- arch/arm64/boot/dts/qcom/sm6150-regulator.dtsi | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm6150-regulator.dtsi b/arch/arm64/boot/dts/qcom/sm6150-regulator.dtsi index 184c771ea70e..ee3ac333f706 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-regulator.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-regulator.dtsi @@ -43,6 +43,14 @@ qcom,init-voltage-level = ; }; + + mx_cdev: mx-cdev-lvl { + compatible = "qcom,regulator-cooling-device"; + regulator-cdev-supply = <&VDD_MX_LEVEL>; + regulator-levels = ; + #cooling-cells = <2>; + }; }; /* pm6150 S1 - VDD_CX supply */ @@ -78,6 +86,13 @@ ; qcom,min-dropout-voltage-level = <(-1)>; }; + + cx_cdev: regulator-cdev { + compatible = "qcom,rpmh-reg-cdev"; + mboxes = <&qmp_aop 0>; + qcom,reg-resource-name = "cx"; + #cooling-cells = <2>; + }; }; -- GitLab From cda951ed403408f7e186f541afb03555b693280b Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Mon, 2 Jul 2018 12:24:09 +0530 Subject: [PATCH 1261/1299] drivers: thermal: virtual-sensor: Add new virtual sensors for SM6150 Add new virtual sensor definitions for cpuss0-max-step and apc1-max-step for SM6150. This virtual sensor can be used to monitor the overall temperature of each CPU cluster device. Change-Id: I4209845ad38a1584c903ac72d4fb01a3d5e33031 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- drivers/thermal/qcom/qti_virtual_sensor.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/thermal/qcom/qti_virtual_sensor.c b/drivers/thermal/qcom/qti_virtual_sensor.c index 31fcfde67a0b..9c2023198440 100644 --- a/drivers/thermal/qcom/qti_virtual_sensor.c +++ b/drivers/thermal/qcom/qti_virtual_sensor.c @@ -120,6 +120,25 @@ static const struct virtual_sensor_data qti_virtual_sensors[] = { "mhm-usr"}, .logic = VIRT_MAXIMUM, }, + { + .virt_zone_name = "cpuss0-max-step", + .num_sensors = 4, + .sensor_names = {"cpuss-0-usr", + "cpuss-1-usr", + "cpuss-2-usr", + "cpuss-3-usr"}, + .logic = VIRT_MAXIMUM, + }, + { + .virt_zone_name = "apc1-max-step", + .num_sensors = 4, + .sensor_names = {"cpu-1-0-usr", + "cpu-1-1-usr", + "cpu-1-2-usr", + "cpu-1-3-usr"}, + .logic = VIRT_MAXIMUM, + }, + }; int qti_virtual_sensor_register(struct device *dev) -- GitLab From 2c2a7f7180fe98bf26641f79fcc76d4fb83160de Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Thu, 5 Jul 2018 14:52:26 +0530 Subject: [PATCH 1262/1299] drivers: irqchip: mpm: Remove GPIOs not used by APPS Remove GPIOs not used by APSS from mpm pin mapping for qcs405. Change-Id: Ic8ed2bd716f915ec2488e6b695336a8c91f92f88 Signed-off-by: Raghavendra Kakarla --- drivers/irqchip/qcom/mpm-qcs405.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/irqchip/qcom/mpm-qcs405.c b/drivers/irqchip/qcom/mpm-qcs405.c index d73cd8111fe9..afefa9978cf3 100644 --- a/drivers/irqchip/qcom/mpm-qcs405.c +++ b/drivers/irqchip/qcom/mpm-qcs405.c @@ -68,9 +68,6 @@ const struct mpm_pin mpm_qcs405_gpio_chip_data[] = { {56, 113}, {57, 114}, {58, 115}, - {64, 3}, - {65, 17}, - {66, 19}, {67, 53}, {68, 54}, {-1}, -- GitLab From 41d439d03e16ef347c90070acde7227cd89a323f Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Thu, 5 Jul 2018 08:10:13 -0700 Subject: [PATCH 1263/1299] soc: qcom: Add support for per-CPU scandump sizes Add support for specification of per-CPU scandump sizes. If the scandump sizes are not specified in the correct format, then no memory will be allocated for the scandump region of any CPU. Change-Id: I7d8a192f38ed665fec4a53f011fff62f453ffcd3 Signed-off-by: Isaac J. Manjarres --- .../bindings/arm/msm/msm_watchdog.txt | 4 +++ drivers/soc/qcom/watchdog_v2.c | 25 ++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt b/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt index 53ad68e2e1b2..82d86ab39553 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt @@ -33,6 +33,9 @@ Optional properties: - qcom,ipi-ping : (boolean) send keep alive ping to other cpus if present - qcom,wakeup-enable : (boolean) enable non secure watchdog to freeze / unfreeze automatically across suspend / resume path. +- qcom,scandump-sizes : an array of 32-bit values that contains the size of the + scandump memory region for each CPU, such that the nth + 32 bit value maps to the scandump size for CPU n. Example: @@ -45,4 +48,5 @@ Example: qcom,pet-time = <10000>; qcom,ipi-ping; qcom,wakeup-enable; + qcom,scandump-size = <0x10100 0x10100 0x10100 0x10100>; }; diff --git a/drivers/soc/qcom/watchdog_v2.c b/drivers/soc/qcom/watchdog_v2.c index aa694f05f8db..ff1dd668bef0 100644 --- a/drivers/soc/qcom/watchdog_v2.c +++ b/drivers/soc/qcom/watchdog_v2.c @@ -54,7 +54,6 @@ #define SCM_SET_REGSAVE_CMD 0x2 #define SCM_SVC_SEC_WDOG_DIS 0x7 #define MAX_CPU_CTX_SIZE 2048 -#define MAX_CPU_SCANDUMP_SIZE 0x10100 static struct msm_watchdog_data *wdog_data; @@ -100,6 +99,7 @@ struct msm_watchdog_data { unsigned long long thread_start; unsigned long long ping_start[NR_CPUS]; unsigned long long ping_end[NR_CPUS]; + unsigned int cpu_scandump_sizes[NR_CPUS]; }; /* @@ -598,8 +598,10 @@ static void configure_scandump(struct msm_watchdog_data *wdog_dd) int cpu; static dma_addr_t dump_addr; static void *dump_vaddr; + unsigned int scandump_size; for_each_cpu(cpu, cpu_present_mask) { + scandump_size = wdog_dd->cpu_scandump_sizes[cpu]; cpu_data = devm_kzalloc(wdog_dd->dev, sizeof(struct msm_dump_data), GFP_KERNEL); @@ -607,17 +609,17 @@ static void configure_scandump(struct msm_watchdog_data *wdog_dd) continue; dump_vaddr = (void *) dma_alloc_coherent(wdog_dd->dev, - MAX_CPU_SCANDUMP_SIZE, + scandump_size, &dump_addr, GFP_KERNEL); if (!dump_vaddr) { dev_err(wdog_dd->dev, "Couldn't get memory for dump\n"); continue; } - memset(dump_vaddr, 0x0, MAX_CPU_SCANDUMP_SIZE); + memset(dump_vaddr, 0x0, scandump_size); cpu_data->addr = dump_addr; - cpu_data->len = MAX_CPU_SCANDUMP_SIZE; + cpu_data->len = scandump_size; snprintf(cpu_data->name, sizeof(cpu_data->name), "KSCANDUMP%d", cpu); dump_entry.id = MSM_DUMP_DATA_SCANDUMP_PER_CPU + cpu; @@ -627,7 +629,7 @@ static void configure_scandump(struct msm_watchdog_data *wdog_dd) if (ret) { dev_err(wdog_dd->dev, "Dump setup failed, id = %d\n", MSM_DUMP_DATA_SCANDUMP_PER_CPU + cpu); - dma_free_coherent(wdog_dd->dev, MAX_CPU_SCANDUMP_SIZE, + dma_free_coherent(wdog_dd->dev, scandump_size, dump_vaddr, dump_addr); devm_kfree(wdog_dd->dev, cpu_data); @@ -752,7 +754,7 @@ static int msm_wdog_dt_to_pdata(struct platform_device *pdev, { struct device_node *node = pdev->dev.of_node; struct resource *res; - int ret; + int ret, cpu, num_scandump_sizes; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wdt-base"); if (!res) @@ -814,6 +816,17 @@ static int msm_wdog_dt_to_pdata(struct platform_device *pdev, pdata->wakeup_irq_enable = of_property_read_bool(node, "qcom,wakeup-enable"); + num_scandump_sizes = of_property_count_elems_of_size(node, + "qcom,scandump-sizes", + sizeof(u32)); + if (num_scandump_sizes < 0 || num_scandump_sizes != NR_CPUS) + dev_info(&pdev->dev, "%s scandump sizes property not correct\n", + __func__); + else + for_each_cpu(cpu, cpu_present_mask) + of_property_read_u32_index(node, "qcom,scandump-sizes", + cpu, + &pdata->cpu_scandump_sizes[cpu]); pdata->irq_ppi = irq_is_percpu(pdata->bark_irq); dump_pdata(pdata); return 0; -- GitLab From a278e9abb3be6c0c563af1f815fb596c61b4a748 Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Thu, 5 Jul 2018 08:22:41 -0700 Subject: [PATCH 1264/1299] ARM: dts: msm: Add scandump sizes for SM8150 CPUs Add scandump sizes for each CPU on the SM8150 chipset to ensure that the correct scandump sizes are used for each CPU. Change-Id: Ib227c35fc81d9fd6375a893de9a5e5fca5f5425f Signed-off-by: Isaac J. Manjarres --- arch/arm64/boot/dts/qcom/sm8150.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index 36e220859582..c2d3591f6e25 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -1757,6 +1757,8 @@ qcom,pet-time = <9360>; qcom,ipi-ping; qcom,wakeup-enable; + qcom,scandump-sizes = <0x10100 0x10100 0x10100 0x10100 + 0x18100 0x18100 0x18100 0x18100>; }; qcom,npu@0x9800000 { -- GitLab From bd8d67f6b5b6af9493c806478f1e3f20aac49167 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Wed, 4 Mar 2015 20:41:21 +0530 Subject: [PATCH 1265/1299] lowmemorykiller: adapt to vmpressure There were issues reported, where page cache thrashing was observed because of LMK not killing tasks when required, resulting in sluggishness and higher app launch latency. LMK does not kill a task for the following reasons. 1. The free and file pages are above the LMK thresholds 2. LMK tries to pick task with an adj level corresponding to current thresholds, but fails to do so because of the absence of tasks in that level. But sometimes it is better to kill a lower adj task, than thrashing. And there are cases where the number of file pages are huge, though we dont thrash, the reclaim process becomes time consuming, since LMK triggers will be delayed because of higher number of file pages. Even in such cases, when reclaim path finds it difficult to reclaim pages, it is better to trigger lmk to free up some memory faster. The basic idea here is to make LMK more aggressive dynamically when such a thrashing scenario is detected. To detect thrashing, this patch uses vmpressure events. The values of vmpressure upon which an action has to be taken, was derived empirically. This patch also adds tracepoints to validate this feature, almk_shrink and almk_vmpressure. Two knobs are available for the user to tune adaptive lmk behaviour. /sys/module/lowmemorykiller/parameters/adaptive_lmk - Write 1 to enable the feature, 0 to disable. By default disabled. /sys/module/lowmemorykiller/parameters/vmpressure_file_min - This parameter controls the behaviour of LMK when vmpressure is in the range of 90-94. Adaptive lmk triggers based on number file pages wrt vmpressure_file_min, when vmpressure is in the range of 90-94. Usually this is a pseudo minfree value, higher than the highest configured value in minfree array. Change-Id: I1a08160c35d3e33bdfd1d2c789c288fc07d0f0d3 Signed-off-by: Vinayak Menon --- drivers/staging/android/lowmemorykiller.c | 100 ++++++++++++++++++++++ include/trace/events/almk.h | 84 ++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 include/trace/events/almk.h diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index b336d997c493..8eca6e28da7d 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -47,6 +47,10 @@ #include #include #include +#include + +#define CREATE_TRACE_POINTS +#include #ifdef CONFIG_HIGHMEM #define _ZONE ZONE_HIGHMEM @@ -93,6 +97,93 @@ static unsigned long lowmem_count(struct shrinker *s, global_node_page_state(NR_INACTIVE_FILE); } +static atomic_t shift_adj = ATOMIC_INIT(0); +static short adj_max_shift = 353; + +/* User knob to enable/disable adaptive lmk feature */ +static int enable_adaptive_lmk; +module_param_named(enable_adaptive_lmk, enable_adaptive_lmk, int, 0644); + +/* + * This parameter controls the behaviour of LMK when vmpressure is in + * the range of 90-94. Adaptive lmk triggers based on number of file + * pages wrt vmpressure_file_min, when vmpressure is in the range of + * 90-94. Usually this is a pseudo minfree value, higher than the + * highest configured value in minfree array. + */ +static int vmpressure_file_min; +module_param_named(vmpressure_file_min, vmpressure_file_min, int, 0644); + +enum { + VMPRESSURE_NO_ADJUST = 0, + VMPRESSURE_ADJUST_ENCROACH, + VMPRESSURE_ADJUST_NORMAL, +}; + +static int adjust_minadj(short *min_score_adj) +{ + int ret = VMPRESSURE_NO_ADJUST; + + if (!enable_adaptive_lmk) + return 0; + + if (atomic_read(&shift_adj) && + (*min_score_adj > adj_max_shift)) { + if (*min_score_adj == OOM_SCORE_ADJ_MAX + 1) + ret = VMPRESSURE_ADJUST_ENCROACH; + else + ret = VMPRESSURE_ADJUST_NORMAL; + *min_score_adj = adj_max_shift; + } + atomic_set(&shift_adj, 0); + + return ret; +} + +static int lmk_vmpressure_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + int other_free, other_file; + unsigned long pressure = action; + int array_size = ARRAY_SIZE(lowmem_adj); + + if (!enable_adaptive_lmk) + return 0; + + if (pressure >= 95) { + other_file = global_node_page_state(NR_FILE_PAGES) - + global_node_page_state(NR_SHMEM) - + total_swapcache_pages(); + other_free = global_zone_page_state(NR_FREE_PAGES); + + atomic_set(&shift_adj, 1); + trace_almk_vmpressure(pressure, other_free, other_file); + } else if (pressure >= 90) { + if (lowmem_adj_size < array_size) + array_size = lowmem_adj_size; + if (lowmem_minfree_size < array_size) + array_size = lowmem_minfree_size; + + other_file = global_node_page_state(NR_FILE_PAGES) - + global_node_page_state(NR_SHMEM) - + total_swapcache_pages(); + + other_free = global_zone_page_state(NR_FREE_PAGES); + + if (other_free < lowmem_minfree[array_size - 1] && + other_file < vmpressure_file_min) { + atomic_set(&shift_adj, 1); + trace_almk_vmpressure(pressure, other_free, other_file); + } + } + + return 0; +} + +static struct notifier_block lmk_vmpr_nb = { + .notifier_call = lmk_vmpressure_notifier, +}; + static int test_task_flag(struct task_struct *p, int flag) { struct task_struct *t = p; @@ -307,6 +398,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) unsigned long rem = 0; int tasksize; int i; + int ret = 0; short min_score_adj = OOM_SCORE_ADJ_MAX + 1; int minfree = 0; int selected_tasksize = 0; @@ -344,11 +436,14 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) } } + ret = adjust_minadj(&min_score_adj); + lowmem_print(3, "%s %lu, %x, ofree %d %d, ma %hd\n", __func__, sc->nr_to_scan, sc->gfp_mask, other_free, other_file, min_score_adj); if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) { + trace_almk_shrink(0, ret, other_free, other_file, 0); lowmem_print(5, "%s %lu, %x, return 0\n", __func__, sc->nr_to_scan, sc->gfp_mask); mutex_unlock(&scan_mutex); @@ -451,7 +546,11 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) rcu_read_unlock(); /* give the system time to free up the memory */ msleep_interruptible(20); + trace_almk_shrink(selected_tasksize, ret, + other_free, other_file, + selected_oom_score_adj); } else { + trace_almk_shrink(1, ret, other_free, other_file, 0); rcu_read_unlock(); } @@ -470,6 +569,7 @@ static struct shrinker lowmem_shrinker = { static int __init lowmem_init(void) { register_shrinker(&lowmem_shrinker); + vmpressure_notifier_register(&lmk_vmpr_nb); return 0; } device_initcall(lowmem_init); diff --git a/include/trace/events/almk.h b/include/trace/events/almk.h new file mode 100644 index 000000000000..85d712d48f50 --- /dev/null +++ b/include/trace/events/almk.h @@ -0,0 +1,84 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM almk + +#if !defined(_TRACE_EVENT_ALMK_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_EVENT_ALMK_H + +#include +#include + +TRACE_EVENT(almk_vmpressure, + + TP_PROTO(unsigned long pressure, + int other_free, + int other_file), + + TP_ARGS(pressure, other_free, other_file), + + TP_STRUCT__entry( + __field(unsigned long, pressure) + __field(int, other_free) + __field(int, other_file) + ), + + TP_fast_assign( + __entry->pressure = pressure; + __entry->other_free = other_free; + __entry->other_file = other_file; + ), + + TP_printk("%lu, %d, %d", + __entry->pressure, __entry->other_free, + __entry->other_file) +); + +TRACE_EVENT(almk_shrink, + + TP_PROTO(int tsize, + int vmp, + int other_free, + int other_file, + short adj), + + TP_ARGS(tsize, vmp, other_free, other_file, adj), + + TP_STRUCT__entry( + __field(int, tsize) + __field(int, vmp) + __field(int, other_free) + __field(int, other_file) + __field(short, adj) + ), + + TP_fast_assign( + __entry->tsize = tsize; + __entry->vmp = vmp; + __entry->other_free = other_free; + __entry->other_file = other_file; + __entry->adj = adj; + ), + + TP_printk("%d, %d, %d, %d, %d", + __entry->tsize, + __entry->vmp, + __entry->other_free, + __entry->other_file, + __entry->adj) +); + +#endif + +#include + -- GitLab From 3e066a00d1fb7136172df9d93a2921ac918e9a79 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Thu, 21 May 2015 20:44:14 +0530 Subject: [PATCH 1266/1299] lowmemorykiller: use for_each_thread instead of buggy while_each_thread Couple of cases were reported few months ago, where the cpu was blocked on the following call stack for /seconds/ after which the watchdog fires. test_task_flag(p = 0xE14ABF00, ?) lowmem_shrink(?, sc = 0xD7A03C04) shrink_slab(shrink = 0xD7A03C04, nr_pages_scanned = 0, lru_pages = 120) try_to_free_pages(zonelist = 0xC1116440, ?, ?, ?) __alloc_pages_nodemask(?, order = 0, ?, nodemask = 0x0) __do_page_cache_readahead(mapping = 0xEB819364, filp = 0xCC16DC00, offset = ra_submit(?, ?, ?) filemap_fault(vma = 0xC105D240, vmf = 0xD7A03DC8) There weren't any dumps to analyse the case, but this can be a possible reason. while_each_thread is known to be buggy and can result in the function looping forever if the task exits, even when protected with rcu_read_lock. Use for_each_thread instead. More details on the problems with while_each_thread can be found at https://lkml.org/lkml/2013/12/2/320 Change-Id: I5eb6e4b463f81142a2a7824db389201357432ec7 Signed-off-by: Vinayak Menon --- drivers/staging/android/lowmemorykiller.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 8eca6e28da7d..d9a5dabe7800 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -186,32 +186,32 @@ static struct notifier_block lmk_vmpr_nb = { static int test_task_flag(struct task_struct *p, int flag) { - struct task_struct *t = p; + struct task_struct *t; - do { + for_each_thread(p, t) { task_lock(t); if (test_tsk_thread_flag(t, flag)) { task_unlock(t); return 1; } task_unlock(t); - } while_each_thread(p, t); + } return 0; } static int test_task_lmk_waiting(struct task_struct *p) { - struct task_struct *t = p; + struct task_struct *t; - do { + for_each_thread(p, t) { task_lock(t); if (task_lmk_waiting(t)) { task_unlock(t); return 1; } task_unlock(t); - } while_each_thread(p, t); + } return 0; } -- GitLab From 553679474b531a17f27d39bca2c30715df06c2f0 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Wed, 19 Aug 2015 16:11:04 +0530 Subject: [PATCH 1267/1299] lowmemorykiller: avoid false adaptive LMK triggers In vmpressure notifier of LMK, shift_adj would have been set by a previous invocation of notifier, which is not followed by a lowmem_shrink yet. If this is follwed by a lower vmpressure, and then by a lowmem_shrink, ALMK still triggers because of the previous higher vmpressure notification. This is wrong. Since vmpressure has improved, reset shift_adj to avoid false adaptive LMK trigger. Change-Id: I2d77103d7c8f4d8a66e4652cba78e619a7bcef9a Signed-off-by: Vinayak Menon --- drivers/staging/android/lowmemorykiller.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index d9a5dabe7800..6ab555fb64ac 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -175,6 +175,20 @@ static int lmk_vmpressure_notifier(struct notifier_block *nb, atomic_set(&shift_adj, 1); trace_almk_vmpressure(pressure, other_free, other_file); } + } else if (atomic_read(&shift_adj)) { + other_file = global_node_page_state(NR_FILE_PAGES) - + global_node_page_state(NR_SHMEM) - + total_swapcache_pages(); + + other_free = global_zone_page_state(NR_FREE_PAGES); + /* + * shift_adj would have been set by a previous invocation + * of notifier, which is not followed by a lowmem_shrink yet. + * Since vmpressure has improved, reset shift_adj to avoid + * false adaptive LMK trigger. + */ + trace_almk_vmpressure(pressure, other_free, other_file); + atomic_set(&shift_adj, 0); } return 0; -- GitLab From 4828e4f22f59313a73a5fd419a5ba8938bacdaed Mon Sep 17 00:00:00 2001 From: Srinivas Ramana Date: Fri, 13 May 2016 18:17:41 +0530 Subject: [PATCH 1268/1299] lowmemorykiller:fix arguments to zone_watermark_ok_safe The alloc_flags argument of zone_watermark_ok_safe() is no more available. Fix the usage. Change-Id: I99b832418b914765a4941682929dd7183d274e1c Signed-off-by: Srinivas Ramana --- drivers/staging/android/lowmemorykiller.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 6ab555fb64ac..aefad06fb917 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -323,8 +323,7 @@ static void adjust_gfp_mask(gfp_t *gfp_mask) if (high_zoneidx == ZONE_NORMAL) { if (zone_watermark_ok_safe( preferred_zone, 0, - high_wmark_pages(preferred_zone), 0, - 0)) + high_wmark_pages(preferred_zone), 0)) *gfp_mask |= __GFP_HIGHMEM; } else if (high_zoneidx == ZONE_HIGHMEM) { *gfp_mask |= __GFP_HIGHMEM; -- GitLab From 246bb7931ab3d20ffb589e2e10d9e1617f4157f0 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Tue, 18 Apr 2017 07:32:20 +0530 Subject: [PATCH 1269/1299] lowmemorykiller: fix scan_mutex contention A livelock can be created in the system by lowmemorykiller trying to kill the same task again and again. Below is the livelock condition. P0 -> binder_main_lock(W) P1 -> binder_main_lock(T)-> mmap_sem(W) P2 -> mmap_sem(T) -> lowmem_scan::scan_mutex(W) P3 -> lowmem_scan::scan_mutex(T) -> send SIGKILL P0 Here multiple tasks are contending on scan_mutex, and binder_main_lock. Change lowmem_scan mutex_lock with mutex_trylock, so in case of lowmem_scan lock contention, task will be allowed to reclaim from other shrinkers. This will also maintain the serialization of lowmemorykiller trigger. If a task is pending MEMDIE'ing, remove sleep before falling back on other shrinkers. If the task selected to be killed is MEMDIE'ing and in un-interruptible sleep state, do not repeat kill but fallback on other shrinkers without any delay. Change-Id: I12131622f7fa7b422c6d5d09f782af848300e412 [guptap: update TIF_MEMDIE check with test lmk_waiting] Signed-off-by: Prakash Gupta --- drivers/staging/android/lowmemorykiller.c | 30 ++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index aefad06fb917..ed3ce90e6037 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -214,6 +214,22 @@ static int test_task_flag(struct task_struct *p, int flag) return 0; } +static int test_task_state(struct task_struct *p, int state) +{ + struct task_struct *t; + + for_each_thread(p, t) { + task_lock(t); + if (t->state & state) { + task_unlock(t); + return 1; + } + task_unlock(t); + } + + return 0; +} + static int test_task_lmk_waiting(struct task_struct *p) { struct task_struct *t; @@ -420,7 +436,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) int other_free; int other_file; - if (mutex_lock_interruptible(&scan_mutex) < 0) + if (!mutex_trylock(&scan_mutex)) return 0; other_free = global_zone_page_state(NR_FREE_PAGES) - totalreserve_pages; @@ -480,8 +496,6 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (time_before_eq(jiffies, lowmem_deathpending_timeout)) { if (test_task_lmk_waiting(tsk)) { rcu_read_unlock(); - /* give the system time to free up the memory */ - msleep_interruptible(20); mutex_unlock(&scan_mutex); return 0; } @@ -518,6 +532,16 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) long cache_limit = minfree * (long)(PAGE_SIZE / 1024); long free = other_free * (long)(PAGE_SIZE / 1024); + if (test_task_lmk_waiting(selected) && + (test_task_state(selected, TASK_UNINTERRUPTIBLE))) { + lowmem_print(2, "'%s' (%d) is already killed\n", + selected->comm, + selected->pid); + rcu_read_unlock(); + mutex_unlock(&scan_mutex); + return 0; + } + task_lock(selected); send_sig(SIGKILL, selected, 0); if (selected->mm) -- GitLab From b95aeb6151cc0180f79df77440bebed9d5854e5b Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Thu, 20 Jul 2017 20:08:08 +0530 Subject: [PATCH 1270/1299] lowmemorykiller: use oom reaper to free pages of task killed by lmk Free the pages parallely for a task that is LMK killed using the oom_reaper. This freeing of pages will help to give the pages to buddy system well advance there by we may achieve less number of killings by LMK. Change-Id: I5e1ed183437ab243f12cbbf3ae10d9ca5211fc06 Signed-off-by: Charan Teja Reddy --- drivers/staging/android/lowmemorykiller.c | 17 +++++++++++++++++ include/linux/oom.h | 2 ++ mm/oom_kill.c | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index ed3ce90e6037..65ac5ef8d423 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -48,6 +48,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -114,6 +115,10 @@ module_param_named(enable_adaptive_lmk, enable_adaptive_lmk, int, 0644); static int vmpressure_file_min; module_param_named(vmpressure_file_min, vmpressure_file_min, int, 0644); +/* User knob to enable/disable oom reaping feature */ +static int oom_reaper; +module_param_named(oom_reaper, oom_reaper, int, 0644); + enum { VMPRESSURE_NO_ADJUST = 0, VMPRESSURE_ADJUST_ENCROACH, @@ -420,6 +425,14 @@ void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc) } } +static void mark_lmk_victim(struct task_struct *tsk) +{ + struct mm_struct *mm = tsk->mm; + + if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) + atomic_inc(&tsk->signal->oom_mm->mm_count); +} + static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) { struct task_struct *tsk; @@ -546,7 +559,11 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) send_sig(SIGKILL, selected, 0); if (selected->mm) task_set_lmk_waiting(selected); + if (oom_reaper) + mark_lmk_victim(selected); task_unlock(selected); + if (oom_reaper) + wake_oom_reaper(selected); trace_lowmemory_kill(selected, cache_size, cache_limit, free); lowmem_print(1, "Killing '%s' (%d) (tgid %d), adj %hd,\n" "to free %ldkB on behalf of '%s' (%d) because\n" diff --git a/include/linux/oom.h b/include/linux/oom.h index efce1a078d88..395ac25d0cfc 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h @@ -116,6 +116,8 @@ extern struct task_struct *find_lock_task_mm(struct task_struct *p); extern void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask); +extern void wake_oom_reaper(struct task_struct *tsk); + /* sysctls */ extern int sysctl_oom_dump_tasks; extern int sysctl_oom_kill_allocating_task; diff --git a/mm/oom_kill.c b/mm/oom_kill.c index b23ca26b13ae..fc89b06591f0 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -626,7 +626,7 @@ static int oom_reaper(void *unused) return 0; } -static void wake_oom_reaper(struct task_struct *tsk) +void wake_oom_reaper(struct task_struct *tsk) { if (!oom_reaper_th) return; -- GitLab From 4eb216d6ac3afd2ab0c55a28b9732e7761ddde03 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Wed, 10 Jan 2018 12:27:39 +0530 Subject: [PATCH 1271/1299] lowmemorykiller: fix memory corruption We only synchronize with the oom reaper if tsk_is_oom_victim which is not true if the final __mmput is called from a different context than the oom victim exit path. This can trivially happen from context of any task which has grabbed mm reference. This was first reported in upstream. Reference commit can be found at commit 065e76dd01e4 ("mm, oom_reaper: fix memory corruption") Change-Id: I5556bf2546d9c7b90688bec1f7f67ee83a4a86ee Signed-off-by: Charan Teja Reddy --- drivers/staging/android/lowmemorykiller.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 65ac5ef8d423..e730ccd1601e 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -429,8 +429,10 @@ static void mark_lmk_victim(struct task_struct *tsk) { struct mm_struct *mm = tsk->mm; - if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) + if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) { atomic_inc(&tsk->signal->oom_mm->mm_count); + set_bit(MMF_OOM_VICTIM, &mm->flags); + } } static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) -- GitLab From c1ab3b92d8465874b342605c948554dafec55f2c Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Mon, 29 Jan 2018 19:17:35 +0530 Subject: [PATCH 1272/1299] lowmemorykiller: ignore the tasks that has null mm for reaping The setting of task_struct->mm to NULL might race when the same process gets selected in the lowmemorykiller path for reaping of memory.So, ignore the process for reaping when its mm NULL. Change-Id: I40a50cc2f6dea892ed9b31df7aad59a349ff8c9c Signed-off-by: Charan Teja Reddy --- drivers/staging/android/lowmemorykiller.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index e730ccd1601e..7eada9400c90 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -559,13 +559,15 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) task_lock(selected); send_sig(SIGKILL, selected, 0); - if (selected->mm) + if (selected->mm) { task_set_lmk_waiting(selected); - if (oom_reaper) - mark_lmk_victim(selected); + if (!test_bit(MMF_OOM_SKIP, &selected->mm->flags) && + oom_reaper) { + mark_lmk_victim(selected); + wake_oom_reaper(selected); + } + } task_unlock(selected); - if (oom_reaper) - wake_oom_reaper(selected); trace_lowmemory_kill(selected, cache_size, cache_limit, free); lowmem_print(1, "Killing '%s' (%d) (tgid %d), adj %hd,\n" "to free %ldkB on behalf of '%s' (%d) because\n" -- GitLab From 94b145b74a27bdf9813b0a36a06e57ebf71862aa Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Wed, 24 Jan 2018 14:59:23 +0530 Subject: [PATCH 1273/1299] lowmemorykiller: avoid selecting task reaped by oom_reaper With oom_reaper enabled for lowmemorykiller, even when the oom_reaper reaps the task, the task struct will have LMK_WAITING flag set. As a side effect, during lowmem_deathpending_timeout period, lowmemorykiller will not select any task while any task has LMK_WAITING flag set. Skip tasks from lmk selection if they are reaped by oom_reaper. Change-Id: I7edb02135df7e54d9364b971caf25ab6ace9a027 Signed-off-by: Prakash Gupta --- drivers/staging/android/lowmemorykiller.c | 37 +++++++++++++++++------ 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 7eada9400c90..1f0d33cae52c 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -508,17 +508,36 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (test_task_flag(tsk, TIF_MM_RELEASED)) continue; - if (time_before_eq(jiffies, lowmem_deathpending_timeout)) { - if (test_task_lmk_waiting(tsk)) { - rcu_read_unlock(); - mutex_unlock(&scan_mutex); - return 0; + if (oom_reaper) { + p = find_lock_task_mm(tsk); + if (!p) + continue; + + if (test_bit(MMF_OOM_VICTIM, &p->mm->flags)) { + if (test_bit(MMF_OOM_SKIP, &p->mm->flags)) { + task_unlock(p); + continue; + } else if (time_before_eq(jiffies, + lowmem_deathpending_timeout)) { + task_unlock(p); + rcu_read_unlock(); + mutex_unlock(&scan_mutex); + return 0; + } } - } + } else { + if (time_before_eq(jiffies, + lowmem_deathpending_timeout)) + if (test_task_lmk_waiting(tsk)) { + rcu_read_unlock(); + mutex_unlock(&scan_mutex); + return 0; + } - p = find_lock_task_mm(tsk); - if (!p) - continue; + p = find_lock_task_mm(tsk); + if (!p) + continue; + } oom_score_adj = p->signal->oom_score_adj; if (oom_score_adj < min_score_adj) { -- GitLab From c7d6dfe4053345d9f80536e8efc963d7aa91f11e Mon Sep 17 00:00:00 2001 From: Yogesh Lal Date: Wed, 25 Oct 2017 18:18:27 +0530 Subject: [PATCH 1274/1299] lowmemorykiller: add a knob to turn on/off the feature Add an option to turn on/off lowmemorykiller so that userspace can enable or disable lowmemorykiller as per requirement. Change-Id: I539f7e23cdf5540e536569f0a582c9e7fe79c3c4 Signed-off-by: Yogesh Lal Signed-off-by: Naitik Bharadiya --- drivers/staging/android/lowmemorykiller.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 1f0d33cae52c..e3ca61b01abf 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -62,6 +62,10 @@ #define CREATE_TRACE_POINTS #include "trace/lowmemorykiller.h" +/* to enable lowmemorykiller */ +static int enable_lmk = 1; +module_param_named(enable_lmk, enable_lmk, int, 0644); + static u32 lowmem_debug_level = 1; static short lowmem_adj[6] = { 0, @@ -92,6 +96,9 @@ static unsigned long lowmem_deathpending_timeout; static unsigned long lowmem_count(struct shrinker *s, struct shrink_control *sc) { + if (!enable_lmk) + return 0; + return global_node_page_state(NR_ACTIVE_ANON) + global_node_page_state(NR_ACTIVE_FILE) + global_node_page_state(NR_INACTIVE_ANON) + -- GitLab From 48d62f919fa66df0ad206c6ad28c16211537ad8a Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Mon, 11 Jun 2018 14:45:31 -0700 Subject: [PATCH 1275/1299] defconfig: sm8150: Enable kernel low memory killer Use the kernel low memory killer instead of the userspace low memory killer for this target. Change-Id: I128c71871bc9bbf11c8191f3600822b601e4ac68 Signed-off-by: Patrick Daly --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 3 +-- arch/arm64/configs/vendor/sm8150_defconfig | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 8382ace603bc..c411c2f212d5 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -16,8 +16,6 @@ CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 -CONFIG_MEMCG=y -CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y @@ -465,6 +463,7 @@ CONFIG_UIO=y CONFIG_UIO_MSM_SHAREDMEM=y CONFIG_STAGING=y CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y CONFIG_ION=y CONFIG_QCOM_GENI_SE=y CONFIG_QPNP_REVID=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index 9e49055d493a..28cd35eefd4e 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -15,8 +15,6 @@ CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 -CONFIG_MEMCG=y -CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y CONFIG_DEBUG_BLK_CGROUP=y CONFIG_RT_GROUP_SCHED=y @@ -487,6 +485,7 @@ CONFIG_UIO=y CONFIG_UIO_MSM_SHAREDMEM=y CONFIG_STAGING=y CONFIG_ASHMEM=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y CONFIG_ION=y CONFIG_QCOM_GENI_SE=y CONFIG_QPNP_REVID=y -- GitLab From a77bea399dd8b2874fdda2d8634f97e1b887edbc Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Tue, 23 Sep 2014 19:31:19 -0700 Subject: [PATCH 1276/1299] lowmemorykiller: Run the showmem notifier when killing When the lowmemory killer starts killing adj 0 tasks, it's useful to be able to see the state of other memory in the system. Call the showmem notifier to get other clients to dump out their state. Change-Id: Ie3b1d47149f0108b42b7961fd47a8cc5efe2c590 Signed-off-by: Laura Abbott Signed-off-by: Prakash Gupta --- drivers/staging/android/lowmemorykiller.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index e3ca61b01abf..fd6070431450 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -52,6 +52,7 @@ #define CREATE_TRACE_POINTS #include +#include #ifdef CONFIG_HIGHMEM #define _ZONE ZONE_HIGHMEM @@ -622,6 +623,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (lowmem_debug_level >= 2 && selected_oom_score_adj == 0) { show_mem(SHOW_MEM_FILTER_NODES, NULL); + show_mem_call_notifiers(); dump_tasks(NULL, NULL); } -- GitLab From 9ed5f4f27453ffd4027ce17c4a3c1dc0e930b434 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Wed, 2 Aug 2017 12:30:55 +0530 Subject: [PATCH 1277/1299] mm: cma: Register with show_mem notification framework Register with the show_mem notification framework to let cma dump out data for debugging. This is an example output with this patch. cma: cma-0 pages: => 0 used of 2048 total pages cma: cma-1 pages: => 0 used of 23552 total pages cma: cma-2 pages: => 1696 used of 3072 total pages cma: cma-3 pages: => 8277 used of 9216 total pages cma: cma-4 pages: => 186 used of 5120 total pages cma: cma-5 pages: => 3792 used of 8192 total pages Change-Id: I80d9291444fd9361f5586bdf60373ed8b5b41705 Signed-off-by: Prakash Gupta --- mm/cma.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/mm/cma.c b/mm/cma.c index 3d91939750a3..e4a219fa0a2d 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include "cma.h" @@ -97,6 +98,29 @@ static void cma_clear_bitmap(struct cma *cma, unsigned long pfn, mutex_unlock(&cma->lock); } +static int cma_showmem_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + int i; + unsigned long used; + struct cma *cma; + + for (i = 0; i < cma_area_count; i++) { + cma = &cma_areas[i]; + used = bitmap_weight(cma->bitmap, + (int)cma_bitmap_maxno(cma)); + used <<= cma->order_per_bit; + pr_info("cma-%d pages: => %lu used of %lu total pages\n", + i, used, cma->count); + } + + return 0; +} + +static struct notifier_block cma_nb = { + .notifier_call = cma_showmem_notifier, +}; + static int __init cma_activate_area(struct cma *cma) { int bitmap_size = BITS_TO_LONGS(cma_bitmap_maxno(cma)) * sizeof(long); @@ -161,6 +185,8 @@ static int __init cma_init_reserved_areas(void) return ret; } + show_mem_notifier_register(&cma_nb); + return 0; } core_initcall(cma_init_reserved_areas); -- GitLab From 09e1bae59c9714eb09f10c2ab42a308fcd9a604e Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Wed, 2 Aug 2017 15:16:35 +0530 Subject: [PATCH 1278/1299] mm, oom: run the showmem notifier in oom When the oom starts killing processes, it's useful to be able to see the state of unaccounted memory in the system. Call the showmem notifier to get other clients to dump out their state. Change-Id: Id32ff6d6747fee7d0889447323ddce25282e93f6 Signed-off-by: Prakash Gupta --- mm/oom_kill.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index fc89b06591f0..13c4daa8a1ee 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -425,8 +425,11 @@ static void dump_header(struct oom_control *oc, struct task_struct *p) dump_stack(); if (oc->memcg) mem_cgroup_print_oom_info(oc->memcg, p); - else + else { show_mem(SHOW_MEM_FILTER_NODES, oc->nodemask); + show_mem_call_notifiers(); + } + if (sysctl_oom_dump_tasks) dump_tasks(oc->memcg, oc->nodemask); } -- GitLab From 17e3983d31329a7c443a85004c6f75716f4cd179 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Wed, 2 Aug 2017 15:20:54 +0530 Subject: [PATCH 1279/1299] mm: run the showmem notifier in alloc failure When the page allocation fails, it's useful to be able to see the state of unaccounted memory in the system. Call the showmem notifier to get other clients to dump out their state. This is an example output with this patch. [ 457.125478] SLUB: Unable to allocate memory on node -1, gfp=0x2008000(GFP_NOWAIT|__GFP_ZERO) [ 457.133982] cache: kmalloc-128, object size: 128, buffer size: 640, default order: 2, min order: 0 [ 457.143179] node 0: slabs: 5903, objs: 132755, free: 26 [ 457.906076] BootAnimation: page allocation failure: order:0, mode:0x2204000(GFP_NOWAIT|__GFP_COMP|__GFP_NOTRACK) [ 457.916395] CPU: 2 PID: 4752 Comm: BootAnimation Not tainted 4.9.37+ #43 [ 457.916398] Hardware name: Qualcomm Technologies, Inc. SDM845 v1 MTP (DT) [ 457.916402] Call trace: [ 457.916420] [] dump_backtrace+0x0/0x2c4 [ 457.916426] [] show_stack+0x20/0x28 [ 457.916434] [] dump_stack+0xb8/0xf4 [ 457.916442] [] warn_alloc+0x154/0x170 [ 457.916447] [] __alloc_pages_nodemask+0x430/0xcdc [ 457.916454] [] new_slab+0x344/0x430 [ 457.916458] [] ___slab_alloc.constprop.72+0x2f4/0x398 [ 457.916463] [] __slab_alloc.isra.69.constprop.71+0x48/0x80 [ 457.916467] [] kmem_cache_alloc_trace+0x210/0x2dc [ 457.916476] [] binder_transaction+0x280/0x2008 [ 457.916480] [] binder_thread_write+0x9f8/0x136c [ 457.916484] [] binder_ioctl_write_read+0x14c/0x3b0 [ 457.916488] [] binder_ioctl+0x2bc/0x868 [ 457.916494] [] do_vfs_ioctl+0xd0/0x858 [ 457.916498] [] SyS_ioctl+0x90/0xa4 [ 457.916503] [] el0_svc_naked+0x24/0x28 [ 457.916505] Mem-Info: [ 457.916515] active_anon:83629 inactive_anon:212 isolated_anon:0\x0a active_file:5955 inactive_file:5745 isolated_file:0\x0a unevictable:630956 dirty:0 writeback:0 unstable:0\x0a slab_recl aimable:16602 slab_unreclaimable:69384\x0a mapped:3609 shmem:308 pagetables:5737 bounce:0\x0a free:4446 free_pcp:482 free_cma:112 [ 457.916524] Node 0 active_anon:334516kB inactive_anon:848kB active_file:23820kB inactive_file:22980kB unevictable:2523824kB isolated(anon):0kB isolated(file):0kB mapped:14436kB dirty:0kB writeback:0kB shmem:1232kB writeback_tmp:0kB unstable:0kB pages_scanned:0 all_unreclaimable? no [ 457.916534] DMA free:12516kB min:3352kB low:4924kB high:6496kB active_anon:45336kB inactive_anon:64kB active_file:3588kB inactive_file:3404kB unevictable:1564224kB writepending:0kB presen t:1854120kB managed:1748064kB mlocked:1564224kB slab_reclaimable:10664kB slab_unreclaimable:24400kB kernel_stack:2608kB pagetables:6376kB bounce:0kB free_pcp:572kB local_pcp:0kB free_cma:448 kB [ 457.916536] lowmem_reserve[]: 0 1901 1901 [ 457.916550] Normal free:5268kB min:4148kB low:6092kB high:8036kB active_anon:289180kB inactive_anon:784kB active_file:20232kB inactive_file:19576kB unevictable:959600kB writepending:0kB p resent:2068224kB managed:1984196kB mlocked:959600kB slab_reclaimable:55744kB slab_unreclaimable:253136kB kernel_stack:19232kB pagetables:16572kB bounce:0kB free_pcp:1356kB local_pcp:116kB fr ee_cma:0kB [ 457.916552] lowmem_reserve[]: 0 0 0 [ 457.916560] DMA: 819*4kB (UMEC) 280*8kB (UMEC) 224*16kB (UME) 98*32kB (UME) 6*64kB (UME) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 12620kB [ 457.916594] Normal: 1118*4kB (UMEH) 38*8kB (UMH) 1*16kB (H) 2*32kB (H) 1*64kB (H) 1*128kB (H) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 5048kB [ 457.916627] 12071 total pagecache pages [ 457.916630] 0 pages in swap cache [ 457.916633] Swap cache stats: add 0, delete 0, find 0/0 [ 457.916634] Free swap = 0kB [ 457.916636] Total swap = 0kB [ 457.916639] 980586 pages RAM [ 457.916641] 0 pages HighMem/MovableOnly [ 457.916643] 47521 pages reserved [ 457.916645] 51200 pages cma reserved [ 457.916651] cma: cma-0 pages: => 0 used of 2048 total pages [ 457.916660] cma: cma-1 pages: => 0 used of 23552 total pages [ 457.916665] cma: cma-2 pages: => 1695 used of 3072 total pages [ 457.916670] cma: cma-3 pages: => 8277 used of 9216 total pages [ 457.916674] cma: cma-4 pages: => 186 used of 5120 total pages [ 457.916679] cma: cma-5 pages: => 3792 used of 8192 total pages [ 457.916685] Heap name Total heap size Total orphaned size [ 457.916687] --------------------------------- [ 457.916691] qsecom 0x ba000 0x 0 [ 457.916694] system 0x 44db000 0x 500000 [ 457.916705] ------------------------------------------------- [ 457.916708] uncached pool = 31027200 cached pool = 0 secure pool = 0 [ 457.916710] pool total (uncached + cached + secure) = 31027200 [ 457.916712] ------------------------------------------------- [ 457.916715] adsp 0x 614000 0x 0 [ 457.916720] spss 0x 0 0x 0 [ 457.916725] secure_display 0x 0 0x 0 [ 457.916727] secure_heap 0x 0 0x 0 Change-Id: Id01cce4abf331ff9c1c7ab9f0c0f9b1fc4146467 Signed-off-by: Prakash Gupta --- mm/page_alloc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d9ac316e3043..23362075c89d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -3234,6 +3235,7 @@ static void warn_alloc_show_mem(gfp_t gfp_mask, nodemask_t *nodemask) filter &= ~SHOW_MEM_FILTER_NODES; show_mem(filter, nodemask); + show_mem_call_notifiers(); } void warn_alloc(gfp_t gfp_mask, nodemask_t *nodemask, const char *fmt, ...) -- GitLab From 6a918627feb1ab0609cee84f756db5614ccb88ab Mon Sep 17 00:00:00 2001 From: "Jennifer L. Zenner" Date: Wed, 25 Apr 2018 16:44:38 -0400 Subject: [PATCH 1280/1299] msm: ipa3: Add support for IPA/GSI emulation system Changes made to the IPA/GSI drivers in support of an emulation system. The emulation system is an FPGA based system that allows for the prototyping of new IPA features before committing them to silicon. Change-Id: I6ad6474c6574e0efb869c1b07e611d6bbd89fae8 CRs-fixed: 2204018 Acked-by: Perry Randise Signed-off-by: Jennifer L. Zenner Signed-off-by: Jie Luo --- .../devicetree/bindings/platform/msm/ipa.txt | 4 + drivers/platform/msm/Kconfig | 6 + drivers/platform/msm/gsi/Makefile | 2 + drivers/platform/msm/gsi/gsi.c | 159 +++- drivers/platform/msm/gsi/gsi.h | 15 + drivers/platform/msm/gsi/gsi_emulation.c | 233 ++++++ drivers/platform/msm/gsi/gsi_emulation.h | 192 +++++ .../platform/msm/gsi/gsi_emulation_stubs.h | 20 + drivers/platform/msm/ipa/ipa_api.c | 141 ++++ drivers/platform/msm/ipa/ipa_api.h | 11 + drivers/platform/msm/ipa/ipa_common_i.h | 4 + drivers/platform/msm/ipa/ipa_v3/Makefile | 2 + drivers/platform/msm/ipa/ipa_v3/ipa.c | 522 +++++++----- .../msm/ipa/ipa_v3/ipa_dt_replacement.c | 765 ++++++++++++++++++ .../msm/ipa/ipa_v3/ipa_emulation_stubs.h | 128 +++ drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 203 ++++- .../platform/msm/ipa/ipa_v3/ipa_interrupts.c | 48 +- drivers/platform/msm/ipa/ipa_v3/ipa_nat.c | 7 + .../platform/msm/ipa/ipa_v3/ipa_qmi_service.h | 6 +- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 345 +++++++- .../msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c | 1 + .../msm/ipa/ipa_v3/ipahal/ipahal_reg.c | 20 + .../msm/ipa/ipa_v3/ipahal/ipahal_reg.h | 6 +- drivers/platform/msm/ipa/test/ipa_test_mhi.c | 29 +- .../platform/msm/ipa/test/ipa_ut_framework.c | 49 +- include/linux/msm_gsi.h | 10 +- 26 files changed, 2688 insertions(+), 240 deletions(-) create mode 100644 drivers/platform/msm/gsi/gsi_emulation.c create mode 100644 drivers/platform/msm/gsi/gsi_emulation.h create mode 100644 drivers/platform/msm/gsi/gsi_emulation_stubs.h create mode 100644 drivers/platform/msm/ipa/ipa_v3/ipa_dt_replacement.c create mode 100644 drivers/platform/msm/ipa/ipa_v3/ipa_emulation_stubs.h diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt index 22e235748496..ff106b318c91 100644 --- a/Documentation/devicetree/bindings/platform/msm/ipa.txt +++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt @@ -122,6 +122,10 @@ Optional properties: controller phandle and "clk_ipa_clk" as macro for "iface_clk" - clock-names: This property shall contain the clock input names used by driver in same order as the clocks property.This should be "iface_clk" +- emulator-bar0-offset: Specifies the offset, within PCIe BAR0, where + IPA/GSI programmable registers reside. This property is used only + with the IPA/GSI emulation system, which is connected to and + communicated with via PCIe. IPA SMMU sub nodes diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig index 269005a50a64..219112d04f12 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -166,4 +166,10 @@ config SEEMP_CORE a log and rates the actions according to whether a typical user would use the tools. +config IPA_EMULATION + bool "IPA on X86 Linux (IPA emulation support)" + depends on X86 && IPA3 + help + This option is used only when building the X86 version of + the IPA/GSI driver. Never set this when building for ARM. endmenu diff --git a/drivers/platform/msm/gsi/Makefile b/drivers/platform/msm/gsi/Makefile index 82d6c6299bb8..a14a203a9e29 100644 --- a/drivers/platform/msm/gsi/Makefile +++ b/drivers/platform/msm/gsi/Makefile @@ -1,2 +1,4 @@ gsidbg-$(CONFIG_DEBUG_FS) += gsi_dbg.o obj-$(CONFIG_GSI) += gsi.o gsidbg.o + +obj-$(CONFIG_IPA_EMULATION) += gsi_emulation.o diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index ee789cc0b92f..118a340ce881 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -20,6 +20,7 @@ #include #include "gsi.h" #include "gsi_reg.h" +#include "gsi_emulation.h" #define GSI_CMD_TIMEOUT (5*HZ) #define GSI_STOP_CMD_TIMEOUT_MS 20 @@ -42,6 +43,13 @@ static const struct of_device_id msm_gsi_match[] = { { }, }; + +#if defined(CONFIG_IPA_EMULATION) +static bool running_emulation = true; +#else +static bool running_emulation; +#endif + struct gsi_ctx *gsi_ctx; static void __gsi_config_type_irq(int ee, uint32_t mask, uint32_t val) @@ -624,7 +632,7 @@ static void gsi_handle_irq(void) if (!type) break; - GSIDBG_LOW("type %x\n", type); + GSIDBG_LOW("type 0x%x\n", type); if (type & GSI_EE_n_CNTXT_TYPE_IRQ_CH_CTRL_BMSK) gsi_handle_ch_ctrl(ee); @@ -859,17 +867,57 @@ int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl) GSIERR("bad irq specified %u\n", props->irq); return -GSI_STATUS_INVALID_PARAMS; } - - res = devm_request_irq(gsi_ctx->dev, props->irq, + /* + * On a real UE, there are two separate interrupt + * vectors that get directed toward the GSI/IPA + * drivers. They are handled by gsi_isr() and + * (ipa_isr() or ipa3_isr()) respectively. In the + * emulation environment, this is not the case; + * instead, interrupt vectors are routed to the + * emualation hardware's interrupt controller, which + * in turn, forwards a single interrupt to the GSI/IPA + * driver. When the new interrupt vector is received, + * the driver needs to probe the interrupt + * controller's registers so see if one, the other, or + * both interrupts have occurred. Given the above, we + * now need to handle both situations, namely: the + * emulator's and the real UE. + */ + if (running_emulation) { + /* + * New scheme involving the emulator's + * interrupt controller. + */ + res = devm_request_threaded_irq( + gsi_ctx->dev, + props->irq, + /* top half handler to follow */ + emulator_hard_irq_isr, + /* threaded bottom half handler to follow */ + emulator_soft_irq_isr, + IRQF_SHARED, + "emulator_intcntrlr", + gsi_ctx); + } else { + /* + * Traditional scheme used on the real UE. + */ + res = devm_request_irq(gsi_ctx->dev, props->irq, gsi_isr, props->req_clk_cb ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_HIGH, "gsi", gsi_ctx); + } if (res) { - GSIERR("failed to register isr for %u\n", props->irq); + GSIERR( + "failed to register isr for %u\n", + props->irq); return -GSI_STATUS_ERROR; } + GSIDBG( + "succeeded to register isr for %u\n", + props->irq); res = enable_irq_wake(props->irq); if (res) @@ -889,6 +937,41 @@ int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl) return -GSI_STATUS_RES_ALLOC_FAILURE; } + GSIDBG("GSI base(%pa) mapped to (%pK) with len (0x%lx)\n", + &(props->phys_addr), + gsi_ctx->base, + props->size); + + if (running_emulation) { + GSIDBG("GSI SW ver register value 0x%x\n", + gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_SW_VERSION_OFFS(0))); + gsi_ctx->intcntrlr_mem_size = + props->emulator_intcntrlr_size; + gsi_ctx->intcntrlr_base = + devm_ioremap_nocache( + gsi_ctx->dev, + props->emulator_intcntrlr_addr, + props->emulator_intcntrlr_size); + if (!gsi_ctx->intcntrlr_base) { + GSIERR( + "failed to remap emulator's interrupt controller HW\n"); + devm_iounmap(gsi_ctx->dev, gsi_ctx->base); + devm_free_irq(gsi_ctx->dev, props->irq, gsi_ctx); + return -GSI_STATUS_RES_ALLOC_FAILURE; + } + + GSIDBG( + "Emulator's interrupt controller base(%pa) mapped to (%pK) with len (0x%lx)\n", + &(props->emulator_intcntrlr_addr), + gsi_ctx->intcntrlr_base, + props->emulator_intcntrlr_size); + + gsi_ctx->intcntrlr_gsi_isr = gsi_isr; + gsi_ctx->intcntrlr_client_isr = + props->emulator_intcntrlr_client_isr; + } + gsi_ctx->per = *props; gsi_ctx->per_registered = true; mutex_init(&gsi_ctx->mlock); @@ -896,11 +979,21 @@ int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl) atomic_set(&gsi_ctx->num_evt_ring, 0); gsi_ctx->max_ch = gsi_get_max_channels(gsi_ctx->per.ver); if (gsi_ctx->max_ch == 0) { + devm_iounmap(gsi_ctx->dev, gsi_ctx->base); + if (running_emulation) + devm_iounmap(gsi_ctx->dev, gsi_ctx->intcntrlr_base); + gsi_ctx->base = gsi_ctx->intcntrlr_base = NULL; + devm_free_irq(gsi_ctx->dev, props->irq, gsi_ctx); GSIERR("failed to get max channels\n"); return -GSI_STATUS_ERROR; } gsi_ctx->max_ev = gsi_get_max_event_rings(gsi_ctx->per.ver); if (gsi_ctx->max_ev == 0) { + devm_iounmap(gsi_ctx->dev, gsi_ctx->base); + if (running_emulation) + devm_iounmap(gsi_ctx->dev, gsi_ctx->intcntrlr_base); + gsi_ctx->base = gsi_ctx->intcntrlr_base = NULL; + devm_free_irq(gsi_ctx->dev, props->irq, gsi_ctx); GSIERR("failed to get max event rings\n"); return -GSI_STATUS_ERROR; } @@ -913,7 +1006,9 @@ int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl) if (props->mhi_er_id_limits_valid && props->mhi_er_id_limits[0] > (gsi_ctx->max_ev - 1)) { devm_iounmap(gsi_ctx->dev, gsi_ctx->base); - gsi_ctx->base = NULL; + if (running_emulation) + devm_iounmap(gsi_ctx->dev, gsi_ctx->intcntrlr_base); + gsi_ctx->base = gsi_ctx->intcntrlr_base = NULL; devm_free_irq(gsi_ctx->dev, props->irq, gsi_ctx); GSIERR("MHI event ring start id %u is beyond max %u\n", props->mhi_er_id_limits[0], gsi_ctx->max_ev); @@ -954,6 +1049,22 @@ int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl) gsi_writel(0, gsi_ctx->base + GSI_EE_n_ERROR_LOG_OFFS(gsi_ctx->per.ee)); + if (running_emulation) { + /* + * Set up the emulator's interrupt controller... + */ + res = setup_emulator_cntrlr( + gsi_ctx->intcntrlr_base, gsi_ctx->intcntrlr_mem_size); + if (res != 0) { + devm_iounmap(gsi_ctx->dev, gsi_ctx->base); + devm_iounmap(gsi_ctx->dev, gsi_ctx->intcntrlr_base); + gsi_ctx->base = gsi_ctx->intcntrlr_base = NULL; + devm_free_irq(gsi_ctx->dev, props->irq, gsi_ctx); + GSIERR("setup_emulator_cntrlr() failed\n"); + return res; + } + } + *dev_hdl = (uintptr_t)gsi_ctx; return GSI_STATUS_SUCCESS; @@ -3103,7 +3214,8 @@ static void gsi_configure_ieps(void *base, enum gsi_ver ver) static void gsi_configure_bck_prs_matrix(void *base) { - void __iomem *gsi_base = base; + void __iomem *gsi_base = (void __iomem *) base; + /* * For now, these are default values. In the future, GSI FW image will * produce optimized back-pressure values based on the FW image. @@ -3372,16 +3484,45 @@ static struct platform_driver msm_gsi_driver = { }, }; +static struct platform_device *pdev; + /** * Module Init. */ static int __init gsi_init(void) { - pr_debug("%s\n", __func__); - return platform_driver_register(&msm_gsi_driver); -} + int ret; + pr_debug("gsi_init\n"); + + ret = platform_driver_register(&msm_gsi_driver); + if (ret < 0) + goto out; + + if (running_emulation) { + pdev = platform_device_register_simple("gsi", -1, NULL, 0); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + platform_driver_unregister(&msm_gsi_driver); + goto out; + } + } + +out: + return ret; +} arch_initcall(gsi_init); +/* + * Module exit. + */ +static void __exit gsi_exit(void) +{ + if (running_emulation && pdev) + platform_device_unregister(pdev); + platform_driver_unregister(&msm_gsi_driver); +} +module_exit(gsi_exit); + MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Generic Software Interface (GSI)"); diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h index 478af3fe6d21..870d8d615ba3 100644 --- a/drivers/platform/msm/gsi/gsi.h +++ b/drivers/platform/msm/gsi/gsi.h @@ -18,8 +18,16 @@ #include #include #include +#include #include +/* + * The following for adding code (ie. for EMULATION) not found on x86. + */ +#if defined(CONFIG_IPA_EMULATION) +# include "gsi_emulation_stubs.h" +#endif + #define GSI_CHAN_MAX 31 #define GSI_EVT_RING_MAX 24 #define GSI_NO_EVT_ERINDEX 31 @@ -204,6 +212,13 @@ struct gsi_ctx { struct completion gen_ee_cmd_compl; void *ipc_logbuf; void *ipc_logbuf_low; + /* + * The following used only on emulation systems. + */ + void __iomem *intcntrlr_base; + u32 intcntrlr_mem_size; + irq_handler_t intcntrlr_gsi_isr; + irq_handler_t intcntrlr_client_isr; }; enum gsi_re_type { diff --git a/drivers/platform/msm/gsi/gsi_emulation.c b/drivers/platform/msm/gsi/gsi_emulation.c new file mode 100644 index 000000000000..adaaaaa47f2a --- /dev/null +++ b/drivers/platform/msm/gsi/gsi_emulation.c @@ -0,0 +1,233 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include "gsi_emulation.h" + +/* + * ***************************************************************************** + * The following used to set up the EMULATION interrupt controller... + * ***************************************************************************** + */ +int setup_emulator_cntrlr( + void __iomem *intcntrlr_base, + u32 intcntrlr_mem_size) +{ + uint32_t val, ver, intrCnt, rangeCnt, range; + + val = gsi_emu_readl(intcntrlr_base + GE_INT_CTL_VER_CNT); + + intrCnt = val & 0xFFFF; + ver = (val >> 16) & 0xFFFF; + rangeCnt = intrCnt / 32; + + GSIDBG( + "CTL_VER_CNT reg val(0x%x) intr cnt(%u) cntrlr ver(0x%x) rangeCnt(%u)\n", + val, intrCnt, ver, rangeCnt); + + /* + * Verify the interrupt controller version + */ + if (ver == 0 || ver == 0xFFFF || ver < DEO_IC_INT_CTL_VER_MIN) { + GSIERR( + "Error: invalid interrupt controller version 0x%x\n", + ver); + return -GSI_STATUS_INVALID_PARAMS; + } + + /* + * Verify the interrupt count + * + * NOTE: intrCnt must be at least one block and multiple of 32 + */ + if ((intrCnt % 32) != 0) { + GSIERR( + "Invalid interrupt count read from HW 0x%04x\n", + intrCnt); + return -GSI_STATUS_ERROR; + } + + /* + * Calculate number of ranges used, each range handles 32 int lines + */ + if (rangeCnt > DEO_IC_MAX_RANGE_CNT) { + GSIERR( + "SW interrupt limit(%u) passed, increase DEO_IC_MAX_RANGE_CNT(%u)\n", + rangeCnt, + DEO_IC_MAX_RANGE_CNT); + return -GSI_STATUS_ERROR; + } + + /* + * Let's take the last register offset minus the first + * register offset (ie. range) and compare it to the interrupt + * controller's dtsi defined memory size. The range better + * fit within the size. + */ + val = GE_SOFT_INT_n(rangeCnt-1) - GE_INT_CTL_VER_CNT; + if (val > intcntrlr_mem_size) { + GSIERR( + "Interrupt controller register range (%u) exceeds dtsi provisioned size (%u)\n", + val, intcntrlr_mem_size); + return -GSI_STATUS_ERROR; + } + + /* + * The following will disable the emulators interrupt controller, + * so that we can config it... + */ + GSIDBG("Writing GE_INT_MASTER_ENABLE\n"); + gsi_emu_writel( + 0x0, + intcntrlr_base + GE_INT_MASTER_ENABLE); + + /* + * Init register maps of all ranges + */ + for (range = 0; range < rangeCnt; range++) { + /* + * Disable all int sources by setting all enable clear bits + */ + GSIDBG("Writing GE_INT_ENABLE_CLEAR_n(%u)\n", range); + gsi_emu_writel( + 0xFFFFFFFF, + intcntrlr_base + GE_INT_ENABLE_CLEAR_n(range)); + + /* + * Clear all raw statuses + */ + GSIDBG("Writing GE_INT_CLEAR_n(%u)\n", range); + gsi_emu_writel( + 0xFFFFFFFF, + intcntrlr_base + GE_INT_CLEAR_n(range)); + + /* + * Init all int types + */ + GSIDBG("Writing GE_INT_TYPE_n(%u)\n", range); + gsi_emu_writel( + 0x0, + intcntrlr_base + GE_INT_TYPE_n(range)); + } + + /* + * The following tells the interrupt controller to interrupt us + * when it sees interupts from ipa and/or gsi. + * + * Interrupts: + * =================================================================== + * DUT0 [ 63 : 16 ] + * ipa_irq [ 3 : 0 ] <---HERE + * ipa_gsi_bam_irq [ 7 : 4 ] <---HERE + * ipa_bam_apu_sec_error_irq [ 8 ] + * ipa_bam_apu_non_sec_error_irq [ 9 ] + * ipa_bam_xpu2_msa_intr [ 10 ] + * ipa_vmidmt_nsgcfgirpt [ 11 ] + * ipa_vmidmt_nsgirpt [ 12 ] + * ipa_vmidmt_gcfgirpt [ 13 ] + * ipa_vmidmt_girpt [ 14 ] + * bam_xpu3_qad_non_secure_intr_sp [ 15 ] + */ + GSIDBG("Writing GE_INT_ENABLE_n(0)\n"); + gsi_emu_writel( + 0x00FF, /* See <---HERE above */ + intcntrlr_base + GE_INT_ENABLE_n(0)); + + /* + * The following will enable the IC post config... + */ + GSIDBG("Writing GE_INT_MASTER_ENABLE\n"); + gsi_emu_writel( + 0x1, + intcntrlr_base + GE_INT_MASTER_ENABLE); + + return 0; +} + +/* + * ***************************************************************************** + * The following for EMULATION hard irq... + * ***************************************************************************** + */ +irqreturn_t emulator_hard_irq_isr( + int irq, + void *ctxt) +{ + struct gsi_ctx *gsi_ctx_ptr = (struct gsi_ctx *) ctxt; + + uint32_t val; + + val = gsi_emu_readl(gsi_ctx_ptr->intcntrlr_base + GE_INT_MASTER_STATUS); + + /* + * If bit zero is set, interrupt is for us, hence return IRQ_NONE + * when it's not set... + */ + if (!(val & 0x00000001)) + return IRQ_NONE; + + /* + * The following will mask (ie. turn off) future interrupts from + * the emulator's interrupt controller. It wil stay this way until + * we turn back on...which will be done in the bottom half + * (ie. emulator_soft_irq_isr)... + */ + gsi_emu_writel( + 0x0, + gsi_ctx_ptr->intcntrlr_base + GE_INT_OUT_ENABLE); + + return IRQ_WAKE_THREAD; +} + +/* + * ***************************************************************************** + * The following for EMULATION soft irq... + * ***************************************************************************** + */ +irqreturn_t emulator_soft_irq_isr( + int irq, + void *ctxt) +{ + struct gsi_ctx *gsi_ctx_ptr = (struct gsi_ctx *) ctxt; + + irqreturn_t retVal = IRQ_HANDLED; + uint32_t val; + + val = gsi_emu_readl(gsi_ctx_ptr->intcntrlr_base + GE_IRQ_STATUS_n(0)); + + GSIDBG("Got irq(%d) with status(0x%08X)\n", irq, val); + + if (val & 0xF0 && gsi_ctx_ptr->intcntrlr_gsi_isr) { + GSIDBG("Got gsi interrupt\n"); + retVal = gsi_ctx_ptr->intcntrlr_gsi_isr(irq, ctxt); + } + + if (val & 0x0F && gsi_ctx_ptr->intcntrlr_client_isr) { + GSIDBG("Got ipa interrupt\n"); + retVal = gsi_ctx_ptr->intcntrlr_client_isr(irq, 0); + } + + /* + * The following will clear the interrupts... + */ + gsi_emu_writel( + 0xFFFFFFFF, + gsi_ctx_ptr->intcntrlr_base + GE_INT_CLEAR_n(0)); + + /* + * The following will unmask (ie. turn on) future interrupts from + * the emulator's interrupt controller... + */ + gsi_emu_writel( + 0x1, + gsi_ctx_ptr->intcntrlr_base + GE_INT_OUT_ENABLE); + + return retVal; +} diff --git a/drivers/platform/msm/gsi/gsi_emulation.h b/drivers/platform/msm/gsi/gsi_emulation.h new file mode 100644 index 000000000000..cd9a5c0368c3 --- /dev/null +++ b/drivers/platform/msm/gsi/gsi_emulation.h @@ -0,0 +1,192 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#if !defined(_GSI_EMULATION_H_) +# define _GSI_EMULATION_H_ + +# include + +# include "gsi.h" +# include "gsi_reg.h" +# include "gsi_emulation_stubs.h" + +# define gsi_emu_readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) +# define gsi_emu_writel(v, c) ({ __iowmb(); writel_relaxed((v), (c)); }) + +# define CNTRLR_BASE 0 + +/* + * The following file contains definitions and declarations that are + * germane only to the IPA emulation system, which is run from an X86 + * environment. Declaration's for non-X86 (ie. arm) are merely stubs + * to facilitate compile and link. + * + * Interrupt controller registers. + * Descriptions taken from the EMULATION interrupt controller SWI. + * - There is only one Master Enable register + * - Each group of 32 interrupt lines (range) is controlled by 8 registers, + * which are consecutive in memory: + * GE_INT_ENABLE_n + * GE_INT_ENABLE_CLEAR_n + * GE_INT_ENABLE_SET_n + * GE_INT_TYPE_n + * GE_IRQ_STATUS_n + * GE_RAW_STATUS_n + * GE_INT_CLEAR_n + * GE_SOFT_INT_n + * - After the above 8 registers, there are the registers of the next + * group (range) of 32 interrupt lines, and so on. + */ + +/** @brief The interrupt controller version and interrupt count register. + * Specifies interrupt controller version (upper 16 bits) and the + * number of interrupt lines supported by HW (lower 16 bits). + */ +# define GE_INT_CTL_VER_CNT \ + (CNTRLR_BASE + 0x0000) + +/** @brief Enable or disable physical IRQ output signal to the system, + * not affecting any status registers. + * + * 0x0 : DISABLE IRQ output disabled + * 0x1 : ENABLE IRQ output enabled + */ +# define GE_INT_OUT_ENABLE \ + (CNTRLR_BASE + 0x0004) + +/** @brief The IRQ master enable register. + * Bit #0: IRQ_ENABLE, set 0 to disable, 1 to enable. + */ +# define GE_INT_MASTER_ENABLE \ + (CNTRLR_BASE + 0x0008) + +# define GE_INT_MASTER_STATUS \ + (CNTRLR_BASE + 0x000C) + +/** @brief Each bit disables (bit=0, default) or enables (bit=1) the + * corresponding interrupt source + */ +# define GE_INT_ENABLE_n(n) \ + (CNTRLR_BASE + 0x0010 + 0x20 * (n)) + +/** @brief Write bit=1 to clear (to 0) the corresponding bit(s) in INT_ENABLE. + * Does nothing for bit=0 + */ +# define GE_INT_ENABLE_CLEAR_n(n) \ + (CNTRLR_BASE + 0x0014 + 0x20 * (n)) + +/** @brief Write bit=1 to set (to 1) the corresponding bit(s) in INT_ENABLE. + * Does nothing for bit=0 + */ +# define GE_INT_ENABLE_SET_n(n) \ + (CNTRLR_BASE + 0x0018 + 0x20 * (n)) + +/** @brief Select level (bit=0, default) or edge (bit=1) sensitive input + * detection logic for each corresponding interrupt source + */ +# define GE_INT_TYPE_n(n) \ + (CNTRLR_BASE + 0x001C + 0x20 * (n)) + +/** @brief Shows the interrupt sources captured in RAW_STATUS that have been + * steered to irq_n by INT_SELECT. Interrupts must also be enabled by + * INT_ENABLE and MASTER_ENABLE. Read only register. + * Bit values: 1=active, 0=inactive + */ +# define GE_IRQ_STATUS_n(n) \ + (CNTRLR_BASE + 0x0020 + 0x20 * (n)) + +/** @brief Shows the interrupt sources that have been latched by the input + * logic of the Interrupt Controller. Read only register. + * Bit values: 1=active, 0=inactive + */ +# define GE_RAW_STATUS_n(n) \ + (CNTRLR_BASE + 0x0024 + 0x20 * (n)) + +/** @brief Write bit=1 to clear the corresponding bit(s) in RAW_STATUS. + * Does nothing for bit=0 + */ +# define GE_INT_CLEAR_n(n) \ + (CNTRLR_BASE + 0x0028 + 0x20 * (n)) + +/** @brief Write bit=1 to set the corresponding bit(s) in RAW_STATUS. + * Does nothing for bit=0. + * @note Only functional for edge detected interrupts + */ +# define GE_SOFT_INT_n(n) \ + (CNTRLR_BASE + 0x002C + 0x20 * (n)) + +/** @brief Maximal number of ranges in SW. Each range supports 32 interrupt + * lines. If HW is extended considerably, increase this value + */ +# define DEO_IC_MAX_RANGE_CNT 8 + +/** @brief Size of the registers of one range in memory, in bytes */ +# define DEO_IC_RANGE_MEM_SIZE 32 /* SWI: 8 registers, no gaps */ + +/** @brief Minimal Interrupt controller HW version */ +# define DEO_IC_INT_CTL_VER_MIN 0x0102 + + +#if defined(CONFIG_IPA_EMULATION) /* declarations to follow */ + +/* + * ***************************************************************************** + * The following used to set up the EMULATION interrupt controller... + * ***************************************************************************** + */ +int setup_emulator_cntrlr( + void __iomem *intcntrlr_base, + u32 intcntrlr_mem_size); + +/* + * ***************************************************************************** + * The following for EMULATION hard irq... + * ***************************************************************************** + */ +irqreturn_t emulator_hard_irq_isr( + int irq, + void *ctxt); + +/* + * ***************************************************************************** + * The following for EMULATION soft irq... + * ***************************************************************************** + */ +irqreturn_t emulator_soft_irq_isr( + int irq, + void *ctxt); + +# else /* #if !defined(CONFIG_IPA_EMULATION) then definitions to follow */ + +static inline int setup_emulator_cntrlr( + void __iomem *intcntrlr_base, + u32 intcntrlr_mem_size) +{ + return 0; +} + +static inline irqreturn_t emulator_hard_irq_isr( + int irq, + void *ctxt) +{ + return IRQ_NONE; +} + +static inline irqreturn_t emulator_soft_irq_isr( + int irq, + void *ctxt) +{ + return IRQ_HANDLED; +} + +# endif /* #if defined(CONFIG_IPA_EMULATION) */ + +#endif /* #if !defined(_GSI_EMULATION_H_) */ diff --git a/drivers/platform/msm/gsi/gsi_emulation_stubs.h b/drivers/platform/msm/gsi/gsi_emulation_stubs.h new file mode 100644 index 000000000000..dd9d0df5d1bf --- /dev/null +++ b/drivers/platform/msm/gsi/gsi_emulation_stubs.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#if !defined(_GSI_EMULATION_STUBS_H_) +# define _GSI_EMULATION_STUBS_H_ + +# include +# define __iormb() rmb() /* used in gsi.h */ +# define __iowmb() wmb() /* used in gsi.h */ + +#endif /* #if !defined(_GSI_EMULATION_STUBS_H_) */ diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c index c96446343be9..524d0083e77d 100644 --- a/drivers/platform/msm/ipa/ipa_api.c +++ b/drivers/platform/msm/ipa/ipa_api.c @@ -19,8 +19,16 @@ #include #include #include +#include #include "ipa_api.h" +/* + * The following for adding code (ie. for EMULATION) not found on x86. + */ +#if defined(CONFIG_IPA_EMULATION) +# include "ipa_v3/ipa_emulation_stubs.h" +#endif + #define DRV_NAME "ipa" #define IPA_API_DISPATCH_RETURN(api, p...) \ @@ -94,6 +102,12 @@ } \ } while (0) +#if defined(CONFIG_IPA_EMULATION) +static bool running_emulation = true; +#else +static bool running_emulation; +#endif + static enum ipa_hw_type ipa_api_hw_type; static struct ipa_api_controller *ipa_api_ctrl; @@ -2889,6 +2903,57 @@ static const struct of_device_id ipa_plat_drv_match[] = { {} }; +/*********************************************************/ +/* PCIe Version */ +/*********************************************************/ + +static const struct of_device_id ipa_pci_drv_match[] = { + { .compatible = "qcom,ipa", }, + {} +}; + +/* + * Forward declarations of static functions required for PCI + * registraion + * + * VENDOR and DEVICE should be defined in pci_ids.h + */ +static int ipa_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); +static void ipa_pci_remove(struct pci_dev *pdev); +static void ipa_pci_shutdown(struct pci_dev *pdev); +static pci_ers_result_t ipa_pci_io_error_detected(struct pci_dev *dev, + pci_channel_state_t state); +static pci_ers_result_t ipa_pci_io_slot_reset(struct pci_dev *dev); +static void ipa_pci_io_resume(struct pci_dev *dev); + +#define LOCAL_VENDOR 0x17CB +#define LOCAL_DEVICE 0x00ff + +static const char ipa_pci_driver_name[] = "qcipav3"; + +static const struct pci_device_id ipa_pci_tbl[] = { + { PCI_DEVICE(LOCAL_VENDOR, LOCAL_DEVICE) }, + { 0, 0, 0, 0, 0, 0, 0 } +}; + +MODULE_DEVICE_TABLE(pci, ipa_pci_tbl); + +/* PCI Error Recovery */ +static const struct pci_error_handlers ipa_pci_err_handler = { + .error_detected = ipa_pci_io_error_detected, + .slot_reset = ipa_pci_io_slot_reset, + .resume = ipa_pci_io_resume, +}; + +static struct pci_driver ipa_pci_driver = { + .name = ipa_pci_driver_name, + .id_table = ipa_pci_tbl, + .probe = ipa_pci_probe, + .remove = ipa_pci_remove, + .shutdown = ipa_pci_shutdown, + .err_handler = &ipa_pci_err_handler +}; + static int ipa_generic_plat_drv_probe(struct platform_device *pdev_p) { int result; @@ -3333,10 +3398,86 @@ static struct platform_driver ipa_plat_drv = { }, }; +/*********************************************************/ +/* PCIe Version */ +/*********************************************************/ + +static int ipa_pci_probe( + struct pci_dev *pci_dev, + const struct pci_device_id *ent) +{ + int result; + + if (!pci_dev || !ent) { + pr_err( + "Bad arg: pci_dev (%pK) and/or ent (%pK)\n", + pci_dev, ent); + return -EOPNOTSUPP; + } + + if (!ipa_api_ctrl) { + ipa_api_ctrl = kzalloc(sizeof(*ipa_api_ctrl), GFP_KERNEL); + if (ipa_api_ctrl == NULL) + return -ENOMEM; + /* Get IPA HW Version */ + result = of_property_read_u32(NULL, + "qcom,ipa-hw-ver", &ipa_api_hw_type); + if (result || ipa_api_hw_type == 0) { + pr_err("ipa: get resource failed for ipa-hw-ver!\n"); + kfree(ipa_api_ctrl); + ipa_api_ctrl = NULL; + return -ENODEV; + } + pr_debug("ipa: ipa_api_hw_type = %d", ipa_api_hw_type); + } + + /* + * Call a reduced version of platform_probe appropriate for PCIe + */ + result = ipa3_pci_drv_probe(pci_dev, ipa_api_ctrl, ipa_pci_drv_match); + + if (result && result != -EPROBE_DEFER) + pr_err("ipa: ipa3_pci_drv_probe failed\n"); + + if (running_emulation) + ipa_ut_module_init(); + + return result; +} + +static void ipa_pci_remove(struct pci_dev *pci_dev) +{ + if (running_emulation) + ipa_ut_module_exit(); +} + +static void ipa_pci_shutdown(struct pci_dev *pci_dev) +{ +} + +static pci_ers_result_t ipa_pci_io_error_detected(struct pci_dev *pci_dev, + pci_channel_state_t state) +{ + return 0; +} + +static pci_ers_result_t ipa_pci_io_slot_reset(struct pci_dev *pci_dev) +{ + return 0; +} + +static void ipa_pci_io_resume(struct pci_dev *pci_dev) +{ +} + static int __init ipa_module_init(void) { pr_debug("IPA module init\n"); + if (running_emulation) { + /* Register as a PCI device driver */ + return pci_register_driver(&ipa_pci_driver); + } /* Register as a platform device driver */ return platform_driver_register(&ipa_plat_drv); } diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h index 8185dfd8ac34..1c84f89a823f 100644 --- a/drivers/platform/msm/ipa/ipa_api.h +++ b/drivers/platform/msm/ipa/ipa_api.h @@ -434,6 +434,10 @@ struct ipa_api_controller { int ipa3_plat_drv_probe(struct platform_device *pdev_p, struct ipa_api_controller *api_ctrl, const struct of_device_id *pdrv_match); +int ipa3_pci_drv_probe( + struct pci_dev *pci_dev, + struct ipa_api_controller *api_ctrl, + const struct of_device_id *pdrv_match); #else static inline int ipa3_plat_drv_probe(struct platform_device *pdev_p, struct ipa_api_controller *api_ctrl, @@ -441,6 +445,13 @@ static inline int ipa3_plat_drv_probe(struct platform_device *pdev_p, { return -ENODEV; } +static inline int ipa3_pci_drv_probe( + struct pci_dev *pci_dev, + struct ipa_api_controller *api_ctrl, + const struct of_device_id *pdrv_match) +{ + return -ENODEV; +} #endif /* (CONFIG_IPA3) */ #endif /* _IPA_API_H_ */ diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h index b8a517ee27ce..530aa545a328 100644 --- a/drivers/platform/msm/ipa/ipa_common_i.h +++ b/drivers/platform/msm/ipa/ipa_common_i.h @@ -15,6 +15,7 @@ #ifndef _IPA_COMMON_I_H_ #define _IPA_COMMON_I_H_ +#include #include #include #include @@ -441,4 +442,7 @@ int ipa_smmu_store_sgt(struct sg_table **out_ch_ptr, struct sg_table *in_sgt_ptr); int ipa_smmu_free_sgt(struct sg_table **out_sgt_ptr); +int ipa_ut_module_init(void); +void ipa_ut_module_exit(void); + #endif /* _IPA_COMMON_I_H_ */ diff --git a/drivers/platform/msm/ipa/ipa_v3/Makefile b/drivers/platform/msm/ipa/ipa_v3/Makefile index 9901e642a6a5..f6f08b152393 100644 --- a/drivers/platform/msm/ipa/ipa_v3/Makefile +++ b/drivers/platform/msm/ipa/ipa_v3/Makefile @@ -6,6 +6,8 @@ ipat-y := ipa.o ipa_debugfs.o ipa_hdr.o ipa_flt.o ipa_rt.o ipa_dp.o ipa_client.o ipa_uc.o ipa_uc_wdi.o ipa_dma.o ipa_uc_mhi.o ipa_mhi.o ipa_uc_ntn.o \ ipa_hw_stats.o ipa_pm.o ipa_wdi3_i.o +ipat-$(CONFIG_IPA_EMULATION) += ipa_dt_replacement.o + obj-$(CONFIG_RMNET_IPA3) += rmnet_ipa.o ipa_qmi_service_v01.o ipa_qmi_service.o rmnet_ipa_fd_ioctl.o obj-$(CONFIG_IPA3_MHI_PROXY) += ipa_mhi_proxy.o diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 7e8f3711e27d..74334115521b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -59,168 +60,14 @@ #define CREATE_TRACE_POINTS #include "ipa_trace.h" -#define IPA_SMP2P_SMEM_STATE_MASK 3 - - -#define IPA_SUMMING_THRESHOLD (0x10) -#define IPA_PIPE_MEM_START_OFST (0x0) -#define IPA_PIPE_MEM_SIZE (0x0) -#define IPA_MOBILE_AP_MODE(x) (x == IPA_MODE_MOBILE_AP_ETH || \ - x == IPA_MODE_MOBILE_AP_WAN || \ - x == IPA_MODE_MOBILE_AP_WLAN) -#define IPA_CNOC_CLK_RATE (75 * 1000 * 1000UL) -#define IPA_A5_MUX_HEADER_LENGTH (8) - -#define IPA_AGGR_MAX_STR_LENGTH (10) - -#define CLEANUP_TAG_PROCESS_TIMEOUT 500 - -#define IPA_AGGR_STR_IN_BYTES(str) \ - (strnlen((str), IPA_AGGR_MAX_STR_LENGTH - 1) + 1) - -#define IPA_TRANSPORT_PROD_TIMEOUT_MSEC 100 - -#define IPA3_ACTIVE_CLIENTS_TABLE_BUF_SIZE 2048 - -#define IPA3_ACTIVE_CLIENT_LOG_TYPE_EP 0 -#define IPA3_ACTIVE_CLIENT_LOG_TYPE_SIMPLE 1 -#define IPA3_ACTIVE_CLIENT_LOG_TYPE_RESOURCE 2 -#define IPA3_ACTIVE_CLIENT_LOG_TYPE_SPECIAL 3 - -#define IPA_MHI_GSI_EVENT_RING_ID_START 10 -#define IPA_MHI_GSI_EVENT_RING_ID_END 12 - -#define IPA_SMEM_SIZE (8 * 1024) - -#define IPA_GSI_CHANNEL_HALT_MIN_SLEEP 5000 -#define IPA_GSI_CHANNEL_HALT_MAX_SLEEP 10000 -#define IPA_GSI_CHANNEL_HALT_MAX_TRY 10 - -/* round addresses for closes page per SMMU requirements */ -#define IPA_SMMU_ROUND_TO_PAGE(iova, pa, size, iova_p, pa_p, size_p) \ - do { \ - (iova_p) = rounddown((iova), PAGE_SIZE); \ - (pa_p) = rounddown((pa), PAGE_SIZE); \ - (size_p) = roundup((size) + (pa) - (pa_p), PAGE_SIZE); \ - } while (0) - - -/* The relative location in /lib/firmware where the FWs will reside */ -#define IPA_FWS_PATH "ipa/ipa_fws.elf" +/* + * The following for adding code (ie. for EMULATION) not found on x86. + */ +#if defined(CONFIG_IPA_EMULATION) +# include "ipa_emulation_stubs.h" +#endif #ifdef CONFIG_COMPAT -#define IPA_IOC_ADD_HDR32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_ADD_HDR, \ - compat_uptr_t) -#define IPA_IOC_DEL_HDR32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_DEL_HDR, \ - compat_uptr_t) -#define IPA_IOC_ADD_RT_RULE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_ADD_RT_RULE, \ - compat_uptr_t) -#define IPA_IOC_DEL_RT_RULE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_DEL_RT_RULE, \ - compat_uptr_t) -#define IPA_IOC_ADD_FLT_RULE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_ADD_FLT_RULE, \ - compat_uptr_t) -#define IPA_IOC_DEL_FLT_RULE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_DEL_FLT_RULE, \ - compat_uptr_t) -#define IPA_IOC_GET_RT_TBL32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_GET_RT_TBL, \ - compat_uptr_t) -#define IPA_IOC_COPY_HDR32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_COPY_HDR, \ - compat_uptr_t) -#define IPA_IOC_QUERY_INTF32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_QUERY_INTF, \ - compat_uptr_t) -#define IPA_IOC_QUERY_INTF_TX_PROPS32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_QUERY_INTF_TX_PROPS, \ - compat_uptr_t) -#define IPA_IOC_QUERY_INTF_RX_PROPS32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_QUERY_INTF_RX_PROPS, \ - compat_uptr_t) -#define IPA_IOC_QUERY_INTF_EXT_PROPS32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_QUERY_INTF_EXT_PROPS, \ - compat_uptr_t) -#define IPA_IOC_GET_HDR32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_GET_HDR, \ - compat_uptr_t) -#define IPA_IOC_ALLOC_NAT_MEM32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_ALLOC_NAT_MEM, \ - compat_uptr_t) -#define IPA_IOC_ALLOC_NAT_TABLE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_ALLOC_NAT_TABLE, \ - compat_uptr_t) -#define IPA_IOC_ALLOC_IPV6CT_TABLE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_ALLOC_IPV6CT_TABLE, \ - compat_uptr_t) -#define IPA_IOC_V4_INIT_NAT32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_V4_INIT_NAT, \ - compat_uptr_t) -#define IPA_IOC_INIT_IPV6CT_TABLE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_INIT_IPV6CT_TABLE, \ - compat_uptr_t) -#define IPA_IOC_TABLE_DMA_CMD32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_TABLE_DMA_CMD, \ - compat_uptr_t) -#define IPA_IOC_V4_DEL_NAT32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_V4_DEL_NAT, \ - compat_uptr_t) -#define IPA_IOC_DEL_NAT_TABLE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_DEL_NAT_TABLE, \ - compat_uptr_t) -#define IPA_IOC_DEL_IPV6CT_TABLE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_DEL_IPV6CT_TABLE, \ - compat_uptr_t) -#define IPA_IOC_NAT_MODIFY_PDN32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_NAT_MODIFY_PDN, \ - compat_uptr_t) -#define IPA_IOC_GET_NAT_OFFSET32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_GET_NAT_OFFSET, \ - compat_uptr_t) -#define IPA_IOC_PULL_MSG32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_PULL_MSG, \ - compat_uptr_t) -#define IPA_IOC_RM_ADD_DEPENDENCY32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_RM_ADD_DEPENDENCY, \ - compat_uptr_t) -#define IPA_IOC_RM_DEL_DEPENDENCY32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_RM_DEL_DEPENDENCY, \ - compat_uptr_t) -#define IPA_IOC_GENERATE_FLT_EQ32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_GENERATE_FLT_EQ, \ - compat_uptr_t) -#define IPA_IOC_QUERY_RT_TBL_INDEX32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_QUERY_RT_TBL_INDEX, \ - compat_uptr_t) -#define IPA_IOC_WRITE_QMAPID32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_WRITE_QMAPID, \ - compat_uptr_t) -#define IPA_IOC_MDFY_FLT_RULE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_MDFY_FLT_RULE, \ - compat_uptr_t) -#define IPA_IOC_NOTIFY_WAN_UPSTREAM_ROUTE_ADD32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_NOTIFY_WAN_UPSTREAM_ROUTE_ADD, \ - compat_uptr_t) -#define IPA_IOC_NOTIFY_WAN_UPSTREAM_ROUTE_DEL32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_NOTIFY_WAN_UPSTREAM_ROUTE_DEL, \ - compat_uptr_t) -#define IPA_IOC_NOTIFY_WAN_EMBMS_CONNECTED32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_NOTIFY_WAN_EMBMS_CONNECTED, \ - compat_uptr_t) -#define IPA_IOC_ADD_HDR_PROC_CTX32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_ADD_HDR_PROC_CTX, \ - compat_uptr_t) -#define IPA_IOC_DEL_HDR_PROC_CTX32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_DEL_HDR_PROC_CTX, \ - compat_uptr_t) -#define IPA_IOC_MDFY_RT_RULE32 _IOWR(IPA_IOC_MAGIC, \ - IPA_IOCTL_MDFY_RT_RULE, \ - compat_uptr_t) - /** * struct ipa3_ioc_nat_alloc_mem32 - nat table memory allocation * properties @@ -244,8 +91,7 @@ struct ipa_ioc_nat_ipv6ct_table_alloc32 { compat_size_t size; compat_off_t offset; }; - -#endif +#endif /* #ifdef CONFIG_COMPAT */ #define IPA_TZ_UNLOCK_ATTRIBUTE 0x0C0311 #define TZ_MEM_PROTECT_REGION_ID 0x10 @@ -285,6 +131,7 @@ static struct ipa3_plat_drv_res ipa3_res = {0, }; static struct clk *ipa3_clk; struct ipa3_context *ipa3_ctx; + static struct { bool present[IPA_SMMU_CB_MAX]; bool arm_smmu; @@ -2801,6 +2648,16 @@ int _ipa_init_sram_v3(void) u32 *ipa_sram_mmio; unsigned long phys_addr; + IPADBG( + "ipa_wrapper_base(0x%08X) ipa_reg_base_ofst(0x%08X) IPA_SRAM_DIRECT_ACCESS_n(0x%08X) smem_restricted_bytes(0x%08X) smem_sz(0x%08X)\n", + ipa3_ctx->ipa_wrapper_base, + ipa3_ctx->ctrl->ipa_reg_base_ofst, + ipahal_get_reg_n_ofst( + IPA_SRAM_DIRECT_ACCESS_n, + ipa3_ctx->smem_restricted_bytes / 4), + ipa3_ctx->smem_restricted_bytes, + ipa3_ctx->smem_sz); + phys_addr = ipa3_ctx->ipa_wrapper_base + ipa3_ctx->ctrl->ipa_reg_base_ofst + ipahal_get_reg_n_ofst(IPA_SRAM_DIRECT_ACCESS_n, @@ -3317,21 +3174,27 @@ static int ipa3_setup_apps_pipes(void) } IPADBG("Apps to IPA cmd pipe is connected\n"); + IPADBG("Will initialize SRAM\n"); ipa3_ctx->ctrl->ipa_init_sram(); IPADBG("SRAM initialized\n"); + IPADBG("Will initialize HDR\n"); ipa3_ctx->ctrl->ipa_init_hdr(); IPADBG("HDR initialized\n"); + IPADBG("Will initialize V4 RT\n"); ipa3_ctx->ctrl->ipa_init_rt4(); IPADBG("V4 RT initialized\n"); + IPADBG("Will initialize V6 RT\n"); ipa3_ctx->ctrl->ipa_init_rt6(); IPADBG("V6 RT initialized\n"); + IPADBG("Will initialize V4 FLT\n"); ipa3_ctx->ctrl->ipa_init_flt4(); IPADBG("V4 FLT initialized\n"); + IPADBG("Will initialize V6 FLT\n"); ipa3_ctx->ctrl->ipa_init_flt6(); IPADBG("V6 FLT initialized\n"); @@ -3628,6 +3491,12 @@ static const struct file_operations ipa3_drv_fops = { static int ipa3_get_clks(struct device *dev) { + if (ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_EMULATION) { + IPADBG("No clock manipulation when running emulation\n"); + ipa3_clk = NULL; + return 0; + } + if (ipa3_res.use_bw_vote) { IPADBG("Vote IPA clock by bw voting via bus scaling driver\n"); ipa3_clk = NULL; @@ -4619,11 +4488,12 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, ipa3_proxy_clk_vote(); /* - * In Virtual mode, IPAHAL initialized at pre_init as - * there is no SMMU. In normal mode need to wait until - * SMMU is attached and thus initialization done here. + * In Virtual and Emulation mode, IPAHAL initialized at + * pre_init as there is no SMMU. In normal mode need to wait + * until SMMU is attached and thus initialization done here. */ - if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL) { + if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL && + ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION) { if (ipahal_init(ipa3_ctx->ipa_hw_type, ipa3_ctx->mmio, ipa3_ctx->pdev)) { IPAERR("fail to init ipahal\n"); @@ -4764,9 +4634,18 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, gsi_props.ver = ipa3_get_gsi_ver(resource_p->ipa_hw_type); gsi_props.ee = resource_p->ee; gsi_props.intr = GSI_INTR_IRQ; - gsi_props.irq = resource_p->transport_irq; gsi_props.phys_addr = resource_p->transport_mem_base; gsi_props.size = resource_p->transport_mem_size; + if (ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_EMULATION) { + gsi_props.irq = resource_p->emulator_irq; + gsi_props.emulator_intcntrlr_client_isr = ipa3_get_isr(); + gsi_props.emulator_intcntrlr_addr = + resource_p->emulator_intcntrlr_mem_base; + gsi_props.emulator_intcntrlr_size = + resource_p->emulator_intcntrlr_mem_size; + } else { + gsi_props.irq = resource_p->transport_irq; + } gsi_props.notify_cb = ipa_gsi_notify_cb; gsi_props.req_clk_cb = NULL; gsi_props.rel_clk_cb = NULL; @@ -4834,12 +4713,12 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, ipa3_register_panic_hdlr(); + ipa3_debugfs_init(); + mutex_lock(&ipa3_ctx->lock); ipa3_ctx->ipa_initialization_complete = true; mutex_unlock(&ipa3_ctx->lock); - ipa3_debugfs_init(); - ipa3_trigger_ipa_ready_cbs(); complete_all(&ipa3_ctx->init_completion_obj); pr_info("IPA driver initialization was successful.\n"); @@ -4852,16 +4731,18 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, gsi_deregister_device(ipa3_ctx->gsi_dev_hdl, false); fail_register_device: ipa3_destroy_flt_tbl_idrs(); - ipa3_proxy_clk_unvote(); fail_allok_pkt_init: ipa3_nat_ipv6ct_destroy_devices(); fail_nat_ipv6ct_init_dev: ipa3_free_dma_task_for_gsi(); fail_dma_task: fail_init_hw: - if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL) + if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL && + ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION) ipahal_destroy(); fail_ipahal: + ipa3_proxy_clk_unvote(); + return result; } @@ -4869,10 +4750,24 @@ static int ipa3_manual_load_ipa_fws(void) { int result; const struct firmware *fw; + const char *path = IPA_FWS_PATH; - IPADBG("Manual FW loading process initiated\n"); + if (ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_EMULATION) { + switch (ipa3_get_emulation_type()) { + case IPA_HW_v3_5_1: + path = IPA_FWS_PATH_3_5_1; + break; + case IPA_HW_v4_0: + path = IPA_FWS_PATH_4_0; + break; + default: + break; + } + } - result = request_firmware(&fw, IPA_FWS_PATH, ipa3_ctx->cdev.dev); + IPADBG("Manual FW loading (%s) process initiated\n", path); + + result = request_firmware(&fw, path, ipa3_ctx->cdev.dev); if (result < 0) { IPAERR("request_firmware failed, error %d\n", result); return result; @@ -4880,8 +4775,16 @@ static int ipa3_manual_load_ipa_fws(void) IPADBG("FWs are available for loading\n"); - result = ipa3_load_fws(fw, ipa3_res.transport_mem_base, - ipa3_get_gsi_ver(ipa3_res.ipa_hw_type)); + if (ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_EMULATION) { + result = emulator_load_fws(fw, + ipa3_res.transport_mem_base, + ipa3_res.transport_mem_size, + ipa3_get_gsi_ver(ipa3_res.ipa_hw_type)); + } else { + result = ipa3_load_fws(fw, ipa3_res.transport_mem_base, + ipa3_get_gsi_ver(ipa3_res.ipa_hw_type)); + } + if (result) { IPAERR("Manual IPA FWs loading has failed\n"); release_firmware(fw); @@ -4900,6 +4803,7 @@ static int ipa3_manual_load_ipa_fws(void) release_firmware(fw); IPADBG("Manual FW loading process is complete\n"); + return 0; } @@ -4933,7 +4837,8 @@ static void ipa3_load_ipa_fw(struct work_struct *work) IPA_ACTIVE_CLIENTS_INC_SIMPLE(); - if (ipa3_is_msm_device() || (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5)) + if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION && + (ipa3_is_msm_device() || (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5))) result = ipa3_pil_load_ipa_fws(); else result = ipa3_manual_load_ipa_fws(); @@ -5264,7 +5169,8 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, goto fail_init_mem_partition; } - if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL) { + if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL && + ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION) { ipa3_ctx->ctrl->msm_bus_data_ptr = msm_bus_cl_get_pdata(ipa3_ctx->master_pdev); if (ipa3_ctx->ctrl->msm_bus_data_ptr == NULL) { @@ -5315,11 +5221,21 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, goto fail_remap; } + IPADBG( + "base(0x%x)+offset(0x%x)=(0x%x) mapped to (%pK) with len (0x%x)\n", + resource_p->ipa_mem_base, + ipa3_ctx->ctrl->ipa_reg_base_ofst, + resource_p->ipa_mem_base + ipa3_ctx->ctrl->ipa_reg_base_ofst, + ipa3_ctx->mmio, + resource_p->ipa_mem_size); + /* - * In Virtual mode, IPAHAL used to load the firmwares - * and there is no SMMU so IPAHAL is initialized here. + * In Virtual and Emulation mode, IPAHAL used to load the + * firmwares and there is no SMMU so IPAHAL is initialized + * here */ - if (ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_VIRTUAL) { + if (ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_VIRTUAL || + ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_EMULATION) { if (ipahal_init(ipa3_ctx->ipa_hw_type, ipa3_ctx->mmio, &(ipa3_ctx->master_pdev->dev))) { @@ -5538,10 +5454,13 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, * We can't register the GSI driver yet, as it expects * the GSI FW to be up and running before the registration. * - * For IPA3.0, the GSI configuration is done by the GSI driver. + * For IPA3.0 and the emulation system, the GSI configuration + * is done by the GSI driver. + * * For IPA3.1 (and on), the GSI configuration is done by TZ. */ - if (ipa3_ctx->ipa_hw_type == IPA_HW_v3_0) { + if (ipa3_ctx->ipa_hw_type == IPA_HW_v3_0 || + ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_EMULATION) { result = ipa3_gsi_pre_fw_load_init(); if (result) { IPAERR("gsi pre FW loading config failed\n"); @@ -5619,7 +5538,8 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, fail_create_transport_wq: destroy_workqueue(ipa3_ctx->power_mgmt_wq); fail_init_hw: - if (ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_VIRTUAL) + if (ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_VIRTUAL || + ipa3_ctx->ipa3_hw_mode == IPA_HW_MODE_EMULATION) ipahal_destroy(); fail_ipahal_init: iounmap(ipa3_ctx->mmio); @@ -5947,6 +5867,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, &ipa_drv_res->ee); if (result) ipa_drv_res->ee = 0; + IPADBG(":ee = %u\n", ipa_drv_res->ee); ipa_drv_res->apply_rg10_wa = of_property_read_bool(pdev->dev.of_node, @@ -5959,7 +5880,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, of_property_read_bool(pdev->dev.of_node, "qcom,do-not-use-ch-gsi-20"); IPADBG(": GSI CH 20 WA is = %s\n", - ipa_drv_res->apply_rg10_wa + ipa_drv_res->gsi_ch20_wa ? "Needed" : "Not needed"); elem_num = of_property_count_elems_of_size(pdev->dev.of_node, @@ -6044,6 +5965,26 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, IPADBG("Is wdi_over_pcie ? (%s)\n", ipa3_ctx->wdi_over_pcie ? "Yes":"No"); + /* + * If we're on emulator, get its interrupt controller's mem + * start and size + */ + if (ipa_drv_res->ipa3_hw_mode == IPA_HW_MODE_EMULATION) { + resource = platform_get_resource_byname( + pdev, IORESOURCE_MEM, "intctrl-base"); + if (!resource) { + IPAERR(":Can't find intctrl-base resource\n"); + return -ENODEV; + } + ipa_drv_res->emulator_intcntrlr_mem_base = + resource->start; + ipa_drv_res->emulator_intcntrlr_mem_size = + resource_size(resource); + IPADBG(":using intctrl-base at 0x%x of size 0x%x\n", + ipa_drv_res->emulator_intcntrlr_mem_base, + ipa_drv_res->emulator_intcntrlr_mem_size); + } + return 0; } @@ -6505,7 +6446,7 @@ static int ipa3_smp2p_probe(struct device *dev) qcom_smem_state_get(dev, "ipa-smp2p-out", &ipa3_ctx->smp2p_info.smem_bit); if (IS_ERR(ipa3_ctx->smp2p_info.smem_state)) { - IPAERR("fail to get smp2p clk resp bit %d\n", + IPAERR("fail to get smp2p clk resp bit %ld\n", PTR_ERR(ipa3_ctx->smp2p_info.smem_state)); return PTR_ERR(ipa3_ctx->smp2p_info.smem_state); } @@ -6836,5 +6777,216 @@ int ipa3_get_smmu_params(struct ipa_smmu_in_params *in, return 0; } +/************************************************************** + * PCIe Version + *************************************************************/ + +int ipa3_pci_drv_probe( + struct pci_dev *pci_dev, + struct ipa_api_controller *api_ctrl, + const struct of_device_id *pdrv_match) +{ + int result; + struct ipa3_plat_drv_res *ipa_drv_res; + u32 bar0_offset; + u32 mem_start; + u32 mem_end; + uint32_t bits; + uint32_t ipa_start, gsi_start, intctrl_start; + struct device *dev; + static struct platform_device platform_dev; + + if (!pci_dev || !api_ctrl || !pdrv_match) { + IPAERR( + "Bad arg: pci_dev (%pK) and/or api_ctrl (%pK) and/or pdrv_match (%pK)\n", + pci_dev, api_ctrl, pdrv_match); + return -EOPNOTSUPP; + } + + dev = &(pci_dev->dev); + + IPADBG("IPA PCI driver probing started\n"); + + /* + * Follow PCI driver flow here. + * pci_enable_device: Enables device and assigns resources + * pci_request_region: Makes BAR0 address region usable + */ + result = pci_enable_device(pci_dev); + if (result < 0) { + IPAERR("pci_enable_device() failed\n"); + return -EOPNOTSUPP; + } + + result = pci_request_region(pci_dev, 0, "IPA Memory"); + if (result < 0) { + IPAERR("pci_request_region() failed\n"); + pci_disable_device(pci_dev); + return -EOPNOTSUPP; + } + + /* + * When in the PCI/emulation environment, &platform_dev is + * passed to get_ipa_dts_configuration(), but is unused, since + * all usages of it in the function are replaced by CPP + * relative to definitions in ipa_emulation_stubs.h. Passing + * &platform_dev makes code validity tools happy. + */ + if (get_ipa_dts_configuration(&platform_dev, &ipa3_res) != 0) { + IPAERR("get_ipa_dts_configuration() failed\n"); + pci_release_region(pci_dev, 0); + pci_disable_device(pci_dev); + return -EOPNOTSUPP; + } + + ipa_drv_res = &ipa3_res; + + result = + of_property_read_u32(NULL, "emulator-bar0-offset", + &bar0_offset); + if (result) { + IPAERR(":get resource failed for emulator-bar0-offset!\n"); + pci_release_region(pci_dev, 0); + pci_disable_device(pci_dev); + return -ENODEV; + } + IPADBG(":using emulator-bar0-offset 0x%08X\n", bar0_offset); + + ipa_start = ipa_drv_res->ipa_mem_base; + gsi_start = ipa_drv_res->transport_mem_base; + intctrl_start = ipa_drv_res->emulator_intcntrlr_mem_base; + + /* + * Where will we be inerrupted at? + */ + ipa_drv_res->emulator_irq = pci_dev->irq; + IPADBG( + "EMULATION PCI_INTERRUPT_PIN(%u)\n", + ipa_drv_res->emulator_irq); + + /* + * Set the ipa_mem_base to the PCI base address of BAR0 + */ + mem_start = pci_resource_start(pci_dev, 0); + mem_end = pci_resource_end(pci_dev, 0); + + IPADBG("PCI START = 0x%x\n", mem_start); + IPADBG("PCI END = 0x%x\n", mem_end); + + ipa_drv_res->ipa_mem_base = mem_start + bar0_offset; + + smmu_info.ipa_base = ipa_drv_res->ipa_mem_base; + smmu_info.ipa_size = ipa_drv_res->ipa_mem_size; + + ipa_drv_res->transport_mem_base = + ipa_drv_res->ipa_mem_base + (gsi_start - ipa_start); + + ipa_drv_res->emulator_intcntrlr_mem_base = + ipa_drv_res->ipa_mem_base + (intctrl_start - ipa_start); + + IPADBG("ipa_mem_base = 0x%x\n", + ipa_drv_res->ipa_mem_base); + IPADBG("ipa_mem_size = 0x%x\n", + ipa_drv_res->ipa_mem_size); + + IPADBG("transport_mem_base = 0x%x\n", + ipa_drv_res->transport_mem_base); + IPADBG("transport_mem_size = 0x%x\n", + ipa_drv_res->transport_mem_size); + + IPADBG("emulator_intcntrlr_mem_base = 0x%x\n", + ipa_drv_res->emulator_intcntrlr_mem_base); + IPADBG("emulator_intcntrlr_mem_size = 0x%x\n", + ipa_drv_res->emulator_intcntrlr_mem_size); + + result = ipa3_bind_api_controller(ipa_drv_res->ipa_hw_type, api_ctrl); + if (result != 0) { + IPAERR("ipa3_bind_api_controller() failed\n"); + pci_release_region(pci_dev, 0); + pci_disable_device(pci_dev); + return result; + } + + bits = (ipa_drv_res->use_64_bit_dma_mask) ? 64 : 32; + + if (dma_set_mask(dev, DMA_BIT_MASK(bits)) != 0) { + IPAERR("dma_set_mask(%pK, %u) failed\n", dev, bits); + pci_release_region(pci_dev, 0); + pci_disable_device(pci_dev); + return -EOPNOTSUPP; + } + + if (dma_set_coherent_mask(dev, DMA_BIT_MASK(bits)) != 0) { + IPAERR("dma_set_coherent_mask(%pK, %u) failed\n", dev, bits); + pci_release_region(pci_dev, 0); + pci_disable_device(pci_dev); + return -EOPNOTSUPP; + } + + pci_set_master(pci_dev); + + memset(&platform_dev, 0, sizeof(platform_dev)); + platform_dev.dev = *dev; + + /* Proceed to real initialization */ + result = ipa3_pre_init(&ipa3_res, &platform_dev); + if (result) { + IPAERR("ipa3_init failed\n"); + pci_clear_master(pci_dev); + pci_release_region(pci_dev, 0); + pci_disable_device(pci_dev); + return result; + } + + return result; +} + +/* + * The following returns transport register memory location and + * size... + */ +int ipa3_get_transport_info( + phys_addr_t *phys_addr_ptr, + unsigned long *size_ptr) +{ + if (!phys_addr_ptr || !size_ptr) { + IPAERR("Bad arg: phys_addr_ptr(%pK) and/or size_ptr(%pK)\n", + phys_addr_ptr, size_ptr); + return -EINVAL; + } + + *phys_addr_ptr = ipa3_res.transport_mem_base; + *size_ptr = ipa3_res.transport_mem_size; + + return 0; +} +EXPORT_SYMBOL(ipa3_get_transport_info); + +static uint emulation_type = IPA_HW_v4_0; + +/* + * The following returns emulation type... + */ +uint ipa3_get_emulation_type(void) +{ + return emulation_type; +} + MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("IPA HW device driver"); + +/* + * Module parameter. Invoke as follows: + * insmod ipat.ko emulation_type=[13|14|...|N] + * Examples: + * insmod ipat.ko emulation_type=13 # for IPA 3.5.1 + * insmod ipat.ko emulation_type=14 # for IPA 4.0 + * + * NOTE: The emulation_type values need to come from: enum ipa_hw_type + * + */ + +module_param(emulation_type, uint, 0000); +MODULE_PARM_DESC( + emulation_type, + "IPA emulation type (Use 13 for IPA 3.5.1, 14 for IPA 4.0)"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dt_replacement.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dt_replacement.c new file mode 100644 index 000000000000..5fe2294819bf --- /dev/null +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dt_replacement.c @@ -0,0 +1,765 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include "ipa_i.h" +#include "ipa_emulation_stubs.h" + +# undef strsame +# define strsame(x, y) \ + (!strcmp((x), (y))) + +/* + * The following enum values used to index tables below. + */ +enum dtsi_index_e { + DTSI_INDEX_3_5_1 = 0, + DTSI_INDEX_4_0 = 1, +}; + +struct dtsi_replacement_u32 { + char *key; + u32 value; +}; + +struct dtsi_replacement_u32_table { + struct dtsi_replacement_u32 *p_table; + u32 num_entries; +}; + +struct dtsi_replacement_bool { + char *key; + bool value; +}; + +struct dtsi_replacement_bool_table { + struct dtsi_replacement_bool *p_table; + u32 num_entries; +}; + +struct dtsi_replacement_u32_array { + char *key; + u32 *p_value; + u32 num_elements; +}; + +struct dtsi_replacement_u32_array_table { + struct dtsi_replacement_u32_array *p_table; + u32 num_entries; +}; + +struct dtsi_replacement_resource_table { + struct resource *p_table; + u32 num_entries; +}; + +/* + * Any of the data below with _4_0 in the name represent data taken + * from the 4.0 dtsi file. + * + * Any of the data below with _3_5_1 in the name represent data taken + * from the 3.5.1 dtsi file. + */ +static struct dtsi_replacement_bool ipa3_plat_drv_bool_4_0[] = { + {"qcom,use-ipa-tethering-bridge", true}, + {"qcom,modem-cfg-emb-pipe-flt", true}, + {"qcom,ipa-wdi2", true}, + {"qcom,use-64-bit-dma-mask", false}, + {"qcom,bandwidth-vote-for-ipa", false}, + {"qcom,skip-uc-pipe-reset", false}, + {"qcom,tethered-flow-control", true}, + {"qcom,use-rg10-limitation-mitigation", false}, + {"qcom,do-not-use-ch-gsi-20", false}, + {"qcom,use-ipa-pm", false}, +}; + +static struct dtsi_replacement_bool ipa3_plat_drv_bool_3_5_1[] = { + {"qcom,use-ipa-tethering-bridge", true}, + {"qcom,modem-cfg-emb-pipe-flt", true}, + {"qcom,ipa-wdi2", true}, + {"qcom,use-64-bit-dma-mask", false}, + {"qcom,bandwidth-vote-for-ipa", true}, + {"qcom,skip-uc-pipe-reset", false}, + {"qcom,tethered-flow-control", false}, + {"qcom,use-rg10-limitation-mitigation", false}, + {"qcom,do-not-use-ch-gsi-20", false}, + {"qcom,use-ipa-pm", false}, +}; + +static struct dtsi_replacement_bool_table +ipa3_plat_drv_bool_table[] = { + { ipa3_plat_drv_bool_3_5_1, + ARRAY_SIZE(ipa3_plat_drv_bool_3_5_1) }, + { ipa3_plat_drv_bool_4_0, + ARRAY_SIZE(ipa3_plat_drv_bool_4_0) }, +}; + +static struct dtsi_replacement_u32 ipa3_plat_drv_u32_4_0[] = { + {"qcom,ipa-hw-ver", IPA_HW_v4_0}, + {"qcom,ipa-hw-mode", 3}, + {"qcom,wan-rx-ring-size", 192}, + {"qcom,lan-rx-ring-size", 192}, + {"qcom,ee", 0}, + {"emulator-bar0-offset", 0x01C00000}, +}; + +static struct dtsi_replacement_u32 ipa3_plat_drv_u32_3_5_1[] = { + {"qcom,ipa-hw-ver", IPA_HW_v3_5_1}, + {"qcom,ipa-hw-mode", 3}, + {"qcom,wan-rx-ring-size", 192}, + {"qcom,lan-rx-ring-size", 192}, + {"qcom,ee", 0}, + {"emulator-bar0-offset", 0x01C00000}, +}; + +static struct dtsi_replacement_u32_table ipa3_plat_drv_u32_table[] = { + { ipa3_plat_drv_u32_3_5_1, + ARRAY_SIZE(ipa3_plat_drv_u32_3_5_1) }, + { ipa3_plat_drv_u32_4_0, + ARRAY_SIZE(ipa3_plat_drv_u32_4_0) }, +}; + +static u32 mhi_event_ring_id_limits_array_4_0[] = { + 9, 10 +}; + +static u32 mhi_event_ring_id_limits_array_3_5_1[] = { + IPA_MHI_GSI_EVENT_RING_ID_START, IPA_MHI_GSI_EVENT_RING_ID_END +}; + +static u32 ipa_tz_unlock_reg_array_4_0[] = { + 0x04043583c, 0x00001000 +}; + +static u32 ipa_tz_unlock_reg_array_3_5_1[] = { + 0x04043583c, 0x00001000 +}; + +static u32 ipa_ram_mmap_array_4_0[] = { + 0x00000280, 0x00000000, 0x00000000, 0x00000288, 0x00000078, + 0x00004000, 0x00000308, 0x00000078, 0x00004000, 0x00000388, + 0x00000078, 0x00004000, 0x00000408, 0x00000078, 0x00004000, + 0x0000000F, 0x00000000, 0x00000007, 0x00000008, 0x0000000E, + 0x00000488, 0x00000078, 0x00004000, 0x00000508, 0x00000078, + 0x00004000, 0x0000000F, 0x00000000, 0x00000007, 0x00000008, + 0x0000000E, 0x00000588, 0x00000078, 0x00004000, 0x00000608, + 0x00000078, 0x00004000, 0x00000688, 0x00000140, 0x000007C8, + 0x00000000, 0x00000800, 0x000007D0, 0x00000200, 0x000009D0, + 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x000013F0, + 0x0000100C, 0x000023FC, 0x00000000, 0x000023FC, 0x00000000, + 0x000023FC, 0x00000000, 0x000023FC, 0x00000000, 0x00000080, + 0x00000200, 0x00002800, 0x000023FC, 0x00000000, 0x000023FC, + 0x00000000, 0x000023FC, 0x00000000, 0x000023FC, 0x00000000, + 0x00002400, 0x00000400, 0x00000BD8, 0x00000050, 0x00000C30, + 0x00000060, 0x00000C90, 0x00000140, 0x00000DD0, 0x00000180, + 0x00000F50, 0x00000180, 0x000010D0, 0x00000180, 0x00001250, + 0x00000180, 0x000013D0, 0x00000020 +}; + +static u32 ipa_ram_mmap_array_3_5_1[] = { + 0x00000280, 0x00000000, 0x00000000, 0x00000288, 0x00000078, + 0x00004000, 0x00000308, 0x00000078, 0x00004000, 0x00000388, + 0x00000078, 0x00004000, 0x00000408, 0x00000078, 0x00004000, + 0x0000000F, 0x00000000, 0x00000007, 0x00000008, 0x0000000E, + 0x00000488, 0x00000078, 0x00004000, 0x00000508, 0x00000078, + 0x00004000, 0x0000000F, 0x00000000, 0x00000007, 0x00000008, + 0x0000000E, 0x00000588, 0x00000078, 0x00004000, 0x00000608, + 0x00000078, 0x00004000, 0x00000688, 0x00000140, 0x000007C8, + 0x00000000, 0x00000800, 0x000007D0, 0x00000200, 0x000009D0, + 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x00000BD8, + 0x00001024, 0x00002000, 0x00000000, 0x00002000, 0x00000000, + 0x00002000, 0x00000000, 0x00002000, 0x00000000, 0x00000080, + 0x00000200, 0x00002000, 0x00002000, 0x00000000, 0x00002000, + 0x00000000, 0x00002000, 0x00000000, 0x00002000, 0x00000000, + 0x00001C00, 0x00000400 +}; + +struct dtsi_replacement_u32_array ipa3_plat_drv_u32_array_4_0[] = { + {"qcom,mhi-event-ring-id-limits", + mhi_event_ring_id_limits_array_4_0, + ARRAY_SIZE(mhi_event_ring_id_limits_array_4_0) }, + {"qcom,ipa-tz-unlock-reg", + ipa_tz_unlock_reg_array_4_0, + ARRAY_SIZE(ipa_tz_unlock_reg_array_4_0) }, + {"qcom,ipa-ram-mmap", + ipa_ram_mmap_array_4_0, + ARRAY_SIZE(ipa_ram_mmap_array_4_0) }, +}; + +struct dtsi_replacement_u32_array ipa3_plat_drv_u32_array_3_5_1[] = { + {"qcom,mhi-event-ring-id-limits", + mhi_event_ring_id_limits_array_3_5_1, + ARRAY_SIZE(mhi_event_ring_id_limits_array_3_5_1) }, + {"qcom,ipa-tz-unlock-reg", + ipa_tz_unlock_reg_array_3_5_1, + ARRAY_SIZE(ipa_tz_unlock_reg_array_3_5_1) }, + {"qcom,ipa-ram-mmap", + ipa_ram_mmap_array_3_5_1, + ARRAY_SIZE(ipa_ram_mmap_array_3_5_1) }, +}; + +struct dtsi_replacement_u32_array_table +ipa3_plat_drv_u32_array_table[] = { + { ipa3_plat_drv_u32_array_3_5_1, + ARRAY_SIZE(ipa3_plat_drv_u32_array_3_5_1) }, + { ipa3_plat_drv_u32_array_4_0, + ARRAY_SIZE(ipa3_plat_drv_u32_array_4_0) }, +}; + +#define INTCTRL_OFFSET 0x083C0000 +#define INTCTRL_SIZE 0x00000110 + +#define IPA_BASE_OFFSET_4_0 0x01e00000 +#define IPA_BASE_SIZE_4_0 0x00034000 +#define GSI_BASE_OFFSET_4_0 0x01e04000 +#define GSI_BASE_SIZE_4_0 0x00028000 + +struct resource ipa3_plat_drv_resource_4_0[] = { + /* + * PLEASE NOTE WELL: The following offset values below + * ("ipa-base", "gsi-base", and "intctrl-base") are used to + * calculate offsets relative to the PCI BAR0 address provided + * by the PCI probe. After their use to calculate the + * offsets, they are not used again, since PCI ultimately + * dictates where things live. + */ + { + IPA_BASE_OFFSET_4_0, + (IPA_BASE_OFFSET_4_0 + IPA_BASE_SIZE_4_0), + "ipa-base", + IORESOURCE_MEM, + 0, + NULL, + NULL, + NULL + }, + + { + GSI_BASE_OFFSET_4_0, + (GSI_BASE_OFFSET_4_0 + GSI_BASE_SIZE_4_0), + "gsi-base", + IORESOURCE_MEM, + 0, + NULL, + NULL, + NULL + }, + + /* + * The following entry is germane only to the emulator + * environment. It is needed to locate the emulator's PCI + * interrupt controller... + */ + { + INTCTRL_OFFSET, + (INTCTRL_OFFSET + INTCTRL_SIZE), + "intctrl-base", + IORESOURCE_MEM, + 0, + NULL, + NULL, + NULL + }, + + { + IPA_PIPE_MEM_START_OFST, + (IPA_PIPE_MEM_START_OFST + IPA_PIPE_MEM_SIZE), + "ipa-pipe-mem", + IORESOURCE_MEM, + 0, + NULL, + NULL, + NULL + }, + + { + 0, + 0, + "gsi-irq", + IORESOURCE_IRQ, + 0, + NULL, + NULL, + NULL + }, + + { + 0, + 0, + "ipa-irq", + IORESOURCE_IRQ, + 0, + NULL, + NULL, + NULL + }, +}; + +#define IPA_BASE_OFFSET_3_5_1 0x01e00000 +#define IPA_BASE_SIZE_3_5_1 0x00034000 +#define GSI_BASE_OFFSET_3_5_1 0x01e04000 +#define GSI_BASE_SIZE_3_5_1 0x0002c000 + +struct resource ipa3_plat_drv_resource_3_5_1[] = { + /* + * PLEASE NOTE WELL: The following offset values below + * ("ipa-base", "gsi-base", and "intctrl-base") are used to + * calculate offsets relative to the PCI BAR0 address provided + * by the PCI probe. After their use to calculate the + * offsets, they are not used again, since PCI ultimately + * dictates where things live. + */ + { + IPA_BASE_OFFSET_3_5_1, + (IPA_BASE_OFFSET_3_5_1 + IPA_BASE_SIZE_3_5_1), + "ipa-base", + IORESOURCE_MEM, + 0, + NULL, + NULL, + NULL + }, + + { + GSI_BASE_OFFSET_3_5_1, + (GSI_BASE_OFFSET_3_5_1 + GSI_BASE_SIZE_3_5_1), + "gsi-base", + IORESOURCE_MEM, + 0, + NULL, + NULL, + NULL + }, + + /* + * The following entry is germane only to the emulator + * environment. It is needed to locate the emulator's PCI + * interrupt controller... + */ + { + INTCTRL_OFFSET, + (INTCTRL_OFFSET + INTCTRL_SIZE), + "intctrl-base", + IORESOURCE_MEM, + 0, + NULL, + NULL, + NULL + }, + + { + IPA_PIPE_MEM_START_OFST, + (IPA_PIPE_MEM_START_OFST + IPA_PIPE_MEM_SIZE), + "ipa-pipe-mem", + IORESOURCE_MEM, + 0, + NULL, + NULL, + NULL + }, + + { + 0, + 0, + "gsi-irq", + IORESOURCE_IRQ, + 0, + NULL, + NULL, + NULL + }, + + { + 0, + 0, + "ipa-irq", + IORESOURCE_IRQ, + 0, + NULL, + NULL, + NULL + }, +}; + +struct dtsi_replacement_resource_table +ipa3_plat_drv_resource_table[] = { + { ipa3_plat_drv_resource_3_5_1, + ARRAY_SIZE(ipa3_plat_drv_resource_3_5_1) }, + { ipa3_plat_drv_resource_4_0, + ARRAY_SIZE(ipa3_plat_drv_resource_4_0) }, +}; + +/* + * The following code uses the data above... + */ +static u32 emulator_type_to_index(void) +{ + /* + * Use the input parameter to the IPA driver loadable module, + * which specifies the type of hardware the driver is running + * on. + */ + u32 index = DTSI_INDEX_4_0; + uint emulation_type = ipa3_get_emulation_type(); + + switch (emulation_type) { + case IPA_HW_v3_5_1: + index = DTSI_INDEX_3_5_1; + break; + case IPA_HW_v4_0: + index = DTSI_INDEX_4_0; + break; + default: + break; + } + + IPADBG("emulation_type(%u) emulation_index(%u)\n", + emulation_type, index); + + return index; +} + +/* From include/linux/of.h */ +/** + * emulator_of_property_read_bool - Find from a property + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device node. + * Returns true if the property exists false otherwise. + */ +bool emulator_of_property_read_bool( + const struct device_node *np, + const char *propname) +{ + u16 i; + u32 index; + struct dtsi_replacement_bool *ipa3_plat_drv_boolP; + + /* + * Get the index for the type of hardware we're running on. + * This is used as a table index. + */ + index = emulator_type_to_index(); + if (index >= ARRAY_SIZE(ipa3_plat_drv_bool_table)) { + IPADBG( + "Did not find ipa3_plat_drv_bool_table for index %u\n", + index); + return false; + } + + ipa3_plat_drv_boolP = + ipa3_plat_drv_bool_table[index].p_table; + + for (i = 0; + i < ipa3_plat_drv_bool_table[index].num_entries; + i++) { + if (strsame(ipa3_plat_drv_boolP[i].key, propname)) { + IPADBG( + "Found value %u for propname %s index %u\n", + ipa3_plat_drv_boolP[i].value, + propname, + index); + return ipa3_plat_drv_boolP[i].value; + } + } + + IPADBG("Did not find match for propname %s index %u\n", + propname, + index); + + return false; +} + +/* From include/linux/of.h */ +int emulator_of_property_read_u32( + const struct device_node *np, + const char *propname, + u32 *out_value) +{ + u16 i; + u32 index; + struct dtsi_replacement_u32 *ipa3_plat_drv_u32P; + + /* + * Get the index for the type of hardware we're running on. + * This is used as a table index. + */ + index = emulator_type_to_index(); + if (index >= ARRAY_SIZE(ipa3_plat_drv_u32_table)) { + IPADBG( + "Did not find ipa3_plat_drv_u32_table for index %u\n", + index); + return false; + } + + ipa3_plat_drv_u32P = + ipa3_plat_drv_u32_table[index].p_table; + + for (i = 0; + i < ipa3_plat_drv_u32_table[index].num_entries; + i++) { + if (strsame(ipa3_plat_drv_u32P[i].key, propname)) { + *out_value = ipa3_plat_drv_u32P[i].value; + IPADBG( + "Found value %u for propname %s index %u\n", + ipa3_plat_drv_u32P[i].value, + propname, + index); + return 0; + } + } + + IPADBG("Did not find match for propname %s index %u\n", + propname, + index); + + return -EINVAL; +} + +/* From include/linux/of.h */ +/** + * emulator_of_property_read_u32_array - Find and read an array of 32 + * bit integers from a property. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_values: pointer to return value, modified only if return value is 0. + * @sz: number of array elements to read + * + * Search for a property in a device node and read 32-bit value(s) from + * it. Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * The out_values is modified only if a valid u32 value can be decoded. + */ +int emulator_of_property_read_u32_array( + const struct device_node *np, + const char *propname, + u32 *out_values, + size_t sz) +{ + u16 i; + u32 index; + struct dtsi_replacement_u32_array *u32_arrayP; + + /* + * Get the index for the type of hardware we're running on. + * This is used as a table index. + */ + index = emulator_type_to_index(); + if (index >= ARRAY_SIZE(ipa3_plat_drv_u32_array_table)) { + IPADBG( + "Did not find ipa3_plat_drv_u32_array_table for index %u\n", + index); + return false; + } + + u32_arrayP = + ipa3_plat_drv_u32_array_table[index].p_table; + for (i = 0; + i < ipa3_plat_drv_u32_array_table[index].num_entries; + i++) { + if (strsame( + u32_arrayP[i].key, propname)) { + u32 num_elements = + u32_arrayP[i].num_elements; + u32 *p_element = + &u32_arrayP[i].p_value[0]; + size_t j = 0; + + if (num_elements > sz) { + IPAERR( + "Found array of %u values for propname %s; only room for %u elements in copy buffer\n", + num_elements, + propname, + (unsigned int) sz); + return -EOVERFLOW; + } + + while (j++ < num_elements) + *out_values++ = *p_element++; + + IPADBG( + "Found array of values starting with %u for propname %s index %u\n", + u32_arrayP[i].p_value[0], + propname, + index); + + return 0; + } + } + + IPADBG("Did not find match for propname %s index %u\n", + propname, + index); + + return -EINVAL; +} + +/* From drivers/base/platform.c */ +/** + * emulator_platform_get_resource_byname - get a resource for a device by name + * @dev: platform device + * @type: resource type + * @name: resource name + */ +struct resource *emulator_platform_get_resource_byname( + struct platform_device *dev, + unsigned int type, + const char *name) +{ + u16 i; + u32 index; + struct resource *ipa3_plat_drv_resourceP; + + /* + * Get the index for the type of hardware we're running on. + * This is used as a table index. + */ + index = emulator_type_to_index(); + if (index >= ARRAY_SIZE(ipa3_plat_drv_resource_table)) { + IPADBG( + "Did not find ipa3_plat_drv_resource_table for index %u\n", + index); + return false; + } + + ipa3_plat_drv_resourceP = + ipa3_plat_drv_resource_table[index].p_table; + for (i = 0; + i < ipa3_plat_drv_resource_table[index].num_entries; + i++) { + struct resource *r = &ipa3_plat_drv_resourceP[i]; + + if (type == resource_type(r) && strsame(r->name, name)) { + IPADBG( + "Found start 0x%x size %u for name %s index %u\n", + (unsigned int) (r->start), + (unsigned int) (resource_size(r)), + name, + index); + return r; + } + } + + IPADBG("Did not find match for name %s index %u\n", + name, + index); + + return NULL; +} + +/* From drivers/of/base.c */ +/** + * emulator_of_property_count_elems_of_size - Count the number of + * elements in a property + * + * @np: device node from which the property value is to + * be read. Not used. + * @propname: name of the property to be searched. + * @elem_size: size of the individual element + * + * Search for a property and count the number of elements of size + * elem_size in it. Returns number of elements on success, -EINVAL if + * the property does not exist or its length does not match a multiple + * of elem_size and -ENODATA if the property does not have a value. + */ +int emulator_of_property_count_elems_of_size( + const struct device_node *np, + const char *propname, + int elem_size) +{ + u32 index; + + /* + * Get the index for the type of hardware we're running on. + * This is used as a table index. + */ + index = emulator_type_to_index(); + + /* + * Use elem_size to determine which table to search for the + * specified property name + */ + if (elem_size == sizeof(u32)) { + u16 i; + struct dtsi_replacement_u32_array *u32_arrayP; + + if (index >= ARRAY_SIZE(ipa3_plat_drv_u32_array_table)) { + IPADBG( + "Did not find ipa3_plat_drv_u32_array_table for index %u\n", + index); + return false; + } + + u32_arrayP = + ipa3_plat_drv_u32_array_table[index].p_table; + + for (i = 0; + i < ipa3_plat_drv_u32_array_table[index].num_entries; + i++) { + if (strsame(u32_arrayP[i].key, propname)) { + if (u32_arrayP[i].p_value == NULL) { + IPADBG( + "Found no elements for propname %s index %u\n", + propname, + index); + return -ENODATA; + } + + IPADBG( + "Found %u elements for propname %s index %u\n", + u32_arrayP[i].num_elements, + propname, + index); + + return u32_arrayP[i].num_elements; + } + } + + IPADBG( + "Found no match in table with elem_size %d for propname %s index %u\n", + elem_size, + propname, + index); + + return -EINVAL; + } + + IPAERR( + "Found no tables with element size %u to search for propname %s index %u\n", + elem_size, + propname, + index); + + return -EINVAL; +} + +int emulator_of_property_read_variable_u32_array( + const struct device_node *np, + const char *propname, + u32 *out_values, + size_t sz_min, + size_t sz_max) +{ + return emulator_of_property_read_u32_array( + np, propname, out_values, sz_max); +} + +resource_size_t emulator_resource_size(const struct resource *res) +{ + return res->end - res->start; +} diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_emulation_stubs.h b/drivers/platform/msm/ipa/ipa_v3/ipa_emulation_stubs.h new file mode 100644 index 000000000000..c4cb81b68f59 --- /dev/null +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_emulation_stubs.h @@ -0,0 +1,128 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#if !defined(_IPA_EMULATION_STUBS_H_) +# define _IPA_EMULATION_STUBS_H_ + +# define outer_flush_range(x, y) +# define __flush_dcache_area(x, y) +# define __cpuc_flush_dcache_area(x, y) __flush_dcache_area(x, y) + +/* Point several API calls to these new EMULATION functions */ +# define of_property_read_bool(np, propname) \ + emulator_of_property_read_bool(NULL, propname) +# define of_property_read_u32(np, propname, out_value) \ + emulator_of_property_read_u32(NULL, propname, out_value) +# define of_property_read_u32_array(np, propname, out_values, sz) \ + emulator_of_property_read_u32_array(NULL, propname, out_values, sz) +# define platform_get_resource_byname(dev, type, name) \ + emulator_platform_get_resource_byname(NULL, type, name) +# define of_property_count_elems_of_size(np, propname, elem_size) \ + emulator_of_property_count_elems_of_size(NULL, propname, elem_size) +# define of_property_read_variable_u32_array( \ + np, propname, out_values, sz_min, sz_max) \ + emulator_of_property_read_variable_u32_array( \ + NULL, propname, out_values, sz_min, sz_max) +# define resource_size(res) \ + emulator_resource_size(res) + +/** + * emulator_of_property_read_bool - Findfrom a property + * @np: device node used to find the property value. (not used) + * @propname: name of the property to be searched. + * + * Search for a property in a device node. + * Returns true if the property exists false otherwise. + */ +bool emulator_of_property_read_bool( + const struct device_node *np, + const char *propname); + +int emulator_of_property_read_u32( + const struct device_node *np, + const char *propname, + u32 *out_value); + +/** + * emulator_of_property_read_u32_array - Find and read an array of 32 + * bit integers from a property. + * + * @np: device node used to find the property value. (not used) + * @propname: name of the property to be searched. + * @out_values: pointer to return value, modified only if return value is 0. + * @sz: number of array elements to read + * + * Search for a property in a device node and read 32-bit value(s) from + * it. Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * The out_values is modified only if a valid u32 value can be decoded. + */ +int emulator_of_property_read_u32_array( + const struct device_node *np, + const char *propname, + u32 *out_values, + size_t sz); + +/** + * emulator_platform_get_resource_byname - get a resource for a device + * by name + * + * @dev: platform device + * @type: resource type + * @name: resource name + */ +struct resource *emulator_platform_get_resource_byname( + struct platform_device *dev, + unsigned int type, + const char *name); + +/** + * emulator_of_property_count_elems_of_size - Count the number of + * elements in a property + * + * @np: device node used to find the property value. (not used) + * @propname: name of the property to be searched. + * @elem_size: size of the individual element + * + * Search for a property and count the number of elements of size + * elem_size in it. Returns number of elements on success, -EINVAL if + * the property does not exist or its length does not match a multiple + * of elem_size and -ENODATA if the property does not have a value. + */ +int emulator_of_property_count_elems_of_size( + const struct device_node *np, + const char *propname, + int elem_size); + +int emulator_of_property_read_variable_u32_array( + const struct device_node *np, + const char *propname, + u32 *out_values, + size_t sz_min, + size_t sz_max); + +resource_size_t emulator_resource_size( + const struct resource *res); + +static inline bool is_device_dma_coherent(struct device *dev) +{ + return false; +} + +static inline phys_addr_t qcom_smem_virt_to_phys(void *addr) +{ + return 0; +} + +#endif /* #if !defined(_IPA_EMULATION_STUBS_H_) */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index e0fa028257da..4dae8950a21a 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -220,6 +220,187 @@ enum { #define IPA_WDI_TX_DB_RES 7 #define IPA_WDI_MAX_RES 8 +#ifdef CONFIG_ARM64 +/* Outer caches unsupported on ARM64 platforms */ +# define outer_flush_range(x, y) +# define __cpuc_flush_dcache_area __flush_dcache_area +#endif + +#define IPA_SMP2P_SMEM_STATE_MASK 3 + + +#define IPA_SUMMING_THRESHOLD (0x10) +#define IPA_PIPE_MEM_START_OFST (0x0) +#define IPA_PIPE_MEM_SIZE (0x0) +#define IPA_MOBILE_AP_MODE(x) (x == IPA_MODE_MOBILE_AP_ETH || \ + x == IPA_MODE_MOBILE_AP_WAN || \ + x == IPA_MODE_MOBILE_AP_WLAN) +#define IPA_CNOC_CLK_RATE (75 * 1000 * 1000UL) +#define IPA_A5_MUX_HEADER_LENGTH (8) + +#define IPA_AGGR_MAX_STR_LENGTH (10) + +#define CLEANUP_TAG_PROCESS_TIMEOUT 500 + +#define IPA_AGGR_STR_IN_BYTES(str) \ + (strnlen((str), IPA_AGGR_MAX_STR_LENGTH - 1) + 1) + +#define IPA_TRANSPORT_PROD_TIMEOUT_MSEC 100 + +#define IPA3_ACTIVE_CLIENTS_TABLE_BUF_SIZE 2048 + +#define IPA3_ACTIVE_CLIENT_LOG_TYPE_EP 0 +#define IPA3_ACTIVE_CLIENT_LOG_TYPE_SIMPLE 1 +#define IPA3_ACTIVE_CLIENT_LOG_TYPE_RESOURCE 2 +#define IPA3_ACTIVE_CLIENT_LOG_TYPE_SPECIAL 3 + +#define IPA_MHI_GSI_EVENT_RING_ID_START 10 +#define IPA_MHI_GSI_EVENT_RING_ID_END 12 + +#define IPA_SMEM_SIZE (8 * 1024) + +#define IPA_GSI_CHANNEL_HALT_MIN_SLEEP 5000 +#define IPA_GSI_CHANNEL_HALT_MAX_SLEEP 10000 +#define IPA_GSI_CHANNEL_HALT_MAX_TRY 10 + +/* round addresses for closes page per SMMU requirements */ +#define IPA_SMMU_ROUND_TO_PAGE(iova, pa, size, iova_p, pa_p, size_p) \ + do { \ + (iova_p) = rounddown((iova), PAGE_SIZE); \ + (pa_p) = rounddown((pa), PAGE_SIZE); \ + (size_p) = roundup((size) + (pa) - (pa_p), PAGE_SIZE); \ + } while (0) + + +/* The relative location in /lib/firmware where the FWs will reside */ +#define IPA_FWS_PATH "ipa/ipa_fws.elf" +/* + * The following paths below are used when building the system for the + * emulation environment. + * + * As new hardware platforms are added into the emulation environment, + * please add the appropriate paths here for their firmwares. + */ +#define IPA_FWS_PATH_4_0 "ipa/4.0/ipa_fws.elf" +#define IPA_FWS_PATH_3_5_1 "ipa/3.5.1/ipa_fws.elf" + +#ifdef CONFIG_COMPAT +#define IPA_IOC_ADD_HDR32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ADD_HDR, \ + compat_uptr_t) +#define IPA_IOC_DEL_HDR32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_DEL_HDR, \ + compat_uptr_t) +#define IPA_IOC_ADD_RT_RULE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ADD_RT_RULE, \ + compat_uptr_t) +#define IPA_IOC_DEL_RT_RULE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_DEL_RT_RULE, \ + compat_uptr_t) +#define IPA_IOC_ADD_FLT_RULE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ADD_FLT_RULE, \ + compat_uptr_t) +#define IPA_IOC_DEL_FLT_RULE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_DEL_FLT_RULE, \ + compat_uptr_t) +#define IPA_IOC_GET_RT_TBL32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_GET_RT_TBL, \ + compat_uptr_t) +#define IPA_IOC_COPY_HDR32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_COPY_HDR, \ + compat_uptr_t) +#define IPA_IOC_QUERY_INTF32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_QUERY_INTF, \ + compat_uptr_t) +#define IPA_IOC_QUERY_INTF_TX_PROPS32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_QUERY_INTF_TX_PROPS, \ + compat_uptr_t) +#define IPA_IOC_QUERY_INTF_RX_PROPS32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_QUERY_INTF_RX_PROPS, \ + compat_uptr_t) +#define IPA_IOC_QUERY_INTF_EXT_PROPS32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_QUERY_INTF_EXT_PROPS, \ + compat_uptr_t) +#define IPA_IOC_GET_HDR32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_GET_HDR, \ + compat_uptr_t) +#define IPA_IOC_ALLOC_NAT_MEM32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ALLOC_NAT_MEM, \ + compat_uptr_t) +#define IPA_IOC_ALLOC_NAT_TABLE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ALLOC_NAT_TABLE, \ + compat_uptr_t) +#define IPA_IOC_ALLOC_IPV6CT_TABLE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ALLOC_IPV6CT_TABLE, \ + compat_uptr_t) +#define IPA_IOC_V4_INIT_NAT32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_V4_INIT_NAT, \ + compat_uptr_t) +#define IPA_IOC_INIT_IPV6CT_TABLE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_INIT_IPV6CT_TABLE, \ + compat_uptr_t) +#define IPA_IOC_TABLE_DMA_CMD32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_TABLE_DMA_CMD, \ + compat_uptr_t) +#define IPA_IOC_V4_DEL_NAT32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_V4_DEL_NAT, \ + compat_uptr_t) +#define IPA_IOC_DEL_NAT_TABLE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_DEL_NAT_TABLE, \ + compat_uptr_t) +#define IPA_IOC_DEL_IPV6CT_TABLE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_DEL_IPV6CT_TABLE, \ + compat_uptr_t) +#define IPA_IOC_NAT_MODIFY_PDN32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_NAT_MODIFY_PDN, \ + compat_uptr_t) +#define IPA_IOC_GET_NAT_OFFSET32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_GET_NAT_OFFSET, \ + compat_uptr_t) +#define IPA_IOC_PULL_MSG32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_PULL_MSG, \ + compat_uptr_t) +#define IPA_IOC_RM_ADD_DEPENDENCY32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_RM_ADD_DEPENDENCY, \ + compat_uptr_t) +#define IPA_IOC_RM_DEL_DEPENDENCY32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_RM_DEL_DEPENDENCY, \ + compat_uptr_t) +#define IPA_IOC_GENERATE_FLT_EQ32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_GENERATE_FLT_EQ, \ + compat_uptr_t) +#define IPA_IOC_QUERY_RT_TBL_INDEX32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_QUERY_RT_TBL_INDEX, \ + compat_uptr_t) +#define IPA_IOC_WRITE_QMAPID32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_WRITE_QMAPID, \ + compat_uptr_t) +#define IPA_IOC_MDFY_FLT_RULE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_MDFY_FLT_RULE, \ + compat_uptr_t) +#define IPA_IOC_NOTIFY_WAN_UPSTREAM_ROUTE_ADD32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_NOTIFY_WAN_UPSTREAM_ROUTE_ADD, \ + compat_uptr_t) +#define IPA_IOC_NOTIFY_WAN_UPSTREAM_ROUTE_DEL32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_NOTIFY_WAN_UPSTREAM_ROUTE_DEL, \ + compat_uptr_t) +#define IPA_IOC_NOTIFY_WAN_EMBMS_CONNECTED32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_NOTIFY_WAN_EMBMS_CONNECTED, \ + compat_uptr_t) +#define IPA_IOC_ADD_HDR_PROC_CTX32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ADD_HDR_PROC_CTX, \ + compat_uptr_t) +#define IPA_IOC_DEL_HDR_PROC_CTX32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_DEL_HDR_PROC_CTX, \ + compat_uptr_t) +#define IPA_IOC_MDFY_RT_RULE32 _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_MDFY_RT_RULE, \ + compat_uptr_t) +#endif /* #ifdef CONFIG_COMPAT */ + +#define IPA_TZ_UNLOCK_ATTRIBUTE 0x0C0311 +#define TZ_MEM_PROTECT_REGION_ID 0x10 + struct ipa3_active_client_htable_entry { struct hlist_node list; char id_string[IPA3_ACTIVE_CLIENTS_LOG_NAME_LEN]; @@ -934,11 +1115,13 @@ struct ipa3_ipv6ct_mem { * @IPA_HW_Normal: Regular IPA hardware * @IPA_HW_Virtual: IPA hardware supporting virtual memory allocation * @IPA_HW_PCIE: IPA hardware supporting memory allocation over PCIE Bridge + * @IPA_HW_Emulation: IPA emulation hardware */ enum ipa3_hw_mode { - IPA_HW_MODE_NORMAL = 0, - IPA_HW_MODE_VIRTUAL = 1, - IPA_HW_MODE_PCIE = 2 + IPA_HW_MODE_NORMAL = 0, + IPA_HW_MODE_VIRTUAL = 1, + IPA_HW_MODE_PCIE = 2, + IPA_HW_MODE_EMULATION = 3, }; enum ipa3_config_this_ep { @@ -1231,6 +1414,7 @@ struct ipa3_char_device_context { * @mode: IPA operating mode * @mmio: iomem * @ipa_wrapper_base: IPA wrapper base address + * @ipa_wrapper_size: size of the memory pointed to by ipa_wrapper_base * @hdr_tbl: IPA header table * @hdr_proc_ctx_tbl: IPA processing context table * @rt_tbl_set: list of routing tables each of which is a list of rules @@ -1450,6 +1634,9 @@ struct ipa3_plat_drv_res { u32 ipa_mem_size; u32 transport_mem_base; u32 transport_mem_size; + u32 emulator_intcntrlr_mem_base; + u32 emulator_intcntrlr_mem_size; + u32 emulator_irq; u32 ipa_irq; u32 transport_irq; u32 ipa_pipe_mem_start_ofst; @@ -2392,6 +2579,11 @@ void ipa3_inc_acquire_wakelock(void); void ipa3_dec_release_wakelock(void); int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base, enum gsi_ver); +int emulator_load_fws( + const struct firmware *firmware, + u32 transport_mem_base, + u32 transport_mem_size, + enum gsi_ver); int ipa3_register_ipa_ready_cb(void (*ipa_ready_cb)(void *), void *user_data); const char *ipa_hw_error_str(enum ipa3_hw_errors err_type); int ipa_gsi_ch20_wa(void); @@ -2418,4 +2610,9 @@ int ipa3_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info, u16 num_regs); void ipa3_init_imm_cmd_desc(struct ipa3_desc *desc, struct ipahal_imm_cmd_pyld *cmd_pyld); int ipa3_is_vlan_mode(enum ipa_vlan_ifaces iface, bool *res); +uint ipa3_get_emulation_type(void); +int ipa3_get_transport_info( + phys_addr_t *phys_addr_ptr, + unsigned long *size_ptr); +irq_handler_t ipa3_get_isr(void); #endif /* _IPA3_I_H_ */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c b/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c index f338b75797c3..e949670762bd 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c @@ -347,6 +347,12 @@ static irqreturn_t ipa3_isr(int irq, void *ctxt) ipa3_dec_client_disable_clks_no_block(&log_info); return IRQ_HANDLED; } + +irq_handler_t ipa3_get_isr(void) +{ + return ipa3_isr; +} + /** * ipa3_add_interrupt_handler() - Adds handler to an interrupt type * @interrupt: Interrupt type @@ -494,21 +500,35 @@ int ipa3_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev) return -ENOMEM; } - res = request_irq(ipa_irq, (irq_handler_t) ipa3_isr, - IRQF_TRIGGER_RISING, "ipa", ipa_dev); - if (res) { - IPAERR("fail to register IPA IRQ handler irq=%d\n", ipa_irq); - return -ENODEV; + /* + * NOTE: + * + * We'll only register an isr on non-emulator (ie. real UE) + * systems. + * + * On the emulator, emulator_soft_irq_isr() will be calling + * ipa3_isr, so hence, no isr registration here, and instead, + * we'll pass the address of ipa3_isr to the gsi layer where + * emulator interrupts are handled... + */ + if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION) { + res = request_irq(ipa_irq, (irq_handler_t) ipa3_isr, + IRQF_TRIGGER_RISING, "ipa", ipa_dev); + if (res) { + IPAERR( + "fail to register IPA IRQ handler irq=%d\n", + ipa_irq); + return -ENODEV; + } + IPADBG("IPA IRQ handler irq=%d registered\n", ipa_irq); + + res = enable_irq_wake(ipa_irq); + if (res) + IPAERR("fail to enable IPA IRQ wakeup irq=%d res=%d\n", + ipa_irq, res); + else + IPADBG("IPA IRQ wakeup enabled irq=%d\n", ipa_irq); } - IPADBG("IPA IRQ handler irq=%d registered\n", ipa_irq); - - res = enable_irq_wake(ipa_irq); - if (res) - IPAERR("fail to enable IPA IRQ wakeup irq=%d res=%d\n", - ipa_irq, res); - else - IPADBG("IPA IRQ wakeup enabled irq=%d\n", ipa_irq); - spin_lock_init(&suspend_wa_lock); return 0; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c index 5a29401114a8..40f16bf147b3 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c @@ -20,6 +20,13 @@ #include "ipahal/ipahal.h" #include "ipahal/ipahal_nat.h" +/* + * The following for adding code (ie. for EMULATION) not found on x86. + */ +#if defined(CONFIG_IPA_EMULATION) +# include "ipa_emulation_stubs.h" +#endif + #define IPA_NAT_PHYS_MEM_OFFSET 0 #define IPA_IPV6CT_PHYS_MEM_OFFSET 0 #define IPA_NAT_PHYS_MEM_SIZE IPA_RAM_NAT_SIZE diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h index 5fb9ebcda4ac..c431baacd527 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h @@ -433,7 +433,11 @@ static inline int ipa3_qmi_send_mhi_cleanup_request( return -EPERM; } -static inline int ipa3_wwan_set_modem_perf_profile(int throughput); +static inline int ipa3_wwan_set_modem_perf_profile( + int throughput) +{ + return -EPERM; +} static inline int ipa3_qmi_enable_per_client_stats( struct ipa_enable_per_client_stats_req_msg_v01 *req, struct ipa_enable_per_client_stats_resp_msg_v01 *resp) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index acbdd4daa4d1..3b02e8b766d0 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -24,6 +24,13 @@ #include "ipahal/ipahal_hw_stats.h" #include "../ipa_rm_i.h" +/* + * The following for adding code (ie. for EMULATION) not found on x86. + */ +#if defined(CONFIG_IPA_EMULATION) +# include "ipa_emulation_stubs.h" +#endif + #define IPA_V3_0_CLK_RATE_SVS2 (37.5 * 1000 * 1000UL) #define IPA_V3_0_CLK_RATE_SVS (75 * 1000 * 1000UL) #define IPA_V3_0_CLK_RATE_NOMINAL (150 * 1000 * 1000UL) @@ -3044,6 +3051,32 @@ enum ipa_client_type ipa3_get_client_mapping(int pipe_idx) return ipa3_ctx->ep[pipe_idx].client; } +/** + * ipa3_get_client_by_pipe() - return client type relative to pipe + * index + * @pipe_idx: IPA end-point number + * + * Return value: client type + */ +static enum ipa_client_type ipa3_get_client_by_pipe(int pipe_idx) +{ + int j = 0; + + for (j = 0; j < IPA_CLIENT_MAX; j++) { + const struct ipa_ep_configuration *iec_ptr = + &(ipa3_ep_mapping[ipa3_get_hw_type_index()][j]); + if (iec_ptr->valid && + iec_ptr->ipa_gsi_ep_info.ipa_ep_num == pipe_idx) + break; + } + + if (j == IPA_CLIENT_MAX) + IPADBG("Got to IPA_CLIENT_MAX (%d) while searching for (%d)\n", + j, pipe_idx); + + return j; +} + /** * ipa_init_ep_flt_bitmap() - Initialize the bitmap * that represents the End-points that supports filtering @@ -5725,7 +5758,8 @@ void ipa3_set_resorce_groups_min_max_limits(void) } /* move rx_hps resource group configuration from HLOS to TZ */ - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_1) { + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_1 && + ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION) { IPAERR("skip configuring ipa_rx_hps_clients from HLOS\n"); return; } @@ -6046,6 +6080,77 @@ static int ipa3_load_single_fw(const struct firmware *firmware, return 0; } +/** + * emulator_load_single_fw() - load firmware into emulator's memory + * + * @firmware: Structure which contains the FW data from the user space. + * @phdr: ELF program header + * @fw_base: memory location to which firmware should get loaded + * @offset_from_base: offset to start relative to fw_base + * + * Return value: 0 on success, negative otherwise + */ +static int emulator_load_single_fw( + const struct firmware *firmware, + const struct elf32_phdr *phdr, + void __iomem *fw_base, + uint32_t offset_from_base) +{ + int index; + uint32_t ofb; + const uint32_t *elf_data_ptr; + + IPADBG("firmware(%pK) phdr(%pK) fw_base(%pK) offset_from_base(0x%x)\n", + firmware, phdr, fw_base, offset_from_base); + + if (phdr->p_offset > firmware->size) { + IPAERR("Invalid ELF: offset=%u is beyond elf_size=%zu\n", + phdr->p_offset, firmware->size); + return -EINVAL; + } + if ((firmware->size - phdr->p_offset) < phdr->p_filesz) { + IPAERR("Invalid ELF: offset=%u filesz=%u elf_size=%zu\n", + phdr->p_offset, phdr->p_filesz, firmware->size); + return -EINVAL; + } + + if (phdr->p_memsz % sizeof(uint32_t)) { + IPAERR("FW mem size %u doesn't align to 32bit\n", + phdr->p_memsz); + return -EFAULT; + } + + if (phdr->p_filesz > phdr->p_memsz) { + IPAERR("FW image too big src_size=%u dst_size=%u\n", + phdr->p_filesz, phdr->p_memsz); + return -EFAULT; + } + + IPADBG("ELF: p_memsz(0x%x) p_filesz(0x%x) p_filesz/4(0x%x)\n", + (uint32_t) phdr->p_memsz, + (uint32_t) phdr->p_filesz, + (uint32_t) (phdr->p_filesz/sizeof(uint32_t))); + + /* Set the entire region to 0s */ + ofb = offset_from_base; + for (index = 0; index < phdr->p_memsz/sizeof(uint32_t); index++) { + writel_relaxed(0, fw_base + ofb); + ofb += sizeof(uint32_t); + } + + elf_data_ptr = (uint32_t *)(firmware->data + phdr->p_offset); + + /* Write the FW */ + ofb = offset_from_base; + for (index = 0; index < phdr->p_filesz/sizeof(uint32_t); index++) { + writel_relaxed(*elf_data_ptr, fw_base + ofb); + elf_data_ptr++; + ofb += sizeof(uint32_t); + } + + return 0; +} + /** * ipa3_load_fws() - Load the IPAv3 FWs into IPA&GSI SRAM. * @@ -6162,6 +6267,243 @@ int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base, return 0; } +/* + * The following needed for the EMULATION system. On a non-emulation + * system (ie. the real UE), this is functionality is done in the + * TZ... + */ +#define IPA_SPARE_REG_1_VAL (0xC0000805) + +static void ipa_gsi_setup_reg(void) +{ + u32 reg_val, start; + int i; + const struct ipa_gsi_ep_config *gsi_ep_info_cfg; + enum ipa_client_type type; + + IPADBG("Setting up registers in preparation for firmware download\n"); + + /* enable GSI interface */ + ipahal_write_reg(IPA_GSI_CONF, 1); + + /* + * Before configuring the FIFOs need to unset bit 30 in the + * spare register + */ + ipahal_write_reg(IPA_SPARE_REG_1, + (IPA_SPARE_REG_1_VAL & (~(1 << 30)))); + + /* setup IPA_ENDP_GSI_CFG_TLV_n reg */ + start = 0; + ipa3_ctx->ipa_num_pipes = ipa3_get_num_pipes(); + IPADBG("ipa_num_pipes=%u\n", ipa3_ctx->ipa_num_pipes); + + for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) { + type = ipa3_get_client_by_pipe(i); + gsi_ep_info_cfg = ipa3_get_gsi_ep_info(type); + IPADBG("for ep %d client is %d\n", i, type); + if (!gsi_ep_info_cfg) + continue; + IPADBG("Config is true"); + reg_val = (gsi_ep_info_cfg->ipa_if_tlv << 16) + start; + start += gsi_ep_info_cfg->ipa_if_tlv; + ipahal_write_reg_n(IPA_ENDP_GSI_CFG_TLV_n, i, reg_val); + } + + /* setup IPA_ENDP_GSI_CFG_AOS_n reg */ + start = 0; + for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) { + type = ipa3_get_client_by_pipe(i); + gsi_ep_info_cfg = ipa3_get_gsi_ep_info(type); + if (!gsi_ep_info_cfg) + continue; + reg_val = (gsi_ep_info_cfg->ipa_if_aos << 16) + start; + start += gsi_ep_info_cfg->ipa_if_aos; + ipahal_write_reg_n(IPA_ENDP_GSI_CFG_AOS_n, i, reg_val); + } + + /* setup IPA_ENDP_GSI_CFG1_n reg */ + for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) { + type = ipa3_get_client_by_pipe(i); + gsi_ep_info_cfg = ipa3_get_gsi_ep_info(type); + if (!gsi_ep_info_cfg) + continue; + reg_val = (1 << 16) + + ((u32)gsi_ep_info_cfg->ipa_gsi_chan_num << 8) + + gsi_ep_info_cfg->ee; + ipahal_write_reg_n(IPA_ENDP_GSI_CFG1_n, i, reg_val); + } + + /* + * Setup IPA_ENDP_GSI_CFG2_n reg: this register must be setup + * as last one + */ + for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) { + type = ipa3_get_client_by_pipe(i); + gsi_ep_info_cfg = ipa3_get_gsi_ep_info(type); + if (!gsi_ep_info_cfg) + continue; + reg_val = 1 << 31; + ipahal_write_reg_n(IPA_ENDP_GSI_CFG2_n, i, reg_val); + reg_val = 0; + ipahal_write_reg_n(IPA_ENDP_GSI_CFG2_n, i, reg_val); + } + + /* + * After configuring the FIFOs need to set bit 30 in the spare + * register + */ + ipahal_write_reg(IPA_SPARE_REG_1, + (IPA_SPARE_REG_1_VAL | (1 << 30))); +} + +/** + * emulator_load_fws() - Load the IPAv3 FWs into IPA&GSI SRAM. + * + * @firmware: Structure which contains the FW data from the user space. + * @transport_mem_base: Where to load + * @transport_mem_size: Space available to load into + * @gsi_ver: Version of the gsi + * + * Return value: 0 on success, negative otherwise + */ +int emulator_load_fws( + const struct firmware *firmware, + u32 transport_mem_base, + u32 transport_mem_size, + enum gsi_ver gsi_ver) +{ + const struct elf32_hdr *ehdr; + const struct elf32_phdr *phdr; + void __iomem *gsi_base; + uint32_t hps_seq_offs, dps_seq_offs; + unsigned long gsi_offset; + int rc; + + IPADBG("Loading firmware(%pK)\n", firmware); + + if (!firmware) { + IPAERR("firmware pointer passed to function is NULL\n"); + return -EINVAL; + } + + /* One program header per FW image: GSI, DPS and HPS */ + if (firmware->size < (sizeof(*ehdr) + 3 * sizeof(*phdr))) { + IPAERR( + "Missing ELF and Program headers firmware size=%zu\n", + firmware->size); + return -EINVAL; + } + + ehdr = (struct elf32_hdr *) firmware->data; + + ipa_assert_on(!ehdr); + + if (ehdr->e_phnum != 3) { + IPAERR("Unexpected number of ELF program headers\n"); + return -EINVAL; + } + + hps_seq_offs = ipahal_get_reg_ofst(IPA_HPS_SEQUENCER_FIRST); + dps_seq_offs = ipahal_get_reg_ofst(IPA_DPS_SEQUENCER_FIRST); + + /* + * Each ELF program header represents a FW image and contains: + * p_vaddr : The starting address to which the FW needs to loaded. + * p_memsz : The size of the IRAM (where the image loaded) + * p_filesz: The size of the FW image embedded inside the ELF + * p_offset: Absolute offset to the image from the head of the ELF + * + * NOTE WELL: On the emulation platform, the p_vaddr address + * is not relevant and is unused. This is because + * on the emulation platform, the registers' + * address location is mutable, since it's mapped + * in via a PCIe probe. Given this, it is the + * mapped address info that's used while p_vaddr is + * ignored. + */ + phdr = (struct elf32_phdr *)(firmware->data + sizeof(*ehdr)); + + phdr += 2; + + /* + * Attempt to load IPA HPS FW image + */ + if (phdr->p_memsz > ipahal_get_hps_img_mem_size()) { + IPAERR("Invalid IPA HPS img size memsz=%d dps_mem_size=%u\n", + phdr->p_memsz, ipahal_get_hps_img_mem_size()); + return -EINVAL; + } + IPADBG("Loading HPS FW\n"); + rc = emulator_load_single_fw( + firmware, phdr, ipa3_ctx->mmio, hps_seq_offs); + if (rc) + return rc; + IPADBG("Loading HPS FW complete\n"); + + --phdr; + + /* + * Attempt to load IPA DPS FW image + */ + if (phdr->p_memsz > ipahal_get_dps_img_mem_size()) { + IPAERR("Invalid IPA DPS img size memsz=%d dps_mem_size=%u\n", + phdr->p_memsz, ipahal_get_dps_img_mem_size()); + return -EINVAL; + } + IPADBG("Loading DPS FW\n"); + rc = emulator_load_single_fw( + firmware, phdr, ipa3_ctx->mmio, dps_seq_offs); + if (rc) + return rc; + IPADBG("Loading DPS FW complete\n"); + + /* + * Run gsi register setup which is normally done in TZ on + * non-EMULATION systems... + */ + ipa_gsi_setup_reg(); + + /* + * Map to the GSI base... + */ + gsi_base = ioremap_nocache(transport_mem_base, transport_mem_size); + + IPADBG("GSI base(0x%x) mapped to (%pK) with len (0x%x)\n", + transport_mem_base, + gsi_base, + transport_mem_size); + + if (!gsi_base) { + IPAERR("ioremap_nocache failed\n"); + return -EFAULT; + } + + --phdr; + + /* + * Attempt to load GSI FW image + */ + if (phdr->p_memsz > transport_mem_size) { + IPAERR( + "Invalid GSI FW img size memsz=%d transport_mem_size=%u\n", + phdr->p_memsz, transport_mem_size); + return -EINVAL; + } + IPADBG("Loading GSI FW\n"); + gsi_get_inst_ram_offset_and_size(&gsi_offset, NULL, gsi_ver); + rc = emulator_load_single_fw( + firmware, phdr, gsi_base, (uint32_t) gsi_offset); + iounmap(gsi_base); + if (rc) + return rc; + IPADBG("Loading GSI FW complete\n"); + + IPADBG("IPA FWs (GSI FW, DPS and HPS) loaded successfully\n"); + + return 0; +} + /** * ipa3_is_msm_device() - Is the running device a MSM or MDM? * Determine according to IPA version @@ -6258,4 +6600,3 @@ void ipa3_init_imm_cmd_desc(struct ipa3_desc *desc, desc->len = cmd_pyld->len; desc->type = IPA_IMM_CMD_DESC; } - diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c index 6ca88e8ced5f..4237e1f7a726 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include "ipahal.h" diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c index f60d7e7d96f3..79b43c376394 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c @@ -134,6 +134,11 @@ static const char *ipareg_name_to_str[IPA_REG_MAX] = { __stringify(IPA_FEC_ATTR_EE_n), __stringify(IPA_MBIM_DEAGGR_FEC_ATTR_EE_n), __stringify(IPA_GEN_DEAGGR_FEC_ATTR_EE_n), + __stringify(IPA_GSI_CONF), + __stringify(IPA_ENDP_GSI_CFG1_n), + __stringify(IPA_ENDP_GSI_CFG2_n), + __stringify(IPA_ENDP_GSI_CFG_AOS_n), + __stringify(IPA_ENDP_GSI_CFG_TLV_n), }; static void ipareg_construct_dummy(enum ipahal_reg_name reg, @@ -2080,6 +2085,21 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = { [IPA_HW_v3_5][IPA_COUNTER_CFG] = { ipareg_construct_counter_cfg, ipareg_parse_counter_cfg, 0x000001F0, 0, 0, 0, 0}, + [IPA_HW_v3_5][IPA_GSI_CONF] = { + ipareg_construct_dummy, ipareg_parse_dummy, + 0x00002790, 0x0, 0, 0, 0 }, + [IPA_HW_v3_5][IPA_ENDP_GSI_CFG1_n] = { + ipareg_construct_dummy, ipareg_parse_dummy, + 0x00002794, 0x4, 0, 0, 0 }, + [IPA_HW_v3_5][IPA_ENDP_GSI_CFG2_n] = { + ipareg_construct_dummy, ipareg_parse_dummy, + 0x00002A2C, 0x4, 0, 0, 0 }, + [IPA_HW_v3_5][IPA_ENDP_GSI_CFG_AOS_n] = { + ipareg_construct_dummy, ipareg_parse_dummy, + 0x000029A8, 0x4, 0, 0, 0 }, + [IPA_HW_v3_5][IPA_ENDP_GSI_CFG_TLV_n] = { + ipareg_construct_dummy, ipareg_parse_dummy, + 0x00002924, 0x4, 0, 0, 0 }, /* IPAv4.0 */ [IPA_HW_v4_0][IPA_IRQ_SUSPEND_INFO_EE_n] = { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h index 494a0d7cb5c6..825c2f3a57ac 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h @@ -135,6 +135,11 @@ enum ipahal_reg_name { IPA_FEC_ATTR_EE_n, IPA_MBIM_DEAGGR_FEC_ATTR_EE_n, IPA_GEN_DEAGGR_FEC_ATTR_EE_n, + IPA_GSI_CONF, + IPA_ENDP_GSI_CFG1_n, + IPA_ENDP_GSI_CFG2_n, + IPA_ENDP_GSI_CFG_AOS_n, + IPA_ENDP_GSI_CFG_TLV_n, IPA_REG_MAX, }; @@ -656,4 +661,3 @@ void ipahal_get_fltrt_hash_flush_valmask( struct ipahal_reg_valmask *valmask); #endif /* _IPAHAL_REG_H_ */ - diff --git a/drivers/platform/msm/ipa/test/ipa_test_mhi.c b/drivers/platform/msm/ipa/test/ipa_test_mhi.c index 755ed583894d..f0109e39aa57 100644 --- a/drivers/platform/msm/ipa/test/ipa_test_mhi.c +++ b/drivers/platform/msm/ipa/test/ipa_test_mhi.c @@ -327,6 +327,8 @@ struct ipa_test_mhi_context { u32 prod_hdl; u32 cons_hdl; u32 test_prod_hdl; + phys_addr_t transport_phys_addr; + unsigned long transport_size; }; static struct ipa_test_mhi_context *test_mhi_ctx; @@ -780,11 +782,6 @@ static int ipa_test_mhi_suite_setup(void **ppriv) IPA_UT_DBG("Start Setup\n"); - if (!gsi_ctx) { - IPA_UT_ERR("No GSI ctx\n"); - return -EINVAL; - } - if (!ipa3_ctx) { IPA_UT_ERR("No IPA ctx\n"); return -EINVAL; @@ -797,11 +794,20 @@ static int ipa_test_mhi_suite_setup(void **ppriv) return -ENOMEM; } - test_mhi_ctx->gsi_mmio = ioremap_nocache(gsi_ctx->per.phys_addr, - gsi_ctx->per.size); - if (!test_mhi_ctx) { + rc = ipa3_get_transport_info(&test_mhi_ctx->transport_phys_addr, + &test_mhi_ctx->transport_size); + if (rc != 0) { + IPA_UT_ERR("ipa3_get_transport_info() failed\n"); + rc = -EFAULT; + goto fail_free_ctx; + } + + test_mhi_ctx->gsi_mmio = + ioremap_nocache(test_mhi_ctx->transport_phys_addr, + test_mhi_ctx->transport_size); + if (!test_mhi_ctx->gsi_mmio) { IPA_UT_ERR("failed to remap GSI HW size=%lu\n", - gsi_ctx->per.size); + test_mhi_ctx->transport_size); rc = -EFAULT; goto fail_free_ctx; } @@ -1385,7 +1391,7 @@ static int ipa_mhi_test_q_transfer_re(struct ipa_mem_buffer *mmio, /* write value to event ring doorbell */ IPA_UT_LOG("DB to event 0x%llx: base %pa ofst 0x%x\n", p_events[event_ring_index].wp, - &(gsi_ctx->per.phys_addr), + &(test_mhi_ctx->transport_phys_addr), GSI_EE_n_EV_CH_k_DOORBELL_0_OFFS( event_ring_index + ipa3_ctx->mhi_evid_limits[0], 0)); iowrite32(p_events[event_ring_index].wp, @@ -1432,7 +1438,7 @@ static int ipa_mhi_test_q_transfer_re(struct ipa_mem_buffer *mmio, IPA_UT_LOG( "DB to channel 0x%llx: base %pa ofst 0x%x\n" , p_channels[channel_idx].wp - , &(gsi_ctx->per.phys_addr) + , &(test_mhi_ctx->transport_phys_addr) , GSI_EE_n_GSI_CH_k_DOORBELL_0_OFFS( channel_idx, 0)); iowrite32(p_channels[channel_idx].wp, @@ -3324,4 +3330,3 @@ IPA_UT_DEFINE_SUITE_START(mhi, "MHI for GSI", ipa_mhi_test_in_loop_channel_reset_ipa_holb, true, IPA_HW_v3_0, IPA_HW_MAX), } IPA_UT_DEFINE_SUITE_END(mhi); - diff --git a/drivers/platform/msm/ipa/test/ipa_ut_framework.c b/drivers/platform/msm/ipa/test/ipa_ut_framework.c index ed8d82b5a1fe..647b140723a1 100644 --- a/drivers/platform/msm/ipa/test/ipa_ut_framework.c +++ b/drivers/platform/msm/ipa/test/ipa_ut_framework.c @@ -1035,9 +1035,10 @@ static void ipa_ut_ipa_ready_cb(void *user_data) * If IPA driver already ready, continue initialization immediately. * if not, wait for IPA ready notification by IPA driver context */ -static int __init ipa_ut_module_init(void) +int __init ipa_ut_module_init(void) { - int ret; + int ret = 0; + bool init_framewok = true; IPA_UT_INFO("Loading IPA test module...\n"); @@ -1049,14 +1050,34 @@ static int __init ipa_ut_module_init(void) mutex_init(&ipa_ut_ctx->lock); if (!ipa_is_ready()) { + init_framewok = false; + IPA_UT_DBG("IPA driver not ready, registering callback\n"); + ret = ipa_register_ipa_ready_cb(ipa_ut_ipa_ready_cb, NULL); /* - * If we received -EEXIST, IPA has initialized. So we need - * to continue the initing process. + * If the call to ipa_register_ipa_ready_cb() above + * returns 0, this means that we've succeeded in + * queuing up a future call to ipa_ut_framework_init() + * and that the call to it will be made once the IPA + * becomes ready. If this is the case, the call to + * ipa_ut_framework_init() below need not be made. + * + * If the call to ipa_register_ipa_ready_cb() above + * returns -EEXIST, it means that during the call to + * ipa_register_ipa_ready_cb(), the IPA has become + * ready, and hence, no indirect call to + * ipa_ut_framework_init() will be made, so we need to + * call it ourselves below. + * + * If the call to ipa_register_ipa_ready_cb() above + * return something other than 0 or -EEXIST, that's a + * hard error. */ - if (ret != -EEXIST) { + if (ret == -EEXIST) { + init_framewok = true; + } else { if (ret) { IPA_UT_ERR("IPA CB reg failed - %d\n", ret); kfree(ipa_ut_ctx); @@ -1066,12 +1087,15 @@ static int __init ipa_ut_module_init(void) } } - ret = ipa_ut_framework_init(); - if (ret) { - IPA_UT_ERR("framework init failed\n"); - kfree(ipa_ut_ctx); - ipa_ut_ctx = NULL; + if (init_framewok) { + ret = ipa_ut_framework_init(); + if (ret) { + IPA_UT_ERR("framework init failed\n"); + kfree(ipa_ut_ctx); + ipa_ut_ctx = NULL; + } } + return ret; } @@ -1080,7 +1104,7 @@ static int __init ipa_ut_module_init(void) * * Destroys the Framework and removes its context */ -static void ipa_ut_module_exit(void) +void ipa_ut_module_exit(void) { IPA_UT_DBG("Entry\n"); @@ -1092,8 +1116,9 @@ static void ipa_ut_module_exit(void) ipa_ut_ctx = NULL; } +#if !defined(CONFIG_IPA_EMULATION) /* On real UE, we have a module */ module_init(ipa_ut_module_init); module_exit(ipa_ut_module_exit); - MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("IPA Unit Test module"); +#endif diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h index fad332bee3f8..32848f9abad5 100644 --- a/include/linux/msm_gsi.h +++ b/include/linux/msm_gsi.h @@ -12,6 +12,7 @@ #ifndef MSM_GSI_H #define MSM_GSI_H #include +#include enum gsi_ver { GSI_VER_ERR = 0, @@ -84,6 +85,9 @@ enum gsi_intr_type { * @irq: IRQ number * @phys_addr: physical address of GSI block * @size: register size of GSI block + * @emulator_intcntrlr_addr: the location of emulator's interrupt control block + * @emulator_intcntrlr_size: the sise of emulator_intcntrlr_addr + * @emulator_intcntrlr_client_isr: client's isr. Called by the emulator's isr * @mhi_er_id_limits_valid: valid flag for mhi_er_id_limits * @mhi_er_id_limits: MHI event ring start and end ids * @notify_cb: general notification callback @@ -109,6 +113,9 @@ struct gsi_per_props { unsigned int irq; phys_addr_t phys_addr; unsigned long size; + phys_addr_t emulator_intcntrlr_addr; + unsigned long emulator_intcntrlr_size; + irq_handler_t emulator_intcntrlr_client_isr; bool mhi_er_id_limits_valid; uint32_t mhi_er_id_limits[2]; void (*notify_cb)(struct gsi_per_notify *notify); @@ -1388,7 +1395,8 @@ static inline int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, return -GSI_STATUS_UNSUPPORTED_OP; } -static inline int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size) +static inline int gsi_enable_fw( + phys_addr_t gsi_base_addr, u32 gsi_size, enum gsi_ver ver) { return -GSI_STATUS_UNSUPPORTED_OP; } -- GitLab From 14fdbf0ff27494b3be241176b3c6efb6d5cc51ee Mon Sep 17 00:00:00 2001 From: Walter Yang Date: Fri, 12 Jan 2018 13:39:39 +0800 Subject: [PATCH 1281/1299] ASoC: wcd-dsp-mgr: add one WDSP signal for WDSP boot timeout Add one signal enum to indicate that it's the internal WDSP boot timeout case. Change-Id: I978745274f6f584cfd693cb5a34ace25cd92dac3 Signed-off-by: Walter Yang --- include/sound/wcd-dsp-mgr.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/sound/wcd-dsp-mgr.h b/include/sound/wcd-dsp-mgr.h index 68d9f8d928d0..52b52c4fc4c6 100644 --- a/include/sound/wcd-dsp-mgr.h +++ b/include/sound/wcd-dsp-mgr.h @@ -80,6 +80,7 @@ enum wdsp_signal { /* Software generated signal indicating debug dumps to be collected */ WDSP_DEBUG_DUMP, + WDSP_DEBUG_DUMP_INTERNAL, }; /* -- GitLab From 3d73bdfb7f4097c473455e643565ee02d3daf804 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Tue, 3 Jul 2018 20:44:07 +0530 Subject: [PATCH 1282/1299] ARM: dts: msm: Fix serial driver device tree node for qcs405 Use UART2 for serial logging instead of UART1 and update corresponding TLMM ping configuration. Change-Id: Iddfe65ad731a93861f5ab013258916c0de8fb0ae Signed-off-by: Avaneesh Kumar Dwivedi --- arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi | 31 ++++++++++++++------ arch/arm64/boot/dts/qcom/qcs405.dtsi | 13 ++++---- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi index 6582cd025fac..e53f43ca428e 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-pinctrl.dtsi @@ -14,7 +14,7 @@ &soc { tlmm: pinctrl@1000000 { compatible = "qcom,qcs405-pinctrl"; - reg = <0x1000000 0x300000>; + reg = <0x1000000 0x500000>; interrupts-extended = <&wakegic GIC_SPI 208 IRQ_TYPE_NONE>; gpio-controller; #gpio-cells = <2>; @@ -22,30 +22,43 @@ interrupt-parent = <&wakegpio>; #interrupt-cells = <2>; - pmx-uartconsole { - uart_console_active: uart_console_active { + blsp1_uart2_console { + blsp_uart_tx_a2_active: blsp_uart_tx_a2_active { mux { - pins = "gpio17", "gpio18"; - function = "blsp1_uart2"; + pins = "gpio17"; + function = "blsp_uart_tx_a2"; }; config { - pins = "gpio17", "gpio18"; + pins = "gpio17"; + drive-strength = <2>; + bias-disable; + }; + }; + + blsp_uart_rx_a2_active: blsp_uart_rx_a2_active { + mux { + pins = "gpio18"; + function = "blsp_uart_rx_a2"; + }; + + config { + pins = "gpio18"; drive-strength = <2>; bias-disable; }; }; - uart_console_sleep: uart_console_sleep { + blsp_uart_tx_rx_a2_sleep: blsp_uart_tx_rx_a2_sleep { mux { pins = "gpio17", "gpio18"; - function = "blsp1_uart2"; + function = "gpio"; }; config { pins = "gpio17", "gpio18"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; }; }; diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 3024a1a47da8..e658b0aaac47 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -348,14 +348,17 @@ status = "disabled"; }; - blsp1_uart1: serial@78b0000 { + blsp1_uart2_console: serial@78b1000 { compatible = "qcom,msm-uartdm", "qcom,msm-uartdm-v1.4"; - reg = <0x78b0000 0x200>; - interrupts = <0 108 0>; - - clocks = <&clock_gcc GCC_BLSP1_UART1_APPS_CLK>, + reg = <0x78b1000 0x200>; + interrupts = <0 118 0>; + clocks = <&clock_gcc GCC_BLSP1_UART2_APPS_CLK>, <&clock_gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&blsp_uart_tx_a2_active + &blsp_uart_rx_a2_active>; + pinctrl-1 = <&blsp_uart_tx_rx_a2_sleep>; status = "okay"; }; -- GitLab From bcc7933a5ad7b3a22db2d31f3fa4f27b8314fe6e Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Tue, 3 Jul 2018 21:31:56 +0530 Subject: [PATCH 1283/1299] defconfig: qcs405: Enable download and poweroff support in qcs405 Enable config options to compile in the power off driver and enable download mode feature. Change-Id: Ia2519c84c839fdf7a35160e35971d6422d224be8 Signed-off-by: Avaneesh Kumar Dwivedi --- arch/arm/configs/vendor/qcs405_defconfig | 3 +++ arch/arm64/configs/vendor/qcs405_defconfig | 2 ++ 2 files changed, 5 insertions(+) diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig index dda9bac15146..27ab2f3f794e 100644 --- a/arch/arm/configs/vendor/qcs405_defconfig +++ b/arch/arm/configs/vendor/qcs405_defconfig @@ -275,6 +275,9 @@ CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y CONFIG_PINCTRL_QCS405=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y CONFIG_GPIOLIB=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_QCOM=y +CONFIG_QCOM_DLOAD_MODE=y CONFIG_POWER_SUPPLY=y CONFIG_SMB1351_USB_CHARGER=y CONFIG_THERMAL=y diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig index 325e9d908d92..4948fd85833f 100644 --- a/arch/arm64/configs/vendor/qcs405_defconfig +++ b/arch/arm64/configs/vendor/qcs405_defconfig @@ -279,6 +279,8 @@ CONFIG_SLIMBUS=y CONFIG_SLIMBUS_MSM_NGD=y CONFIG_PINCTRL_QCS405=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_POWER_RESET_QCOM=y +CONFIG_QCOM_DLOAD_MODE=y CONFIG_SMB1351_USB_CHARGER=y CONFIG_THERMAL=y CONFIG_THERMAL_WRITABLE_TRIPS=y -- GitLab From 545a131319c3ccf14c920243e474246a26336c6e Mon Sep 17 00:00:00 2001 From: Vijaykumar Badiger Date: Thu, 5 Jul 2018 12:39:19 -0700 Subject: [PATCH 1284/1299] defconfig: rename automotive defconfig to sa8155 Rename automotive defconfig from sm8150-auto to sa8155. Change-Id: I160c93c1ec760a25d0e90d66c8f77344bb1e13b8 Signed-off-by: Vijaykumar Badiger --- .../vendor/{sm8150-auto-perf_defconfig => sa8155-perf_defconfig} | 0 .../configs/vendor/{sm8150-auto_defconfig => sa8155_defconfig} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename arch/arm64/configs/vendor/{sm8150-auto-perf_defconfig => sa8155-perf_defconfig} (100%) rename arch/arm64/configs/vendor/{sm8150-auto_defconfig => sa8155_defconfig} (100%) diff --git a/arch/arm64/configs/vendor/sm8150-auto-perf_defconfig b/arch/arm64/configs/vendor/sa8155-perf_defconfig similarity index 100% rename from arch/arm64/configs/vendor/sm8150-auto-perf_defconfig rename to arch/arm64/configs/vendor/sa8155-perf_defconfig diff --git a/arch/arm64/configs/vendor/sm8150-auto_defconfig b/arch/arm64/configs/vendor/sa8155_defconfig similarity index 100% rename from arch/arm64/configs/vendor/sm8150-auto_defconfig rename to arch/arm64/configs/vendor/sa8155_defconfig -- GitLab From 17933a7c8895d31c50b6b6d6d24ea62463f52b70 Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Thu, 5 Jul 2018 14:54:59 -0700 Subject: [PATCH 1285/1299] ARM: dts: msm: Disable ATOS for apps smmu for sm8150 The power collapsible TBUs could miss getting a reset signal, which would lead to incorrect behavior. This effects the ATOS functionality. Hence, disable it until a proper workaround is set in place. Change-Id: I50ed01406505638ac791ef9b9f728b62765213aa Signed-off-by: Sudarshan Rajagopalan --- arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi index ec9721f00de7..ed019eac9d88 100644 --- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi +++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sm8150-v2.dtsi @@ -72,6 +72,7 @@ qcom,skip-init; qcom,use-3-lvl-tables; qcom,no-asid-retention; + qcom,disable-atos; #global-interrupts = <1>; #size-cells = <1>; #address-cells = <1>; -- GitLab From 9b11918f3945d1a2d496569533dde65010779afd Mon Sep 17 00:00:00 2001 From: Srinivas Ramana Date: Fri, 6 Jul 2018 11:28:38 +0530 Subject: [PATCH 1286/1299] ARM: dts: msm: Remove CDP and MTP device tree files on sm6150 sm6150 does not have MTP and CDP platforms. Remove the device tree files corresponding to CDP and MTP. Change-Id: Idd1d77e3b209f83ee125e0169cf859b4600b7b9b Signed-off-by: Srinivas Ramana --- arch/arm64/boot/dts/qcom/Makefile | 6 ----- .../boot/dts/qcom/sm6150-cdp-overlay.dts | 25 ------------------- arch/arm64/boot/dts/qcom/sm6150-cdp.dts | 22 ---------------- .../boot/dts/qcom/sm6150-mtp-overlay.dts | 25 ------------------- arch/arm64/boot/dts/qcom/sm6150-mtp.dts | 22 ---------------- 5 files changed, 100 deletions(-) delete mode 100644 arch/arm64/boot/dts/qcom/sm6150-cdp-overlay.dts delete mode 100644 arch/arm64/boot/dts/qcom/sm6150-cdp.dts delete mode 100644 arch/arm64/boot/dts/qcom/sm6150-mtp-overlay.dts delete mode 100644 arch/arm64/boot/dts/qcom/sm6150-mtp.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index ee0aacda55d1..48755200f711 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -83,21 +83,15 @@ endif ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y) dtbo-$(CONFIG_ARCH_SM6150) += \ - sm6150-cdp-overlay.dtbo \ - sm6150-mtp-overlay.dtbo \ sm6150-rumi-overlay.dtbo \ sm6150-qrd-overlay.dtbo \ sm6150-idp-overlay.dtbo \ -sm6150-cdp-overlay.dtbo-base := sm6150.dtb -sm6150-mtp-overlay.dtbo-base := sm6150.dtb sm6150-rumi-overlay.dtbo-base := sm6150.dtb sm6150-qrd-overlay.dtbo-base := sm6150.dtb sm6150-idp-overlay.dtbo-base := sm6150.dtb else dtb-$(CONFIG_ARCH_SM6150) += sm6150-rumi.dtb \ - sm6150-mtp.dtb \ - sm6150-cdp.dtb \ sm6150-qrd.dtb \ sm6150-idp.dtb endif diff --git a/arch/arm64/boot/dts/qcom/sm6150-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sm6150-cdp-overlay.dts deleted file mode 100644 index 9ddfa9bbc06b..000000000000 --- a/arch/arm64/boot/dts/qcom/sm6150-cdp-overlay.dts +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/dts-v1/; -/plugin/; - -#include - -#include "sm6150-cdp.dtsi" - -/ { - model = "Qualcomm Technologies, Inc. SM6150 CDP"; - compatible = "qcom,sm6150-cdp", "qcom,sm6150", "qcom,cdp"; - qcom,msm-id = <355 0x0>; - qcom,board-id = <1 0>; -}; diff --git a/arch/arm64/boot/dts/qcom/sm6150-cdp.dts b/arch/arm64/boot/dts/qcom/sm6150-cdp.dts deleted file mode 100644 index 14c73223a7d9..000000000000 --- a/arch/arm64/boot/dts/qcom/sm6150-cdp.dts +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/dts-v1/; - -#include "sm6150.dtsi" -#include "sm6150-cdp.dtsi" - -/ { - model = "Qualcomm Technologies, Inc. SM6150 CDP"; - compatible = "qcom,sm6150-cdp", "qcom,sm6150", "qcom,cdp"; - qcom,board-id = <1 0>; -}; diff --git a/arch/arm64/boot/dts/qcom/sm6150-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sm6150-mtp-overlay.dts deleted file mode 100644 index b15202a05868..000000000000 --- a/arch/arm64/boot/dts/qcom/sm6150-mtp-overlay.dts +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/dts-v1/; -/plugin/; - -#include - -#include "sm6150-mtp.dtsi" - -/ { - model = "Qualcomm Technologies, Inc. SM6150 MTP"; - compatible = "qcom,sm6150-mtp", "qcom,sm6150", "qcom,mtp"; - qcom,msm-id = <355 0x0>; - qcom,board-id = <8 0>; -}; diff --git a/arch/arm64/boot/dts/qcom/sm6150-mtp.dts b/arch/arm64/boot/dts/qcom/sm6150-mtp.dts deleted file mode 100644 index a45cad060403..000000000000 --- a/arch/arm64/boot/dts/qcom/sm6150-mtp.dts +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/dts-v1/; - -#include "sm6150.dtsi" -#include "sm6150-mtp.dtsi" - -/ { - model = "Qualcomm Technologies, Inc. SM6150 MTP"; - compatible = "qcom,sm6150-mtp", "qcom,sm6150", "qcom,mtp"; - qcom,board-id = <8 0>; -}; -- GitLab From 4d9484ac7eb15715c7141f411a8052d9bcc036df Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Fri, 16 Mar 2018 19:47:48 +0530 Subject: [PATCH 1287/1299] msm: kgsl: Avoid duplicate entries in snapshot GMU related registers and debug bus blocks are duplicated in the gpu snapshot. Fix this by avoiding the duplicate dump in kgsl_device_snapshot(). a6xx_snapshot internally calls a6xx_snapshot_gmu to dump GMU state. Don't invoke a6xx_snapshot_gmu explicitly after a6xx_snapshot to avoid duplicate entries in snapshot. Change-Id: I03453f6ca1f4d706d9a6fe45d2e3be9954dd3db0 Signed-off-by: Akhil P Oommen --- drivers/gpu/msm/kgsl_snapshot.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c index 5e41611f7286..0ed17d859080 100644 --- a/drivers/gpu/msm/kgsl_snapshot.c +++ b/drivers/gpu/msm/kgsl_snapshot.c @@ -719,8 +719,6 @@ void kgsl_device_snapshot(struct kgsl_device *device, if (device->ftbl->snapshot) device->ftbl->snapshot(device, snapshot, context); - if (device->ftbl->snapshot_gmu) - device->ftbl->snapshot_gmu(device, snapshot); } /* -- GitLab From f082e945c9733e0b4b4effdece0b88c1e8639336 Mon Sep 17 00:00:00 2001 From: Saranya Chidura Date: Mon, 2 Jul 2018 14:42:01 +0530 Subject: [PATCH 1288/1299] ARM: dts: msm: fix the byte-cntr interrupt for qcs405 ETR Byte Counter interrupt port is updated for QCS405. Change-Id: I0f3e4978736e542208c5bd57575e117e10b8178d Signed-off-by: Saranya Chidura --- arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi b/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi index ddb3896cc986..f423a1dea89b 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-coresight.dtsi @@ -79,7 +79,7 @@ <&clock_rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "core_a_clk"; - interrupts = ; + interrupts = ; interrupt-names = "byte-cntr-irq"; port { -- GitLab From c8f6285cc078992c1eba1a2434ad2fbe5a6fd849 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Thu, 5 Jul 2018 17:08:28 +0530 Subject: [PATCH 1289/1299] usb: phy: Fix deadlock because of mutex recursion The driver acquires the lock on same mutex twice in the DP DM regulator enable and disable call. Fix this my removing the mutex_lock and unlock from dpdm_regulator enable and disable calls. Change-Id: Ib60c870a5026eac27d872161b22fc3f7f9605fc4 Signed-off-by: Sriharsha Allenki --- drivers/usb/phy/phy-qcom-snps-28nm-hs.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/phy/phy-qcom-snps-28nm-hs.c b/drivers/usb/phy/phy-qcom-snps-28nm-hs.c index be1cc29da670..f6540313a9a7 100644 --- a/drivers/usb/phy/phy-qcom-snps-28nm-hs.c +++ b/drivers/usb/phy/phy-qcom-snps-28nm-hs.c @@ -426,17 +426,14 @@ static int msm_snps_dpdm_regulator_enable(struct regulator_dev *rdev) int ret = 0; struct msm_snps_hsphy *phy = rdev_get_drvdata(rdev); - mutex_lock(&phy->phy_lock); if (phy->dpdm_enable) { dev_dbg(phy->phy.dev, "%s: DP DM regulator already enabled\n", __func__); - mutex_unlock(&phy->phy_lock); return 0; } msm_snps_hsphy_enable_regulators(phy); phy->dpdm_enable = true; - mutex_unlock(&phy->phy_lock); return ret; } @@ -446,17 +443,14 @@ static int msm_snps_dpdm_regulator_disable(struct regulator_dev *rdev) int ret = 0; struct msm_snps_hsphy *phy = rdev_get_drvdata(rdev); - mutex_lock(&phy->phy_lock); if (!phy->dpdm_enable) { dev_dbg(phy->phy.dev, "%s: DP DM regulator already enabled\n", __func__); - mutex_unlock(&phy->phy_lock); return 0; } msm_snps_hsphy_disable_regulators(phy); phy->dpdm_enable = false; - mutex_unlock(&phy->phy_lock); return ret; } -- GitLab From 34948992c0a8f295bd2d4658136d2542ecc8bdce Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Tue, 26 Jun 2018 12:53:05 +0800 Subject: [PATCH 1290/1299] usb: misc: Add USB super speed re-driver support for QRD8150 Due to USB sub board design on QRD8150, we use TypeC redrive chipset to improve signal quality for USB3.1 Gen2 up to 10Gbps. Different board level designs may need to use different parameters, so expose four interfaces under /sys/kerne/debug for the tuning, that is eq, flat_gain, output_comp and loss_match. Change-Id: Ia662fec69063cb676b0511486d09b4cffa57e25a Signed-off-by: Liangliang Lu --- .../bindings/usb/onsemi_redriver.txt | 29 + drivers/usb/misc/Kconfig | 6 + drivers/usb/misc/Makefile | 1 + drivers/usb/misc/ssusb-redriver-nb7vpq904m.c | 1079 +++++++++++++++++ 4 files changed, 1115 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/onsemi_redriver.txt create mode 100644 drivers/usb/misc/ssusb-redriver-nb7vpq904m.c diff --git a/Documentation/devicetree/bindings/usb/onsemi_redriver.txt b/Documentation/devicetree/bindings/usb/onsemi_redriver.txt new file mode 100644 index 000000000000..3b3f1c0e130c --- /dev/null +++ b/Documentation/devicetree/bindings/usb/onsemi_redriver.txt @@ -0,0 +1,29 @@ +ON Semiconductor USB Type-C and display port 10Gbps Linear Re-Driver + +Required properties: +- compatible: Must be "onnn,redriver". +- reg: I2C address on the selected bus. +- extcon: phandles to external connector devices. The first phandle + should point to the external connector which provides + both "USB" cable events and "USB-HOST" cable events. + An optional second phandle may be specified for DP + lane events. + +Optional properties: +- eq: Equalization value of re-driver channel A/B/C/D, 8 bit. +- flat-gain: Flat gain control value of re-driver channel A/B/C/D, 8 bit. +- output-comp: Output compression value of re-driver channel A/B/C/D, + 8 bit. +- loss-match: Loss profile matching control value of re-driver channel + A/B/C/D, 8 bit. + +Example: + redriver@19 { + compatible = "onnn,redriver"; + reg = <0x19>; + extcon = <&pm8150b_pdphy>, <&pm8150b_pdphy>; + eq = /bits/ 8 <0x5 0x4 0x4 0x5>; + flat-gain = /bits/ 8 <0x3 0x1 0x1 0x3>; + output-comp = /bits/ 8 <0x2 0x2 0x2 0x2>; + loss-match = /bits/ 8 <0x0 0x3 0x3 0x0>; + }; diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 0f9f25db9163..740db57464fc 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -275,3 +275,9 @@ config USB_CHAOSKEY To compile this driver as a module, choose M here: the module will be called chaoskey. + +config USB_REDRIVER_NB7VPQ904M + tristate "USB 3.1 Gen1/Gen2 10Gbps re-driver driver for NB7VPQ904M" + depends on USB_PHY + help + Say Y here if you want to support USB super speed re-driver NB7VPQ904M. diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 109f54f5b9aa..4f7d20242470 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -31,3 +31,4 @@ obj-$(CONFIG_USB_CHAOSKEY) += chaoskey.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ obj-$(CONFIG_USB_LINK_LAYER_TEST) += lvstest.o +obj-$(CONFIG_USB_REDRIVER_NB7VPQ904M) += ssusb-redriver-nb7vpq904m.o diff --git a/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c b/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c new file mode 100644 index 000000000000..df69da4a697d --- /dev/null +++ b/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c @@ -0,0 +1,1079 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* priority: INT_MAX >= x >= 0 */ +#define NOTIFIER_PRIORITY 1 + +/* Registers Address */ +#define GEN_DEV_SET_REG 0x00 +#define CHIP_VERSION_REG 0x17 + +#define REDRIVER_REG_MAX 0x1f + +#define EQ_SET_REG_BASE 0x01 +#define FLAT_GAIN_REG_BASE 0x18 +#define OUT_COMP_AND_POL_REG_BASE 0x02 +#define LOSS_MATCH_REG_BASE 0x19 + +/* Default Register Value */ +#define GEN_DEV_SET_REG_DEFAULT 0xFB + +/* Register bits */ +/* General Device Settings Register Bits */ +#define CHIP_EN BIT(0) +#define CHNA_EN BIT(4) +#define CHNB_EN BIT(5) +#define CHNC_EN BIT(6) +#define CHND_EN BIT(7) + +#define CHANNEL_NUM 4 + +#define OP_MODE_SHIFT 1 + +#define EQ_SETTING_MASK 0x07 +#define OUTPUT_COMPRESSION_MASK 0x03 +#define LOSS_MATCH_MASK 0x03 +#define FLAT_GAIN_MASK 0x03 + +#define EQ_SETTING_SHIFT 0x01 +#define OUTPUT_COMPRESSION_SHIFT 0x01 +#define LOSS_MATCH_SHIFT 0x00 +#define FLAT_GAIN_SHIFT 0x00 + +/* for type c cable */ +enum plug_orientation { + ORIENTATION_NONE, + ORIENTATION_CC1, + ORIENTATION_CC2, +}; + +/* + * Three Modes of Operations: + * - One/Two ports of USB 3.1 Gen1/Gen2 (Default Mode) + * - Two lanes of DisplayPort 1.4 + One port of USB 3.1 Gen1/Gen2 + * - Four lanes of DisplayPort 1.4 + */ +enum operation_mode { + OP_MODE_USB, /* One/Two ports of USB */ + OP_MODE_DP, /* DP 4 Lane and DP 2 Lane */ + OP_MODE_USB_AND_DP, /* One port of USB and DP 2 Lane */ +}; + +/** + * struct ssusb_redriver - representation of USB re-driver + * @dev: struct device pointer + * @regmap: used for I2C communication on accessing registers + * @client: i2c client structure pointer + * @config_work: used to configure re-driver + * @redriver_wq: work queue used for @config_work + * @usb_psy: structure that holds USB power supply status + * @host_active: used to indicate USB host mode is enabled or not + * @vbus_active: used to indicate USB device mode is enabled or not + * @is_usb3: used to indicate USB3 or not + * @typec_orientation: used to inditate Type C orientation + * @op_mode: used to store re-driver operation mode + * @extcon_usb: external connector used for USB host/device mode + * @extcon_dp: external connector used for DP + * @vbus_nb: used for vbus event reception + * @id_nb: used for id event reception + * @dp_nb: used for DP event reception + * @panic_nb: used for panic event reception + * @eq: equalization register value + * @output_comp: output compression register value + * @loss_match: loss profile matching control register value + * @flat_gain: flat gain control register value + * @debug_root: debugfs entry for this context + */ +struct ssusb_redriver { + struct device *dev; + struct regmap *regmap; + struct i2c_client *client; + + struct work_struct config_work; + struct workqueue_struct *redriver_wq; + + struct power_supply *usb_psy; + bool host_active; + bool vbus_active; + bool is_usb3; + enum plug_orientation typec_orientation; + enum operation_mode op_mode; + + struct extcon_dev *extcon_usb; + struct extcon_dev *extcon_dp; + struct notifier_block vbus_nb; + struct notifier_block id_nb; + struct notifier_block dp_nb; + + struct notifier_block panic_nb; + + u8 eq[CHANNEL_NUM]; + u8 output_comp[CHANNEL_NUM]; + u8 loss_match[CHANNEL_NUM]; + u8 flat_gain[CHANNEL_NUM]; + + struct dentry *debug_root; +}; + +static void ssusb_redriver_debugfs_entries(struct ssusb_redriver *redriver); + +static int redriver_i2c_reg_get(struct ssusb_redriver *redriver, + u8 reg, u8 *val) +{ + int ret; + unsigned int val_tmp; + + ret = regmap_read(redriver->regmap, (unsigned int)reg, &val_tmp); + if (ret < 0) { + dev_err(redriver->dev, "reading reg 0x%02x failure\n", reg); + return ret; + } + + *val = (u8)val_tmp; + + dev_dbg(redriver->dev, "reading reg 0x%02x=0x%02x\n", reg, *val); + + return 0; +} + +static int redriver_i2c_reg_set(struct ssusb_redriver *redriver, + u8 reg, u8 val) +{ + int ret; + + ret = regmap_write(redriver->regmap, (unsigned int)reg, + (unsigned int)val); + if (ret < 0) { + dev_err(redriver->dev, "writing reg 0x%02x failure\n", reg); + return ret; + } + + dev_dbg(redriver->dev, "writing reg 0x%02x=0x%02x\n", reg, val); + + return 0; +} + +/** + * Handle Re-driver chip operation mode and channel settings. + * + * Three Modes of Operations: + * - One/Two ports of USB 3.1 Gen1/Gen2 (Default Mode) + * - Two lanes of DisplayPort 1.4 + One port of USB 3.1 Gen1/Gen2 + * - Four lanes of DisplayPort 1.4 + * + * @redriver - contain redriver status + * @on - re-driver chip enable or not + */ +static void ssusb_redriver_gen_dev_set( + struct ssusb_redriver *redriver, bool on) +{ + int ret; + u8 val; + + val = 0; + + switch (redriver->op_mode) { + case OP_MODE_USB: + /* Use source side I/O mapping */ + if (redriver->typec_orientation + == ORIENTATION_CC1) { + /* Enable channel C and D */ + val &= ~(CHNA_EN | CHNB_EN); + val |= (CHNC_EN | CHND_EN); + } else if (redriver->typec_orientation + == ORIENTATION_CC2) { + /* Enable channel A and B*/ + val |= (CHNA_EN | CHNB_EN); + val &= ~(CHNC_EN | CHND_EN); + } else { + /* Enable channel A, B, C and D */ + val |= (CHNA_EN | CHNB_EN); + val |= (CHNC_EN | CHND_EN); + } + + /* Set to default USB Mode */ + val |= (0x5 << OP_MODE_SHIFT); + + break; + case OP_MODE_DP: + /* Enable channel A, B, C and D */ + val |= (CHNA_EN | CHNB_EN); + val |= (CHNC_EN | CHND_EN); + + /* Set to DP 4 Lane Mode (OP Mode 2) */ + val |= (0x2 << OP_MODE_SHIFT); + + break; + case OP_MODE_USB_AND_DP: + /* Enable channel A, B, C and D */ + val |= (CHNA_EN | CHNB_EN); + val |= (CHNC_EN | CHND_EN); + + if (redriver->typec_orientation + == ORIENTATION_CC1) + /* Set to DP 4 Lane Mode (OP Mode 1) */ + val |= (0x1 << OP_MODE_SHIFT); + else if (redriver->typec_orientation + == ORIENTATION_CC2) + /* Set to DP 4 Lane Mode (OP Mode 0) */ + val |= (0x0 << OP_MODE_SHIFT); + else { + dev_err(redriver->dev, + "can't get orientation, op mode %d\n", + redriver->op_mode); + goto err_exit; + } + + break; + default: + dev_err(redriver->dev, + "Error: op mode: %d, vbus: %d, host: %d.\n", + redriver->op_mode, redriver->vbus_active, + redriver->host_active); + goto err_exit; + } + + /* exit/enter deep-sleep power mode */ + if (on) + val |= CHIP_EN; + else + val &= ~CHIP_EN; + + ret = redriver_i2c_reg_set(redriver, GEN_DEV_SET_REG, val); + if (ret < 0) + goto err_exit; + + dev_dbg(redriver->dev, + "successfully (%s) the redriver chip, reg 0x00 = 0x%x\n", + on ? "ENABLE":"DISABLE", val); + + return; + +err_exit: + dev_err(redriver->dev, + "failure to (%s) the redriver chip, reg 0x00 = 0x%x\n", + on ? "ENABLE":"DISABLE", val); +} + +static void ssusb_redriver_config_work(struct work_struct *w) +{ + struct ssusb_redriver *redriver = container_of(w, + struct ssusb_redriver, config_work); + struct extcon_dev *edev = NULL; + union extcon_property_value val; + unsigned int extcon_id = EXTCON_NONE; + int ret = 0; + + dev_dbg(redriver->dev, "%s: USB SS redriver config work\n", + __func__); + + edev = redriver->extcon_usb; + + if (redriver->vbus_active) + extcon_id = EXTCON_USB; + else if (redriver->host_active) + extcon_id = EXTCON_USB_HOST; + + if (edev && (extcon_id != EXTCON_NONE) + && extcon_get_state(edev, extcon_id)) { + ret = extcon_get_property(edev, extcon_id, + EXTCON_PROP_USB_SS, &val); + if (!ret) { + redriver->is_usb3 = (val.intval != 0); + + dev_dbg(redriver->dev, "SS Lane is used? [%s].\n", + redriver->is_usb3 ? "true" : "false"); + } else { + redriver->is_usb3 = true; + + dev_dbg(redriver->dev, "Default true as speed isn't reported.\n"); + } + + if (redriver->is_usb3 || (redriver->op_mode != OP_MODE_USB)) { + ret = extcon_get_property(edev, extcon_id, + EXTCON_PROP_USB_TYPEC_POLARITY, &val); + if (!ret) + redriver->typec_orientation = val.intval ? + ORIENTATION_CC2 : ORIENTATION_CC1; + else if (redriver->op_mode == OP_MODE_USB) + redriver->typec_orientation = ORIENTATION_NONE; + else + dev_err(redriver->dev, "fail to get orientation when has DP.\n"); + + ssusb_redriver_gen_dev_set(redriver, true); + } else { + dev_dbg(redriver->dev, + "Disable chip when not in SS USB mode.\n"); + + ssusb_redriver_gen_dev_set(redriver, false); + } + + dev_dbg(redriver->dev, "Type C orientation code is %d.\n", + redriver->typec_orientation); + } else { + dev_dbg(redriver->dev, "USB Cable is disconnected.\n"); + + /* Set back to USB only mode when cable disconnect */ + redriver->op_mode = OP_MODE_USB; + + ssusb_redriver_gen_dev_set(redriver, false); + } +} + +static int ssusb_redriver_dp_notifier(struct notifier_block *nb, + unsigned long dp_lane, void *ptr) +{ + struct ssusb_redriver *redriver = container_of(nb, + struct ssusb_redriver, dp_nb); + enum operation_mode op_mode; + + dev_dbg(redriver->dev, + "redriver op mode change: %ld event received\n", dp_lane); + + if (dp_lane == 0) + op_mode = OP_MODE_USB; + else if (dp_lane == 2) + op_mode = OP_MODE_USB_AND_DP; + else if (dp_lane == 4) + op_mode = OP_MODE_DP; + else + return 0; + + if (redriver->op_mode == op_mode) + return 0; + + redriver->op_mode = op_mode; + + queue_work(redriver->redriver_wq, &redriver->config_work); + + return 0; +} + +static int ssusb_redriver_vbus_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct ssusb_redriver *redriver = container_of(nb, + struct ssusb_redriver, vbus_nb); + + dev_dbg(redriver->dev, "vbus:%ld event received\n", event); + + if (redriver->vbus_active == event) + return NOTIFY_DONE; + + redriver->vbus_active = event; + + if (redriver->vbus_active) + queue_work(redriver->redriver_wq, &redriver->config_work); + + return NOTIFY_DONE; +} + +static int ssusb_redriver_id_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct ssusb_redriver *redriver = container_of(nb, + struct ssusb_redriver, id_nb); + bool host_active = (bool)event; + + dev_dbg(redriver->dev, "host_active:%s event received\n", + host_active ? "true" : "false"); + + if (redriver->host_active == host_active) + return NOTIFY_DONE; + + redriver->host_active = host_active; + + if (redriver->host_active) + queue_work(redriver->redriver_wq, &redriver->config_work); + + return NOTIFY_DONE; +} + +static int ssusb_redriver_extcon_register(struct ssusb_redriver *redriver) +{ + struct device_node *node = redriver->dev->of_node; + struct extcon_dev *edev; + int ret = 0; + + if (!of_find_property(node, "extcon", NULL)) { + dev_err(redriver->dev, "failed to get extcon for redriver\n"); + return 0; + } + + edev = extcon_get_edev_by_phandle(redriver->dev, 0); + if (IS_ERR(edev) && PTR_ERR(edev) != -ENODEV) { + dev_err(redriver->dev, "failed to get phandle for redriver\n"); + return PTR_ERR(edev); + } + + if (!IS_ERR(edev)) { + redriver->extcon_usb = edev; + + redriver->vbus_nb.notifier_call = ssusb_redriver_vbus_notifier; + redriver->vbus_nb.priority = NOTIFIER_PRIORITY; + ret = extcon_register_notifier(edev, EXTCON_USB, + &redriver->vbus_nb); + if (ret < 0) { + dev_err(redriver->dev, + "failed to register notifier for redriver\n"); + return ret; + } + + redriver->id_nb.notifier_call = ssusb_redriver_id_notifier; + redriver->id_nb.priority = NOTIFIER_PRIORITY; + ret = extcon_register_notifier(edev, EXTCON_USB_HOST, + &redriver->id_nb); + if (ret < 0) { + dev_err(redriver->dev, + "failed to register notifier for USB-HOST\n"); + goto err; + } + } + + edev = NULL; + /* Use optional phandle (index 1) for DP lane events */ + if (of_count_phandle_with_args(node, "extcon", NULL) > 1) { + edev = extcon_get_edev_by_phandle(redriver->dev, 1); + if (IS_ERR(edev) && PTR_ERR(edev) != -ENODEV) { + ret = PTR_ERR(edev); + goto err1; + } + } + + if (!IS_ERR_OR_NULL(edev)) { + redriver->extcon_dp = edev; + redriver->dp_nb.notifier_call = + ssusb_redriver_dp_notifier; + redriver->dp_nb.priority = NOTIFIER_PRIORITY; + ret = extcon_register_blocking_notifier(edev, EXTCON_DISP_DP, + &redriver->dp_nb); + if (ret < 0) { + dev_err(redriver->dev, + "failed to register blocking notifier\n"); + goto err1; + } + } + + /* Update initial VBUS/ID state from extcon */ + if (extcon_get_state(redriver->extcon_usb, EXTCON_USB)) + ssusb_redriver_vbus_notifier(&redriver->vbus_nb, true, + redriver->extcon_usb); + else if (extcon_get_state(redriver->extcon_usb, EXTCON_USB_HOST)) + ssusb_redriver_id_notifier(&redriver->id_nb, true, + redriver->extcon_usb); + + return 0; + +err1: + if (redriver->extcon_usb) + extcon_unregister_notifier(redriver->extcon_usb, + EXTCON_USB_HOST, &redriver->id_nb); +err: + if (redriver->extcon_usb) + extcon_unregister_notifier(redriver->extcon_usb, + EXTCON_USB, &redriver->vbus_nb); + return ret; +} + +static int ssusb_redriver_param_config(struct ssusb_redriver *redriver, + u8 reg_base, u8 channel, u8 mask, u8 shift, u8 val, + u8 *stored_val) +{ + int i, ret = -EINVAL; + u8 reg_addr, reg_val; + + if (channel == CHANNEL_NUM) { + for (i = 0; i < CHANNEL_NUM; i++) { + reg_addr = reg_base + (i << 1); + + ret = redriver_i2c_reg_get(redriver, + reg_addr, ®_val); + if (ret < 0) + return ret; + + reg_val &= ~(mask << shift); + reg_val |= (val << shift); + + ret = redriver_i2c_reg_set(redriver, + reg_addr, reg_val); + if (ret < 0) + return ret; + + stored_val[i] = val; + } + } else if (channel < CHANNEL_NUM) { + reg_addr = reg_base + (channel << 1); + + ret = redriver_i2c_reg_get(redriver, + reg_addr, ®_val); + if (ret < 0) + return ret; + + reg_val &= ~(mask << shift); + reg_val |= (val << shift); + + ret = redriver_i2c_reg_set(redriver, + reg_addr, reg_val); + if (ret < 0) + return ret; + + stored_val[channel] = val; + } else { + dev_err(redriver->dev, "error channel value.\n"); + return ret; + } + + return 0; +} + +static int ssusb_redriver_eq_config( + struct ssusb_redriver *redriver, u8 channel, u8 val) +{ + if (val <= EQ_SETTING_MASK) + return ssusb_redriver_param_config(redriver, + EQ_SET_REG_BASE, channel, EQ_SETTING_MASK, + EQ_SETTING_SHIFT, val, redriver->eq); + else + return -EINVAL; +} + +static int ssusb_redriver_flat_gain_config( + struct ssusb_redriver *redriver, u8 channel, u8 val) +{ + if (val <= FLAT_GAIN_MASK) + return ssusb_redriver_param_config(redriver, + FLAT_GAIN_REG_BASE, channel, FLAT_GAIN_MASK, + FLAT_GAIN_SHIFT, val, redriver->flat_gain); + else + return -EINVAL; +} + +static int ssusb_redriver_output_comp_config( + struct ssusb_redriver *redriver, u8 channel, u8 val) +{ + if (val <= OUTPUT_COMPRESSION_MASK) + return ssusb_redriver_param_config(redriver, + OUT_COMP_AND_POL_REG_BASE, channel, + OUTPUT_COMPRESSION_MASK, + OUTPUT_COMPRESSION_SHIFT, val, + redriver->output_comp); + else + return -EINVAL; +} + +static int ssusb_redriver_loss_match_config( + struct ssusb_redriver *redriver, u8 channel, u8 val) +{ + if (val <= LOSS_MATCH_MASK) + return ssusb_redriver_param_config(redriver, + LOSS_MATCH_REG_BASE, channel, LOSS_MATCH_MASK, + LOSS_MATCH_SHIFT, val, redriver->loss_match); + else + return -EINVAL; +} + +static int ssusb_redriver_default_config(struct ssusb_redriver *redriver) +{ + struct device_node *node = redriver->dev->of_node; + int ret = 0, i = 0; + + if (of_find_property(node, "eq", NULL)) { + ret = of_property_read_u8_array(node, "eq", redriver->eq, + ARRAY_SIZE(redriver->eq)); + if (!ret) { + for (i = 0; i < CHANNEL_NUM; i++) { + ret = ssusb_redriver_eq_config( + redriver, i, + redriver->eq[i]); + if (ret) + goto err; + } + } else + goto err; + } + + if (of_find_property(node, "flat-gain", NULL)) { + ret = of_property_read_u8_array(node, + "flat-gain", redriver->flat_gain, + ARRAY_SIZE(redriver->flat_gain)); + if (!ret) { + for (i = 0; i < CHANNEL_NUM; i++) { + ret = ssusb_redriver_flat_gain_config( + redriver, i, + redriver->flat_gain[i]); + if (ret) + goto err; + } + } else + goto err; + } + + if (of_find_property(node, "output-comp", NULL)) { + ret = of_property_read_u8_array(node, + "output-comp", redriver->output_comp, + ARRAY_SIZE(redriver->output_comp)); + if (!ret) { + for (i = 0; i < CHANNEL_NUM; i++) { + ret = ssusb_redriver_output_comp_config( + redriver, i, + redriver->output_comp[i]); + if (ret) + goto err; + } + } else + goto err; + } + + if (of_find_property(node, "loss-match", NULL)) { + ret = of_property_read_u8_array(node, + "loss-match", redriver->loss_match, + ARRAY_SIZE(redriver->loss_match)); + if (!ret) { + for (i = 0; i < CHANNEL_NUM; i++) { + ret = ssusb_redriver_loss_match_config( + redriver, i, + redriver->loss_match[i]); + if (ret) + goto err; + } + } else + goto err; + } + + return 0; + +err: + dev_err(redriver->dev, + "%s: set default parameters failure.\n", __func__); + return ret; +} + +static int ssusb_redriver_panic_notifier(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct ssusb_redriver *redriver = container_of(this, + struct ssusb_redriver, panic_nb); + + pr_err("%s: op mode: %d, vbus: %d, host: %d\n", __func__, + redriver->op_mode, redriver->vbus_active, + redriver->host_active); + + return NOTIFY_OK; +} + +static const struct regmap_config redriver_regmap = { + .max_register = REDRIVER_REG_MAX, + .reg_bits = 8, + .val_bits = 8, +}; + +static int redriver_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ssusb_redriver *redriver; + union power_supply_propval pval = {0}; + int ret; + + redriver = devm_kzalloc(&client->dev, sizeof(struct ssusb_redriver), + GFP_KERNEL); + if (!redriver) + return -ENOMEM; + + INIT_WORK(&redriver->config_work, ssusb_redriver_config_work); + + redriver->redriver_wq = alloc_ordered_workqueue("redriver_wq", + WQ_HIGHPRI); + if (!redriver->redriver_wq) { + dev_err(&client->dev, + "%s: Unable to create workqueue redriver_wq\n", + __func__); + return -ENOMEM; + } + + redriver->dev = &client->dev; + + redriver->regmap = devm_regmap_init_i2c(client, &redriver_regmap); + if (IS_ERR(redriver->regmap)) { + ret = PTR_ERR(redriver->regmap); + dev_err(&client->dev, + "Failed to allocate register map: %d\n", ret); + goto destroy_wq; + } + + redriver->client = client; + i2c_set_clientdata(client, redriver); + + /* Set default parameters for A/B/C/D channels. */ + ret = ssusb_redriver_default_config(redriver); + if (ret < 0) + goto destroy_wq; + + /* Set id_state as float by default*/ + redriver->host_active = false; + + /* Set to USB by default */ + redriver->op_mode = OP_MODE_USB; + + redriver->usb_psy = power_supply_get_by_name("usb"); + if (!redriver->usb_psy) { + dev_warn(&client->dev, "Could not get usb power_supply\n"); + pval.intval = -EINVAL; + } else { + power_supply_get_property(redriver->usb_psy, + POWER_SUPPLY_PROP_PRESENT, &pval); + + /* USB cable is not connected */ + if (!pval.intval) + ssusb_redriver_gen_dev_set(redriver, false); + } + + ret = ssusb_redriver_extcon_register(redriver); + if (ret) + goto put_psy; + + redriver->panic_nb.notifier_call = ssusb_redriver_panic_notifier; + atomic_notifier_chain_register(&panic_notifier_list, + &redriver->panic_nb); + + ssusb_redriver_debugfs_entries(redriver); + + dev_dbg(&client->dev, "USB 3.1 Gen1/Gen2 Re-Driver Probed.\n"); + + return 0; + +put_psy: + if (redriver->usb_psy) + power_supply_put(redriver->usb_psy); + +destroy_wq: + destroy_workqueue(redriver->redriver_wq); + + return ret; +} + +static int redriver_i2c_remove(struct i2c_client *client) +{ + struct ssusb_redriver *redriver = i2c_get_clientdata(client); + + debugfs_remove(redriver->debug_root); + atomic_notifier_chain_unregister(&panic_notifier_list, + &redriver->panic_nb); + + if (redriver->usb_psy) + power_supply_put(redriver->usb_psy); + + destroy_workqueue(redriver->redriver_wq); + + return 0; +} + +static ssize_t channel_config_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos, + int (*config_func)(struct ssusb_redriver *redriver, + u8 channel, u8 val)) +{ + struct seq_file *s = file->private_data; + struct ssusb_redriver *redriver = s->private; + char buf[20]; + char *token_chan, *token_val, *this_buf; + int ret = 0; + + memset(buf, 0, sizeof(buf)); + + this_buf = buf; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (isdigit(buf[0])) { + ret = config_func(redriver, CHANNEL_NUM, buf[0] - '0'); + if (ret < 0) + goto err; + } else if (isalpha(buf[0])) { + while ((token_chan = strsep(&this_buf, " ")) != NULL) { + if (isalpha(*token_chan) + && (__toupper(*token_chan) >= 'A') + && (__toupper(*token_chan) <= 'D')) { + token_val = strsep(&this_buf, " "); + if (!isdigit(*token_val)) + goto err; + } else + goto err; + + ret = config_func(redriver, *token_chan - 'A', + *token_val - '0'); + if (ret < 0) + goto err; + } + } else + goto err; + + + return count; + +err: + pr_err("Used to config redriver A/B/C/D channels' parameters\n" + "1. Set all channels to same value\n" + "echo n > [eq|output_comp|flat_gain|loss_match]\n" + "- eq: Equalization, range 0-7\n" + "- output_comp: Output Compression, range 0-3\n" + "- loss_match: LOSS Profile Matching, range 0-3\n" + "- flat_gain: Flat Gain, range 0-3\n" + "Example: Set all channels to same EQ value\n" + "echo 1 > eq\n" + "2. Set two channels to different values leave others unchanged\n" + "echo [A|B|C|D] n [A|B|C|D] n > [eq|output_comp|flat_gain|loss_match]\n" + "Example2: set channel B flat gain value 2, set channel C flat gain value 3\n" + "echo B 2 C 3 > flat_gain\n"); + + return -EFAULT; +} + +static int eq_status(struct seq_file *s, void *p) +{ + struct ssusb_redriver *redriver = s->private; + + seq_puts(s, "\t\t\t A\t B\t C\t D\n"); + seq_printf(s, "Equalization:\t\t %d\t %d\t %d\t %d\t\n", + redriver->eq[0], redriver->eq[1], + redriver->eq[2], redriver->eq[3]); + return 0; +} + +static int eq_status_open(struct inode *inode, + struct file *file) +{ + return single_open(file, eq_status, inode->i_private); +} + +static ssize_t eq_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + return channel_config_write(file, ubuf, count, ppos, + ssusb_redriver_eq_config); +} + +static const struct file_operations eq_ops = { + .open = eq_status_open, + .read = seq_read, + .write = eq_write, +}; + +static int flat_gain_status(struct seq_file *s, void *p) +{ + struct ssusb_redriver *redriver = s->private; + + seq_puts(s, "\t\t\t A\t B\t C\t D\n"); + seq_printf(s, "TX/RX Flat Gain:\t %d\t %d\t %d\t %d\t\n", + redriver->flat_gain[0], redriver->flat_gain[1], + redriver->flat_gain[2], redriver->flat_gain[3]); + return 0; +} + +static int flat_gain_status_open(struct inode *inode, + struct file *file) +{ + return single_open(file, flat_gain_status, inode->i_private); +} + +static ssize_t flat_gain_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + return channel_config_write(file, ubuf, count, ppos, + ssusb_redriver_flat_gain_config); +} + +static const struct file_operations flat_gain_ops = { + .open = flat_gain_status_open, + .read = seq_read, + .write = flat_gain_write, +}; + +static int output_comp_status(struct seq_file *s, void *p) +{ + struct ssusb_redriver *redriver = s->private; + + seq_puts(s, "\t\t\t A\t B\t C\t D\n"); + seq_printf(s, "Output Compression:\t %d\t %d\t %d\t %d\t\n", + redriver->output_comp[0], redriver->output_comp[1], + redriver->output_comp[2], redriver->output_comp[3]); + return 0; +} + +static int output_comp_status_open(struct inode *inode, + struct file *file) +{ + return single_open(file, output_comp_status, inode->i_private); +} + +static ssize_t output_comp_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + return channel_config_write(file, ubuf, count, ppos, + ssusb_redriver_output_comp_config); +} + +static const struct file_operations output_comp_ops = { + .open = output_comp_status_open, + .read = seq_read, + .write = output_comp_write, +}; + +static int loss_match_status(struct seq_file *s, void *p) +{ + struct ssusb_redriver *redriver = s->private; + + seq_puts(s, "\t\t\t A\t B\t C\t D\n"); + seq_printf(s, "Loss Profile Match:\t %d\t %d\t %d\t %d\t\n", + redriver->loss_match[0], redriver->loss_match[1], + redriver->loss_match[2], redriver->loss_match[3]); + return 0; +} + +static int loss_match_status_open(struct inode *inode, + struct file *file) +{ + return single_open(file, loss_match_status, inode->i_private); +} + +static ssize_t loss_match_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + return channel_config_write(file, ubuf, count, ppos, + ssusb_redriver_loss_match_config); +} + +static const struct file_operations loss_match_ops = { + .open = loss_match_status_open, + .read = seq_read, + .write = loss_match_write, +}; + +static void ssusb_redriver_debugfs_entries( + struct ssusb_redriver *redriver) +{ + struct dentry *ent; + + redriver->debug_root = debugfs_create_dir("ssusb_redriver", NULL); + if (!redriver->debug_root) { + dev_warn(redriver->dev, "Couldn't create debug dir\n"); + return; + } + + ent = debugfs_create_file("eq", 0600, + redriver->debug_root, redriver, &eq_ops); + if (IS_ERR_OR_NULL(ent)) + dev_warn(redriver->dev, "Couldn't create eq file\n"); + + ent = debugfs_create_file("flat_gain", 0600, + redriver->debug_root, redriver, &flat_gain_ops); + if (IS_ERR_OR_NULL(ent)) + dev_warn(redriver->dev, "Couldn't create flat_gain file\n"); + + ent = debugfs_create_file("output_comp", 0600, + redriver->debug_root, redriver, &output_comp_ops); + if (IS_ERR_OR_NULL(ent)) + dev_warn(redriver->dev, "Couldn't create output_comp file\n"); + + ent = debugfs_create_file("loss_match", 0600, + redriver->debug_root, redriver, &loss_match_ops); + if (IS_ERR_OR_NULL(ent)) + dev_warn(redriver->dev, "Couldn't create loss_match file\n"); +} + +static int __maybe_unused redriver_i2c_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ssusb_redriver *redriver = i2c_get_clientdata(client); + + dev_dbg(redriver->dev, "%s: SS USB redriver suspend.\n", + __func__); + + /* Disable redriver chip when USB cable disconnected */ + if ((!redriver->vbus_active) + && (!redriver->host_active)) + ssusb_redriver_gen_dev_set(redriver, false); + + flush_workqueue(redriver->redriver_wq); + + return 0; +} + +static int __maybe_unused redriver_i2c_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ssusb_redriver *redriver = i2c_get_clientdata(client); + + dev_dbg(redriver->dev, "%s: SS USB redriver resume.\n", + __func__); + + flush_workqueue(redriver->redriver_wq); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(redriver_i2c_pm, redriver_i2c_suspend, + redriver_i2c_resume); + +static void redriver_i2c_shutdown(struct i2c_client *client) +{ + struct ssusb_redriver *redriver = i2c_get_clientdata(client); + int ret; + + /* Set back to USB mode with four channel enabled */ + ret = redriver_i2c_reg_set(redriver, GEN_DEV_SET_REG, + GEN_DEV_SET_REG_DEFAULT); + if (ret < 0) + dev_err(&client->dev, + "%s: fail to set USB mode with 4 channel enabled.\n", + __func__); + else + dev_dbg(&client->dev, + "%s: successfully set back to USB mode.\n", + __func__); +} + +static const struct of_device_id redriver_match_table[] = { + { .compatible = "onnn,redriver",}, + { }, +}; + +static const struct i2c_device_id redriver_i2c_id[] = { + { "ssusb redriver", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, redriver_i2c_id); + +static struct i2c_driver redriver_i2c_driver = { + .driver = { + .name = "ssusb redriver", + .owner = THIS_MODULE, + .of_match_table = redriver_match_table, + .pm = &redriver_i2c_pm, + }, + + .probe = redriver_i2c_probe, + .remove = redriver_i2c_remove, + + .shutdown = redriver_i2c_shutdown, + + .id_table = redriver_i2c_id, +}; + +module_i2c_driver(redriver_i2c_driver); + +MODULE_DESCRIPTION("USB Super Speed Linear Re-Driver Driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From c48dd4475245094f38622f2e011cac670cd0d439 Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Thu, 21 Jun 2018 10:33:59 +0800 Subject: [PATCH 1291/1299] defconfig: sm8150: Add defconfig for USB redriver Enable USB redriver driver for ONSEMI NB7VPQ904M redriver chipset. Change-Id: Id59be4b6c527a63bec6edf7b95ee2da95a1e76f2 Signed-off-by: Liangliang Lu --- arch/arm64/configs/vendor/sm8150-perf_defconfig | 1 + arch/arm64/configs/vendor/sm8150_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 9fb85b7fe1c1..25a342222552 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -410,6 +410,7 @@ CONFIG_USB_DWC3=y CONFIG_USB_DWC3_MSM=y CONFIG_USB_ISP1760=y CONFIG_USB_ISP1760_HOST_ROLE=y +CONFIG_USB_REDRIVER_NB7VPQ904M=y CONFIG_NOP_USB_XCEIV=y CONFIG_USB_QCOM_EMU_PHY=y CONFIG_USB_MSM_SSPHY_QMP=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index c4873fb06ba4..8413f7160dd6 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -427,6 +427,7 @@ CONFIG_USB_DWC3=y CONFIG_USB_DWC3_MSM=y CONFIG_USB_ISP1760=y CONFIG_USB_ISP1760_HOST_ROLE=y +CONFIG_USB_REDRIVER_NB7VPQ904M=y CONFIG_NOP_USB_XCEIV=y CONFIG_USB_QCOM_EMU_PHY=y CONFIG_USB_MSM_SSPHY_QMP=y -- GitLab From 0ec4edf81bd861825b030c0bee41b00a58ed9165 Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Thu, 7 Jun 2018 16:48:20 +0800 Subject: [PATCH 1292/1299] ARM: dts: msm: Enable USB 3.1 Gen/Gen2 re-driver on QRD8150 Enable USB USB3.1 Gen1/Gen2 re-driver which used on QRD8150. Change-Id: I3497cea31dcbe1dd505bf175bf14bfbc2e0bb871 Signed-off-by: Liangliang Lu --- arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi index d82e480bc2d0..5fc01975aacc 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi @@ -225,6 +225,15 @@ &qupv3_se4_i2c { status = "ok"; + redriver@19 { + compatible = "onnn,redriver"; + reg = <0x19>; + extcon = <&pm8150b_pdphy>, <&pm8150b_pdphy>; + eq = /bits/ 8 <0x5 0x4 0x4 0x5>; + flat-gain = /bits/ 8 <0x3 0x1 0x1 0x3>; + output-comp = /bits/ 8 <0x2 0x2 0x2 0x2>; + loss-match = /bits/ 8 <0x0 0x3 0x3 0x0>; + }; }; &ufsphy_mem { -- GitLab From 088ec5cb88bd65d587fd4dc030e8509cb4a38c67 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Mon, 2 Jul 2018 23:29:31 +0530 Subject: [PATCH 1293/1299] adsprpc: Do not print fastrpc channel opened messages Adsprpc channel opened messages are flooding kernel log, so do not print channel openend messages. Change-Id: I862766d0ab9352d5718d9540a19f943050f772e5 Acked-by: Chenna Kesava Raju Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index c39d1b888064..1fb13255ce35 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2791,9 +2791,6 @@ static int fastrpc_channel_open(struct fastrpc_file *fl) err = -ENOTCONN; goto bail; } - pr_info("'opened /dev/%s c %d %d'\n", gcinfo[cid].name, - MAJOR(me->dev_no), cid); - if (cid == ADSP_DOMAIN_ID && me->channel[cid].ssrcount != me->channel[cid].prevssrcount) { mutex_lock(&fl->map_mutex); -- GitLab From 820d5139732253afd8cd396e7fdb8c6ca8b0a1b8 Mon Sep 17 00:00:00 2001 From: Tirupathi Reddy Date: Fri, 6 Jul 2018 13:30:27 +0530 Subject: [PATCH 1294/1299] ARM: dts: msm: add dpdm regulator for smb1351 of qcs405 use usb_phy0 device as dpdm regulator for smb1351 device. It is used to float D+/D-. Change-Id: Ic99b31afaf6f0c5e8a845622626093f1871c0bc1 Signed-off-by: Tirupathi Reddy --- arch/arm64/boot/dts/qcom/qcs405.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index 3024a1a47da8..d8735e012cba 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -1073,6 +1073,7 @@ pinctrl-names = "default"; pinctrl-0 = <&smb_stat>; qcom,switch-freq = <2>; + dpdm-supply = <&usb2_phy0>; }; }; -- GitLab From 96300d27e7caa824092aaa187e62d4e8c17574a8 Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Wed, 4 Jul 2018 20:43:11 +0530 Subject: [PATCH 1295/1299] ARM: dts: msm: Add EMAC, USB3 and PCIE master/slave nodes for qcs405 Add EMAC, USB3 and PCIE master and slave nodes to the bus topology so that clients can vote for the bandwidth on qcs405. Change-Id: Ib089cc5b9feb991363f70252890e029ecff033ea Signed-off-by: Odelu Kukatla --- arch/arm64/boot/dts/qcom/qcs405-bus.dtsi | 114 +++++++++++++++++++---- include/dt-bindings/msm/msm-bus-ids.h | 47 +++++++++- 2 files changed, 143 insertions(+), 18 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs405-bus.dtsi b/arch/arm64/boot/dts/qcom/qcs405-bus.dtsi index ca659e0dc2ce..d8b2ef74467c 100644 --- a/arch/arm64/boot/dts/qcom/qcs405-bus.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405-bus.dtsi @@ -172,8 +172,9 @@ qcom,bus-dev = <&fab_pcnoc>; qcom,mas-rpm-id = ; qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_1 &pcnoc_s_10 - &pcnoc_s_2 &pcnoc_s_4 &pcnoc_s_6 - &pcnoc_s_7 &pcnoc_s_8 &pcnoc_s_9>; + &pcnoc_s_11 &pcnoc_s_2 &pcnoc_s_4 + &pcnoc_s_6 &pcnoc_s_7 &pcnoc_s_8 + &pcnoc_s_9>; }; mas_crypto: mas-crypto { @@ -186,8 +187,9 @@ qcom,bus-dev = <&fab_pcnoc>; qcom,mas-rpm-id = ; qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_1 &pcnoc_s_10 - &pcnoc_s_2 &pcnoc_s_4 &pcnoc_s_6 - &pcnoc_s_7 &pcnoc_s_8 &pcnoc_s_9>; + &pcnoc_s_11 &pcnoc_s_2 &pcnoc_s_4 + &pcnoc_s_6 &pcnoc_s_7 &pcnoc_s_8 + &pcnoc_s_9>; }; mas_sdcc_1: mas-sdcc-1 { @@ -199,8 +201,9 @@ qcom,bus-dev = <&fab_pcnoc>; qcom,mas-rpm-id = ; qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_1 &pcnoc_s_10 - &pcnoc_s_2 &pcnoc_s_4 &pcnoc_s_6 - &pcnoc_s_7 &pcnoc_s_8 &pcnoc_s_9>; + &pcnoc_s_11 &pcnoc_s_2 &pcnoc_s_4 + &pcnoc_s_6 &pcnoc_s_7 &pcnoc_s_8 + &pcnoc_s_9>; }; mas_sdcc_2: mas-sdcc-2 { @@ -212,8 +215,9 @@ qcom,bus-dev = <&fab_pcnoc>; qcom,mas-rpm-id = ; qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_1 &pcnoc_s_10 - &pcnoc_s_2 &pcnoc_s_4 &pcnoc_s_6 - &pcnoc_s_7 &pcnoc_s_8 &pcnoc_s_9>; + &pcnoc_s_11 &pcnoc_s_2 &pcnoc_s_4 + &pcnoc_s_6 &pcnoc_s_7 &pcnoc_s_8 + &pcnoc_s_9>; }; mas_snoc_pcnoc: mas-snoc-pcnoc { @@ -240,8 +244,9 @@ qcom,bus-dev = <&fab_pcnoc>; qcom,mas-rpm-id = ; qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_1 &pcnoc_s_10 - &pcnoc_s_2 &pcnoc_s_4 &pcnoc_s_6 - &pcnoc_s_7 &pcnoc_s_8 &pcnoc_s_9>; + &pcnoc_s_11 &pcnoc_s_2 &pcnoc_s_4 + &pcnoc_s_6 &pcnoc_s_7 &pcnoc_s_8 + &pcnoc_s_9>; }; /*SNOC Masters*/ @@ -297,6 +302,51 @@ qcom,mas-rpm-id = ; }; + mas_emac: mas-emac { + cell-id = ; + label = "mas-emac"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,ap-owned; + qcom,qport = <27>; + qcom,qos-mode = "fixed"; + qcom,connections = <&slv_snoc_bimc_1 &snoc_int_1>; + qcom,prio1 = <1>; + qcom,prio0 = <1>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + }; + + mas_pcie: mas-pcie { + cell-id = ; + label = "mas-pcie"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,ap-owned; + qcom,qport = <18>; + qcom,qos-mode = "fixed"; + qcom,connections = <&slv_snoc_bimc_1 &snoc_int_1>; + qcom,prio1 = <1>; + qcom,prio0 = <1>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + }; + + mas_usb3: mas-usb3 { + cell-id = ; + label = "mas-usb3"; + qcom,buswidth = <8>; + qcom,agg-ports = <1>; + qcom,ap-owned; + qcom,qport = <26>; + qcom,qos-mode = "fixed"; + qcom,connections = <&slv_snoc_bimc_1 &snoc_int_1>; + qcom,prio1 = <1>; + qcom,prio0 = <1>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + }; + /*Internal nodes*/ pcnoc_int_0: pcnoc-int-0 { cell-id = ; @@ -314,11 +364,12 @@ label = "pcnoc-int-2"; qcom,buswidth = <8>; qcom,agg-ports = <1>; - qcom,connections = <&pcnoc_s_10 &slv_tcu &pcnoc_s_2 - &pcnoc_s_3 &pcnoc_s_0 - &pcnoc_s_1 &pcnoc_s_6 - &pcnoc_s_7 &pcnoc_s_4 - &pcnoc_s_8 &pcnoc_s_9>; + qcom,connections = <&pcnoc_s_10 &slv_tcu + &pcnoc_s_11 &pcnoc_s_2 + &pcnoc_s_3 &pcnoc_s_0 + &pcnoc_s_1 &pcnoc_s_6 + &pcnoc_s_7 &pcnoc_s_4 + &pcnoc_s_8 &pcnoc_s_9>; qcom,bus-dev = <&fab_pcnoc>; qcom,mas-rpm-id = ; qcom,slv-rpm-id = ; @@ -396,7 +447,8 @@ label = "pcnoc-s-6"; qcom,buswidth = <4>; qcom,agg-ports = <1>; - qcom,connections = <&slv_blsp_1 &slv_tlmm_north>; + qcom,connections = <&slv_blsp_1 &slv_tlmm_north + &slv_ethernet>; qcom,bus-dev = <&fab_pcnoc>; qcom,mas-rpm-id = ; qcom,slv-rpm-id = ; @@ -448,6 +500,17 @@ qcom,slv-rpm-id = ; }; + pcnoc_s_11: pcnoc-s-11 { + cell-id = ; + label = "pcnoc-s-11"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,connections = <&slv_usb3>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + qdss_int: qdss-int { cell-id = ; label = "qdss-int"; @@ -617,6 +680,16 @@ qcom,slv-rpm-id = ; }; + slv_ethernet:slv-ethernet { + cell-id = ; + label = "slv-ethernet"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + slv_blsp_2:slv-blsp-2 { cell-id = ; label = "slv-blsp-2"; @@ -690,6 +763,15 @@ qcom,slv-rpm-id = ; }; + slv_usb3:slv-usb3 { + cell-id = ; + label = "slv-usb3"; + qcom,buswidth = <4>; + qcom,agg-ports = <1>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + slv_crypto_0_cfg:slv-crypto-0-cfg { cell-id = ; label = "slv-crypto-0-cfg"; diff --git a/include/dt-bindings/msm/msm-bus-ids.h b/include/dt-bindings/msm/msm-bus-ids.h index c53b2551ac54..f646c7b7b9b8 100644 --- a/include/dt-bindings/msm/msm-bus-ids.h +++ b/include/dt-bindings/msm/msm-bus-ids.h @@ -363,6 +363,7 @@ #define MSM_BUS_SLAVE_SNOC_GEM_NOC_GC 10072 #define MSM_BUS_SLAVE_SNOC_GEM_NOC_SF 10073 #define MSM_BUS_PNOC_SLV_10 10074 +#define MSM_BUS_PNOC_SLV_11 10075 #define MSM_BUS_INT_TEST_ID 20000 #define MSM_BUS_INT_TEST_LAST 20050 @@ -822,7 +823,19 @@ #define ICBID_MASTER_CNOC_A2NOC 146 #define ICBID_MASTER_WLAN 147 #define ICBID_MASTER_MSS_CE 148 -#define ICBID_MASTER_PCNOC_S_10 149 +#define ICBID_MASTER_CDSP_PROC 149 +#define ICBID_MASTER_GNOC_SNOC 150 +#define ICBID_MASTER_MODEM_WRAPPER 151 +#define ICBID_MASTER_SDIO 152 +#define ICBID_MASTER_BIMC_SNOC_PCIE 153 +#define ICBID_MASTER_WLAN_PROC 154 +#define ICBID_MASTER_CRVIRT_PCNOC 155 +#define ICBID_MASTER_WLAN_INT 156 +#define ICBID_MASTER_PCNOC_S_10 157 +#define ICBID_MASTER_PCNOC_S_11 158 +#define ICBID_MASTER_LPASS_LPAIF 159 +#define ICBID_MASTER_LPASS_LEC 160 +#define ICBID_MASTER_LPASS_ANOC_BIMC 161 #define ICBID_SLAVE_EBI1 0 #define ICBID_SLAVE_APPSS_L2 1 @@ -1052,5 +1065,35 @@ #define ICBID_SLAVE_TLMM_NORTH 214 #define ICBID_SLAVE_TLMM_WEST 215 #define ICBID_SLAVE_TLMM_SOUTH 216 -#define ICBID_SLAVE_PCNOC_S_10 217 +#define ICBID_SLAVE_TLMM_CENTER 217 +#define ICBID_SLAVE_MSS_NAV_CE_MPU_CFG 218 +#define ICBID_SLAVE_A2NOC_THROTTLE_CFG 219 +#define ICBID_SLAVE_CDSP 220 +#define ICBID_SLAVE_CDSP_SMMU_CFG 221 +#define ICBID_SLAVE_LPASS_MPU_CFG 222 +#define ICBID_SLAVE_CSI_PHY_CFG 223 +#define ICBID_SLAVE_DDRSS_CFG 224 +#define ICBID_SLAVE_DDRSS_MPU_CFG 225 +#define ICBID_SLAVE_SNOC_MSS_XPU_CFG 226 +#define ICBID_SLAVE_BIMC_MSS_XPU_CFG 227 +#define ICBID_SLAVE_MSS_SNOC_MPU_CFG 228 +#define ICBID_SLAVE_MSS 229 +#define ICBID_SLAVE_SDIO 230 +#define ICBID_SLAVE_QM_MPU_CFG 231 +#define ICBID_SLAVE_BIMC_SNOC_PCIE 232 +#define ICBID_SLAVE_BOOTIMEM 233 +#define ICBID_SLAVE_CDSP_CFG 234 +#define ICBID_SLAVE_WLAN_DSP_CFG 235 +#define ICBID_SLAVE_GENIR_XPU_CFG 236 +#define ICBID_SLAVE_BOOTIMEM_MPU 237 +#define ICBID_SLAVE_CRVIRT_PCNOC 238 +#define ICBID_SLAVE_WLAN_INT 239 +#define ICBID_SLAVE_WLAN_MPU_CFG 240 +#define ICBID_SLAVE_LPASS_AGNOC_CFG 241 +#define ICBID_SLAVE_LPASS_AGNOC_XPU_CFG 242 +#define ICBID_SLAVE_PLL_BIAS_CFG 243 +#define ICBID_SLAVE_EMAC 244 +#define ICBID_SLAVE_PCNOC_S_10 245 +#define ICBID_SLAVE_PCNOC_S_11 246 +#define ICBID_SLAVE_LPASS_ANOC_BIMC 247 #endif -- GitLab From 9049260b0405e9ac9d5a671fcbef2f533a6ae3e1 Mon Sep 17 00:00:00 2001 From: Vijaykumar Badiger Date: Fri, 6 Jul 2018 11:31:16 -0700 Subject: [PATCH 1296/1299] defconfig: move vendor defconfigs to vendor/ subdirectory Move all defconfigs down one level to vendor/. Create symlinks as necessary for userspace components that are still hard-coded to the older location. Change-Id: I98dac06f61eded8636912313122f90a8e93c6025 Signed-off-by: Vijaykumar Badiger --- arch/arm64/configs/sa8155-perf_defconfig | 1 + arch/arm64/configs/sa8155_defconfig | 1 + 2 files changed, 2 insertions(+) create mode 120000 arch/arm64/configs/sa8155-perf_defconfig create mode 120000 arch/arm64/configs/sa8155_defconfig diff --git a/arch/arm64/configs/sa8155-perf_defconfig b/arch/arm64/configs/sa8155-perf_defconfig new file mode 120000 index 000000000000..8fb0cc34e9ac --- /dev/null +++ b/arch/arm64/configs/sa8155-perf_defconfig @@ -0,0 +1 @@ +vendor/sa8155-perf_defconfig \ No newline at end of file diff --git a/arch/arm64/configs/sa8155_defconfig b/arch/arm64/configs/sa8155_defconfig new file mode 120000 index 000000000000..005726151a08 --- /dev/null +++ b/arch/arm64/configs/sa8155_defconfig @@ -0,0 +1 @@ +vendor/sa8155_defconfig \ No newline at end of file -- GitLab From 9cc49ddf56b504c76fb62177d372f922d7615445 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Wed, 27 Jun 2018 11:12:53 -0700 Subject: [PATCH 1297/1299] Documentation: Add doc for EMAC node for auto platform Add EMAC node documentation for auto platform. Change-Id: Ie92ad024337bc7adcee5a5e62bcacda025e8cfd1 Acked-by: Nisha Menon Signed-off-by: Skylar Chang --- .../bindings/net/qcom,emac-dwc-eqos.txt | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/qcom,emac-dwc-eqos.txt diff --git a/Documentation/devicetree/bindings/net/qcom,emac-dwc-eqos.txt b/Documentation/devicetree/bindings/net/qcom,emac-dwc-eqos.txt new file mode 100644 index 000000000000..5dc958dab32f --- /dev/null +++ b/Documentation/devicetree/bindings/net/qcom,emac-dwc-eqos.txt @@ -0,0 +1,86 @@ +Qualcomm Technologies Inc. EMAC Gigabit Ethernet controller + +This network controller consists of the MAC and +RGMII IO Macro for interfacing with PHY. + +Required properties: + +emac_hw node: +- compatible: Should be "qcom,emac-dwc-eqos" +- reg: Offset and length of the register regions for the mac and io-macro +- interrupts: Interrupt number used by this controller +- io-macro-info: Internal io-macro-info +- emac_emb_smmu: Internal emac smmu node + +Optional: +- qcom,msm-bus,name: String representing the client-name +- qcom,msm-bus,num-cases: Total number of usecases +- qcom,msm-bus,num-paths: Total number of master-slave pairs +- qcom,msm-bus,vectors-KBps: Arrays of unsigned integers representing: + master-id, slave-id, arbitrated bandwidth + in KBps, instantaneous bandwidth in KBps +qcom,bus-vector-names: specifies string IDs for the corresponding bus vectors + in the same order as qcom,msm-bus,vectors-KBps property. +- qcom,arm-smmu: Boolean, if present enables EMAC SMMU support in sdxpoorwills. + +Internal io-macro-info: +- io-macro-bypass-mode: <0 or 1> internal or external delay configuration +- io-interface: PHY interface used + +Internal emac_emb_smmu: +- compatible: Should be "qcom,emac-smmu-embedded". +- qcom,smmu-s1-bypass: Boolean, if present S1 bypass is enabled. +- iommus: Includes the <&smmu_phandle stream_id size> pair for each context + bank. +- qcom,iova-mapping: of the smmu context bank. + +Example: + +soc { + emac_hw: qcom,emac@00020000 { + compatible = "qcom,emac-dwc-eqos"; + qcom,arm-smmu; + reg = <0x20000 0x10000>, + <0x36000 0x100>; + <0x3D00000 0x300000>; + reg-names = "emac-base", "rgmii-base"; + interrupts = <0 62 4>, <0 60 4>, + <0 49 4>, <0 50 4>, + <0 51 4>, <0 52 4>, + <0 53 4>, <0 54 4>, + <0 55 4>, <0 56 4>, + <0 57 4>; + interrupt-names = "sbd-intr", "lpi-intr", + "phy-intr", "tx-ch0-intr", + "tx-ch1-intr", "tx-ch2-intr", + "tx-ch3-intr", "tx-ch4-intr", + "rx-ch0-intr", "rx-ch1-intr", + "rx-ch2-intr", "rx-ch3-intr"; + qcom,msm-bus,name = "emac"; + qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-paths = <2>; + qcom,msm-bus,vectors-KBps = + <98 512 0 0>, <1 781 0 0>, /* No vote */ + <98 512 1250 0>, <1 781 0 40000>, /* 10Mbps vote */ + <98 512 12500 0>, <1 781 0 40000>, /* 100Mbps vote */ + <98 512 125000 0>, <1 781 0 40000>; /* 1000Mbps vote */ + qcom,bus-vector-names = "10", "100", "1000"; + clock-names = "emac_axi_clk", "emac_ptp_clk", + "emac_rgmii_clk", "emac_slv_ahb_clk"; + qcom,phy-reset = <&tlmm 79 GPIO_ACTIVE_HIGH>; + qcom,phy-intr-redirect = <&tlmm 124 GPIO_ACTIVE_LOW>; + gdsc_emac-supply = <&emac_gdsc>; + + io-macro-info { + io-macro-bypass-mode = <0>; + io-interface = "rgmii"; + }; + + emac_emb_smmu: emac_emb_smmu { + compatible = "qcom,emac-smmu-embedded"; + qcom,smmu-s1-bypass; + iommus = <&apps_smmu 0x3C0 0x0>; + qcom,iova-mapping = <0x80000000 0x40000000>; + }; + }; +} -- GitLab From ad19e73fe24bb548ce04eaab6cee28a7d00817d1 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Fri, 18 May 2018 15:26:19 -0700 Subject: [PATCH 1298/1299] ARM: dts: msm: Add EMAC node for auto platform Add pinctrl settings for emac related gpios. Change-Id: Ic7ecfbab68c245aca8d2d9bfa6c9bb7a68bd5310 Acked-by: Nisha Menon Signed-off-by: Skylar Chang --- arch/arm64/boot/dts/qcom/sa8155.dtsi | 86 +++++++++ arch/arm64/boot/dts/qcom/sm8150-pinctrl.dtsi | 176 +++++++++++++++++++ 2 files changed, 262 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sa8155.dtsi b/arch/arm64/boot/dts/qcom/sa8155.dtsi index dc4df2a85882..bc0f3ac595c1 100644 --- a/arch/arm64/boot/dts/qcom/sa8155.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155.dtsi @@ -602,3 +602,89 @@ &mdss_mdp { connectors = <&dsi_dp1 &dsi_dp2 &sde_dp &sde_wb>; }; + +#include + +&soc { + emac_hw: qcom,emac@00020000 { + compatible = "qcom,emac-dwc-eqos"; + qcom,arm-smmu; + emac-core-version = <2>; + reg = <0x20000 0x10000>, + <0x36000 0x100>, + <0x3D00000 0x300000>; + reg-names = "emac-base", "rgmii-base", "tlmm-central-base"; + interrupts-extended = <&pdc 0 689 4>, <&pdc 0 699 4>, + <&tlmm 124 2>, <&pdc 0 691 4>, + <&pdc 0 692 4>, <&pdc 0 693 4>, + <&pdc 0 694 4>, <&pdc 0 695 4>, + <&pdc 0 696 4>, <&pdc 0 697 4>, + <&pdc 0 698 4>, <&pdc 0 699 4>; + interrupt-names = "sbd-intr", "lpi-intr", + "phy-intr", "tx-ch0-intr", + "tx-ch1-intr", "tx-ch2-intr", + "tx-ch3-intr", "tx-ch4-intr", + "rx-ch0-intr", "rx-ch1-intr", + "rx-ch2-intr", "rx-ch3-intr"; + qcom,msm-bus,name = "emac"; + qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-paths = <2>; + qcom,msm-bus,vectors-KBps = + <98 512 0 0>, <1 781 0 0>, /* No vote */ + <98 512 1250 0>, <1 781 0 40000>, /* 10Mbps vote */ + <98 512 12500 0>, <1 781 0 40000>, /* 100Mbps vote */ + <98 512 125000 0>, <1 781 0 40000>; /* 1000Mbps vote */ + qcom,bus-vector-names = "10", "100", "1000"; + clocks = <&clock_gcc GCC_EMAC_AXI_CLK>, + <&clock_gcc GCC_EMAC_PTP_CLK>, + <&clock_gcc GCC_EMAC_RGMII_CLK>, + <&clock_gcc GCC_EMAC_SLV_AHB_CLK>; + clock-names = "emac_axi_clk", "emac_ptp_clk", + "emac_rgmii_clk", "emac_slv_ahb_clk"; + qcom,phy-reset = <&tlmm 79 GPIO_ACTIVE_HIGH>; + qcom,phy-intr-redirect = <&tlmm 124 GPIO_ACTIVE_LOW>; + gdsc_emac-supply = <&emac_gdsc>; + pinctrl-names = "dev-emac-mdc", + "dev-emac-mdio", + "dev-emac-rgmii_txd0_state", + "dev-emac-rgmii_txd1_state", + "dev-emac-rgmii_txd2_state", + "dev-emac-rgmii_txd3_state", + "dev-emac-rgmii_txc_state", + "dev-emac-rgmii_tx_ctl_state", + "dev-emac-rgmii_rxd0_state", + "dev-emac-rgmii_rxd1_state", + "dev-emac-rgmii_rxd2_state", + "dev-emac-rgmii_rxd3_state", + "dev-emac-rgmii_rxc_state", + "dev-emac-rgmii_rx_ctl_state"; + + pinctrl-0 = <&emac_mdc>; + pinctrl-1 = <&emac_mdio>; + + pinctrl-2 = <&emac_rgmii_txd0>; + pinctrl-3 = <&emac_rgmii_txd1>; + pinctrl-4 = <&emac_rgmii_txd2>; + pinctrl-5 = <&emac_rgmii_txd3>; + pinctrl-6 = <&emac_rgmii_txc>; + pinctrl-7 = <&emac_rgmii_tx_ctl>; + + pinctrl-8 = <&emac_rgmii_rxd0>; + pinctrl-9 = <&emac_rgmii_rxd1>; + pinctrl-10 = <&emac_rgmii_rxd2>; + pinctrl-11 = <&emac_rgmii_rxd3>; + pinctrl-12 = <&emac_rgmii_rxc>; + pinctrl-13 = <&emac_rgmii_rx_ctl>; + + io-macro-info { + io-macro-bypass-mode = <0>; + io-interface = "rgmii"; + }; + emac_emb_smmu: emac_emb_smmu { + compatible = "qcom,emac-smmu-embedded"; + qcom,smmu-s1-bypass; + iommus = <&apps_smmu 0x3C0 0x0>; + qcom,iova-mapping = <0x80000000 0x40000000>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8150-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sm8150-pinctrl.dtsi index 9fc716ff9126..a0fa356d831a 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-pinctrl.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-pinctrl.dtsi @@ -3947,5 +3947,181 @@ bias-pull-up; }; }; + + emac { + emac_mdc: emac_mdc { + mux { + pins = "gpio7"; + function = "rgmii_mdc"; + }; + + config { + pins = "gpio7"; + bias-pull-up; + }; + }; + emac_mdio: emac_mdio { + mux { + pins = "gpio59"; + function = "rgmii_mdio"; + }; + + config { + pins = "gpio59"; + bias-pull-up; + }; + }; + + emac_rgmii_txd0: emac_rgmii_txd0 { + mux { + pins = "gpio122"; + function = "rgmii_txd0"; + }; + + config { + pins = "gpio122"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + emac_rgmii_txd1: emac_rgmii_txd1 { + mux { + pins = "gpio4"; + function = "rgmii_txd1"; + }; + + config { + pins = "gpio4"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + emac_rgmii_txd2: emac_rgmii_txd2 { + mux { + pins = "gpio5"; + function = "rgmii_txd2"; + }; + + config { + pins = "gpio5"; + bias-pull-up; + drive-strength = <16>; + }; + }; + emac_rgmii_txd3: emac_rgmii_txd3 { + mux { + pins = "gpio6"; + function = "rgmii_txd3"; + }; + + config { + pins = "gpio6"; + bias-pull-up; + drive-strength = <16>; + }; + }; + emac_rgmii_txc: emac_rgmii_txc { + mux { + pins = "gpio114"; + function = "rgmii_txc"; + }; + + config { + pins = "gpio114"; + bias-pull-up; + drive-strength = <16>; + }; + }; + emac_rgmii_tx_ctl: emac_rgmii_tx_ctl { + mux { + pins = "gpio121"; + function = "rgmii_tx"; + }; + + config { + pins = "gpio121"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + + emac_rgmii_rxd0: emac_rgmii_rxd0 { + mux { + pins = "gpio117"; + function = "rgmii_rxd0"; + }; + + config { + pins = "gpio117"; + bias-disable; /* NO pull */ + drive-strength = <2>; /* 2MA */ + }; + }; + + emac_rgmii_rxd1: emac_rgmii_rxd1 { + mux { + pins = "gpio118"; + function = "rgmii_rxd1"; + }; + + config { + pins = "gpio118"; + bias-disable; /* NO pull */ + drive-strength = <2>; + }; + }; + + emac_rgmii_rxd2: emac_rgmii_rxd2 { + mux { + pins = "gpio119"; + function = "rgmii_rxd2"; + }; + + config { + pins = "gpio119"; + bias-disable; /* NO pull */ + drive-strength = <2>; + }; + }; + emac_rgmii_rxd3: emac_rgmii_rxd3 { + mux { + pins = "gpio120"; + function = "rgmii_rxd3"; + }; + + config { + pins = "gpio120"; + bias-disable; /* NO pull */ + drive-strength = <2>; + }; + }; + emac_rgmii_rxc: emac_rgmii_rxc { + mux { + pins = "gpio115"; + function = "rgmii_rxc"; + }; + + config { + pins = "gpio115"; + bias-disable; /* NO pull */ + drive-strength = <2>; + }; + }; + emac_rgmii_rx_ctl: emac_rgmii_rx_ctl { + mux { + pins = "gpio116"; + function = "rgmii_rx"; + }; + + config { + pins = "gpio116"; + bias-disable; /* NO pull */ + drive-strength = <2>; + }; + }; + }; }; }; -- GitLab From 3e3fb0c431ed9617ed606ac6173bae14f1d23141 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Sat, 7 Jul 2018 03:54:08 +0530 Subject: [PATCH 1299/1299] msm: adsprpc: remove debug message while getting device info Remove printing of error message when getting device info fails, to avoid flooding of kernel logs Change-Id: If160c581159dff7c689207d5e62b885eef67e35d Acked-by: Amol Mahesh Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index f6bd4dbd37dd..1147893df453 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2905,9 +2905,6 @@ static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info) */ if (fl->apps->channel[cid].secure == SECURE_CHANNEL) { err = -EPERM; - pr_err("adsprpc: GetInfo failed dev %d, cid %d, secure %d\n", - fl->dev_minor, cid, - fl->apps->channel[cid].secure); goto bail; } } -- GitLab