diff options
| -rw-r--r-- | arch/arm/boot/dts/qcom/msm8998-mdss.dtsi | 8 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom/msm8998.dtsi | 2 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom/sdm630.dtsi | 2 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom/sdm660.dtsi | 2 | ||||
| -rw-r--r-- | drivers/input/touchscreen/st/fts.c | 28 | ||||
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1 | ||||
| -rw-r--r-- | drivers/misc/hdcp.c | 47 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/pci.c | 30 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/pci.h | 1 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/fg-util.c | 29 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_gsi.c | 230 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp.c | 26 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp.h | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp_util.c | 2 |
14 files changed, 319 insertions, 91 deletions
diff --git a/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi b/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi index 5708fce44378..fbde8d21f22c 100644 --- a/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi @@ -497,12 +497,16 @@ <&clock_mmss clk_mmss_mdss_dp_link_clk>, <&clock_mmss clk_mmss_mdss_dp_link_intf_clk>, <&clock_mmss clk_mmss_mdss_dp_crypto_clk>, - <&clock_mmss clk_mmss_mdss_dp_pixel_clk>; + <&clock_mmss clk_mmss_mdss_dp_pixel_clk>, + <&mdss_dp_pll clk_vco_divided_clk_src_mux>, + <&mdss_dp_pll clk_vco_divsel_two_clk_src>, + <&mdss_dp_pll clk_vco_divsel_four_clk_src>; clock-names = "core_mnoc_clk", "core_iface_clk", "core_bus_clk", "core_mdp_core_clk", "core_alt_iface_clk", "core_aux_clk", "core_ref_clk_src", "core_ref_clk", "ctrl_link_clk", "ctrl_link_iface_clk", - "ctrl_crypto_clk", "ctrl_pixel_clk"; + "ctrl_crypto_clk", "ctrl_pixel_clk", "pixel_parent", + "pixel_clk_two_div", "pixel_clk_four_div"; qcom,dp-usbpd-detection = <&pmi8998_pdphy>; diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi index 76e3282d327e..132f3e7ce332 100644 --- a/arch/arm/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998.dtsi @@ -292,7 +292,7 @@ dev = "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor"; type = "ext4"; mnt_flags = "ro,barrier=1,discard"; - fsmgr_flags = "wait,slotselect"; + fsmgr_flags = "wait,slotselect,verify"; status = "ok"; }; }; diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi index e918864a3df7..ae110fe22535 100644 --- a/arch/arm/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630.dtsi @@ -309,7 +309,7 @@ dev = "/dev/block/platform/soc/c0c4000.sdhci/by-name/vendor"; type = "ext4"; mnt_flags = "ro,barrier=1,discard"; - fsmgr_flags = "wait,slotselect"; + fsmgr_flags = "wait,slotselect,verify"; status = "ok"; }; }; diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi index c626698ffd51..48437ac9d31a 100644 --- a/arch/arm/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660.dtsi @@ -307,7 +307,7 @@ dev = "/dev/block/platform/soc/c0c4000.sdhci/by-name/vendor"; type = "ext4"; mnt_flags = "ro,barrier=1,discard"; - fsmgr_flags = "wait,slotselect"; + fsmgr_flags = "wait,slotselect,verify"; status = "ok"; }; }; diff --git a/drivers/input/touchscreen/st/fts.c b/drivers/input/touchscreen/st/fts.c index 08bfb83a9447..06f7f569f417 100644 --- a/drivers/input/touchscreen/st/fts.c +++ b/drivers/input/touchscreen/st/fts.c @@ -105,7 +105,7 @@ static void fts_interrupt_enable(struct fts_ts_info *info); static int fts_init_hw(struct fts_ts_info *info); static int fts_mode_handler(struct fts_ts_info *info, int force); static int fts_command(struct fts_ts_info *info, unsigned char cmd); - +static void fts_unblank(struct fts_ts_info *info); static int fts_chip_initialization(struct fts_ts_info *info); void touch_callback(unsigned int status) @@ -1487,8 +1487,12 @@ static int fts_init(struct fts_ts_info *info) error = fts_interrupt_install(info); - if (error != OK) + if (error != OK) { logError(1, "%s Init (1) error (ERROR = %08X)\n", error); + return error; + } + + fts_unblank(info); return error; } @@ -1773,6 +1777,26 @@ static int fts_fb_state_chg_callback(struct notifier_block *nb, unsigned long va } +static void fts_unblank(struct fts_ts_info *info) +{ + int i; + + for (i = 0; i < TOUCH_ID_MAX; i++) { + input_mt_slot(info->input_dev, i); + input_mt_report_slot_state(info->input_dev, + (i < FINGER_MAX) ? MT_TOOL_FINGER : MT_TOOL_PEN, 0); + } + input_sync(info->input_dev); + + info->resume_bit = 1; + + fts_mode_handler(info, 0); + + info->sensor_sleep = false; + + fts_enableInterrupt(); +} + static struct notifier_block fts_noti_block = { .notifier_call = fts_fb_state_chg_callback, }; diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 2f1c03783414..9db0dac938d3 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -879,6 +879,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar int compatible_arg = 1; long err = 0; + memset(&karg, 0, sizeof(karg)); /* First, convert the command. */ switch (cmd) { case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c index c6f2dbfe573d..687f55bd5afd 100644 --- a/drivers/misc/hdcp.c +++ b/drivers/misc/hdcp.c @@ -116,7 +116,7 @@ #define HDCP_CREATE_DEVICE_ID(x) (HDCP_DEVICE_ID | (x)) #define HDCP_TXMTR_HDMI HDCP_CREATE_DEVICE_ID(1) - +#define HDCP_TXMTR_DP HDCP_CREATE_DEVICE_ID(2) #define HDCP_TXMTR_SERVICE_ID 0x0001000 #define SERVICE_CREATE_CMD(x) (HDCP_TXMTR_SERVICE_ID | x) @@ -639,7 +639,8 @@ static int hdcp_lib_get_next_message(struct hdcp_lib_handle *handle, case LC_SEND_L_PRIME_MESSAGE_ID: return SKE_SEND_EKS_MESSAGE_ID; case SKE_SEND_EKS_MESSAGE_ID: - if (!handle->repeater_flag) + if (!handle->repeater_flag && + handle->device_type == HDCP_TXMTR_DP) return SKE_SEND_TYPE_ID; case SKE_SEND_TYPE_ID: case REPEATER_AUTH_STREAM_READY_MESSAGE_ID: @@ -1778,6 +1779,19 @@ exit: return rc; } +static void hdcp_lib_prep_type_id(struct hdcp_lib_handle *handle, + struct hdmi_hdcp_wakeup_data *cdata) +{ + memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); + handle->listener_buf[0] = SKE_SEND_TYPE_ID; + handle->msglen = 2; + cdata->cmd = HDMI_HDCP_WKUP_CMD_SEND_MESSAGE; + cdata->send_msg_buf = handle->listener_buf; + cdata->send_msg_len = handle->msglen; + handle->last_msg = hdcp_lib_get_next_message(handle, + cdata); +} + static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle) { struct hdmi_hdcp_wakeup_data cdata = { HDMI_HDCP_WKUP_CMD_INVALID }; @@ -1802,18 +1816,29 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle) cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL; break; case SKE_SEND_EKS_MESSAGE_ID: + /* + * a) if its a repeater irrespective of device type we + * start CMD_LINK_POLL to trigger repeater auth + * b) if its not a repeater and device is DP we + * first send the SKE_SEND_TYPE_ID and upon success + * enable encryption + * c) if its not a repeater and device is HDMI we + * dont send SKE_SEND_TYPE_ID and enable encryption + * and start part III of authentication + */ if (handle->repeater_flag) { /* poll for link check */ cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL; - } else { - memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); - handle->listener_buf[0] = SKE_SEND_TYPE_ID; - handle->msglen = 2; - cdata.cmd = HDMI_HDCP_WKUP_CMD_SEND_MESSAGE; - cdata.send_msg_buf = handle->listener_buf; - cdata.send_msg_len = handle->msglen; - handle->last_msg = hdcp_lib_get_next_message(handle, - &cdata); + } else if (handle->device_type == HDCP_TXMTR_DP) { + hdcp_lib_prep_type_id(handle, &cdata); + } else if (handle->device_type == HDCP_TXMTR_HDMI) { + if (!hdcp_lib_enable_encryption(handle)) { + handle->authenticated = true; + cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS; + hdcp_lib_wakeup_client(handle, &cdata); + } + /* poll for link check */ + cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL; } break; case REPEATER_AUTH_SEND_ACK_MESSAGE_ID: diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 2c297fba5c34..22fad9210945 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -60,7 +60,6 @@ MODULE_PARM_DESC(fbc_bypass, static int cnss_set_pci_config_space(struct cnss_pci_data *pci_priv, bool save) { - int ret = 0; struct pci_dev *pci_dev = pci_priv->pci_dev; struct cnss_plat_data *plat_priv = pci_priv->plat_priv; bool link_down_or_recovery; @@ -80,12 +79,8 @@ static int cnss_set_pci_config_space(struct cnss_pci_data *pci_priv, bool save) } } else { if (link_down_or_recovery) { - ret = msm_pcie_recover_config(pci_dev); - if (ret) { - cnss_pr_err("Failed to recover PCI config space, err = %d\n", - ret); - return ret; - } + pci_load_saved_state(pci_dev, pci_priv->default_state); + pci_restore_state(pci_dev); } else if (pci_priv->saved_state) { pci_load_and_free_saved_state(pci_dev, &pci_priv->saved_state); @@ -100,27 +95,15 @@ static int cnss_set_pci_link(struct cnss_pci_data *pci_priv, bool link_up) { int ret = 0; struct pci_dev *pci_dev = pci_priv->pci_dev; - struct cnss_plat_data *plat_priv = pci_priv->plat_priv; - bool link_down_or_recovery; - - if (!plat_priv) - return -ENODEV; - - link_down_or_recovery = pci_priv->pci_link_down_ind || - (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)); ret = msm_pcie_pm_control(link_up ? MSM_PCIE_RESUME : MSM_PCIE_SUSPEND, pci_dev->bus->number, pci_dev, NULL, - link_down_or_recovery ? - PM_OPTIONS_LINK_DOWN : PM_OPTIONS_DEFAULT); if (ret) { - cnss_pr_err("Failed to %s PCI link with %s option, err = %d\n", - link_up ? "resume" : "suspend", - link_down_or_recovery ? "link down" : "default", - ret); + cnss_pr_err("Failed to %s PCI link with default option, err = %d\n", + link_up ? "resume" : "suspend", ret); return ret; } @@ -1443,6 +1426,9 @@ static int cnss_pci_probe(struct pci_dev *pci_dev, if (ret) goto dereg_pci_event; + pci_save_state(pci_dev); + pci_priv->default_state = pci_store_saved_state(pci_dev); + switch (pci_dev->device) { case QCA6174_DEVICE_ID: pci_read_config_word(pci_dev, QCA6174_REV_ID_OFFSET, @@ -1514,6 +1500,8 @@ static void cnss_pci_remove(struct pci_dev *pci_dev) break; } + pci_load_and_free_saved_state(pci_dev, &pci_priv->saved_state); + cnss_pci_disable_bus(pci_priv); cnss_dereg_pci_event(pci_priv); if (pci_priv->smmu_mapping) diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h index 4dc29c3c1f10..e26e331e2f8a 100644 --- a/drivers/net/wireless/cnss2/pci.h +++ b/drivers/net/wireless/cnss2/pci.h @@ -65,6 +65,7 @@ struct cnss_pci_data { bool pci_link_state; bool pci_link_down_ind; struct pci_saved_state *saved_state; + struct pci_saved_state *default_state; struct msm_pcie_register_event msm_pci_event; atomic_t auto_suspended; bool monitor_wake_intr; diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c index 0cb1dea7113b..23dd9131d402 100644 --- a/drivers/power/supply/qcom/fg-util.c +++ b/drivers/power/supply/qcom/fg-util.c @@ -264,8 +264,7 @@ static inline bool fg_sram_address_valid(u16 address, int len) int fg_sram_write(struct fg_chip *chip, u16 address, u8 offset, u8 *val, int len, int flags) { - int rc = 0; - bool tried_again = false; + int rc = 0, tries = 0; bool atomic_access = false; if (!chip) @@ -292,7 +291,7 @@ int fg_sram_write(struct fg_chip *chip, u16 address, u8 offset, } else { flags = FG_IMA_DEFAULT; } -wait: + /* * Atomic access mean waiting upon SOC_UPDATE interrupt from * FG_ALG and do the transaction after that. This is to make @@ -301,16 +300,20 @@ wait: * FG cycle (~1.47 seconds). */ if (atomic_access) { - /* Wait for SOC_UPDATE completion */ - rc = wait_for_completion_interruptible_timeout( - &chip->soc_update, - msecs_to_jiffies(SOC_UPDATE_WAIT_MS)); - - /* If we were interrupted wait again one more time. */ - if (rc == -ERESTARTSYS && !tried_again) { - tried_again = true; - goto wait; - } else if (rc <= 0) { + for (tries = 0; tries < 2; tries++) { + /* Wait for SOC_UPDATE completion */ + rc = wait_for_completion_interruptible_timeout( + &chip->soc_update, + msecs_to_jiffies(SOC_UPDATE_WAIT_MS)); + if (rc > 0) { + rc = 0; + break; + } else if (!rc) { + rc = -ETIMEDOUT; + } + } + + if (rc < 0) { pr_err("wait for soc_update timed out rc=%d\n", rc); goto out; } diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 3b925d9b000e..18e3c5cdcc24 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -40,6 +40,15 @@ MODULE_PARM_DESC(qti_packet_debug, "Print QTI Packet's Raw Data"); static struct workqueue_struct *ipa_usb_wq; +static struct gsi_inst_status { + struct mutex gsi_lock; + bool inst_exist; + struct gsi_opts *opts; +} inst_status[IPA_USB_MAX_TETH_PROT_SIZE]; + +/* Deregister misc device and free instance structures */ +static void gsi_inst_clean(struct gsi_opts *opts); + static void ipa_disconnect_handler(struct gsi_data_port *d_port); static int gsi_ctrl_send_notification(struct f_gsi *gsi); static int gsi_alloc_trb_buffer(struct f_gsi *gsi); @@ -946,38 +955,71 @@ static int gsi_ctrl_dev_open(struct inode *ip, struct file *fp) struct gsi_ctrl_port *c_port = container_of(fp->private_data, struct gsi_ctrl_port, ctrl_device); + struct f_gsi *gsi; + struct gsi_inst_status *inst_cur; if (!c_port) { - log_event_err("%s: gsi ctrl port %pK", __func__, c_port); + pr_err_ratelimited("%s: gsi ctrl port %pK", __func__, c_port); return -ENODEV; } - log_event_dbg("%s: open ctrl dev %s", __func__, c_port->name); + pr_devel_ratelimited("%s: open ctrl dev %s", __func__, c_port->name); + + gsi = container_of(c_port, struct f_gsi, c_port); + inst_cur = &inst_status[gsi->prot_id]; + + mutex_lock(&inst_cur->gsi_lock); + + fp->private_data = &gsi->prot_id; + + if (!inst_cur->inst_exist) { + mutex_unlock(&inst_cur->gsi_lock); + pr_err_ratelimited( + "%s: [prot_id = %d], GSI instance freed already\n", + __func__, gsi->prot_id); + return -ENODEV; + } if (c_port->is_open) { - log_event_err("%s: Already opened", __func__); + mutex_unlock(&inst_cur->gsi_lock); + log_event_err("%s: Already opened\n", __func__); return -EBUSY; } c_port->is_open = true; + mutex_unlock(&inst_cur->gsi_lock); + return 0; } static int gsi_ctrl_dev_release(struct inode *ip, struct file *fp) { - struct gsi_ctrl_port *c_port = container_of(fp->private_data, - struct gsi_ctrl_port, - ctrl_device); + enum ipa_usb_teth_prot prot_id = + *(enum ipa_usb_teth_prot *)(fp->private_data); + struct gsi_inst_status *inst_cur = &inst_status[prot_id]; - if (!c_port) { - log_event_err("%s: gsi ctrl port %pK", __func__, c_port); + mutex_lock(&inst_cur->gsi_lock); + + if (unlikely(inst_cur->inst_exist == false)) { + if (inst_cur->opts) { + /* GSI instance clean up */ + gsi_inst_clean(inst_cur->opts); + inst_cur->opts = NULL; + } + mutex_unlock(&inst_cur->gsi_lock); + pr_err_ratelimited( + "%s: [prot_id = %d], Delayed free instance memory\n", + __func__, prot_id); return -ENODEV; } - log_event_dbg("close ctrl dev %s", c_port->name); + inst_cur->opts->gsi->c_port.is_open = false; + + mutex_unlock(&inst_cur->gsi_lock); - c_port->is_open = false; + log_event_dbg("close ctrl dev %s\n", + inst_cur->opts->gsi->c_port.name); return 0; } @@ -985,16 +1027,27 @@ static int gsi_ctrl_dev_release(struct inode *ip, struct file *fp) static ssize_t gsi_ctrl_dev_read(struct file *fp, char __user *buf, size_t count, loff_t *pos) { - struct gsi_ctrl_port *c_port = container_of(fp->private_data, - struct gsi_ctrl_port, - ctrl_device); - + struct gsi_ctrl_port *c_port; struct gsi_ctrl_pkt *cpkt = NULL; + enum ipa_usb_teth_prot prot_id = + *(enum ipa_usb_teth_prot *)(fp->private_data); + struct gsi_inst_status *inst_cur = &inst_status[prot_id]; unsigned long flags; int ret = 0; log_event_dbg("%s: Enter %zu", __func__, count); + mutex_lock(&inst_cur->gsi_lock); + if (unlikely(inst_cur->inst_exist == false)) { + mutex_unlock(&inst_cur->gsi_lock); + pr_err_ratelimited( + "%s: free_inst is called, free memory until dev is closed\n", + __func__); + return -ENODEV; + } + mutex_unlock(&inst_cur->gsi_lock); + + c_port = &inst_cur->opts->gsi->c_port; if (!c_port) { log_event_err("%s: gsi ctrl port %pK", __func__, c_port); return -ENODEV; @@ -1062,14 +1115,29 @@ static ssize_t gsi_ctrl_dev_write(struct file *fp, const char __user *buf, int ret = 0; unsigned long flags; struct gsi_ctrl_pkt *cpkt; - struct gsi_ctrl_port *c_port = container_of(fp->private_data, - struct gsi_ctrl_port, - ctrl_device); - struct f_gsi *gsi = c_port_to_gsi(c_port); - struct usb_request *req = c_port->notify_req; + struct gsi_ctrl_port *c_port; + struct usb_request *req; + enum ipa_usb_teth_prot prot_id = + *(enum ipa_usb_teth_prot *)(fp->private_data); + struct gsi_inst_status *inst_cur = &inst_status[prot_id]; + struct f_gsi *gsi; log_event_dbg("Enter %zu", count); + mutex_lock(&inst_cur->gsi_lock); + if (unlikely(inst_cur->inst_exist == false)) { + mutex_unlock(&inst_cur->gsi_lock); + pr_err_ratelimited( + "%s: free_inst is called, free memory until dev is closed\n", + __func__); + return -ENODEV; + } + mutex_unlock(&inst_cur->gsi_lock); + + gsi = inst_cur->opts->gsi; + c_port = &gsi->c_port; + req = c_port->notify_req; + if (!c_port || !req || !req->buf) { log_event_err("%s: c_port %pK req %pK req->buf %pK", __func__, c_port, req, req ? req->buf : req); @@ -1126,15 +1194,29 @@ static ssize_t gsi_ctrl_dev_write(struct file *fp, const char __user *buf, static long gsi_ctrl_dev_ioctl(struct file *fp, unsigned cmd, unsigned long arg) { - struct gsi_ctrl_port *c_port = container_of(fp->private_data, - struct gsi_ctrl_port, - ctrl_device); - struct f_gsi *gsi = c_port_to_gsi(c_port); + struct gsi_ctrl_port *c_port; + struct f_gsi *gsi; struct gsi_ctrl_pkt *cpkt; struct ep_info info; + enum ipa_usb_teth_prot prot_id = + *(enum ipa_usb_teth_prot *)(fp->private_data); + struct gsi_inst_status *inst_cur = &inst_status[prot_id]; int val, ret = 0; unsigned long flags; + mutex_lock(&inst_cur->gsi_lock); + if (unlikely(inst_cur->inst_exist == false)) { + mutex_unlock(&inst_cur->gsi_lock); + pr_err_ratelimited( + "%s: free_inst is called, free memory until dev is closed\n", + __func__); + return -ENODEV; + } + mutex_unlock(&inst_cur->gsi_lock); + + gsi = inst_cur->opts->gsi; + c_port = &gsi->c_port; + if (!c_port) { log_event_err("%s: gsi ctrl port %pK", __func__, c_port); return -ENODEV; @@ -1255,12 +1337,24 @@ exit_ioctl: static unsigned int gsi_ctrl_dev_poll(struct file *fp, poll_table *wait) { - struct gsi_ctrl_port *c_port = container_of(fp->private_data, - struct gsi_ctrl_port, - ctrl_device); + struct gsi_ctrl_port *c_port; + enum ipa_usb_teth_prot prot_id = + *(enum ipa_usb_teth_prot *)(fp->private_data); + struct gsi_inst_status *inst_cur = &inst_status[prot_id]; unsigned long flags; unsigned int mask = 0; + mutex_lock(&inst_cur->gsi_lock); + if (unlikely(inst_cur->inst_exist == false)) { + mutex_unlock(&inst_cur->gsi_lock); + pr_err_ratelimited( + "%s: free_inst is called, free memory until dev is closed\n", + __func__); + return -ENODEV; + } + mutex_unlock(&inst_cur->gsi_lock); + + c_port = &inst_cur->opts->gsi->c_port; if (!c_port) { log_event_err("%s: gsi ctrl port %pK", __func__, c_port); return -ENODEV; @@ -1578,6 +1672,7 @@ static void gsi_rndis_command_complete(struct usb_ep *ep, struct usb_request *req) { struct f_gsi *rndis = req->context; + rndis_init_msg_type *buf; int status; if (req->status != 0) { @@ -1590,6 +1685,16 @@ static void gsi_rndis_command_complete(struct usb_ep *ep, if (status < 0) log_event_err("RNDIS command error %d, %d/%d", status, req->actual, req->length); + + buf = (rndis_init_msg_type *)req->buf; + if (buf->MessageType == RNDIS_MSG_INIT) { + rndis->d_port.in_aggr_size = min_t(u32, + rndis->d_port.in_aggr_size, + rndis->params->dl_max_xfer_size); + log_event_dbg("RNDIS host dl_aggr_size:%d in_aggr_size:%d\n", + rndis->params->dl_max_xfer_size, + rndis->d_port.in_aggr_size); + } } static void @@ -2749,7 +2854,7 @@ static void gsi_unbind(struct usb_configuration *c, struct usb_function *f) static void gsi_free_func(struct usb_function *f) { - pr_debug("%s\n", __func__); + log_event_dbg("%s\n", __func__); } int gsi_bind_config(struct f_gsi *gsi) @@ -2845,6 +2950,7 @@ static void gsi_opts_release(struct config_item *item) { struct gsi_opts *opts = to_gsi_opts(item); + log_event_dbg("Release GSI: %s\n", __func__); usb_put_function_instance(&opts->func_inst); } @@ -3044,48 +3150,89 @@ static struct config_item_type gsi_func_type = { .ct_owner = THIS_MODULE, }; +static void gsi_inst_clean(struct gsi_opts *opts) +{ + if (opts->gsi->c_port.ctrl_device.fops) + misc_deregister(&opts->gsi->c_port.ctrl_device); + + kfree(opts->gsi); + kfree(opts); +} + static int gsi_set_inst_name(struct usb_function_instance *fi, const char *name) { - int ret, name_len; + int prot_id, name_len; struct f_gsi *gsi; - struct gsi_opts *opts = container_of(fi, struct gsi_opts, func_inst); + struct gsi_opts *opts, *opts_prev; + + opts = container_of(fi, struct gsi_opts, func_inst); name_len = strlen(name) + 1; if (name_len > MAX_INST_NAME_LEN) return -ENAMETOOLONG; - ret = name_to_prot_id(name); - if (ret < 0) { - pr_err("%s: failed to find prot id for %s instance\n", + prot_id = name_to_prot_id(name); + if (prot_id < 0) { + log_event_err("%s: failed to find prot id for %s instance\n", __func__, name); return -EINVAL; } - if (ret == IPA_USB_RNDIS) + mutex_lock(&inst_status[prot_id].gsi_lock); + opts_prev = inst_status[prot_id].opts; + if (opts_prev) { + mutex_unlock(&inst_status[prot_id].gsi_lock); + log_event_err("%s: prot_id = %d, prev inst do not freed yet\n", + __func__, prot_id); + return -EBUSY; + } + mutex_unlock(&inst_status[prot_id].gsi_lock); + + if (prot_id == IPA_USB_RNDIS) config_group_init_type_name(&opts->func_inst.group, "", &gsi_func_rndis_type); - gsi = gsi_function_init(ret); + gsi = gsi_function_init(prot_id); if (IS_ERR(gsi)) return PTR_ERR(gsi); opts->gsi = gsi; + /* Set instance status */ + mutex_lock(&inst_status[prot_id].gsi_lock); + inst_status[prot_id].inst_exist = true; + inst_status[prot_id].opts = opts; + mutex_unlock(&inst_status[prot_id].gsi_lock); + return 0; } static void gsi_free_inst(struct usb_function_instance *f) { struct gsi_opts *opts = container_of(f, struct gsi_opts, func_inst); + enum ipa_usb_teth_prot prot_id; if (!opts->gsi) return; - if (opts->gsi->c_port.ctrl_device.fops) - misc_deregister(&opts->gsi->c_port.ctrl_device); + prot_id = opts->gsi->prot_id; - kfree(opts->gsi); - kfree(opts); + mutex_lock(&inst_status[prot_id].gsi_lock); + if (opts->gsi->c_port.is_open) { + /* Mark instance exist as false */ + inst_status[prot_id].inst_exist = false; + mutex_unlock(&inst_status[prot_id].gsi_lock); + log_event_err( + "%s: [prot_id = %d] Dev is open, free mem when dev close\n", + __func__, prot_id); + return; + } + + /* Clear instance status */ + gsi_inst_clean(opts); + inst_status[prot_id].inst_exist = false; + inst_status[prot_id].opts = NULL; + mutex_unlock(&inst_status[prot_id].gsi_lock); } static struct usb_function_instance *gsi_alloc_inst(void) @@ -3099,7 +3246,7 @@ static struct usb_function_instance *gsi_alloc_inst(void) opts->func_inst.set_inst_name = gsi_set_inst_name; opts->func_inst.free_func_inst = gsi_free_inst; config_group_init_type_name(&opts->func_inst.group, "", - &gsi_func_type); + &gsi_func_type); return &opts->func_inst; } @@ -3124,6 +3271,8 @@ MODULE_DESCRIPTION("GSI function driver"); static int fgsi_init(void) { + int i; + ipa_usb_wq = alloc_workqueue("k_ipa_usb", WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_FREEZABLE, 1); if (!ipa_usb_wq) { @@ -3131,6 +3280,9 @@ static int fgsi_init(void) return -ENOMEM; } + for (i = 0; i < IPA_USB_MAX_TETH_PROT_SIZE; i++) + mutex_init(&inst_status[i].gsi_lock); + return usb_function_register(&gsiusb_func); } module_init(fgsi_init); diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index bc325a91a9bf..6b003239ed34 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -422,6 +422,22 @@ static int mdss_dp_clk_init(struct mdss_dp_drv_pdata *dp_drv, __func__); dp_drv->pixel_parent = NULL; } + + dp_drv->pixel_clk_two_div = devm_clk_get(dev, + "pixel_clk_two_div"); + if (IS_ERR(dp_drv->pixel_clk_two_div)) { + pr_debug("%s: Unable to get DP pixel two div clk\n", + __func__); + dp_drv->pixel_clk_two_div = NULL; + } + + dp_drv->pixel_clk_four_div = devm_clk_get(dev, + "pixel_clk_four_div"); + if (IS_ERR(dp_drv->pixel_clk_four_div)) { + pr_debug("%s: Unable to get DP pixel four div clk\n", + __func__); + dp_drv->pixel_clk_four_div = NULL; + } } else { if (dp_drv->pixel_parent) devm_clk_put(dev, dp_drv->pixel_parent); @@ -1418,6 +1434,16 @@ static int mdss_dp_enable_mainlink_clocks(struct mdss_dp_drv_pdata *dp) return ret; } + if (dp->pixel_parent && dp->pixel_clk_two_div && + dp->pixel_clk_four_div) { + if (dp->link_rate == DP_LINK_RATE_540) + clk_set_parent(dp->pixel_parent, + dp->pixel_clk_four_div); + else + clk_set_parent(dp->pixel_parent, + dp->pixel_clk_two_div); + } + mdss_dp_set_clock_rate(dp, "ctrl_link_clk", (dp->link_rate * DP_LINK_RATE_MULTIPLIER) / DP_KHZ_TO_HZ); diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index 983f5e34a515..f3f9ca277762 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -614,6 +614,8 @@ struct mdss_dp_drv_pdata { /* DP Pixel clock RCG and PLL parent */ struct clk *pixel_clk_rcg; struct clk *pixel_parent; + struct clk *pixel_clk_two_div; + struct clk *pixel_clk_four_div; /* regulators */ struct dss_module_power power_data[DP_MAX_PM]; diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c index f7b3d4664e86..037741df4382 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.c +++ b/drivers/video/fbdev/msm/mdss_dp_util.c @@ -835,6 +835,8 @@ void mdss_dp_sw_config_msa(struct mdss_dp_drv_pdata *dp) pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n); mvid = (pixel_m & 0xFFFF) * 5; nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); + if (dp->link_rate == DP_LINK_RATE_540) + nvid *= 2; } pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid); |
