diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/diag/diagchar.h | 1 | ||||
-rw-r--r-- | drivers/char/diag/diagchar_core.c | 20 | ||||
-rw-r--r-- | drivers/char/diag/diagfwd_cntl.c | 6 | ||||
-rw-r--r-- | drivers/iio/adc/qcom-rradc.c | 13 | ||||
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 10 | ||||
-rw-r--r-- | drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c | 16 | ||||
-rw-r--r-- | drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c | 22 | ||||
-rw-r--r-- | drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-msm.c | 4 | ||||
-rw-r--r-- | drivers/pci/host/pci-msm.c | 50 | ||||
-rw-r--r-- | drivers/power/supply/qcom/fg-core.h | 1 | ||||
-rw-r--r-- | drivers/power/supply/qcom/fg-memif.c | 78 | ||||
-rw-r--r-- | drivers/power/supply/qcom/qpnp-fg-gen3.c | 1 | ||||
-rw-r--r-- | drivers/power/supply/qcom/qpnp-qnovo.c | 143 | ||||
-rw-r--r-- | drivers/power/supply/qcom/qpnp-smb2.c | 2 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb-lib.h | 1 | ||||
-rw-r--r-- | drivers/soc/qcom/glink_private.h | 5 | ||||
-rw-r--r-- | drivers/soc/qcom/glink_ssr.c | 84 | ||||
-rw-r--r-- | drivers/usb/phy/phy-msm-ssusb-qmp.c | 8 |
19 files changed, 368 insertions, 99 deletions
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h index 9d235b7abc58..dbbd5514cdcc 100644 --- a/drivers/char/diag/diagchar.h +++ b/drivers/char/diag/diagchar.h @@ -418,6 +418,7 @@ struct diag_md_session_t { struct diag_mask_info *msg_mask; struct diag_mask_info *log_mask; struct diag_mask_info *event_mask; + struct thread_info *md_client_thread_info; struct task_struct *task; }; diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 335064352789..009a2a4f90a2 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -1237,11 +1237,10 @@ int diag_md_session_create(int mode, int peripheral_mask, int proc) mutex_unlock(&driver->md_session_lock); return -ENOMEM; } - new_session->peripheral_mask = 0; new_session->pid = current->tgid; new_session->task = current; - + new_session->md_client_thread_info = current_thread_info(); new_session->log_mask = kzalloc(sizeof(struct diag_mask_info), GFP_KERNEL); if (!new_session->log_mask) { @@ -1359,7 +1358,6 @@ static void diag_md_session_close(struct diag_md_session_t *session_info) struct diag_md_session_t *diag_md_session_get_pid(int pid) { int i; - for (i = 0; i < NUM_MD_SESSIONS; i++) { if (driver->md_session_map[i] && driver->md_session_map[i]->pid == pid) @@ -1475,7 +1473,10 @@ static int diag_md_session_check(int curr_mode, int req_mode, * If this session owns all the requested peripherals, then * call function to switch the modes/masks for the md_session */ + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(current->tgid); + mutex_unlock(&driver->md_session_lock); + if (!session_info) { *change_mode = 1; return 0; @@ -1504,7 +1505,9 @@ static int diag_md_session_check(int curr_mode, int req_mode, * owned by this md session */ change_mask = driver->md_session_mask & param->peripheral_mask; + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(current->tgid); + mutex_unlock(&driver->md_session_lock); if (session_info) { if ((session_info->peripheral_mask & change_mask) @@ -1892,8 +1895,9 @@ static int diag_ioctl_hdlc_toggle(unsigned long ioarg) { uint8_t hdlc_support; struct diag_md_session_t *session_info = NULL; - + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(current->tgid); + mutex_unlock(&driver->md_session_lock); if (copy_from_user(&hdlc_support, (void __user *)ioarg, sizeof(uint8_t))) return -EFAULT; @@ -2603,7 +2607,9 @@ static int diag_user_process_raw_data(const char __user *buf, int len) } else { wait_event_interruptible(driver->wait_q, (driver->in_busy_pktdata == 0)); + mutex_lock(&driver->md_session_lock); info = diag_md_session_get_pid(current->tgid); + mutex_unlock(&driver->md_session_lock); ret = diag_process_apps_pkt(user_space_data, len, info); if (ret == 1) diag_send_error_rsp((void *)(user_space_data), len, @@ -2671,7 +2677,9 @@ static int diag_user_process_userspace_data(const char __user *buf, int len) /* send masks to local processor now */ if (!remote_proc) { + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(current->tgid); + mutex_unlock(&driver->md_session_lock); if (!session_info) { pr_err("diag:In %s request came from invalid md session pid:%d", __func__, current->tgid); @@ -2832,7 +2840,9 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int)); /* place holder for number of data field */ ret += sizeof(int); + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(current->tgid); + mutex_unlock(&driver->md_session_lock); exit_stat = diag_md_copy_to_user(buf, &ret, count, session_info); goto exit; @@ -2846,7 +2856,9 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, data_type = driver->data_ready[index] & HDLC_SUPPORT_TYPE; driver->data_ready[index] ^= HDLC_SUPPORT_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int)); + mutex_lock(&driver->md_session_lock); session_info = diag_md_session_get_pid(current->tgid); + mutex_unlock(&driver->md_session_lock); if (session_info) COPY_USER_SPACE_OR_EXIT(buf+4, session_info->hdlc_disabled, diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c index 62c8d0028af9..96f4a15a5d67 100644 --- a/drivers/char/diag/diagfwd_cntl.c +++ b/drivers/char/diag/diagfwd_cntl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-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 @@ -124,7 +124,9 @@ void diag_notify_md_client(uint8_t peripheral, int data) info.si_signo = SIGCONT; if (driver->md_session_map[peripheral] && driver->md_session_map[peripheral]->task) { - if (driver->md_session_map[peripheral]->pid == + if (driver->md_session_map[peripheral]-> + md_client_thread_info->task != NULL + && driver->md_session_map[peripheral]->pid == driver->md_session_map[peripheral]->task->tgid) { DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "md_session %d pid = %d, md_session %d task tgid = %d\n", diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c index 202fee4711c1..537cca877f66 100644 --- a/drivers/iio/adc/qcom-rradc.c +++ b/drivers/iio/adc/qcom-rradc.c @@ -164,11 +164,6 @@ #define FG_ADC_RR_DIE_TEMP_SLOPE 2 #define FG_ADC_RR_DIE_TEMP_OFFSET_MILLI_DEGC 25000 -#define FAB_ID_GF 0x30 -#define FAB_ID_SMIC 0x11 -#define FAB_ID_660_GF 0x0 -#define FAB_ID_660_TSMC 0x2 -#define FAB_ID_660_MX 0x3 #define FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV 1303168 #define FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C 3784 #define FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV 1338433 @@ -402,11 +397,11 @@ static int rradc_get_660_fab_coeff(struct rradc_chip *chip, int64_t *offset, int64_t *slope) { switch (chip->pmic_fab_id->fab_id) { - case FAB_ID_660_GF: + case PM660_FAB_ID_GF: *offset = FG_ADC_RR_CHG_TEMP_660_GF_OFFSET_UV; *slope = FG_RR_CHG_TEMP_660_GF_SLOPE_UV_PER_C; break; - case FAB_ID_660_TSMC: + case PM660_FAB_ID_TSMC: *offset = FG_ADC_RR_CHG_TEMP_660_SMIC_OFFSET_UV; *slope = FG_RR_CHG_TEMP_660_SMIC_SLOPE_UV_PER_C; break; @@ -422,11 +417,11 @@ static int rradc_get_8998_fab_coeff(struct rradc_chip *chip, int64_t *offset, int64_t *slope) { switch (chip->pmic_fab_id->fab_id) { - case FAB_ID_GF: + case PMI8998_FAB_ID_GF: *offset = FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV; *slope = FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C; break; - case FAB_ID_SMIC: + case PMI8998_FAB_ID_SMIC: *offset = FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV; *slope = FG_ADC_RR_CHG_TEMP_SMIC_SLOPE_UV_PER_C; break; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 075c18e0e4ae..1d4e8a4ce206 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1128,6 +1128,16 @@ config TOUCHSCREEN_FT5X06_GESTURE If unsure, say N. +config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + bool "Synaptics DSX firmware update extra sysfs attributes" + depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE + help + Say Y here to enable support for extra sysfs attributes + supporting firmware update in a development environment. + This does not affect the core or other subsystem attributes. + + If unsure, say N. + config TOUCHSCREEN_ROHM_BU21023 tristate "ROHM BU21023/24 Dual touch support resistive touchscreens" depends on I2C diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c index 0ec16e606545..4787f2bcd768 100644 --- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c +++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c @@ -102,6 +102,7 @@ (fwu->config_data[2] == config_id[2]) && \ (fwu->config_data[3] == config_id[3])) +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static ssize_t fwu_sysfs_show_image(struct file *data_file, struct kobject *kobj, struct bin_attribute *attributes, char *buf, loff_t pos, size_t count); @@ -157,6 +158,7 @@ static ssize_t fwu_sysfs_config_id_show(struct device *dev, static ssize_t fwu_sysfs_package_id_show(struct device *dev, struct device_attribute *attr, char *buf); +#endif enum bl_version { V5 = 5, @@ -296,6 +298,7 @@ struct synaptics_rmi4_fwu_handle { struct synaptics_rmi4_data *rmi4_data; }; +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static struct bin_attribute dev_attr_data = { .attr = { .name = "data", @@ -305,9 +308,11 @@ static struct bin_attribute dev_attr_data = { .read = fwu_sysfs_show_image, .write = fwu_sysfs_store_image, }; +#endif static struct device_attribute attrs[] = { +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS __ATTR(force_update_fw, S_IWUSR | S_IWGRP, NULL, fwu_sysfs_force_reflash_store), @@ -353,6 +358,7 @@ static struct device_attribute attrs[] = { __ATTR(package_id, S_IRUGO, fwu_sysfs_package_id_show, synaptics_rmi4_store_error), +#endif }; static struct synaptics_rmi4_fwu_handle *fwu; @@ -1220,6 +1226,7 @@ write_config: return retval; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static int fwu_start_write_config(void) { int retval; @@ -1395,6 +1402,7 @@ exit: return retval; } +#endif static int fwu_do_lockdown(void) { @@ -1585,6 +1593,7 @@ int synaptics_dsx_fw_updater(unsigned char *fw_data) } EXPORT_SYMBOL(synaptics_dsx_fw_updater); +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static ssize_t fwu_sysfs_show_image(struct file *data_file, struct kobject *kobj, struct bin_attribute *attributes, char *buf, loff_t pos, size_t count) @@ -1972,6 +1981,7 @@ static ssize_t fwu_sysfs_package_id_show(struct device *dev, (package_id[1] << 8) | package_id[0], (package_id[3] << 8) | package_id[2]); } +#endif static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, unsigned char intr_mask) @@ -2045,6 +2055,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) fwu->do_lockdown = DO_LOCKDOWN; fwu->initialized = true; +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); if (retval < 0) { @@ -2053,6 +2064,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) __func__); goto exit_free_fwu; } +#endif for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, @@ -2074,7 +2086,9 @@ exit_remove_attrs: &attrs[attr_count].attr); } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +#endif exit_free_fwu: kfree(fwu); @@ -2096,7 +2110,9 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) &attrs[attr_count].attr); } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +#endif kfree(fwu->read_config_buf); kfree(fwu); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 54b237a9fc05..b44b7573e0e6 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -2441,7 +2441,7 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg) total_bandwidth += stream_info->bandwidth[ vfe_idx]; - stream_info->state = PAUSING; + stream_info->state = PAUSED; } spin_unlock_irqrestore(&stream_info->lock, flags); } @@ -2455,7 +2455,7 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg) msm_isp_get_stream_common_data(vfe_dev, ab_ib_vote->stream_src[i]); spin_lock_irqsave(&stream_info->lock, flags); - if (stream_info->state == PAUSING) { + if (stream_info->state == PAUSED) { vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev, stream_info); @@ -2813,6 +2813,7 @@ static int __msm_isp_check_stream_state(struct msm_vfe_axi_stream *stream_info, case RESUMING: case RESUME_PENDING: case ACTIVE: + case PAUSED: if (cmd != 0) return -EALREADY; break; @@ -2879,9 +2880,11 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev, * those state transitions instead of directly forcing stream to * be INACTIVE */ - while (stream_info->state != ACTIVE) - __msm_isp_axi_stream_update(stream_info, + if (stream_info->state != PAUSED) { + while (stream_info->state != ACTIVE) + __msm_isp_axi_stream_update(stream_info, ×tamp); + } msm_isp_cfg_stream_scratch(stream_info, VFE_PING_FLAG); msm_isp_cfg_stream_scratch(stream_info, VFE_PONG_FLAG); stream_info->undelivered_request_cnt = 0; @@ -2894,8 +2897,15 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev, vfe_dev->hw_info->vfe_ops.axi_ops. clear_wm_irq_mask(vfe_dev, stream_info); } - init_completion(&stream_info->inactive_comp); - stream_info->state = STOP_PENDING; + if (stream_info->state == ACTIVE) { + init_completion(&stream_info->inactive_comp); + stream_info->state = STOP_PENDING; + } else if (stream_info->state == PAUSED) { + /* don't wait for reg update */ + stream_info->state = STOP_PENDING; + msm_isp_axi_stream_enable_cfg(stream_info); + stream_info->state = INACTIVE; + } spin_unlock_irqrestore(&stream_info->lock, flags); } diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c index 9d52107c9993..41d8ef577a27 100644 --- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c @@ -73,7 +73,7 @@ static void msm_ispif_io_dump_reg(struct ispif_device *ispif) static inline int msm_ispif_is_intf_valid(uint32_t csid_version, - uint8_t intf_type) + enum msm_ispif_vfe_intf intf_type) { return ((csid_version <= CSID_VERSION_V22 && intf_type != VFE0) || (intf_type >= VFE_MAX)) ? false : true; diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index b696f54286da..3e51c9a86250 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -3913,8 +3913,8 @@ void sdhci_msm_pm_qos_cpu_init(struct sdhci_host *host, group->req.type = PM_QOS_REQ_AFFINE_CORES; cpumask_copy(&group->req.cpus_affine, &msm_host->pdata->pm_qos_data.cpu_group_map.mask[i]); - /* For initialization phase, set the performance mode latency */ - group->latency = latency[i].latency[SDHCI_PERFORMANCE_MODE]; + /* We set default latency here for all pm_qos cpu groups. */ + 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", diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index 584ad96c703f..6e9a8649ee2f 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -2511,6 +2511,48 @@ int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base, } EXPORT_SYMBOL(msm_pcie_debug_info); +#ifdef CONFIG_SYSFS +static ssize_t msm_pcie_enumerate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct msm_pcie_dev_t *pcie_dev = (struct msm_pcie_dev_t *) + dev_get_drvdata(dev); + + if (pcie_dev) + msm_pcie_enumerate(pcie_dev->rc_idx); + + return count; +} + +static DEVICE_ATTR(enumerate, S_IWUSR, NULL, msm_pcie_enumerate_store); + +static void msm_pcie_sysfs_init(struct msm_pcie_dev_t *dev) +{ + int ret; + + ret = device_create_file(&dev->pdev->dev, &dev_attr_enumerate); + if (ret) + PCIE_DBG_FS(dev, + "RC%d: failed to create sysfs enumerate node\n", + dev->rc_idx); +} + +static void msm_pcie_sysfs_exit(struct msm_pcie_dev_t *dev) +{ + if (dev->pdev) + device_remove_file(&dev->pdev->dev, &dev_attr_enumerate); +} +#else +static void msm_pcie_sysfs_init(struct msm_pcie_dev_t *dev) +{ +} + +static void msm_pcie_sysfs_exit(struct msm_pcie_dev_t *dev) +{ +} +#endif + #ifdef CONFIG_DEBUG_FS static struct dentry *dent_msm_pcie; static struct dentry *dfile_rc_sel; @@ -6277,6 +6319,9 @@ static int msm_pcie_probe(struct platform_device *pdev) msm_pcie_dev[rc_idx].pcidev_table[i].registered = true; } + dev_set_drvdata(&msm_pcie_dev[rc_idx].pdev->dev, &msm_pcie_dev[rc_idx]); + msm_pcie_sysfs_init(&msm_pcie_dev[rc_idx]); + ret = msm_pcie_get_resources(&msm_pcie_dev[rc_idx], msm_pcie_dev[rc_idx].pdev); @@ -6490,11 +6535,16 @@ int __init pcie_init(void) static void __exit pcie_exit(void) { + int i; + PCIE_GEN_DBG("pcie:%s.\n", __func__); platform_driver_unregister(&msm_pcie_driver); msm_pcie_debugfs_exit(); + + for (i = 0; i < MAX_RC_NUM; i++) + msm_pcie_sysfs_exit(&msm_pcie_dev[i]); } subsys_initcall_sync(pcie_init); diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index d4191561256a..f2047592a94b 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -375,6 +375,7 @@ struct fg_chip { bool soc_reporting_ready; bool esr_flt_cold_temp_en; bool slope_limit_en; + bool use_ima_single_mode; struct completion soc_update; struct completion soc_ready; struct delayed_work profile_load_work; diff --git a/drivers/power/supply/qcom/fg-memif.c b/drivers/power/supply/qcom/fg-memif.c index c00c72c5884c..8a949bfe61d0 100644 --- a/drivers/power/supply/qcom/fg-memif.c +++ b/drivers/power/supply/qcom/fg-memif.c @@ -48,6 +48,10 @@ static int fg_config_access_mode(struct fg_chip *chip, bool access, bool burst) int rc; u8 intf_ctl = 0; + fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "access: %d burst: %d\n", + access, burst); + + WARN_ON(burst && chip->use_ima_single_mode); intf_ctl = ((access == FG_WRITE) ? IMA_WR_EN_BIT : 0) | (burst ? MEM_ACS_BURST_BIT : 0); @@ -293,7 +297,9 @@ static int fg_check_iacs_ready(struct fg_chip *chip) /* check for error condition */ rc = fg_clear_ima_errors_if_any(chip, false); if (rc < 0) { - pr_err("Failed to check for ima errors rc=%d\n", rc); + if (rc != -EAGAIN) + pr_err("Failed to check for ima errors rc=%d\n", + rc); return rc; } @@ -357,7 +363,12 @@ static int __fg_interleaved_mem_write(struct fg_chip *chip, u16 address, /* check for error condition */ rc = fg_clear_ima_errors_if_any(chip, false); if (rc < 0) { - pr_err("Failed to check for ima errors rc=%d\n", rc); + if (rc == -EAGAIN) + pr_err("IMA error cleared, address [%d %d] len %d\n", + address, offset, len); + else + pr_err("Failed to check for ima errors rc=%d\n", + rc); return rc; } @@ -365,6 +376,15 @@ static int __fg_interleaved_mem_write(struct fg_chip *chip, u16 address, len -= num_bytes; offset = byte_enable = 0; + if (chip->use_ima_single_mode && len) { + address++; + rc = fg_set_address(chip, address); + if (rc < 0) { + pr_err("failed to set address rc = %d\n", rc); + return rc; + } + } + rc = fg_check_iacs_ready(chip); if (rc < 0) { pr_debug("IACS_RDY failed rc=%d\n", rc); @@ -403,22 +423,40 @@ static int __fg_interleaved_mem_read(struct fg_chip *chip, u16 address, /* check for error condition */ rc = fg_clear_ima_errors_if_any(chip, false); if (rc < 0) { - pr_err("Failed to check for ima errors rc=%d\n", rc); + if (rc == -EAGAIN) + pr_err("IMA error cleared, address [%d %d] len %d\n", + address, offset, len); + else + pr_err("Failed to check for ima errors rc=%d\n", + rc); return rc; } - if (len && len < BYTES_PER_SRAM_WORD) { - /* - * Move to single mode. Changing address is not - * required here as it must be in burst mode. Address - * will get incremented internally by FG HW once the MSB - * of RD_DATA is read. - */ - rc = fg_config_access_mode(chip, FG_READ, 0); - if (rc < 0) { - pr_err("failed to move to single mode rc=%d\n", - rc); - return -EIO; + if (chip->use_ima_single_mode) { + if (len) { + address++; + rc = fg_set_address(chip, address); + if (rc < 0) { + pr_err("failed to set address rc = %d\n", + rc); + return rc; + } + } + } else { + if (len && len < BYTES_PER_SRAM_WORD) { + /* + * Move to single mode. Changing address is not + * required here as it must be in burst mode. + * Address will get incremented internally by FG + * HW once the MSB of RD_DATA is read. + */ + rc = fg_config_access_mode(chip, FG_READ, + false); + if (rc < 0) { + pr_err("failed to move to single mode rc=%d\n", + rc); + return -EIO; + } } } @@ -489,6 +527,7 @@ static int fg_interleaved_mem_config(struct fg_chip *chip, u8 *val, u16 address, int offset, int len, bool access) { int rc = 0; + bool burst_mode = false; if (!is_mem_access_available(chip, access)) return -EBUSY; @@ -503,7 +542,8 @@ static int fg_interleaved_mem_config(struct fg_chip *chip, u8 *val, } /* configure for the read/write, single/burst mode */ - rc = fg_config_access_mode(chip, access, (offset + len) > 4); + burst_mode = chip->use_ima_single_mode ? false : ((offset + len) > 4); + rc = fg_config_access_mode(chip, access, burst_mode); if (rc < 0) { pr_err("failed to set memory access rc = %d\n", rc); return rc; @@ -583,7 +623,7 @@ retry: if (rc < 0) { count++; if (rc == -EAGAIN) { - pr_err("IMA access failed retry_count = %d\n", count); + pr_err("IMA read failed retry_count = %d\n", count); goto retry; } pr_err("failed to read SRAM address rc = %d\n", rc); @@ -667,8 +707,8 @@ retry: rc = __fg_interleaved_mem_write(chip, address, offset, val, len); if (rc < 0) { count++; - if ((rc == -EAGAIN) && (count < RETRY_COUNT)) { - pr_err("IMA access failed retry_count = %d\n", count); + if (rc == -EAGAIN) { + pr_err("IMA write failed retry_count = %d\n", count); goto retry; } pr_err("failed to write SRAM address rc = %d\n", rc); diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index 4290fbf00f32..59216a567662 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -3766,6 +3766,7 @@ static int fg_parse_dt(struct fg_chip *chip) case PM660_SUBTYPE: chip->sp = pmi8998_v2_sram_params; chip->alg_flags = pmi8998_v2_alg_flags; + chip->use_ima_single_mode = true; break; default: return -EINVAL; diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c index ada231905df9..8f9514a25f63 100644 --- a/drivers/power/supply/qcom/qpnp-qnovo.c +++ b/drivers/power/supply/qcom/qpnp-qnovo.c @@ -29,6 +29,7 @@ #define QNOVO_PTRAIN_STS 0x08 #define QNOVO_ERROR_STS 0x09 #define QNOVO_ERROR_BIT BIT(0) +#define QNOVO_ERROR_STS2 0x0A #define QNOVO_INT_RT_STS 0x10 #define QNOVO_INT_SET_TYPE 0x11 #define QNOVO_INT_POLARITY_HIGH 0x12 @@ -272,28 +273,22 @@ static int qnovo_disable_cb(struct votable *votable, void *data, int disable, const char *client) { struct qnovo *chip = data; - int rc = 0; + union power_supply_propval pval = {0}; + int rc; - if (disable) { - rc = qnovo_batt_psy_update(chip, true); - if (rc < 0) - return rc; - } + if (!is_batt_available(chip)) + return -EINVAL; - rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT, - disable ? 0 : QNOVO_PTRAIN_EN_BIT); + pval.intval = !disable; + rc = power_supply_set_property(chip->batt_psy, + POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE, + &pval); if (rc < 0) { - dev_err(chip->dev, "Couldn't %s pulse train rc=%d\n", - disable ? "disable" : "enable", rc); - return rc; - } - - if (!disable) { - rc = qnovo_batt_psy_update(chip, false); - if (rc < 0) - return rc; + pr_err("Couldn't set prop qnovo_enable rc = %d\n", rc); + return -EINVAL; } + rc = qnovo_batt_psy_update(chip, disable); return rc; } @@ -348,13 +343,15 @@ static int qnovo_check_chg_version(struct qnovo *chip) enum { VER = 0, OK_TO_QNOVO, - ENABLE, + QNOVO_ENABLE, + PT_ENABLE, FV_REQUEST, FCC_REQUEST, PE_CTRL_REG, PE_CTRL2_REG, PTRAIN_STS_REG, INT_RT_STS_REG, + ERR_STS2_REG, PREST1, PPULS1, NREST1, @@ -394,6 +391,12 @@ struct param_info { }; static struct param_info params[] = { + [PT_ENABLE] = { + .name = "PT_ENABLE", + .start_addr = QNOVO_PTRAIN_EN, + .num_regs = 1, + .units_str = "", + }, [FV_REQUEST] = { .units_str = "uV", }, @@ -424,6 +427,12 @@ static struct param_info params[] = { .num_regs = 1, .units_str = "", }, + [ERR_STS2_REG] = { + .name = "RAW_CHGR_ERR", + .start_addr = QNOVO_ERROR_STS2, + .num_regs = 1, + .units_str = "", + }, [PREST1] = { .name = "PREST1", .start_addr = QNOVO_PREST1_CTRL, @@ -648,30 +657,70 @@ static ssize_t ok_to_qnovo_show(struct class *c, struct class_attribute *attr, return snprintf(buf, PAGE_SIZE, "%d\n", chip->cs.ok_to_qnovo); } -static ssize_t enable_show(struct class *c, struct class_attribute *attr, +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; + int val = get_effective_result(chip->disable_votable); - val = get_client_vote(chip->disable_votable, USER_VOTER); - val = !val; - return snprintf(ubuf, PAGE_SIZE, "%d\n", val); + 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 ssize_t enable_store(struct class *c, struct class_attribute *attr, +static ssize_t pt_enable_show(struct class *c, struct class_attribute *attr, + char *ubuf) +{ + int i = attr - qnovo_attributes; + struct qnovo *chip = container_of(c, struct qnovo, qnovo_class); + u8 buf[2] = {0, 0}; + u16 regval; + int rc; + + rc = qnovo_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, "%d\n", + (int)(regval & QNOVO_PTRAIN_EN_BIT)); +} + +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; - bool disable; + int rc = 0; + + if (get_effective_result(chip->disable_votable)) + return -EINVAL; if (kstrtoul(ubuf, 0, &val)) return -EINVAL; - disable = !val; + rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT, + (bool)val ? QNOVO_PTRAIN_EN_BIT : 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't %s pulse train rc=%d\n", + (bool)val ? "enable" : "disable", rc); + return rc; + } - vote(chip->disable_votable, USER_VOTER, disable, 0); return count; } @@ -698,6 +747,9 @@ static ssize_t val_store(struct class *c, struct class_attribute *attr, int i = attr - qnovo_attributes; unsigned long val; + if (get_effective_result(chip->disable_votable)) + return -EINVAL; + if (kstrtoul(ubuf, 0, &val)) return -EINVAL; @@ -707,6 +759,8 @@ static ssize_t val_store(struct class *c, struct class_attribute *attr, if (i == FCC_REQUEST) chip->fcc_uA_request = val; + qnovo_batt_psy_update(chip, false); + return count; } @@ -1016,8 +1070,8 @@ static ssize_t batt_prop_show(struct class *c, struct class_attribute *attr, static struct class_attribute qnovo_attributes[] = { [VER] = __ATTR_RO(version), [OK_TO_QNOVO] = __ATTR_RO(ok_to_qnovo), - [ENABLE] = __ATTR(enable, 0644, - enable_show, enable_store), + [QNOVO_ENABLE] = __ATTR_RW(qnovo_enable), + [PT_ENABLE] = __ATTR_RW(pt_enable), [FV_REQUEST] = __ATTR(fv_uV_request, 0644, val_show, val_store), [FCC_REQUEST] = __ATTR(fcc_uA_request, 0644, @@ -1030,6 +1084,8 @@ static struct class_attribute qnovo_attributes[] = { reg_show, NULL), [INT_RT_STS_REG] = __ATTR(INT_RT_STS_REG, 0444, reg_show, NULL), + [ERR_STS2_REG] = __ATTR(ERR_STS2_REG, 0444, + reg_show, NULL), [PREST1] = __ATTR(PREST1_mS, 0644, time_show, time_store), [PPULS1] = __ATTR(PPULS1_uC, 0644, @@ -1050,7 +1106,7 @@ static struct class_attribute qnovo_attributes[] = { time_show, NULL), [PREST2] = __ATTR(PREST2_mS, 0644, time_show, time_store), - [PPULS2] = __ATTR(PPULS2_mS, 0644, + [PPULS2] = __ATTR(PPULS2_uC, 0644, coulomb_show, coulomb_store), [NREST2] = __ATTR(NREST2_mS, 0644, time_show, time_store), @@ -1135,8 +1191,7 @@ static void get_chg_status(struct qnovo *chip, const struct chg_props *cp, { cs->ok_to_qnovo = false; - if (cp->charging && - (cp->usb_online || cp->dc_online)) + if (cp->charging && (cp->usb_online || cp->dc_online)) cs->ok_to_qnovo = true; } @@ -1152,17 +1207,10 @@ static void status_change_work(struct work_struct *work) get_chg_status(chip, &cp, &cs); if (cs.ok_to_qnovo ^ chip->cs.ok_to_qnovo) { - /* - * when it is not okay to Qnovo charge, disable both voters, - * so that when it becomes okay to Qnovo charge the user voter - * has to specifically enable its vote to being Qnovo charging - */ - if (!cs.ok_to_qnovo) { - vote(chip->disable_votable, OK_TO_QNOVO_VOTER, 1, 0); - vote(chip->disable_votable, USER_VOTER, 1, 0); - } else { - vote(chip->disable_votable, OK_TO_QNOVO_VOTER, 0, 0); - } + vote(chip->disable_votable, OK_TO_QNOVO_VOTER, + !cs.ok_to_qnovo, 0); + if (!cs.ok_to_qnovo) + vote(chip->disable_votable, USER_VOTER, true, 0); notify_uevent = true; } @@ -1192,8 +1240,6 @@ static irqreturn_t handle_ptrain_done(int irq, void *data) { struct qnovo *chip = data; - /* disable user voter here */ - vote(chip->disable_votable, USER_VOTER, 0, 0); kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE); return IRQ_HANDLED; } @@ -1206,7 +1252,7 @@ static int qnovo_hw_init(struct qnovo *chip) u8 vadc_offset, vadc_gain; u8 val; - vote(chip->disable_votable, USER_VOTER, 1, 0); + vote(chip->disable_votable, USER_VOTER, true, 0); val = 0; rc = qnovo_write(chip, QNOVO_STRM_CTRL, &val, 1); @@ -1318,6 +1364,9 @@ static int qnovo_request_interrupts(struct qnovo *chip) irq_ptrain_done, rc); return rc; } + + enable_irq_wake(irq_ptrain_done); + return rc; } @@ -1399,6 +1448,8 @@ static int qnovo_probe(struct platform_device *pdev) goto unreg_notifier; } + device_init_wakeup(chip->dev, true); + return rc; unreg_notifier: diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index ee4b78181ade..e8249163e948 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -999,6 +999,8 @@ static int smb2_batt_set_prop(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CURRENT_QNOVO: chg->qnovo_fcc_ua = val->intval; + vote(chg->pl_disable_votable, PL_QNOVO_VOTER, + val->intval != -EINVAL && val->intval < 2000000, 0); rc = rerun_election(chg->fcc_votable); break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index 0645b60310b3..32a1c29bb376 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -37,6 +37,7 @@ enum print_reason { #define USB_PSY_VOTER "USB_PSY_VOTER" #define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER" #define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER" +#define PL_QNOVO_VOTER "PL_QNOVO_VOTER" #define USBIN_I_VOTER "USBIN_I_VOTER" #define USBIN_V_VOTER "USBIN_V_VOTER" #define CHG_STATE_VOTER "CHG_STATE_VOTER" diff --git a/drivers/soc/qcom/glink_private.h b/drivers/soc/qcom/glink_private.h index cdd6988418f7..24053c853a83 100644 --- a/drivers/soc/qcom/glink_private.h +++ b/drivers/soc/qcom/glink_private.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-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 @@ -693,6 +693,7 @@ enum ssr_command { * edge: The G-Link edge name for the channel associated with * this callback data * do_cleanup_data: Structure containing the G-Link SSR do_cleanup message. + * cb_kref: Kref object to maintain cb_data reference. */ struct ssr_notify_data { bool tx_done; @@ -700,6 +701,7 @@ struct ssr_notify_data { bool responded; const char *edge; struct do_cleanup_msg *do_cleanup_data; + struct kref cb_kref; }; /** @@ -734,6 +736,7 @@ struct subsys_info { int notify_list_len; bool link_up; spinlock_t link_up_lock; + spinlock_t cb_lock; }; /** diff --git a/drivers/soc/qcom/glink_ssr.c b/drivers/soc/qcom/glink_ssr.c index 5e2dbc8b1d20..7e23b0bc3852 100644 --- a/drivers/soc/qcom/glink_ssr.c +++ b/drivers/soc/qcom/glink_ssr.c @@ -115,6 +115,44 @@ static LIST_HEAD(subsystem_list); static atomic_t responses_remaining = ATOMIC_INIT(0); static wait_queue_head_t waitqueue; +/** + * cb_data_release() - Free cb_data and set to NULL + * @kref_ptr: pointer to kref. + * + * This function releses cb_data. + */ +static inline void cb_data_release(struct kref *kref_ptr) +{ + struct ssr_notify_data *cb_data; + + cb_data = container_of(kref_ptr, struct ssr_notify_data, cb_kref); + kfree(cb_data); +} + +/** + * check_and_get_cb_data() - Try to get reference to kref of cb_data + * @ss_info: pointer to subsystem info structure. + * + * Return: NULL is cb_data is NULL, pointer to cb_data otherwise + */ +static struct ssr_notify_data *check_and_get_cb_data( + struct subsys_info *ss_info) +{ + struct ssr_notify_data *cb_data; + unsigned long flags; + + spin_lock_irqsave(&ss_info->cb_lock, flags); + if (ss_info->cb_data == NULL) { + GLINK_SSR_LOG("<SSR> %s: cb_data is NULL\n", __func__); + spin_unlock_irqrestore(&ss_info->cb_lock, flags); + return 0; + } + kref_get(&ss_info->cb_data->cb_kref); + cb_data = ss_info->cb_data; + spin_unlock_irqrestore(&ss_info->cb_lock, flags); + return cb_data; +} + static void rx_done_cb_worker(struct work_struct *work) { struct rx_done_ch_work *rx_done_work = @@ -338,8 +376,10 @@ void close_ch_worker(struct work_struct *work) ss_info->link_state_handle = link_state_handle; BUG_ON(!ss_info->cb_data); - kfree(ss_info->cb_data); + spin_lock_irqsave(&ss_info->cb_lock, flags); + kref_put(&ss_info->cb_data->cb_kref, cb_data_release); ss_info->cb_data = NULL; + spin_unlock_irqrestore(&ss_info->cb_lock, flags); kfree(close_work); } @@ -507,13 +547,18 @@ int notify_for_subsystem(struct subsys_info *ss_info) return -ENODEV; } handle = ss_info_channel->handle; - ss_leaf_entry->cb_data = ss_info_channel->cb_data; + ss_leaf_entry->cb_data = check_and_get_cb_data( + ss_info_channel); + if (!ss_leaf_entry->cb_data) { + GLINK_SSR_LOG("<SSR> %s: CB data is NULL\n", __func__); + atomic_dec(&responses_remaining); + continue; + } spin_lock_irqsave(&ss_info->link_up_lock, flags); if (IS_ERR_OR_NULL(ss_info_channel->handle) || - !ss_info_channel->cb_data || !ss_info_channel->link_up || - ss_info_channel->cb_data->event + ss_leaf_entry->cb_data->event != GLINK_CONNECTED) { GLINK_SSR_LOG( @@ -526,6 +571,8 @@ int notify_for_subsystem(struct subsys_info *ss_info) spin_unlock_irqrestore(&ss_info->link_up_lock, flags); atomic_dec(&responses_remaining); + kref_put(&ss_leaf_entry->cb_data->cb_kref, + cb_data_release); continue; } spin_unlock_irqrestore(&ss_info->link_up_lock, flags); @@ -536,6 +583,8 @@ int notify_for_subsystem(struct subsys_info *ss_info) GLINK_SSR_ERR( "%s %s: Could not allocate do_cleanup_msg\n", "<SSR>", __func__); + kref_put(&ss_leaf_entry->cb_data->cb_kref, + cb_data_release); return -ENOMEM; } @@ -567,6 +616,8 @@ int notify_for_subsystem(struct subsys_info *ss_info) __func__); } atomic_dec(&responses_remaining); + kref_put(&ss_leaf_entry->cb_data->cb_kref, + cb_data_release); continue; } @@ -596,10 +647,12 @@ int notify_for_subsystem(struct subsys_info *ss_info) __func__); } atomic_dec(&responses_remaining); + kref_put(&ss_leaf_entry->cb_data->cb_kref, + cb_data_release); continue; } - sequence_number++; + kref_put(&ss_leaf_entry->cb_data->cb_kref, cb_data_release); } wait_ret = wait_event_timeout(waitqueue, @@ -608,6 +661,21 @@ int notify_for_subsystem(struct subsys_info *ss_info) list_for_each_entry(ss_leaf_entry, &ss_info->notify_list, notify_list_node) { + ss_info_channel = + get_info_for_subsystem(ss_leaf_entry->ssr_name); + if (ss_info_channel == NULL) { + GLINK_SSR_ERR( + "<SSR> %s: unable to find subsystem name\n", + __func__); + continue; + } + + ss_leaf_entry->cb_data = check_and_get_cb_data( + ss_info_channel); + if (!ss_leaf_entry->cb_data) { + GLINK_SSR_LOG("<SSR> %s: CB data is NULL\n", __func__); + continue; + } if (!wait_ret && !IS_ERR_OR_NULL(ss_leaf_entry->cb_data) && !ss_leaf_entry->cb_data->responded) { GLINK_SSR_ERR("%s %s: Subsystem %s %s\n", @@ -626,6 +694,7 @@ int notify_for_subsystem(struct subsys_info *ss_info) if (!IS_ERR_OR_NULL(ss_leaf_entry->cb_data)) ss_leaf_entry->cb_data->responded = false; + kref_put(&ss_leaf_entry->cb_data->cb_kref, cb_data_release); } complete(¬ifications_successful_complete); return 0; @@ -644,6 +713,7 @@ static int configure_and_open_channel(struct subsys_info *ss_info) struct glink_open_config open_cfg; struct ssr_notify_data *cb_data = NULL; void *handle = NULL; + unsigned long flags; if (!ss_info) { GLINK_SSR_ERR("<SSR> %s: ss_info structure invalid\n", @@ -660,7 +730,10 @@ static int configure_and_open_channel(struct subsys_info *ss_info) cb_data->responded = false; cb_data->event = GLINK_SSR_EVENT_INIT; cb_data->edge = ss_info->edge; + spin_lock_irqsave(&ss_info->cb_lock, flags); ss_info->cb_data = cb_data; + kref_init(&cb_data->cb_kref); + spin_unlock_irqrestore(&ss_info->cb_lock, flags); memset(&open_cfg, 0, sizeof(struct glink_open_config)); @@ -876,6 +949,7 @@ static int glink_ssr_probe(struct platform_device *pdev) ss_info->link_state_handle = NULL; ss_info->cb_data = NULL; spin_lock_init(&ss_info->link_up_lock); + spin_lock_init(&ss_info->cb_lock); nb = kmalloc(sizeof(struct restart_notifier_block), GFP_KERNEL); if (!nb) { diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c index c9df25286342..aa11cf2f7417 100644 --- a/drivers/usb/phy/phy-msm-ssusb-qmp.c +++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c @@ -330,10 +330,6 @@ static int msm_ssphy_qmp_init(struct usb_phy *uphy) phy->clk_enabled = true; } - /* select usb3 phy mode */ - if (phy->tcsr_usb3_dp_phymode) - writel_relaxed(0x0, phy->tcsr_usb3_dp_phymode); - writel_relaxed(0x01, phy->base + phy->phy_reg[USB3_PHY_POWER_DOWN_CONTROL]); @@ -409,6 +405,10 @@ static int msm_ssphy_qmp_reset(struct usb_phy *uphy) goto deassert_phy_phy_reset; } + /* select usb3 phy mode */ + if (phy->tcsr_usb3_dp_phymode) + writel_relaxed(0x0, phy->tcsr_usb3_dp_phymode); + /* Deassert USB3 PHY CSR reset */ ret = reset_control_deassert(phy->phy_reset); if (ret) { |