summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp40.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp44.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp46.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.c6
-rw-r--r--drivers/media/platform/msm/vidc/msm_vdec.c8
-rw-r--r--drivers/media/platform/msm/vidc/msm_venc.c6
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_common.c2
-rw-r--r--drivers/mmc/card/block.c68
-rw-r--r--drivers/mmc/core/mmc.c8
-rw-r--r--drivers/mmc/host/sdhci-msm.c11
-rw-r--r--drivers/platform/msm/ipa/ipa_api.c19
-rw-r--r--drivers/platform/msm/ipa/ipa_api.h7
-rw-r--r--drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c38
-rw-r--r--drivers/platform/msm/ipa/ipa_common_i.h3
-rw-r--r--drivers/platform/msm/ipa/ipa_uc_offload_common_i.h5
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_i.h2
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_uc_ntn.c13
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_utils.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_i.h2
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c47
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_utils.c2
-rw-r--r--drivers/power/supply/qcom/qpnp-fg-gen3.c6
-rw-r--r--drivers/scsi/ufs/ufs-qcom.h1
-rw-r--r--drivers/scsi/ufs/ufshcd.c19
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c15
-rw-r--r--drivers/usb/gadget/composite.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c4
-rw-r--r--include/linux/ipa_uc_offload.h38
28 files changed, 323 insertions, 29 deletions
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index f5533fd9062e..981832b5a586 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -702,6 +702,12 @@ static void msm_vfe40_reg_update(struct vfe_device *vfe_dev,
vfe_dev->reg_update_requested;
if ((vfe_dev->is_split && vfe_dev->pdev->id == ISP_VFE1) &&
((frame_src == VFE_PIX_0) || (frame_src == VFE_SRC_MAX))) {
+ if (!vfe_dev->common_data->dual_vfe_res->vfe_base[ISP_VFE0]) {
+ pr_err("%s vfe_base for ISP_VFE0 is NULL\n", __func__);
+ spin_unlock_irqrestore(&vfe_dev->reg_update_lock,
+ flags);
+ return;
+ }
msm_camera_io_w_mb(update_mask,
vfe_dev->common_data->dual_vfe_res->vfe_base[ISP_VFE0]
+ 0x378);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
index c85bf1655b8c..cc4dd5eaf93e 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
@@ -560,6 +560,12 @@ static void msm_vfe44_reg_update(struct vfe_device *vfe_dev,
vfe_dev->reg_update_requested;
if ((vfe_dev->is_split && vfe_dev->pdev->id == ISP_VFE1) &&
((frame_src == VFE_PIX_0) || (frame_src == VFE_SRC_MAX))) {
+ if (!vfe_dev->common_data->dual_vfe_res->vfe_base[ISP_VFE0]) {
+ pr_err("%s vfe_base for ISP_VFE0 is NULL\n", __func__);
+ spin_unlock_irqrestore(&vfe_dev->reg_update_lock,
+ flags);
+ return;
+ }
msm_camera_io_w_mb(update_mask,
vfe_dev->common_data->dual_vfe_res->vfe_base[ISP_VFE0]
+ 0x378);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
index 72ce32940c29..632624034a04 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
@@ -499,6 +499,12 @@ static void msm_vfe46_reg_update(struct vfe_device *vfe_dev,
vfe_dev->reg_update_requested;
if ((vfe_dev->is_split && vfe_dev->pdev->id == ISP_VFE1) &&
((frame_src == VFE_PIX_0) || (frame_src == VFE_SRC_MAX))) {
+ if (!vfe_dev->common_data->dual_vfe_res->vfe_base[ISP_VFE0]) {
+ pr_err("%s vfe_base for ISP_VFE0 is NULL\n", __func__);
+ spin_unlock_irqrestore(&vfe_dev->reg_update_lock,
+ flags);
+ return;
+ }
msm_camera_io_w_mb(update_mask,
vfe_dev->common_data->dual_vfe_res->vfe_base[ISP_VFE0]
+ 0x3D8);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index 24d1c6cba84d..6716bb6caad6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -735,6 +735,12 @@ void msm_vfe47_reg_update(struct vfe_device *vfe_dev,
vfe_dev->reg_update_requested;
if ((vfe_dev->is_split && vfe_dev->pdev->id == ISP_VFE1) &&
((frame_src == VFE_PIX_0) || (frame_src == VFE_SRC_MAX))) {
+ if (!vfe_dev->common_data->dual_vfe_res->vfe_base[ISP_VFE0]) {
+ pr_err("%s vfe_base for ISP_VFE0 is NULL\n", __func__);
+ spin_unlock_irqrestore(&vfe_dev->reg_update_lock,
+ flags);
+ return;
+ }
msm_camera_io_w_mb(update_mask,
vfe_dev->common_data->dual_vfe_res->vfe_base[ISP_VFE0]
+ 0x4AC);
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 78cced2abd47..c80f535d95e1 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -847,6 +847,14 @@ int msm_vdec_streamoff(struct msm_vidc_inst *inst, enum v4l2_buf_type i)
return -EINVAL;
}
dprintk(VIDC_DBG, "Calling streamoff\n");
+
+ if (!inst->in_reconfig) {
+ rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
+ if (rc)
+ dprintk(VIDC_ERR,
+ "Failed to move inst: %pK to res done state\n", inst);
+ }
+
mutex_lock(&q->lock);
rc = vb2_streamoff(&q->vb2_bufq, i);
mutex_unlock(&q->lock);
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index e4698e0cdcd8..947ade9c99ed 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -4620,6 +4620,12 @@ int msm_venc_streamoff(struct msm_vidc_inst *inst, enum v4l2_buf_type i)
return -EINVAL;
}
dprintk(VIDC_DBG, "Calling streamoff on port: %d\n", i);
+
+ rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
+ if (rc)
+ dprintk(VIDC_ERR,
+ "Failed to move inst: %pK to res done state\n", inst);
+
mutex_lock(&q->lock);
rc = vb2_streamoff(&q->vb2_bufq, i);
mutex_unlock(&q->lock);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 1d910f4b235c..4cb8f92c4e38 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1179,7 +1179,7 @@ static void handle_event_change(enum hal_command_response cmd, void *data)
__func__, inst, &event_notify->packet_buffer,
&event_notify->extra_data_buffer);
- if (inst->state == MSM_VIDC_CORE_INVALID ||
+ if (inst->state >= MSM_VIDC_STOP ||
inst->core->state == VIDC_CORE_INVALID) {
dprintk(VIDC_DBG,
"Event release buf ref received in invalid state - discard\n");
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index d39b4056c169..c002fa5ff602 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -3894,6 +3894,7 @@ static inline int mmc_blk_cmdq_part_switch(struct mmc_card *card,
struct mmc_host *host = card->host;
struct mmc_cmdq_context_info *ctx = &host->cmdq_ctx;
u8 part_config = card->ext_csd.part_config;
+ int ret = 0, err = 0;
if ((main_md->part_curr == md->part_type) &&
(card->part_curr == md->part_type))
@@ -3903,40 +3904,70 @@ static inline int mmc_blk_cmdq_part_switch(struct mmc_card *card,
card->ext_csd.cmdq_support &&
(md->flags & MMC_BLK_CMD_QUEUE)));
- if (!test_bit(CMDQ_STATE_HALT, &ctx->curr_state))
- WARN_ON(mmc_cmdq_halt(host, true));
+ if (!test_bit(CMDQ_STATE_HALT, &ctx->curr_state)) {
+ ret = mmc_cmdq_halt(host, true);
+ if (ret) {
+ pr_err("%s: %s: halt: failed: %d\n",
+ mmc_hostname(host), __func__, ret);
+ goto out;
+ }
+ }
/* disable CQ mode in card */
if (mmc_card_cmdq(card)) {
- WARN_ON(mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_CMDQ, 0,
- card->ext_csd.generic_cmd6_time));
+ card->ext_csd.generic_cmd6_time);
+ if (ret) {
+ pr_err("%s: %s: cmdq mode disable failed %d\n",
+ mmc_hostname(host), __func__, ret);
+ goto cmdq_unhalt;
+ }
mmc_card_clr_cmdq(card);
}
part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
part_config |= md->part_type;
- WARN_ON(mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_PART_CONFIG, part_config,
- card->ext_csd.part_time));
+ card->ext_csd.part_time);
+ if (ret) {
+ pr_err("%s: %s: mmc_switch failure, %d -> %d , err = %d\n",
+ mmc_hostname(host), __func__, main_md->part_curr,
+ md->part_type, ret);
+ goto cmdq_switch;
+ }
card->ext_csd.part_config = part_config;
card->part_curr = md->part_type;
main_md->part_curr = md->part_type;
- WARN_ON(mmc_blk_cmdq_switch(card, md, true));
- WARN_ON(mmc_cmdq_halt(host, false));
-
- return 0;
+cmdq_switch:
+ err = mmc_blk_cmdq_switch(card, md, true);
+ if (err) {
+ pr_err("%s: %s: mmc_blk_cmdq_switch failed: %d\n",
+ mmc_hostname(host), __func__, err);
+ ret = err;
+ }
+cmdq_unhalt:
+ err = mmc_cmdq_halt(host, false);
+ if (err) {
+ pr_err("%s: %s: unhalt: failed: %d\n",
+ mmc_hostname(host), __func__, err);
+ ret = err;
+ }
+out:
+ return ret;
}
static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req)
{
- int ret;
+ int ret, err = 0;
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
+ struct mmc_host *host = card->host;
unsigned int cmd_flags = req ? req->cmd_flags : 0;
mmc_get_card(card);
@@ -3958,9 +3989,20 @@ static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req)
ret = mmc_blk_cmdq_part_switch(card, md);
if (ret) {
- pr_err("%s: %s: partition switch failed %d\n",
+ pr_err("%s: %s: partition switch failed %d, resetting cmdq\n",
md->disk->disk_name, __func__, ret);
- goto out;
+
+ mmc_blk_cmdq_reset(host, false);
+ err = mmc_blk_cmdq_part_switch(card, md);
+ if (!err) {
+ pr_err("%s: %s: partition switch success err = %d\n",
+ md->disk->disk_name, __func__, err);
+ } else {
+ pr_err("%s: %s: partition switch failed err = %d\n",
+ md->disk->disk_name, __func__, err);
+ ret = 0;
+ goto out;
+ }
}
if (req) {
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index a28d6b98a042..6f4f81a370d8 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2056,11 +2056,11 @@ reinit:
}
card->clk_scaling_lowest = host->f_min;
- if ((card->mmc_avail_type | EXT_CSD_CARD_TYPE_HS400) ||
- (card->mmc_avail_type | EXT_CSD_CARD_TYPE_HS200))
+ if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400) ||
+ (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200))
card->clk_scaling_highest = card->ext_csd.hs200_max_dtr;
- else if ((card->mmc_avail_type | EXT_CSD_CARD_TYPE_HS) ||
- (card->mmc_avail_type | EXT_CSD_CARD_TYPE_DDR_52))
+ else if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) ||
+ (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52))
card->clk_scaling_highest = card->ext_csd.hs_max_dtr;
else
card->clk_scaling_highest = card->csd.max_dtr;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index c86a800fc203..df3fce93b6d1 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -142,6 +142,7 @@
#define CORE_START_CDC_TRAFFIC (1 << 6)
#define CORE_PWRSAVE_DLL (1 << 3)
+#define CORE_FIFO_ALT_EN (1 << 10)
#define CORE_CMDEN_HS400_INPUT_MASK_CNT (1 << 13)
#define CORE_DDR_CAL_EN (1 << 0)
@@ -4154,7 +4155,7 @@ static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host,
* starts coming.
*/
if ((major == 1) && ((minor == 0x42) || (minor == 0x46) ||
- (minor == 0x49)))
+ (minor == 0x49) || (minor >= 0x6b)))
msm_host->use_14lpp_dll = true;
/* Fake 3.0V support for SDIO devices which requires such voltage */
@@ -4484,6 +4485,14 @@ static int sdhci_msm_probe(struct platform_device *pdev)
writel_relaxed(CORE_VENDOR_SPEC_POR_VAL,
host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC);
+ /*
+ * Ensure SDHCI FIFO is enabled by disabling alternative FIFO
+ */
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC3) &
+ ~CORE_FIFO_ALT_EN), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC3);
+
if (!msm_host->mci_removed) {
/* Set HC_MODE_EN bit in HC_MODE register */
writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 1a6ba1a915a0..bc0263c371a1 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -2943,6 +2943,25 @@ struct device *ipa_get_pdev(void)
}
EXPORT_SYMBOL(ipa_get_pdev);
+int ipa_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *user_data),
+ void *user_data)
+{
+ int ret;
+
+ IPA_API_DISPATCH_RETURN(ipa_ntn_uc_reg_rdyCB,
+ ipauc_ready_cb, user_data);
+
+ return ret;
+}
+EXPORT_SYMBOL(ipa_ntn_uc_reg_rdyCB);
+
+void ipa_ntn_uc_dereg_rdyCB(void)
+{
+ IPA_API_DISPATCH(ipa_ntn_uc_dereg_rdyCB);
+}
+EXPORT_SYMBOL(ipa_ntn_uc_dereg_rdyCB);
+
+
static const struct dev_pm_ops ipa_pm_ops = {
.suspend_noirq = ipa_ap_suspend,
.resume_noirq = ipa_ap_resume,
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index 69bc4ae1fa6a..1fb0e7122042 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -374,6 +374,11 @@ struct ipa_api_controller {
int ipa_ep_idx_dl);
struct device *(*ipa_get_pdev)(void);
+
+ int (*ipa_ntn_uc_reg_rdyCB)(void (*ipauc_ready_cb)(void *user_data),
+ void *user_data);
+
+ void (*ipa_ntn_uc_dereg_rdyCB)(void);
};
#ifdef CONFIG_IPA
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c b/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
index 51c930a81c8d..3a1e38f32321 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
@@ -622,3 +622,41 @@ int ipa_uc_offload_cleanup(u32 clnt_hdl)
return ret;
}
EXPORT_SYMBOL(ipa_uc_offload_cleanup);
+
+/**
+ * ipa_uc_offload_uc_rdyCB() - To register uC ready CB if uC not
+ * ready
+ * @inout: [in/out] input/output parameters
+ * from/to client
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ */
+int ipa_uc_offload_reg_rdyCB(struct ipa_uc_ready_params *inp)
+{
+ int ret = 0;
+
+ if (!inp) {
+ IPA_UC_OFFLOAD_ERR("Invalid input\n");
+ return -EINVAL;
+ }
+
+ if (inp->proto == IPA_UC_NTN)
+ ret = ipa_ntn_uc_reg_rdyCB(inp->notify, inp->priv);
+
+ if (ret == -EEXIST) {
+ inp->is_uC_ready = true;
+ ret = 0;
+ } else
+ inp->is_uC_ready = false;
+
+ return ret;
+}
+EXPORT_SYMBOL(ipa_uc_offload_reg_rdyCB);
+
+void ipa_uc_offload_dereg_rdyCB(enum ipa_uc_offload_proto proto)
+{
+ if (proto == IPA_UC_NTN)
+ ipa_ntn_uc_dereg_rdyCB();
+}
+EXPORT_SYMBOL(ipa_uc_offload_dereg_rdyCB);
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index d5f102eaaac6..911db0b19079 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -379,6 +379,9 @@ u8 *ipa_write_16(u16 hw, u8 *dest);
u8 *ipa_write_8(u8 b, u8 *dest);
u8 *ipa_pad_to_64(u8 *dest);
u8 *ipa_pad_to_32(u8 *dest);
+int ipa_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *user_data),
+ void *user_data);
+void ipa_ntn_uc_dereg_rdyCB(void);
const char *ipa_get_version_string(enum ipa_hw_type ver);
#endif /* _IPA_COMMON_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_uc_offload_common_i.h b/drivers/platform/msm/ipa/ipa_uc_offload_common_i.h
index ae6cfc4fcd50..0bc4b768e847 100644
--- a/drivers/platform/msm/ipa/ipa_uc_offload_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_uc_offload_common_i.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* 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
@@ -21,4 +21,7 @@ int ipa_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
struct ipa_ntn_conn_out_params *outp);
int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
+int ipa_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *user_data),
+ void *user_data);
+void ipa_ntn_uc_dereg_rdyCB(void);
#endif /* _IPA_UC_OFFLOAD_COMMON_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index 39d82fab325f..28689eb83d4e 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -1576,6 +1576,8 @@ int ipa2_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *inp,
ipa_notify_cb notify, void *priv, u8 hdr_len,
struct ipa_ntn_conn_out_params *outp);
int ipa2_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
+int ipa2_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *), void *priv);
+void ipa2_ntn_uc_dereg_rdyCB(void);
/*
* To retrieve doorbell physical address of
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_ntn.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_ntn.c
index 0b46ab2a8439..2aedfe04b5a3 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_ntn.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_ntn.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-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
@@ -165,6 +165,17 @@ int ipa2_register_ipa_ready_cb(void (*ipa_ready_cb)(void *), void *user_data)
return -EEXIST;
}
+int ipa2_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *), void *priv)
+{
+ return ipa2_register_ipa_ready_cb(ipauc_ready_cb, priv);
+}
+
+void ipa2_ntn_uc_dereg_rdyCB(void)
+{
+ ipa_ctx->uc_ntn_ctx.uc_ready_cb = NULL;
+ ipa_ctx->uc_ntn_ctx.priv = NULL;
+}
+
static void ipa_uc_ntn_loaded_handler(void)
{
if (!ipa_ctx) {
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index 50a8e46d3b12..a9bd0e11b330 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -5155,6 +5155,8 @@ int ipa2_bind_api_controller(enum ipa_hw_type ipa_hw_type,
api_ctrl->ipa_tear_down_uc_offload_pipes =
ipa2_tear_down_uc_offload_pipes;
api_ctrl->ipa_get_pdev = ipa2_get_pdev;
+ api_ctrl->ipa_ntn_uc_reg_rdyCB = ipa2_ntn_uc_reg_rdyCB;
+ api_ctrl->ipa_ntn_uc_dereg_rdyCB = ipa2_ntn_uc_dereg_rdyCB;
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 8ae714d4e7cc..5ff926a60129 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1733,6 +1733,8 @@ int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
ipa_notify_cb notify, void *priv, u8 hdr_len,
struct ipa_ntn_conn_out_params *outp);
int ipa3_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
+int ipa3_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *), void *priv);
+void ipa3_ntn_uc_dereg_rdyCB(void);
/*
* To retrieve doorbell physical address of
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 fdb6d05f683d..d4ff9c6ff851 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-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
@@ -149,6 +149,49 @@ int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats)
return 0;
}
+
+int ipa3_ntn_uc_reg_rdyCB(void (*ipa_ready_cb)(void *), void *user_data)
+{
+ int ret;
+
+ if (!ipa3_ctx) {
+ IPAERR("IPA ctx is null\n");
+ return -ENXIO;
+ }
+
+ ret = ipa3_uc_state_check();
+ if (ret) {
+ ipa3_ctx->uc_ntn_ctx.uc_ready_cb = ipa_ready_cb;
+ ipa3_ctx->uc_ntn_ctx.priv = user_data;
+ return 0;
+ }
+
+ return -EEXIST;
+}
+
+void ipa3_ntn_uc_dereg_rdyCB(void)
+{
+ ipa3_ctx->uc_ntn_ctx.uc_ready_cb = NULL;
+ ipa3_ctx->uc_ntn_ctx.priv = NULL;
+}
+
+static void ipa3_uc_ntn_loaded_handler(void)
+{
+ if (!ipa3_ctx) {
+ IPAERR("IPA ctx is null\n");
+ return;
+ }
+
+ if (ipa3_ctx->uc_ntn_ctx.uc_ready_cb) {
+ ipa3_ctx->uc_ntn_ctx.uc_ready_cb(
+ ipa3_ctx->uc_ntn_ctx.priv);
+
+ ipa3_ctx->uc_ntn_ctx.uc_ready_cb =
+ NULL;
+ ipa3_ctx->uc_ntn_ctx.priv = NULL;
+ }
+}
+
int ipa3_ntn_init(void)
{
struct ipa3_uc_hdlrs uc_ntn_cbs = { 0 };
@@ -156,6 +199,8 @@ int ipa3_ntn_init(void)
uc_ntn_cbs.ipa_uc_event_hdlr = ipa3_uc_ntn_event_handler;
uc_ntn_cbs.ipa_uc_event_log_info_hdlr =
ipa3_uc_ntn_event_log_info_handler;
+ uc_ntn_cbs.ipa_uc_loaded_hdlr =
+ ipa3_uc_ntn_loaded_handler;
ipa3_uc_register_handlers(IPA_HW_FEATURE_NTN, &uc_ntn_cbs);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 4979f62b928f..29f2046610c8 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -3287,6 +3287,8 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type,
api_ctrl->ipa_tear_down_uc_offload_pipes =
ipa3_tear_down_uc_offload_pipes;
api_ctrl->ipa_get_pdev = ipa3_get_pdev;
+ api_ctrl->ipa_ntn_uc_reg_rdyCB = ipa3_ntn_uc_reg_rdyCB;
+ api_ctrl->ipa_ntn_uc_dereg_rdyCB = ipa3_ntn_uc_dereg_rdyCB;
return 0;
}
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 8afd4b274335..626926e8b97d 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -1750,12 +1750,12 @@ static int fg_charge_full_update(struct fg_chip *chip)
/* We need 2 most significant bytes here */
bsoc = (u32)bsoc >> 16;
- rc = fg_get_msoc(chip, &msoc);
+ rc = fg_get_msoc_raw(chip, &msoc_raw);
if (rc < 0) {
- pr_err("Error in getting msoc, rc=%d\n", rc);
+ pr_err("Error in getting msoc_raw, rc=%d\n", rc);
goto out;
}
- msoc_raw = DIV_ROUND_CLOSEST(msoc * FULL_SOC_RAW, FULL_CAPACITY);
+ msoc = DIV_ROUND_CLOSEST(msoc_raw * FULL_CAPACITY, FULL_SOC_RAW);
fg_dbg(chip, FG_STATUS, "msoc: %d bsoc: %x health: %d status: %d full: %d\n",
msoc, bsoc, chip->health, chip->charge_status,
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index 460213536e14..9d532691f001 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -21,6 +21,7 @@
#define MAX_UFS_QCOM_HOSTS 1
#define MAX_U32 (~(u32)0)
#define MPHY_TX_FSM_STATE 0x41
+#define MPHY_RX_FSM_STATE 0xC1
#define TX_FSM_HIBERN8 0x1
#define HBRN8_POLL_TOUT_MS 100
#define DEFAULT_CLK_RATE_HZ 1000000
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c23023f43d30..523a2cff44a3 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -839,6 +839,24 @@ static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap)
}
}
+static void ufshcd_print_fsm_state(struct ufs_hba *hba)
+{
+ int err = 0, tx_fsm_val = 0, rx_fsm_val = 0;
+
+ err = ufshcd_dme_get(hba,
+ UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
+ UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+ &tx_fsm_val);
+ dev_err(hba->dev, "%s: TX_FSM_STATE = %u, err = %d\n", __func__,
+ tx_fsm_val, err);
+ err = ufshcd_dme_get(hba,
+ UIC_ARG_MIB_SEL(MPHY_RX_FSM_STATE,
+ UIC_ARG_MPHY_RX_GEN_SEL_INDEX(0)),
+ &rx_fsm_val);
+ dev_err(hba->dev, "%s: RX_FSM_STATE = %u, err = %d\n", __func__,
+ rx_fsm_val, err);
+}
+
static void ufshcd_print_host_state(struct ufs_hba *hba)
{
if (!(hba->ufshcd_dbg_print & UFSHCD_DBG_PRINT_HOST_STATE_EN))
@@ -863,6 +881,7 @@ static void ufshcd_print_host_state(struct ufs_hba *hba)
hba->capabilities, hba->caps);
dev_err(hba->dev, "quirks=0x%x, dev. quirks=0x%x\n", hba->quirks,
hba->dev_quirks);
+ ufshcd_print_fsm_state(hba);
}
/**
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 5ad68df298cd..3c0f68deee34 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -233,6 +233,7 @@ struct dwc3_msm {
struct pm_qos_request pm_qos_req_dma;
struct delayed_work perf_vote_work;
struct delayed_work sdp_check;
+ struct mutex suspend_resume_mutex;
};
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
@@ -1997,8 +1998,10 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
dbg_event(0xFF, "Ctl Sus", atomic_read(&dwc->in_lpm));
+ mutex_lock(&mdwc->suspend_resume_mutex);
if (atomic_read(&dwc->in_lpm)) {
dev_dbg(mdwc->dev, "%s: Already suspended\n", __func__);
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return 0;
}
@@ -2015,6 +2018,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
__func__, evt->count / 4);
dbg_print_reg("PENDING DEVICE EVENT",
*(u32 *)(evt->buf + evt->lpos));
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return -EBUSY;
}
}
@@ -2034,6 +2038,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
dev_dbg(mdwc->dev,
"%s: cable disconnected while not in idle otg state\n",
__func__);
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return -EBUSY;
}
@@ -2047,12 +2052,15 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
pr_err("%s(): Trying to go in LPM with state:%d\n",
__func__, dwc->gadget.state);
pr_err("%s(): LPM is not performed.\n", __func__);
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return -EBUSY;
}
ret = dwc3_msm_prepare_suspend(mdwc);
- if (ret)
+ if (ret) {
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return ret;
+ }
/* Initialize variables here */
can_suspend_ssphy = !(mdwc->in_host_mode &&
@@ -2153,6 +2161,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
}
dev_info(mdwc->dev, "DWC3 in low power mode\n");
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return 0;
}
@@ -2164,8 +2173,10 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__);
+ mutex_lock(&mdwc->suspend_resume_mutex);
if (!atomic_read(&dwc->in_lpm)) {
dev_dbg(mdwc->dev, "%s: Already resumed\n", __func__);
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return 0;
}
@@ -2300,6 +2311,7 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
msecs_to_jiffies(1000 * PM_QOS_SAMPLE_SEC));
dbg_event(0xFF, "Ctl Res", atomic_read(&dwc->in_lpm));
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return 0;
}
@@ -3179,6 +3191,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)
POWER_SUPPLY_PROP_PRESENT, &pval);
}
+ mutex_init(&mdwc->suspend_resume_mutex);
/* Update initial VBUS/ID state from extcon */
if (mdwc->extcon_vbus && extcon_get_cable_state_(mdwc->extcon_vbus,
EXTCON_USB))
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 442d44278f33..22ba45f40f0b 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -2088,7 +2088,7 @@ static ssize_t suspended_show(struct device *dev, struct device_attribute *attr,
struct usb_gadget *gadget = dev_to_usb_gadget(dev);
struct usb_composite_dev *cdev = get_gadget_data(gadget);
- return sprintf(buf, "%d\n", cdev->suspended);
+ return snprintf(buf, PAGE_SIZE, "%d\n", cdev->suspended);
}
static DEVICE_ATTR_RO(suspended);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index 13c57f811a81..af95a4a6dccd 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -3160,6 +3160,10 @@ static int hdmi_tx_power_off(struct hdmi_tx_ctrl *hdmi_ctrl)
if (hdmi_ctrl->panel_ops.off)
hdmi_ctrl->panel_ops.off(pdata);
+ hdmi_tx_set_mode(hdmi_ctrl, false);
+ hdmi_tx_phy_reset(hdmi_ctrl);
+ hdmi_tx_set_mode(hdmi_ctrl, true);
+
hdmi_tx_core_off(hdmi_ctrl);
hdmi_ctrl->panel_power_on = false;
diff --git a/include/linux/ipa_uc_offload.h b/include/linux/ipa_uc_offload.h
index 0277e87a2570..85d0ce92e6f6 100644
--- a/include/linux/ipa_uc_offload.h
+++ b/include/linux/ipa_uc_offload.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-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
@@ -163,6 +163,20 @@ struct ipa_perf_profile {
u32 max_supported_bw_mbps;
};
+/**
+ * struct ipa_uc_ready_params - uC ready CB parameters
+ * @is_uC_ready: uC loaded or not
+ * @priv : callback cookie
+ * @notify: callback
+ * @proto: uC offload protocol type
+ */
+struct ipa_uc_ready_params {
+ bool is_uC_ready;
+ void *priv;
+ ipa_uc_ready_cb notify;
+ enum ipa_uc_offload_proto proto;
+};
+
#if defined CONFIG_IPA || defined CONFIG_IPA3
/**
@@ -223,6 +237,19 @@ int ipa_uc_offload_disconn_pipes(u32 clnt_hdl);
*/
int ipa_set_perf_profile(struct ipa_perf_profile *profile);
+
+/*
+ * To register uC ready callback if uC not ready
+ * and also check uC readiness
+ * if uC not ready only, register callback
+ */
+int ipa_uc_offload_reg_rdyCB(struct ipa_uc_ready_params *param);
+
+/*
+ * To de-register uC ready callback
+ */
+void ipa_uc_offload_dereg_rdyCB(enum ipa_uc_offload_proto proto);
+
#else /* (CONFIG_IPA || CONFIG_IPA3) */
static inline int ipa_uc_offload_reg_intf(
@@ -254,6 +281,15 @@ static inline int ipa_set_perf_profile(struct ipa_perf_profile *profile)
return -EPERM;
}
+static inline int ipa_uc_offload_reg_rdyCB(struct ipa_uc_ready_params *param)
+{
+ return -EPERM;
+}
+
+static void ipa_uc_offload_dereg_rdyCB(enum ipa_uc_offload_proto proto)
+{
+}
+
#endif /* CONFIG_IPA3 */
#endif /* _IPA_UC_OFFLOAD_H_ */