diff options
| -rw-r--r-- | Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt | 8 | ||||
| -rw-r--r-- | drivers/clk/clk.c | 40 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/fg-core.h | 2 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/qpnp-fg-gen3.c | 33 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_gsi.c | 4 | ||||
| -rw-r--r-- | include/linux/clk-provider.h | 10 | ||||
| -rw-r--r-- | kernel/sched/hmp.c | 17 | ||||
| -rw-r--r-- | net/netlink/af_netlink.c | 37 | ||||
| -rw-r--r-- | net/netlink/af_netlink.h | 1 |
9 files changed, 121 insertions, 31 deletions
diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt index 421379116989..808e18b495d5 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt @@ -63,6 +63,14 @@ First Level Node - FG Gen3 device Definition: The voltage threshold (in mV) which upon set will be used for configuring the low battery voltage threshold. +- qcom,fg-recharge-voltage + Usage: optional + Value type: <u32> + Definition: The voltage threshold (in mV) based on which the charging + will be resumed once the charging is complete. If this + property is not specified, then the default value will be + 4250mV. + - qcom,fg-chg-term-current Usage: optional Value type: <u32> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index b42b68482279..c1865f9ee8b3 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3128,8 +3128,13 @@ static int __clk_init(struct device *dev, struct clk *clk_user) core->ops->init(core->hw); if (core->flags & CLK_IS_CRITICAL) { + unsigned long flags; + clk_core_prepare(core); + + flags = clk_enable_lock(); clk_core_enable(core); + clk_enable_unlock(flags); } kref_init(&core->ref); @@ -3864,6 +3869,41 @@ static int parent_ready(struct device_node *np) } /** + * of_clk_detect_critical() - set CLK_IS_CRITICAL flag from Device Tree + * @np: Device node pointer associated with clock provider + * @index: clock index + * @flags: pointer to clk_core->flags + * + * Detects if the clock-critical property exists and, if so, sets the + * corresponding CLK_IS_CRITICAL flag. + * + * Do not use this function. It exists only for legacy Device Tree + * bindings, such as the one-clock-per-node style that are outdated. + * Those bindings typically put all clock data into .dts and the Linux + * driver has no clock data, thus making it impossible to set this flag + * correctly from the driver. Only those drivers may call + * of_clk_detect_critical from their setup functions. + * + * Return: error code or zero on success + */ +int of_clk_detect_critical(struct device_node *np, + int index, unsigned long *flags) +{ + struct property *prop; + const __be32 *cur; + uint32_t idx; + + if (!np || !flags) + return -EINVAL; + + of_property_for_each_u32(np, "clock-critical", prop, cur, idx) + if (index == idx) + *flags |= CLK_IS_CRITICAL; + + return 0; +} + +/** * of_clk_init() - Scan and init clock providers from the DT * @matches: array of compatible values and init functions for providers. * diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index d612016b1b79..f0de532f196c 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -151,6 +151,7 @@ enum fg_sram_param_id { FG_SRAM_CHG_TERM_CURR, FG_SRAM_DELTA_SOC_THR, FG_SRAM_RECHARGE_SOC_THR, + FG_SRAM_RECHARGE_VBATT_THR, FG_SRAM_KI_COEFF_MED_DISCHG, FG_SRAM_KI_COEFF_HI_DISCHG, FG_SRAM_MAX, @@ -198,6 +199,7 @@ struct fg_dt_props { int sys_term_curr_ma; int delta_soc_thr; int recharge_soc_thr; + int recharge_volt_thr_mv; int rsense_sel; int jeita_thresholds[NUM_JEITA_LEVELS]; int esr_timer_charging; diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index 6ff0e9e45b00..4d2cfc84d455 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -112,6 +112,8 @@ #define EMPTY_VOLT_v2_OFFSET 3 #define VBATT_LOW_v2_WORD 16 #define VBATT_LOW_v2_OFFSET 0 +#define RECHARGE_VBATT_THR_v2_WORD 16 +#define RECHARGE_VBATT_THR_v2_OFFSET 1 #define FLOAT_VOLT_v2_WORD 16 #define FLOAT_VOLT_v2_OFFSET 2 @@ -236,6 +238,9 @@ static struct fg_sram_param pmi8998_v2_sram_params[] = { PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_v2_WORD, RECHARGE_SOC_THR_v2_OFFSET, 1, 256, 100, 0, fg_encode_default, NULL), + PARAM(RECHARGE_VBATT_THR, RECHARGE_VBATT_THR_v2_WORD, + RECHARGE_VBATT_THR_v2_OFFSET, 1, 1000, 15625, -2000, + fg_encode_voltage, NULL), PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD, ESR_TIMER_DISCHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL), @@ -2395,8 +2400,8 @@ static int fg_hw_init(struct fg_chip *chip) return rc; } - /* This SRAM register is only present in v2.0 */ - if (chip->pmic_rev_id->rev4 == PMI8998_V2P0_REV4 && + /* This SRAM register is only present in v2.0 and above */ + if (chip->pmic_rev_id->rev4 >= PMI8998_V2P0_REV4 && chip->bp.float_volt_uv > 0) { fg_encode(chip->sp, FG_SRAM_FLOAT_VOLT, chip->bp.float_volt_uv / 1000, buf); @@ -2476,6 +2481,23 @@ static int fg_hw_init(struct fg_chip *chip) } } + /* This configuration is available only for pmicobalt v2.0 and above */ + if (chip->pmic_rev_id->rev4 >= PMI8998_V2P0_REV4 && + chip->dt.recharge_volt_thr_mv > 0) { + fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR, + chip->dt.recharge_volt_thr_mv, buf); + rc = fg_sram_write(chip, + chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_word, + chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_byte, + buf, chip->sp[FG_SRAM_RECHARGE_VBATT_THR].len, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing recharge_vbatt_thr, rc=%d\n", + rc); + return rc; + } + } + if (chip->dt.rsense_sel >= SRC_SEL_BATFET && chip->dt.rsense_sel < SRC_SEL_RESERVED) { rc = fg_masked_write(chip, BATT_INFO_IBATT_SENSING_CFG(chip), @@ -2935,6 +2957,7 @@ static int fg_parse_ki_coefficients(struct fg_chip *chip) #define DEFAULT_CUTOFF_VOLT_MV 3200 #define DEFAULT_EMPTY_VOLT_MV 2800 +#define DEFAULT_RECHARGE_VOLT_MV 4250 #define DEFAULT_CHG_TERM_CURR_MA 100 #define DEFAULT_SYS_TERM_CURR_MA -125 #define DEFAULT_DELTA_SOC_THR 1 @@ -3096,6 +3119,12 @@ static int fg_parse_dt(struct fg_chip *chip) else chip->dt.recharge_soc_thr = temp; + rc = of_property_read_u32(node, "qcom,fg-recharge-voltage", &temp); + if (rc < 0) + chip->dt.recharge_volt_thr_mv = DEFAULT_RECHARGE_VOLT_MV; + else + chip->dt.recharge_volt_thr_mv = temp; + rc = of_property_read_u32(node, "qcom,fg-rsense-sel", &temp); if (rc < 0) chip->dt.rsense_sel = SRC_SEL_BATFET_SMB; diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 738f20d935d6..af20033b621f 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -1984,6 +1984,10 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) atomic_set(&gsi->connected, 1); + /* send 0 len pkt to qti to notify state change */ + if (gsi->prot_id == IPA_USB_DIAG) + gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0); + return 0; notify_ep_disable: diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 83e9c6e23f2f..aed90a4902c7 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -788,7 +788,8 @@ int of_clk_get_parent_count(struct device_node *np); int of_clk_parent_fill(struct device_node *np, const char **parents, unsigned int size); const char *of_clk_get_parent_name(struct device_node *np, int index); - +int of_clk_detect_critical(struct device_node *np, int index, + unsigned long *flags); void of_clk_init(const struct of_device_id *matches); #else /* !CONFIG_OF */ @@ -826,6 +827,13 @@ static inline const char *of_clk_get_parent_name(struct device_node *np, { return NULL; } + +static inline int of_clk_detect_critical(struct device_node *np, int index, + unsigned long *flags) +{ + return 0; +} + #define of_clk_init(matches) \ { while (0); } #endif /* CONFIG_OF */ diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c index a9ccb63c8e23..5ff7a11d043f 100644 --- a/kernel/sched/hmp.c +++ b/kernel/sched/hmp.c @@ -1771,20 +1771,20 @@ static int send_notification(struct rq *rq, int check_pred, int check_groups) if (freq_required < cur_freq + sysctl_sched_pred_alert_freq) return 0; } else { - read_lock(&related_thread_group_lock); + read_lock_irqsave(&related_thread_group_lock, flags); /* * Protect from concurrent update of rq->prev_runnable_sum and * group cpu load */ - raw_spin_lock_irqsave(&rq->lock, flags); + raw_spin_lock(&rq->lock); if (check_groups) _group_load_in_cpu(cpu_of(rq), &group_load, NULL); new_load = rq->prev_runnable_sum + group_load; new_load = freq_policy_load(rq, new_load); - raw_spin_unlock_irqrestore(&rq->lock, flags); - read_unlock(&related_thread_group_lock); + raw_spin_unlock(&rq->lock); + read_unlock_irqrestore(&related_thread_group_lock, flags); cur_freq = load_to_freq(rq, rq->old_busy_time); freq_required = load_to_freq(rq, new_load); @@ -3206,14 +3206,16 @@ void sched_get_cpus_busy(struct sched_load *busy, if (unlikely(cpus == 0)) return; + local_irq_save(flags); + + read_lock(&related_thread_group_lock); + /* * This function could be called in timer context, and the * current task may have been executing for a long time. Ensure * that the window stats are current by doing an update. */ - read_lock(&related_thread_group_lock); - local_irq_save(flags); for_each_cpu(cpu, query_cpus) raw_spin_lock(&cpu_rq(cpu)->lock); @@ -3313,10 +3315,11 @@ skip_early: for_each_cpu(cpu, query_cpus) raw_spin_unlock(&(cpu_rq(cpu))->lock); - local_irq_restore(flags); read_unlock(&related_thread_group_lock); + local_irq_restore(flags); + i = 0; for_each_cpu(cpu, query_cpus) { rq = cpu_rq(cpu); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 7a5fa0c98377..2b67ae1c53e4 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -926,16 +926,6 @@ static void netlink_skb_set_owner_r(struct sk_buff *skb, struct sock *sk) static void netlink_sock_destruct(struct sock *sk) { - struct netlink_sock *nlk = nlk_sk(sk); - - if (nlk->cb_running) { - if (nlk->cb.done) - nlk->cb.done(&nlk->cb); - - module_put(nlk->cb.module); - kfree_skb(nlk->cb.skb); - } - skb_queue_purge(&sk->sk_receive_queue); #ifdef CONFIG_NETLINK_MMAP if (1) { @@ -1070,8 +1060,9 @@ static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid) rcu_read_lock(); sk = __netlink_lookup(table, portid, net); - if (sk) - sock_hold(sk); + if (sk && !atomic_inc_not_zero(&sk->sk_refcnt)) + sk = NULL; + rcu_read_unlock(); return sk; @@ -1198,6 +1189,7 @@ static int __netlink_create(struct net *net, struct socket *sock, mutex_init(&nlk->pg_vec_lock); #endif + sock_set_flag(sk, SOCK_RCU_FREE); sk->sk_destruct = netlink_sock_destruct; sk->sk_protocol = protocol; return 0; @@ -1262,13 +1254,6 @@ out_module: goto out; } -static void deferred_put_nlk_sk(struct rcu_head *head) -{ - struct netlink_sock *nlk = container_of(head, struct netlink_sock, rcu); - - sock_put(&nlk->sk); -} - static int netlink_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -1341,7 +1326,19 @@ static int netlink_release(struct socket *sock) local_bh_disable(); sock_prot_inuse_add(sock_net(sk), &netlink_proto, -1); local_bh_enable(); - call_rcu(&nlk->rcu, deferred_put_nlk_sk); + if (nlk->cb_running) { + mutex_lock(nlk->cb_mutex); + if (nlk->cb_running) { + if (nlk->cb.done) + nlk->cb.done(&nlk->cb); + + module_put(nlk->cb.module); + kfree_skb(nlk->cb.skb); + nlk->cb_running = false; + } + mutex_unlock(nlk->cb_mutex); + } + sock_put(sk); return 0; } diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index 14437d9b1965..6acee01a419f 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h @@ -52,7 +52,6 @@ struct netlink_sock { #endif /* CONFIG_NETLINK_MMAP */ struct rhash_head node; - struct rcu_head rcu; }; static inline struct netlink_sock *nlk_sk(struct sock *sk) |
