mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-25 06:03:36 -04:00
Merge 91a7f066e1 on remote branch
Change-Id: I826320b3aa563dabb7d6bfa1b5bc2f4ee5cd2b76
This commit is contained in:
commit
12398f32a8
79 changed files with 4501 additions and 1649 deletions
|
|
@ -1 +1 @@
|
|||
LTS_5.4.86_ccdcd307cf7e
|
||||
LTS_5.4.86_7d99cf8c84a7
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -92,6 +92,7 @@
|
|||
devm_phy_get
|
||||
devm_pinctrl_register
|
||||
devm_platform_ioremap_resource
|
||||
devm_regmap_field_alloc
|
||||
__devm_regmap_init_mmio_clk
|
||||
devm_regulator_bulk_get
|
||||
devm_regulator_get
|
||||
|
|
@ -213,6 +214,7 @@
|
|||
irq_set_irq_wake
|
||||
irq_to_desc
|
||||
jiffies
|
||||
jiffies_to_usecs
|
||||
kfree
|
||||
kfree_skb
|
||||
kimage_vaddr
|
||||
|
|
@ -251,6 +253,8 @@
|
|||
__netdev_alloc_skb
|
||||
netif_napi_add
|
||||
netif_napi_del
|
||||
nvmem_cell_get
|
||||
nvmem_cell_put
|
||||
nvmem_cell_read
|
||||
of_address_to_resource
|
||||
of_alias_get_id
|
||||
|
|
@ -368,6 +372,7 @@
|
|||
__register_rpmsg_driver
|
||||
regmap_bulk_read
|
||||
regmap_bulk_write
|
||||
regmap_field_read
|
||||
regmap_read
|
||||
regmap_update_bits_base
|
||||
regmap_write
|
||||
|
|
@ -1048,8 +1053,6 @@
|
|||
no_llseek
|
||||
nsecs_to_jiffies
|
||||
ns_to_timespec
|
||||
nvmem_cell_get
|
||||
nvmem_cell_put
|
||||
of_device_is_available
|
||||
of_dma_configure
|
||||
of_drm_find_bridge
|
||||
|
|
@ -1227,10 +1230,8 @@
|
|||
of_irq_get
|
||||
|
||||
# required by qcom_hwspinlock.ko
|
||||
devm_regmap_field_alloc
|
||||
hwspin_lock_register
|
||||
hwspin_lock_unregister
|
||||
regmap_field_read
|
||||
regmap_field_update_bits_base
|
||||
|
||||
# required by qcom_q6v5.ko
|
||||
|
|
@ -1252,7 +1253,6 @@
|
|||
__memcpy_toio
|
||||
|
||||
# required by qcom_spmi-regulator.ko
|
||||
jiffies_to_usecs
|
||||
regulator_disable_regmap
|
||||
regulator_enable_regmap
|
||||
regulator_is_enabled_regmap
|
||||
|
|
@ -1263,6 +1263,10 @@
|
|||
rproc_get_by_child
|
||||
try_wait_for_completion
|
||||
|
||||
# required by qcom_tsens.ko
|
||||
devm_thermal_zone_of_sensor_register
|
||||
thermal_zone_get_slope
|
||||
|
||||
# required by qmi_helpers.ko
|
||||
init_net
|
||||
kernel_getsockname
|
||||
|
|
|
|||
|
|
@ -1462,6 +1462,7 @@
|
|||
static_key_initialized
|
||||
static_key_slow_dec
|
||||
static_key_slow_inc
|
||||
stpcpy
|
||||
strcasecmp
|
||||
strcat
|
||||
strchr
|
||||
|
|
|
|||
|
|
@ -1103,9 +1103,11 @@
|
|||
gpiochip_generic_free
|
||||
gpiochip_generic_request
|
||||
gpiochip_get_data
|
||||
gpiochip_irqchip_add_key
|
||||
gpiochip_line_is_valid
|
||||
gpiochip_lock_as_irq
|
||||
gpiochip_remove
|
||||
gpiochip_set_nested_irqchip
|
||||
gpiochip_unlock_as_irq
|
||||
gpiod_direction_input
|
||||
gpiod_direction_output
|
||||
|
|
|
|||
|
|
@ -45,10 +45,12 @@
|
|||
backlight_device_unregister
|
||||
bin2hex
|
||||
__bitmap_clear
|
||||
bitmap_find_free_region
|
||||
bitmap_find_next_zero_area_off
|
||||
bitmap_free
|
||||
bitmap_parselist
|
||||
bitmap_print_to_pagebuf
|
||||
bitmap_release_region
|
||||
__bitmap_set
|
||||
__bitmap_subset
|
||||
bitmap_zalloc
|
||||
|
|
@ -1803,6 +1805,7 @@
|
|||
__pm_runtime_use_autosuspend
|
||||
__pm_stay_awake
|
||||
pm_stay_awake
|
||||
pm_system_cancel_wakeup
|
||||
pm_system_wakeup
|
||||
pm_wakeup_dev_event
|
||||
pm_wakeup_ws_event
|
||||
|
|
@ -2024,6 +2027,7 @@
|
|||
rpmsg_set_signals
|
||||
rpmsg_trysend
|
||||
rpmsg_unregister_device
|
||||
rtc_add_group
|
||||
rtc_class_close
|
||||
rtc_class_open
|
||||
rtc_read_time
|
||||
|
|
|
|||
1
arch/arm/configs/vendor/monaco.config
vendored
1
arch/arm/configs/vendor/monaco.config
vendored
|
|
@ -430,6 +430,7 @@ CONFIG_INCREMENTAL_FS=y
|
|||
CONFIG_QFMT_V2=y
|
||||
# CONFIG_QFMT_V1 is not set
|
||||
CONFIG_MSM_ADSPRPC=y
|
||||
CONFIG_MSM_RDBG=m
|
||||
CONFIG_QSEECOM=y
|
||||
CONFIG_USB_CONFIGFS_F_ACC=y
|
||||
CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
|
||||
|
|
|
|||
|
|
@ -890,3 +890,5 @@ CONFIG_QTI_SYSTEM_PM_RPM=y
|
|||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_STM_PROTO_BASIC=y
|
||||
CONFIG_QTI_ADC_TM=y
|
||||
CONFIG_PANIC_ON_SCHED_BUG=y
|
||||
CONFIG_PANIC_ON_RT_THROTTLING=y
|
||||
|
|
|
|||
72
arch/arm/configs/vendor/sdxnightjar.config
vendored
72
arch/arm/configs/vendor/sdxnightjar.config
vendored
|
|
@ -64,6 +64,62 @@ CONFIG_INTERCONNECT_TEST=y
|
|||
CONFIG_INTERCONNECT_QCOM=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_ARCH_SDXNIGHTJAR=y
|
||||
CONFIG_ETHERNET=y
|
||||
# CONFIG_NET_VENDOR_3COM is not set
|
||||
# CONFIG_NET_VENDOR_ADAPTEC is not set
|
||||
# CONFIG_NET_VENDOR_AGERE is not set
|
||||
# CONFIG_NET_VENDOR_ALACRITECH is not set
|
||||
# CONFIG_NET_VENDOR_ALTEON is not set
|
||||
# CONFIG_ALTERA_TSE is not set
|
||||
# CONFIG_NET_VENDOR_AMAZON is not set
|
||||
# CONFIG_NET_VENDOR_AMD is not set
|
||||
# CONFIG_NET_VENDOR_AQUANTIA is not set
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
CONFIG_NET_VENDOR_ATHEROS=y
|
||||
# CONFIG_ATL2 is not set
|
||||
# CONFIG_ATL1 is not set
|
||||
# CONFIG_ATL1E is not set
|
||||
# CONFIG_ATL1C is not set
|
||||
# CONFIG_ALX is not set
|
||||
# CONFIG_NET_VENDOR_AURORA is not set
|
||||
# CONFIG_NET_VENDOR_BROADCOM is not set
|
||||
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||
# CONFIG_NET_VENDOR_CADENCE is not set
|
||||
# CONFIG_NET_VENDOR_CAVIUM is not set
|
||||
# CONFIG_NET_VENDOR_CHELSIO is not set
|
||||
# CONFIG_NET_VENDOR_CIRRUS is not set
|
||||
# CONFIG_NET_VENDOR_CISCO is not set
|
||||
# CONFIG_NET_VENDOR_CORTINA is not set
|
||||
# CONFIG_DM9000 is not set
|
||||
# CONFIG_DNET is not set
|
||||
# CONFIG_NET_VENDOR_DEC is not set
|
||||
# CONFIG_NET_VENDOR_DLINK is not set
|
||||
# CONFIG_NET_VENDOR_EMULEX is not set
|
||||
# CONFIG_NET_VENDOR_EZCHIP is not set
|
||||
# CONFIG_NET_VENDOR_FARADAY is not set
|
||||
# CONFIG_NET_VENDOR_GOOGLE is not set
|
||||
# CONFIG_NET_VENDOR_HISILICON is not set
|
||||
# CONFIG_NET_VENDOR_HP is not set
|
||||
# CONFIG_NET_VENDOR_HUAWEI is not set
|
||||
# CONFIG_NET_VENDOR_INTEL is not set
|
||||
# CONFIG_JME is not set
|
||||
# CONFIG_NET_VENDOR_MARVELL is not set
|
||||
# CONFIG_NET_VENDOR_MELLANOX is not set
|
||||
# CONFIG_NET_VENDOR_MICREL is not set
|
||||
# CONFIG_NET_VENDOR_MICROCHIP is not set
|
||||
# CONFIG_NET_VENDOR_MICROSEMI is not set
|
||||
# CONFIG_NET_VENDOR_MYRI is not set
|
||||
# CONFIG_FEALNX is not set
|
||||
# CONFIG_NET_VENDOR_NATSEMI is not set
|
||||
# CONFIG_NET_VENDOR_NETERION is not set
|
||||
# CONFIG_NET_VENDOR_NETRONOME is not set
|
||||
# CONFIG_NET_VENDOR_NI is not set
|
||||
# CONFIG_NET_VENDOR_NVIDIA is not set
|
||||
# CONFIG_NET_VENDOR_OKI is not set
|
||||
# CONFIG_ETHOC is not set
|
||||
# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
|
||||
# CONFIG_NET_VENDOR_PENSANDO is not set
|
||||
# CONFIG_NET_VENDOR_QLOGIC is not set
|
||||
CONFIG_PINCTRL_SDXNIGHTJAR=y
|
||||
# CONFIG_ARCH_SDXLEMUR is not set
|
||||
# CONFIG_PINCTRL_SDXLEMUR is not set
|
||||
|
|
@ -926,3 +982,19 @@ CONFIG_PCIEPORTBUS=y
|
|||
CONFIG_PCIEAER=y
|
||||
CONFIG_PCI_QTI=y
|
||||
CONFIG_PCIEASPM_POWER_SUPERSAVE=y
|
||||
# CONFIG_WLAN_VENDOR_ADMTEK is not set
|
||||
# CONFIG_WLAN_VENDOR_ATH is not set
|
||||
# CONFIG_WLAN_VENDOR_ATMEL is not set
|
||||
# CONFIG_WLAN_VENDOR_BROADCOM is not set
|
||||
# CONFIG_WLAN_VENDOR_CISCO is not set
|
||||
# CONFIG_WLAN_VENDOR_INTEL is not set
|
||||
# CONFIG_WLAN_VENDOR_INTERSIL is not set
|
||||
# CONFIG_WLAN_VENDOR_MARVELL is not set
|
||||
# CONFIG_WLAN_VENDOR_MEDIATEK is not set
|
||||
# CONFIG_WLAN_VENDOR_RALINK is not set
|
||||
# CONFIG_WLAN_VENDOR_REALTEK is not set
|
||||
# CONFIG_WLAN_VENDOR_RSI is not set
|
||||
# CONFIG_WLAN_VENDOR_ST is not set
|
||||
# CONFIG_WLAN_VENDOR_TI is not set
|
||||
# CONFIG_WLAN_VENDOR_ZYDAS is not set
|
||||
# CONFIG_WLAN_VENDOR_QUANTENNA is not set
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
|
|||
CONFIG_PINCTRL_SDM845=m
|
||||
CONFIG_POWER_RESET_QCOM_PON=m
|
||||
CONFIG_SYSCON_REBOOT_MODE=m
|
||||
CONFIG_QCOM_TSENS=m
|
||||
CONFIG_QCOM_WDT=m
|
||||
CONFIG_PM8916_WATCHDOG=m
|
||||
CONFIG_MFD_SPMI_PMIC=m
|
||||
|
|
|
|||
1
arch/arm64/configs/vendor/holi_GKI.config
vendored
1
arch/arm64/configs/vendor/holi_GKI.config
vendored
|
|
@ -239,3 +239,4 @@ CONFIG_SM_GCC_BLAIR=m
|
|||
CONFIG_SM_GPUCC_BLAIR=m
|
||||
CONFIG_SM_DISPCC_BLAIR=m
|
||||
CONFIG_SM_DEBUGCC_BLAIR=m
|
||||
CONFIG_QCOM_CX_IPEAK=m
|
||||
|
|
|
|||
1
arch/arm64/configs/vendor/lahaina_GKI.config
vendored
1
arch/arm64/configs/vendor/lahaina_GKI.config
vendored
|
|
@ -198,6 +198,7 @@ CONFIG_VIDEOBUF2_VMALLOC=m
|
|||
CONFIG_SLIMBUS_MSM_NGD=m
|
||||
CONFIG_QRTR_HAVEN=m
|
||||
CONFIG_QCOM_CDSP_RM=m
|
||||
CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS=m
|
||||
CONFIG_QCOM_PDC=m
|
||||
CONFIG_HEADER_TEST=y
|
||||
CONFIG_HEADERS_INSTALL=y
|
||||
|
|
|
|||
|
|
@ -630,7 +630,10 @@ static struct elevator_type *elevator_get_default(struct request_queue *q)
|
|||
{
|
||||
if (q->nr_hw_queues != 1)
|
||||
return NULL;
|
||||
|
||||
#if defined(CONFIG_SDC_QTI) || defined(CONFIG_SCSI_UFSHCD_QTI)
|
||||
if (IS_ENABLED(CONFIG_IOSCHED_BFQ))
|
||||
return elevator_get(q, "bfq", false);
|
||||
#endif
|
||||
return elevator_get(q, "mq-deadline", false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1373,7 +1373,7 @@ static void device_links_purge(struct device *dev)
|
|||
return;
|
||||
|
||||
mutex_lock(&wfs_lock);
|
||||
list_del(&dev->links.needs_suppliers);
|
||||
list_del_init(&dev->links.needs_suppliers);
|
||||
mutex_unlock(&wfs_lock);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -925,6 +925,7 @@ void pm_system_cancel_wakeup(void)
|
|||
{
|
||||
atomic_dec_if_positive(&pm_abort_suspend);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_system_cancel_wakeup);
|
||||
|
||||
void pm_wakeup_clear(bool reset)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -276,6 +276,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
|
|||
#define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0)
|
||||
#define LUCID_EVO_PLL_CAL_L_VAL_MASK GENMASK(31, 16)
|
||||
|
||||
/*
|
||||
* The lucid_5lpe CPU PLL on SDX targets overloaded this field. Reading it
|
||||
* returns PCAL_DONE and writing it asserts the latch.
|
||||
*/
|
||||
#define LUCID_5LPE_SDX_CPU_LATCH_INPUT LUCID_5LPE_PCAL_DONE
|
||||
|
||||
/* ZONDA PLL specific offsets */
|
||||
#define ZONDA_PLL_OUT_MASK 0xF
|
||||
#define ZONDA_STAY_IN_CFA BIT(16)
|
||||
|
|
@ -3190,6 +3196,61 @@ static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int alpha_pll_lucid_5lpe_sdx_cpu_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long prate)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
unsigned long rrate;
|
||||
u32 regval, l;
|
||||
u64 a;
|
||||
int ret;
|
||||
|
||||
rrate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_16BIT_WIDTH);
|
||||
|
||||
/*
|
||||
* Due to a limited number of bits for fractional rate programming, the
|
||||
* rounded up rate could be marginally higher than the requested rate.
|
||||
*/
|
||||
if (rrate > (rate + PLL_OUT_RATE_MARGIN) || rrate < rate) {
|
||||
pr_err("Call set rate on the PLL with rounded rates!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
|
||||
regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
|
||||
|
||||
/* Latch the PLL input */
|
||||
ret = regmap_write_bits(pll->clkr.regmap, PLL_MODE(pll),
|
||||
LUCID_5LPE_SDX_CPU_LATCH_INPUT,
|
||||
LUCID_5LPE_SDX_CPU_LATCH_INPUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Wait for 2 reference cycles before checking the ACK bit. */
|
||||
udelay(1);
|
||||
regmap_read(pll->clkr.regmap, PLL_MODE(pll), ®val);
|
||||
if (!(regval & LUCID_5LPE_ALPHA_PLL_ACK_LATCH)) {
|
||||
WARN_CLK(&pll->clkr.hw, 1,
|
||||
"PLL latch failed. Output may be unstable!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Return the latch input to 0 */
|
||||
ret = regmap_write_bits(pll->clkr.regmap, PLL_MODE(pll),
|
||||
LUCID_5LPE_SDX_CPU_LATCH_INPUT, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (clk_hw_is_enabled(hw)) {
|
||||
ret = wait_for_pll_enable_lock(pll);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long parent_rate)
|
||||
{
|
||||
|
|
@ -3331,6 +3392,25 @@ const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = {
|
|||
};
|
||||
EXPORT_SYMBOL(clk_alpha_pll_lucid_5lpe_ops);
|
||||
|
||||
const struct clk_ops clk_alpha_pll_lucid_5lpe_sdx_cpu_ops = {
|
||||
.prepare = alpha_pll_lucid_5lpe_prepare,
|
||||
.unprepare = clk_unprepare_regmap,
|
||||
.pre_rate_change = clk_pre_change_regmap,
|
||||
.post_rate_change = clk_post_change_regmap,
|
||||
.enable = alpha_pll_lucid_5lpe_enable,
|
||||
.disable = alpha_pll_lucid_5lpe_disable,
|
||||
.is_enabled = alpha_pll_lucid_is_enabled,
|
||||
.recalc_rate = alpha_pll_lucid_recalc_rate,
|
||||
.round_rate = clk_alpha_pll_round_rate,
|
||||
.set_rate = alpha_pll_lucid_5lpe_sdx_cpu_set_rate,
|
||||
.debug_init = clk_common_debug_init,
|
||||
.init = clk_lucid_pll_init,
|
||||
#ifdef CONFIG_COMMON_CLK_QCOM_DEBUG
|
||||
.list_rate_vdd_level = clk_list_rate_vdd_level,
|
||||
#endif
|
||||
};
|
||||
EXPORT_SYMBOL(clk_alpha_pll_lucid_5lpe_sdx_cpu_ops);
|
||||
|
||||
const struct clk_ops clk_alpha_pll_fixed_lucid_ops = {
|
||||
.prepare = clk_prepare_regmap,
|
||||
.unprepare = clk_unprepare_regmap,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2015-2016, 2018-2020 The Linux Foundation.
|
||||
* Copyright (c) 2015-2016, 2018-2021 The Linux Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
@ -173,6 +173,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_zonda_ops;
|
|||
extern const struct clk_ops clk_alpha_pll_zonda_5lpe_ops;
|
||||
|
||||
extern const struct clk_ops clk_alpha_pll_lucid_5lpe_ops;
|
||||
extern const struct clk_ops clk_alpha_pll_lucid_5lpe_sdx_cpu_ops;
|
||||
extern const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops;
|
||||
extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops;
|
||||
extern const struct clk_ops clk_alpha_pll_slew_ops;
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ static struct clk_alpha_pll apcs_cpu_pll = {
|
|||
.fw_name = "bi_tcxo_ao",
|
||||
},
|
||||
.num_parents = 1,
|
||||
.ops = &clk_alpha_pll_lucid_5lpe_ops,
|
||||
.ops = &clk_alpha_pll_lucid_5lpe_sdx_cpu_ops,
|
||||
},
|
||||
.vdd_data = {
|
||||
.vdd_class = &vdd_pll,
|
||||
|
|
@ -361,7 +361,6 @@ static struct regmap_config cpu_regmap_config = {
|
|||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = 0x3C,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ static const char *const gcc_debug_mux_parent_names[] = {
|
|||
};
|
||||
|
||||
static int gcc_debug_mux_sels[] = {
|
||||
0xBA, /* cpu_cc_debug_mux */
|
||||
0xBF, /* cpu_cc_debug_mux */
|
||||
0x43, /* disp_cc_debug_mux */
|
||||
0x67, /* gcc_ahb2phy_csi_clk */
|
||||
0x68, /* gcc_ahb2phy_usb_clk */
|
||||
|
|
@ -349,7 +349,7 @@ static int gcc_debug_mux_sels[] = {
|
|||
0x15B, /* gcc_video_venus_ctl_clk */
|
||||
0x3F, /* gcc_video_xo_clk */
|
||||
0xFB, /* gpu_cc_debug_mux */
|
||||
0xA9, /* mc_cc_debug_mux */
|
||||
0xAE, /* mc_cc_debug_mux */
|
||||
0x38, /* measure_only_gcc_camera_ahb_clk */
|
||||
0x40, /* measure_only_gcc_camera_xo_clk */
|
||||
0xBA, /* measure_only_gcc_cpuss_gnoc_clk */
|
||||
|
|
|
|||
|
|
@ -661,7 +661,10 @@ static struct regmap_config gdsc_regmap_config = {
|
|||
|
||||
void gdsc_debug_print_regs(struct regulator *regulator)
|
||||
{
|
||||
struct gdsc *sc = rdev_get_drvdata(regulator->rdev);
|
||||
struct regulator_dev *rdev = regulator->rdev;
|
||||
struct gdsc *sc = rdev_get_drvdata(rdev);
|
||||
struct regulator *reg;
|
||||
const char *supply_name;
|
||||
uint32_t regvals[3] = {0};
|
||||
int ret;
|
||||
|
||||
|
|
@ -670,6 +673,23 @@ void gdsc_debug_print_regs(struct regulator *regulator)
|
|||
return;
|
||||
}
|
||||
|
||||
ww_mutex_lock(&rdev->mutex, NULL);
|
||||
|
||||
if (rdev->open_count)
|
||||
pr_info("%-32s EN\n", "Device-Supply");
|
||||
|
||||
list_for_each_entry(reg, &rdev->consumer_list, list) {
|
||||
if (reg->supply_name)
|
||||
supply_name = reg->supply_name;
|
||||
else
|
||||
supply_name = "(null)-(null)";
|
||||
|
||||
pr_info("%-32s %c\n", supply_name,
|
||||
(reg->enable_count ? 'Y' : 'N'));
|
||||
}
|
||||
|
||||
ww_mutex_unlock(&rdev->mutex);
|
||||
|
||||
ret = regmap_bulk_read(sc->regmap, REG_OFFSET, regvals,
|
||||
gdsc_regmap_config.max_register ? 3 : 1);
|
||||
if (ret) {
|
||||
|
|
|
|||
|
|
@ -2632,7 +2632,7 @@ int a6xx_gmu_probe(struct kgsl_device *device,
|
|||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
|
||||
struct resource *res;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
gmu->pdev = pdev;
|
||||
|
||||
|
|
@ -2662,7 +2662,20 @@ int a6xx_gmu_probe(struct kgsl_device *device,
|
|||
ret = devm_clk_bulk_get_all(&pdev->dev, &gmu->clks);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Voting for apb_pclk will enable power and clocks required for
|
||||
* QDSS path to function. However, if CORESIGHT is not enabled,
|
||||
* QDSS is essentially unusable. Hence, if QDSS cannot be used,
|
||||
* don't vote for this clock.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_CORESIGHT)) {
|
||||
for (i = 0; i < ret; i++) {
|
||||
if (!strcmp(gmu->clks[i].id, "apb_pclk")) {
|
||||
gmu->clks[i].clk = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
gmu->num_clks = ret;
|
||||
|
||||
/* Set up GMU IOMMU and shared memory with GMU */
|
||||
|
|
@ -2935,6 +2948,8 @@ static int a6xx_boot(struct adreno_device *adreno_dev)
|
|||
kgsl_pwrscale_wake(device);
|
||||
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -3003,6 +3018,7 @@ static int a6xx_first_boot(struct adreno_device *adreno_dev)
|
|||
set_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags);
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -3264,6 +3280,8 @@ static void a6xx_gmu_touch_wakeup(struct adreno_device *adreno_dev)
|
|||
kgsl_pwrscale_wake(device);
|
||||
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
|
@ -500,6 +500,7 @@ static void a6xx_hwsched_touch_wakeup(struct adreno_device *adreno_dev)
|
|||
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -541,6 +542,8 @@ static int a6xx_hwsched_boot(struct adreno_device *adreno_dev)
|
|||
kgsl_pwrscale_wake(device);
|
||||
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -589,6 +592,7 @@ static int a6xx_hwsched_first_boot(struct adreno_device *adreno_dev)
|
|||
set_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags);
|
||||
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
|
|||
|
|
@ -896,6 +896,7 @@ static int a6xx_boot(struct adreno_device *adreno_dev)
|
|||
|
||||
set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -934,6 +935,7 @@ static void a6xx_rgmu_touch_wakeup(struct adreno_device *adreno_dev)
|
|||
|
||||
set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -1002,6 +1004,7 @@ static int a6xx_first_boot(struct adreno_device *adreno_dev)
|
|||
set_bit(RGMU_PRIV_FIRST_BOOT_DONE, &rgmu->flags);
|
||||
set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags);
|
||||
|
||||
device->pwrctrl.last_stat_updated = ktime_get();
|
||||
device->state = KGSL_STATE_ACTIVE;
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);
|
||||
|
|
@ -1248,12 +1251,25 @@ static int a6xx_rgmu_regulators_probe(struct a6xx_rgmu_device *rgmu)
|
|||
static int a6xx_rgmu_clocks_probe(struct a6xx_rgmu_device *rgmu,
|
||||
struct device_node *node)
|
||||
{
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
ret = devm_clk_bulk_get_all(&rgmu->pdev->dev, &rgmu->clks);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Voting for apb_pclk will enable power and clocks required for
|
||||
* QDSS path to function. However, if CORESIGHT is not enabled,
|
||||
* QDSS is essentially unusable. Hence, if QDSS cannot be used,
|
||||
* don't vote for this clock.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_CORESIGHT)) {
|
||||
for (i = 0; i < ret; i++) {
|
||||
if (!strcmp(rgmu->clks[i].id, "apb_pclk")) {
|
||||
rgmu->clks[i].clk = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rgmu->num_clks = ret;
|
||||
|
||||
rgmu->gpu_clk = kgsl_of_clk_by_name(rgmu->clks, ret, "core");
|
||||
|
|
|
|||
|
|
@ -304,6 +304,9 @@ static void _retire_timestamp(struct kgsl_drawobj *drawobj)
|
|||
context->id, drawobj->timestamp,
|
||||
!!(drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME));
|
||||
|
||||
if (drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME)
|
||||
atomic64_inc(&context->proc_priv->frame_count);
|
||||
|
||||
/*
|
||||
* For A3xx we still get the rptr from the CP_RB_RPTR instead of
|
||||
* rptr scratch out address. At this point GPU clocks turned off.
|
||||
|
|
@ -2355,6 +2358,9 @@ static void retire_cmdobj(struct adreno_device *adreno_dev,
|
|||
context->id, drawobj->timestamp,
|
||||
!!(drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME));
|
||||
|
||||
if (drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME)
|
||||
atomic64_inc(&context->proc_priv->frame_count);
|
||||
|
||||
/*
|
||||
* For A3xx we still get the rptr from the CP_RB_RPTR instead of
|
||||
* rptr scratch out address. At this point GPU clocks turned off.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/ion.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/msm_kgsl.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
|
@ -335,6 +336,27 @@ static void kgsl_destroy_ion(struct kgsl_dma_buf_meta *meta)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void kgsl_process_sub_stats(struct kgsl_process_private *priv,
|
||||
unsigned int type, uint64_t size)
|
||||
{
|
||||
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
|
||||
struct task_struct *task;
|
||||
struct mm_struct *mm;
|
||||
|
||||
task = get_pid_task(priv->pid, PIDTYPE_PID);
|
||||
if (task) {
|
||||
mm = get_task_mm(task);
|
||||
if (mm) {
|
||||
add_mm_counter(mm, MM_UNRECLAIMABLE,
|
||||
-(size >> PAGE_SHIFT));
|
||||
mmput(mm);
|
||||
}
|
||||
put_task_struct(task);
|
||||
}
|
||||
#endif
|
||||
atomic64_sub(size, &priv->stats[type].cur);
|
||||
}
|
||||
|
||||
void
|
||||
kgsl_mem_entry_destroy(struct kref *kref)
|
||||
{
|
||||
|
|
@ -349,7 +371,7 @@ kgsl_mem_entry_destroy(struct kref *kref)
|
|||
/* pull out the memtype before the flags get cleared */
|
||||
memtype = kgsl_memdesc_usermem_type(&entry->memdesc);
|
||||
|
||||
atomic64_sub(entry->memdesc.size, &entry->priv->stats[memtype].cur);
|
||||
kgsl_process_sub_stats(entry->priv, memtype, entry->memdesc.size);
|
||||
|
||||
/* Detach from process list */
|
||||
kgsl_mem_entry_detach_process(entry);
|
||||
|
|
@ -1043,6 +1065,24 @@ done:
|
|||
return private;
|
||||
}
|
||||
|
||||
int kgsl_gpu_frame_count(pid_t pid, u64 *frame_count)
|
||||
{
|
||||
struct kgsl_process_private *p;
|
||||
|
||||
if (!frame_count)
|
||||
return -EINVAL;
|
||||
|
||||
p = kgsl_process_private_find(pid);
|
||||
if (!p)
|
||||
return -ENOENT;
|
||||
|
||||
*frame_count = atomic64_read(&p->frame_count);
|
||||
kgsl_process_private_put(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(kgsl_gpu_frame_count);
|
||||
|
||||
static int kgsl_close_device(struct kgsl_device *device)
|
||||
{
|
||||
int result = 0;
|
||||
|
|
@ -2753,10 +2793,12 @@ static void kgsl_process_add_stats(struct kgsl_process_private *priv,
|
|||
|
||||
if (ret > priv->stats[type].max)
|
||||
priv->stats[type].max = ret;
|
||||
|
||||
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
|
||||
add_mm_counter(current->mm, MM_UNRECLAIMABLE, (size >> PAGE_SHIFT));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv,
|
||||
unsigned int cmd, void *data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@
|
|||
#ifndef __KGSL_H
|
||||
#define __KGSL_H
|
||||
|
||||
#include <uapi/linux/msm_kgsl.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/msm_kgsl.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "kgsl_gmu_core.h"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2013-2017,2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2017,2019,2021 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef __KGSL_COMPAT_H
|
||||
#define __KGSL_COMPAT_H
|
||||
|
||||
#include <uapi/linux/msm_kgsl.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/msm_kgsl.h>
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
|
|
|
|||
|
|
@ -437,6 +437,7 @@ struct kgsl_context {
|
|||
* @fd_count: Counter for the number of FDs for this process
|
||||
* @ctxt_count: Count for the number of contexts for this process
|
||||
* @ctxt_count_lock: Spinlock to protect ctxt_count
|
||||
* @frame_count: Count for the number of frames processed
|
||||
*/
|
||||
struct kgsl_process_private {
|
||||
unsigned long priv;
|
||||
|
|
@ -460,6 +461,7 @@ struct kgsl_process_private {
|
|||
int fd_count;
|
||||
atomic_t ctxt_count;
|
||||
spinlock_t ctxt_count_lock;
|
||||
atomic64_t frame_count;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2511,9 +2511,10 @@ int kgsl_iommu_probe(struct kgsl_device *device)
|
|||
*/
|
||||
kgsl_iommu_map_globals(mmu, mmu->defaultpagetable);
|
||||
kgsl_iommu_map_globals(mmu, mmu->lpac_pagetable);
|
||||
|
||||
device->qdss_desc = kgsl_allocate_global_fixed(device,
|
||||
"qcom,gpu-qdss-stm", "gpu-qdss");
|
||||
/* QDSS is supported only when CORESIGHT is enabled */
|
||||
if (IS_ENABLED(CONFIG_CORESIGHT))
|
||||
device->qdss_desc = kgsl_allocate_global_fixed(device,
|
||||
"qcom,gpu-qdss-stm", "gpu-qdss");
|
||||
|
||||
device->qtimer_desc = kgsl_allocate_global_fixed(device,
|
||||
"qcom,gpu-timer", "gpu-qtimer");
|
||||
|
|
|
|||
|
|
@ -450,6 +450,11 @@ done:
|
|||
pcount++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
|
||||
mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES,
|
||||
(1 << order));
|
||||
#endif
|
||||
|
||||
return pcount;
|
||||
|
||||
eagain:
|
||||
|
|
@ -521,6 +526,11 @@ static void kgsl_pool_free_page(struct page *page)
|
|||
|
||||
page_order = compound_order(page);
|
||||
|
||||
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
|
||||
mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES,
|
||||
-(1 << page_order));
|
||||
#endif
|
||||
|
||||
if (!kgsl_pool_max_pages ||
|
||||
(kgsl_pool_size_total() < kgsl_pool_max_pages)) {
|
||||
pool = _kgsl_get_pool_from_order(page_order);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/msm_kgsl.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
|
@ -1426,6 +1427,9 @@ static int _get_clocks(struct kgsl_device *device)
|
|||
for (i = 0; i < KGSL_MAX_CLKS; i++) {
|
||||
if (pwr->grp_clks[i] || strcmp(clocks[i], name))
|
||||
continue;
|
||||
/* apb_pclk should only be enabled if CORESIGHT is enabled */
|
||||
if (!strcmp(name, "apb_pclk") && !IS_ENABLED(CONFIG_CORESIGHT))
|
||||
continue;
|
||||
|
||||
pwr->grp_clks[i] = devm_clk_get(dev, name);
|
||||
|
||||
|
|
@ -1875,6 +1879,7 @@ static int _wake(struct kgsl_device *device)
|
|||
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE);
|
||||
|
||||
device->ftbl->deassert_gbif_halt(device);
|
||||
pwr->last_stat_updated = ktime_get();
|
||||
/*
|
||||
* No need to turn on/off irq here as it no longer affects
|
||||
* power collapse
|
||||
|
|
@ -2255,3 +2260,42 @@ int kgsl_pwrctrl_set_default_gpu_pwrlevel(struct kgsl_device *device)
|
|||
/* Request adjusted DCVS level */
|
||||
return device->ftbl->gpu_clock_set(device, pwr->active_pwrlevel);
|
||||
}
|
||||
|
||||
int kgsl_gpu_num_freqs(void)
|
||||
{
|
||||
struct kgsl_device *device = kgsl_get_device(0);
|
||||
|
||||
if (!device)
|
||||
return -ENODEV;
|
||||
|
||||
return device->pwrctrl.num_pwrlevels;
|
||||
}
|
||||
EXPORT_SYMBOL(kgsl_gpu_num_freqs);
|
||||
|
||||
int kgsl_gpu_stat(struct kgsl_gpu_freq_stat *stats, u32 numfreq)
|
||||
{
|
||||
struct kgsl_device *device = kgsl_get_device(0);
|
||||
struct kgsl_pwrctrl *pwr;
|
||||
int i;
|
||||
|
||||
if (!device)
|
||||
return -ENODEV;
|
||||
|
||||
pwr = &device->pwrctrl;
|
||||
|
||||
if (!stats || (numfreq < pwr->num_pwrlevels))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&device->mutex);
|
||||
kgsl_pwrscale_update_stats(device);
|
||||
|
||||
for (i = 0; i < pwr->num_pwrlevels; i++) {
|
||||
stats[i].freq = pwr->pwrlevels[i].gpu_freq;
|
||||
stats[i].active_time = pwr->clock_times[i];
|
||||
stats[i].idle_time = pwr->time_in_pwrlevel[i] - pwr->clock_times[i];
|
||||
}
|
||||
mutex_unlock(&device->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(kgsl_gpu_stat);
|
||||
|
|
|
|||
|
|
@ -175,6 +175,10 @@ struct kgsl_pwrctrl {
|
|||
u32 minbw_timeout;
|
||||
/** @ddr_qos_devfreq: Devfreq device for setting DDR qos policy */
|
||||
struct devfreq *ddr_qos_devfreq;
|
||||
/** @time_in_pwrlevel: Each pwrlevel active duration in usec */
|
||||
u64 time_in_pwrlevel[KGSL_MAX_PWRLEVELS];
|
||||
/** @last_stat_updated: The last time stats were updated */
|
||||
ktime_t last_stat_updated;
|
||||
};
|
||||
|
||||
int kgsl_pwrctrl_init(struct kgsl_device *device);
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ void kgsl_pwrscale_update_stats(struct kgsl_device *device)
|
|||
|
||||
if (device->state == KGSL_STATE_ACTIVE) {
|
||||
struct kgsl_power_stats stats;
|
||||
ktime_t cur_time = ktime_get();
|
||||
|
||||
device->ftbl->power_stats(device, &stats);
|
||||
device->pwrscale.accum_stats.busy_time += stats.busy_time;
|
||||
|
|
@ -129,6 +130,9 @@ void kgsl_pwrscale_update_stats(struct kgsl_device *device)
|
|||
device->pwrscale.accum_stats.ram_wait += stats.ram_wait;
|
||||
pwrctrl->clock_times[pwrctrl->active_pwrlevel] +=
|
||||
stats.busy_time;
|
||||
pwrctrl->time_in_pwrlevel[pwrctrl->active_pwrlevel] +=
|
||||
ktime_us_delta(cur_time, pwrctrl->last_stat_updated);
|
||||
pwrctrl->last_stat_updated = cur_time;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -952,6 +952,11 @@ static void kgsl_contiguous_free(struct kgsl_memdesc *memdesc)
|
|||
|
||||
atomic_long_sub(memdesc->size, &kgsl_driver.stats.coherent);
|
||||
|
||||
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
|
||||
mod_node_page_state(page_pgdat(phys_to_page(memdesc->physaddr)),
|
||||
NR_UNRECLAIMABLE_PAGES, -(memdesc->size >> PAGE_SHIFT));
|
||||
#endif
|
||||
|
||||
_kgsl_contiguous_free(memdesc);
|
||||
}
|
||||
|
||||
|
|
@ -961,6 +966,7 @@ static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc)
|
|||
int i;
|
||||
struct scatterlist *sg;
|
||||
int ret = unlock_sgt(memdesc->sgt);
|
||||
int order = get_order(PAGE_SIZE);
|
||||
|
||||
if (ret) {
|
||||
/*
|
||||
|
|
@ -979,7 +985,11 @@ static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc)
|
|||
for_each_sg(memdesc->sgt->sgl, sg, memdesc->sgt->nents, i) {
|
||||
struct page *page = sg_page(sg);
|
||||
|
||||
__free_pages(page, get_order(PAGE_SIZE));
|
||||
__free_pages(page, order);
|
||||
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
|
||||
mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES,
|
||||
-(1 << order));
|
||||
#endif
|
||||
}
|
||||
|
||||
sg_free_table(memdesc->sgt);
|
||||
|
|
@ -1032,15 +1042,20 @@ static void kgsl_free_pool_pages(struct kgsl_memdesc *memdesc)
|
|||
|
||||
static void kgsl_free_system_pages(struct kgsl_memdesc *memdesc)
|
||||
{
|
||||
int i;
|
||||
int i, order = get_order(PAGE_SIZE);
|
||||
|
||||
kgsl_paged_unmap_kernel(memdesc);
|
||||
WARN_ON(memdesc->hostptr);
|
||||
|
||||
atomic_long_sub(memdesc->size, &kgsl_driver.stats.page_alloc);
|
||||
|
||||
for (i = 0; i < memdesc->page_count; i++)
|
||||
__free_pages(memdesc->pages[i], get_order(PAGE_SIZE));
|
||||
for (i = 0; i < memdesc->page_count; i++) {
|
||||
__free_pages(memdesc->pages[i], order);
|
||||
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
|
||||
mod_node_page_state(page_pgdat(memdesc->pages[i]),
|
||||
NR_UNRECLAIMABLE_PAGES, -(1 << order));
|
||||
#endif
|
||||
}
|
||||
|
||||
memdesc->page_count = 0;
|
||||
kvfree(memdesc->pages);
|
||||
|
|
@ -1087,6 +1102,7 @@ static int kgsl_system_alloc_pages(u64 size, struct page ***pages,
|
|||
struct scatterlist sg;
|
||||
struct page **local;
|
||||
int i, npages = size >> PAGE_SHIFT;
|
||||
int order = get_order(PAGE_SIZE);
|
||||
|
||||
local = kvcalloc(npages, sizeof(*pages), GFP_KERNEL);
|
||||
if (!local)
|
||||
|
|
@ -1098,8 +1114,13 @@ static int kgsl_system_alloc_pages(u64 size, struct page ***pages,
|
|||
|
||||
local[i] = alloc_pages(gfp, get_order(PAGE_SIZE));
|
||||
if (!local[i]) {
|
||||
for (i = i - 1; i >= 0; i--)
|
||||
__free_pages(local[i], get_order(PAGE_SIZE));
|
||||
for (i = i - 1; i >= 0; i--) {
|
||||
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
|
||||
mod_node_page_state(page_pgdat(local[i]),
|
||||
NR_UNRECLAIMABLE_PAGES, -(1 << order));
|
||||
#endif
|
||||
__free_pages(local[i], order);
|
||||
}
|
||||
kvfree(local);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
@ -1110,6 +1131,10 @@ static int kgsl_system_alloc_pages(u64 size, struct page ***pages,
|
|||
sg_dma_address(&sg) = page_to_phys(local[i]);
|
||||
|
||||
dma_sync_sg_for_device(dev, &sg, 1, DMA_BIDIRECTIONAL);
|
||||
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
|
||||
mod_node_page_state(page_pgdat(local[i]), NR_UNRECLAIMABLE_PAGES,
|
||||
(1 << order));
|
||||
#endif
|
||||
}
|
||||
|
||||
*pages = local;
|
||||
|
|
@ -1256,9 +1281,14 @@ static int kgsl_alloc_contiguous(struct kgsl_device *device,
|
|||
memdesc->ops = &kgsl_contiguous_ops;
|
||||
ret = _kgsl_alloc_contiguous(&device->pdev->dev, memdesc, size, 0);
|
||||
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
KGSL_STATS_ADD(size, &kgsl_driver.stats.coherent,
|
||||
&kgsl_driver.stats.coherent_max);
|
||||
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
|
||||
mod_node_page_state(page_pgdat(phys_to_page(memdesc->physaddr)),
|
||||
NR_UNRECLAIMABLE_PAGES, (size >> PAGE_SHIFT));
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ EXPORT_SYMBOL_GPL(hid_register_report);
|
|||
* Register a new field for this report.
|
||||
*/
|
||||
|
||||
static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
|
||||
static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages)
|
||||
{
|
||||
struct hid_field *field;
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
|
|||
|
||||
field = kzalloc((sizeof(struct hid_field) +
|
||||
usages * sizeof(struct hid_usage) +
|
||||
values * sizeof(unsigned)), GFP_KERNEL);
|
||||
usages * sizeof(unsigned)), GFP_KERNEL);
|
||||
if (!field)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -300,7 +300,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
|
|||
usages = max_t(unsigned, parser->local.usage_index,
|
||||
parser->global.report_count);
|
||||
|
||||
field = hid_register_field(report, usages, parser->global.report_count);
|
||||
field = hid_register_field(report, usages);
|
||||
if (!field)
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
|
|
@ -173,10 +174,20 @@
|
|||
#define CAL_RC_CLK_AUTO_VAL 1
|
||||
#define CAL_RC_CLK_MANUAL_VAL 2
|
||||
|
||||
/* These registers are only applicable for PM5100 */
|
||||
#define HAP_CFG_HPWR_INTF_CTL_REG 0x80
|
||||
#define INTF_CTL_MASK GENMASK(1, 0)
|
||||
#define INTF_CTL_BOB 1
|
||||
#define INTF_CTL_BHARGER 2
|
||||
|
||||
#define HAP_CFG_VHPWR_REG 0x84
|
||||
#define VHPWR_STEP_MV 32
|
||||
|
||||
/* version register definitions for HAPTICS_PATTERN module */
|
||||
#define HAP_PTN_REVISION2_REG 0x01
|
||||
#define HAP_PTN_V1 0x1
|
||||
#define HAP_PTN_V2 0x2
|
||||
#define HAP_PTN_V3 0x3
|
||||
|
||||
/* status register definition for HAPTICS_PATTERN module */
|
||||
#define HAP_PTN_FIFO_READY_STS_REG 0x08
|
||||
|
|
@ -267,10 +278,6 @@
|
|||
#define F_LRA_VARIATION_HZ 5
|
||||
#define NON_HBOOST_MAX_VMAX_MV 4000
|
||||
|
||||
#define MAX_FIFO_SAMPLES(chip) \
|
||||
((chip)->ptn_revision == HAP_PTN_V1 ? 104 : 640)
|
||||
#define FIFO_EMPTY_THRESHOLD(chip) \
|
||||
((chip)->ptn_revision == HAP_PTN_V1 ? 48 : 280)
|
||||
#define is_between(val, min, max) \
|
||||
(((min) <= (max)) && ((min) <= (val)) && ((val) <= (max)))
|
||||
#define HAP_BOOST_CLAMP_5V_REG_OFFSET(chip) \
|
||||
|
|
@ -346,6 +353,11 @@ enum custom_effect_param {
|
|||
CUSTOM_DATA_LEN,
|
||||
};
|
||||
|
||||
enum pmic_type {
|
||||
PM8350B,
|
||||
PM5100,
|
||||
};
|
||||
|
||||
static const char * const src_str[] = {
|
||||
"FIFO",
|
||||
"DIRECT_PLAY",
|
||||
|
|
@ -495,7 +507,9 @@ struct haptics_chip {
|
|||
u32 hbst_addr_base;
|
||||
u8 cfg_revision;
|
||||
u8 ptn_revision;
|
||||
u8 hpwr_intf_ctl;
|
||||
u16 hbst_revision;
|
||||
enum pmic_type pmic_type;
|
||||
bool fifo_empty_irq_en;
|
||||
bool swr_slave_enabled;
|
||||
bool clamp_at_5v;
|
||||
|
|
@ -507,6 +521,86 @@ struct haptics_reg_info {
|
|||
u8 val;
|
||||
};
|
||||
|
||||
static inline int get_max_fifo_samples(struct haptics_chip *chip)
|
||||
{
|
||||
int val = 0;
|
||||
|
||||
switch (chip->ptn_revision) {
|
||||
case HAP_PTN_V1:
|
||||
val = 104;
|
||||
break;
|
||||
case HAP_PTN_V2:
|
||||
val = 640;
|
||||
break;
|
||||
case HAP_PTN_V3:
|
||||
val = 1024;
|
||||
break;
|
||||
default:
|
||||
pr_err("Invalid pattern revision\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int get_fifo_empty_threshold(struct haptics_chip *chip)
|
||||
{
|
||||
int val = 0;
|
||||
|
||||
switch (chip->ptn_revision) {
|
||||
case HAP_PTN_V1:
|
||||
val = 48;
|
||||
break;
|
||||
case HAP_PTN_V2:
|
||||
val = 280;
|
||||
break;
|
||||
case HAP_PTN_V3:
|
||||
val = 288;
|
||||
break;
|
||||
default:
|
||||
pr_err("Invalid pattern revision\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int get_fifo_threshold_per_bit(struct haptics_chip *chip)
|
||||
{
|
||||
int val = -EINVAL;
|
||||
|
||||
switch (chip->ptn_revision) {
|
||||
case HAP_PTN_V1:
|
||||
val = 4;
|
||||
break;
|
||||
case HAP_PTN_V2:
|
||||
val = 40;
|
||||
break;
|
||||
case HAP_PTN_V3:
|
||||
val = 32;
|
||||
break;
|
||||
default:
|
||||
pr_err("Invalid pattern revision\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static bool is_haptics_external_powered(struct haptics_chip *chip)
|
||||
{
|
||||
/* SW based explicit vote */
|
||||
if (chip->hpwr_vreg)
|
||||
return true;
|
||||
|
||||
/* Implicit voting by HW */
|
||||
if (chip->pmic_type == PM5100)
|
||||
return true;
|
||||
|
||||
/* Powered by HBOOST */
|
||||
return false;
|
||||
}
|
||||
|
||||
static int haptics_read(struct haptics_chip *chip,
|
||||
u16 base, u8 offset, u8 *val, u32 length)
|
||||
{
|
||||
|
|
@ -890,7 +984,7 @@ static int haptics_get_closeloop_lra_period_v2(
|
|||
|
||||
rc_clk_cal = ((val[0] & CAL_RC_CLK_MASK) >> CAL_RC_CLK_SHIFT);
|
||||
/* read auto resonance calibration result */
|
||||
if (in_boot) {
|
||||
if (in_boot && (chip->pmic_type == PM8350B)) {
|
||||
if (chip->hap_cfg_nvmem == NULL) {
|
||||
dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n");
|
||||
return -EINVAL;
|
||||
|
|
@ -1164,6 +1258,9 @@ static int haptics_boost_vreg_enable(struct haptics_chip *chip, bool en)
|
|||
int rc;
|
||||
u8 val;
|
||||
|
||||
if (is_haptics_external_powered(chip))
|
||||
return 0;
|
||||
|
||||
if (chip->hap_cfg_nvmem == NULL) {
|
||||
dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n");
|
||||
return 0;
|
||||
|
|
@ -1208,6 +1305,9 @@ static bool is_boost_vreg_enabled_in_open_loop(struct haptics_chip *chip)
|
|||
int rc;
|
||||
u8 val;
|
||||
|
||||
if (is_haptics_external_powered(chip))
|
||||
return false;
|
||||
|
||||
rc = haptics_read(chip, chip->hbst_addr_base,
|
||||
HAP_BOOST_HW_CTRL_FOLLOW_REG, &val, 1);
|
||||
if (!rc && !(val & FOLLOW_HW_EN_BIT)) {
|
||||
|
|
@ -1229,6 +1329,8 @@ static int haptics_wait_hboost_ready(struct haptics_chip *chip)
|
|||
int i, rc;
|
||||
u8 val;
|
||||
|
||||
if (is_haptics_external_powered(chip))
|
||||
return 0;
|
||||
/*
|
||||
* Wait ~20ms until hBoost is ready, otherwise
|
||||
* bail out and return -EBUSY
|
||||
|
|
@ -1325,7 +1427,7 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en)
|
|||
u8 val;
|
||||
|
||||
if ((is_boost_vreg_enabled_in_open_loop(chip) ||
|
||||
chip->hpwr_vreg != NULL) && en) {
|
||||
is_haptics_external_powered(chip)) && en) {
|
||||
/* Force VREG_RDY */
|
||||
rc = haptics_masked_write(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT,
|
||||
|
|
@ -1357,7 +1459,7 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en)
|
|||
|
||||
dev_dbg(chip->dev, "Toggle CAL_EN in open-loop-VREG playing\n");
|
||||
}
|
||||
} else if (chip->hpwr_vreg == NULL) {
|
||||
} else if (!is_haptics_external_powered(chip)) {
|
||||
rc = haptics_masked_write(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_VSET_CFG_REG,
|
||||
FORCE_VREG_RDY_BIT, 0);
|
||||
|
|
@ -1619,16 +1721,16 @@ static int haptics_get_available_fifo_memory(struct haptics_chip *chip)
|
|||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (fill > MAX_FIFO_SAMPLES(chip)) {
|
||||
if (fill > get_max_fifo_samples(chip)) {
|
||||
dev_err(chip->dev, "Filled FIFO number %d exceed the max %d\n",
|
||||
fill, MAX_FIFO_SAMPLES(chip));
|
||||
fill, get_max_fifo_samples(chip));
|
||||
return -EINVAL;
|
||||
} else if (fill == MAX_FIFO_SAMPLES(chip)) {
|
||||
} else if (fill == get_max_fifo_samples(chip)) {
|
||||
dev_err(chip->dev, "no FIFO space available\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
available = MAX_FIFO_SAMPLES(chip) - fill;
|
||||
available = get_max_fifo_samples(chip) - fill;
|
||||
return available;
|
||||
}
|
||||
|
||||
|
|
@ -1717,12 +1819,16 @@ static int haptics_set_fifo_empty_threshold(struct haptics_chip *chip,
|
|||
u8 reg, thresh_per_bit;
|
||||
int rc;
|
||||
|
||||
rc = get_fifo_threshold_per_bit(chip);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
thresh_per_bit = rc;
|
||||
|
||||
reg = (chip->ptn_revision == HAP_PTN_V1) ?
|
||||
HAP_PTN_V1_FIFO_EMPTY_CFG_REG : HAP_PTN_V2_FIFO_EMPTY_CFG_REG;
|
||||
thresh_per_bit = (chip->ptn_revision == HAP_PTN_V1) ?
|
||||
HAP_PTN_V1_FIFO_THRESH_LSB : HAP_PTN_V2_FIFO_THRESH_LSB;
|
||||
rc = haptics_masked_write(chip, chip->ptn_addr_base,
|
||||
reg, EMPTY_THRESH_MASK, thresh / thresh_per_bit);
|
||||
rc = haptics_masked_write(chip, chip->ptn_addr_base, reg,
|
||||
EMPTY_THRESH_MASK, (thresh / thresh_per_bit));
|
||||
if (rc < 0)
|
||||
dev_err(chip->dev, "Set FIFO empty threshold failed, rc=%d\n",
|
||||
rc);
|
||||
|
|
@ -1782,7 +1888,7 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)
|
|||
|
||||
if (chip->ptn_revision == HAP_PTN_V1 &&
|
||||
fifo->period_per_s > F_8KHZ &&
|
||||
fifo->num_s > MAX_FIFO_SAMPLES(chip)) {
|
||||
fifo->num_s > get_max_fifo_samples(chip)) {
|
||||
dev_err(chip->dev, "PM8350B v1 doesn't support playing long FIFO pattern higher than 8 KHz play rate\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1808,7 +1914,7 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)
|
|||
* more than MAX_FIFO_SAMPLES samples, the rest will be
|
||||
* written if any FIFO memory is available after playing.
|
||||
*/
|
||||
num = min_t(u32, fifo->num_s, MAX_FIFO_SAMPLES(chip));
|
||||
num = min_t(u32, fifo->num_s, get_max_fifo_samples(chip));
|
||||
available = haptics_get_available_fifo_memory(chip);
|
||||
if (available < 0)
|
||||
return available;
|
||||
|
|
@ -1861,7 +1967,7 @@ static int haptics_load_constant_effect(struct haptics_chip *chip, u8 amplitude)
|
|||
play->effect = NULL;
|
||||
|
||||
/* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */
|
||||
if (chip->hpwr_vreg) {
|
||||
if (is_haptics_external_powered(chip)) {
|
||||
rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv);
|
||||
if (rc < 0)
|
||||
goto unlock;
|
||||
|
|
@ -2199,7 +2305,7 @@ static u8 get_direct_play_max_amplitude(struct haptics_chip *chip)
|
|||
u32 amplitude = DIRECT_PLAY_MAX_AMPLITUDE, hdrm_mv;
|
||||
int rc;
|
||||
|
||||
if (chip->hpwr_vreg) {
|
||||
if (is_haptics_external_powered(chip)) {
|
||||
rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv);
|
||||
if (rc < 0)
|
||||
return 0;
|
||||
|
|
@ -2477,12 +2583,15 @@ static int haptics_hw_init(struct haptics_chip *chip)
|
|||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = haptics_read(chip, chip->hbst_addr_base,
|
||||
HAP_BOOST_CLAMP_5V_REG_OFFSET(chip), val, 1);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (!is_haptics_external_powered(chip)) {
|
||||
rc = haptics_read(chip, chip->hbst_addr_base,
|
||||
HAP_BOOST_CLAMP_5V_REG_OFFSET(chip), val, 1);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
chip->clamp_at_5v = val[0] & CLAMP_5V_BIT;
|
||||
}
|
||||
|
||||
chip->clamp_at_5v = val[0] & CLAMP_5V_BIT;
|
||||
/* Config VMAX */
|
||||
rc = haptics_set_vmax_mv(chip, config->vmax_mv);
|
||||
if (rc < 0)
|
||||
|
|
@ -2506,8 +2615,29 @@ static int haptics_hw_init(struct haptics_chip *chip)
|
|||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Force VREG_RDY if non-HBoost is used for powering haptics */
|
||||
if (chip->hpwr_vreg) {
|
||||
if ((chip->pmic_type == PM5100) && !chip->hpwr_vreg) {
|
||||
/* Indicates if HPWR is BOB or Bharger */
|
||||
rc = haptics_read(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_HPWR_INTF_CTL_REG, val, 1);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
chip->hpwr_intf_ctl = val[0] & INTF_CTL_MASK;
|
||||
|
||||
/* Read HPWR voltage to adjust the VMAX */
|
||||
if (chip->hpwr_voltage_mv == 0 &&
|
||||
chip->hpwr_intf_ctl == INTF_CTL_BOB) {
|
||||
rc = haptics_read(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_VHPWR_REG, val, 1);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
chip->hpwr_voltage_mv = val[0] * VHPWR_STEP_MV;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_haptics_external_powered(chip)) {
|
||||
/* Force VREG_RDY if non-HBoost is used for powering haptics */
|
||||
rc = haptics_masked_write(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT,
|
||||
FORCE_VREG_RDY_BIT);
|
||||
|
|
@ -2597,9 +2727,9 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data)
|
|||
* memory, defer the stop into erase() function.
|
||||
*/
|
||||
num = haptics_get_available_fifo_memory(chip);
|
||||
if (num != MAX_FIFO_SAMPLES(chip)) {
|
||||
if (num != get_max_fifo_samples(chip)) {
|
||||
dev_dbg(chip->dev, "%d FIFO samples still in playing\n",
|
||||
MAX_FIFO_SAMPLES(chip) - num);
|
||||
get_max_fifo_samples(chip) - num);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
|
|
@ -3686,14 +3816,21 @@ static int haptics_get_revision(struct haptics_chip *chip)
|
|||
return rc;
|
||||
|
||||
chip->ptn_revision = val[0];
|
||||
rc = haptics_read(chip, chip->hbst_addr_base,
|
||||
HAP_BOOST_REVISION1, val, 2);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
chip->hbst_revision = (val[1] << 8) | val[0];
|
||||
dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x, HAP_HBST %#x\n",
|
||||
chip->cfg_revision, chip->ptn_revision, chip->hbst_revision);
|
||||
if (is_haptics_external_powered(chip)) {
|
||||
dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x\n",
|
||||
chip->cfg_revision, chip->ptn_revision);
|
||||
} else {
|
||||
rc = haptics_read(chip, chip->hbst_addr_base,
|
||||
HAP_BOOST_REVISION1, val, 2);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
chip->hbst_revision = (val[1] << 8) | val[0];
|
||||
dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x, HAP_HBST %#x\n",
|
||||
chip->cfg_revision, chip->ptn_revision, chip->hbst_revision);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3791,13 +3928,14 @@ static int haptics_parse_dt(struct haptics_chip *chip)
|
|||
|
||||
chip->ptn_addr_base = be32_to_cpu(*addr);
|
||||
addr = of_get_address(node, 2, NULL, NULL);
|
||||
if (!addr) {
|
||||
if (!addr && !is_haptics_external_powered(chip)) {
|
||||
dev_err(chip->dev, "Read HAPTICS_HBOOST address failed\n");
|
||||
rc = -EINVAL;
|
||||
goto free_pbs;
|
||||
} else if (addr != NULL) {
|
||||
chip->hbst_addr_base = be32_to_cpu(*addr);
|
||||
}
|
||||
|
||||
chip->hbst_addr_base = be32_to_cpu(*addr);
|
||||
rc = haptics_get_revision(chip);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Get revision failed, rc=%d\n", rc);
|
||||
|
|
@ -3820,12 +3958,12 @@ static int haptics_parse_dt(struct haptics_chip *chip)
|
|||
goto free_pbs;
|
||||
}
|
||||
|
||||
config->fifo_empty_thresh = FIFO_EMPTY_THRESHOLD(chip);
|
||||
config->fifo_empty_thresh = get_fifo_empty_threshold(chip);
|
||||
of_property_read_u32(node, "qcom,fifo-empty-threshold",
|
||||
&config->fifo_empty_thresh);
|
||||
if (config->fifo_empty_thresh >= MAX_FIFO_SAMPLES(chip)) {
|
||||
if (config->fifo_empty_thresh >= get_max_fifo_samples(chip)) {
|
||||
dev_err(chip->dev, "FIFO empty threshold (%d) should be less than %d\n",
|
||||
config->fifo_empty_thresh, MAX_FIFO_SAMPLES(chip));
|
||||
config->fifo_empty_thresh, get_max_fifo_samples(chip));
|
||||
rc = -EINVAL;
|
||||
goto free_pbs;
|
||||
}
|
||||
|
|
@ -4044,7 +4182,7 @@ static u32 get_lra_impedance_capable_max(struct haptics_chip *chip)
|
|||
if (chip->clamp_at_5v)
|
||||
mohms = MAX_IMPEDANCE_MOHM / 2;
|
||||
|
||||
if (chip->hpwr_vreg)
|
||||
if (is_haptics_external_powered(chip))
|
||||
mohms = (chip->hpwr_voltage_mv * 1000) / MIN_ISC_MA;
|
||||
|
||||
dev_dbg(chip->dev, "LRA impedance capable max: %u mohms\n", mohms);
|
||||
|
|
@ -4210,7 +4348,7 @@ static int haptics_detect_lra_frequency(struct haptics_chip *chip)
|
|||
goto restore;
|
||||
|
||||
/* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */
|
||||
if (chip->hpwr_vreg)
|
||||
if (is_haptics_external_powered(chip))
|
||||
vmax_mv = chip->hpwr_voltage_mv - LRA_CALIBRATION_VMAX_HDRM_MV;
|
||||
|
||||
rc = haptics_set_vmax_mv(chip, vmax_mv);
|
||||
|
|
@ -4401,6 +4539,9 @@ static int haptics_probe(struct platform_device *pdev)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
chip->pmic_type =
|
||||
(enum pmic_type)(uintptr_t)of_device_get_match_data(chip->dev);
|
||||
|
||||
rc = haptics_parse_dt(chip);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Parse device-tree failed, rc = %d\n", rc);
|
||||
|
|
@ -4572,8 +4713,18 @@ static const struct dev_pm_ops haptics_pm_ops = {
|
|||
};
|
||||
|
||||
static const struct of_device_id haptics_match_table[] = {
|
||||
{ .compatible = "qcom,hv-haptics" },
|
||||
{ .compatible = "qcom,pm8350b-haptics" },
|
||||
{
|
||||
.compatible = "qcom,hv-haptics",
|
||||
.data = (void *)PM8350B,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,pm8350b-haptics",
|
||||
.data = (void *)PM8350B,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,pm5100-haptics",
|
||||
.data = (void *)PM5100,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include "sdhci-pltfm.h"
|
||||
#include "cqhci.h"
|
||||
|
|
@ -4379,6 +4380,13 @@ static int sdhci_msm_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
/* Toggle wlan_en pin to reset SDIO card to correct state */
|
||||
if (host->mmc->pm_caps & MMC_PM_KEEP_POWER) {
|
||||
pinctrl_pm_select_sleep_state(&pdev->dev);
|
||||
mdelay(1);
|
||||
pinctrl_pm_select_default_state(&pdev->dev);
|
||||
}
|
||||
|
||||
/* Reset the vendor spec register to power on reset state */
|
||||
writel_relaxed(CORE_VENDOR_SPEC_POR_VAL,
|
||||
host->ioaddr + msm_offset->core_vendor_spec);
|
||||
|
|
|
|||
|
|
@ -2941,7 +2941,14 @@ static int msm_nand_read_partial_page(struct mtd_info *mtd,
|
|||
no_copy = false;
|
||||
|
||||
ops->datbuf = no_copy ? actual_buf : bounce_buf;
|
||||
if (info->nand_chip.caps & MSM_NAND_CAP_PAGE_SCOPE_READ)
|
||||
|
||||
/*
|
||||
* Do a Pagescope read only if PAGE_SCOPE_READ is enabled
|
||||
* and request length is greater than codeword size or
|
||||
* the page offset is not aligned to start of the page.
|
||||
*/
|
||||
if ((info->nand_chip.caps & MSM_NAND_CAP_PAGE_SCOPE_READ) &&
|
||||
((len > ONE_CODEWORD_SIZE) || (offset != 0)))
|
||||
err = msm_nand_read_pagescope(mtd, aligned_from, ops);
|
||||
else {
|
||||
if ((len <= ONE_CODEWORD_SIZE) && (offset == 0))
|
||||
|
|
|
|||
|
|
@ -79,9 +79,9 @@
|
|||
#define WLAN_BOOTSTRAP_GPIO_NAME "wlan-bootstrap-gpio"
|
||||
#define PM_OPTIONS 0
|
||||
#define PM_OPTIONS_SUSPEND_LINK_DOWN \
|
||||
(MSM_PCIE_CONFIG_NO_CFG_RESTORE | MSM_PCIE_CONFIG_LINKDOWN)
|
||||
(PM_OPTIONS | MSM_PCIE_CONFIG_LINKDOWN)
|
||||
#define PM_OPTIONS_RESUME_LINK_DOWN \
|
||||
(MSM_PCIE_CONFIG_NO_CFG_RESTORE)
|
||||
(PM_OPTIONS)
|
||||
|
||||
#define SOC_SWREG_VOLT_MAX 1200000
|
||||
#define SOC_SWREG_VOLT_MIN 1200000
|
||||
|
|
@ -231,6 +231,7 @@ static struct cnss_data {
|
|||
bool pci_register_again;
|
||||
bool notify_modem_status;
|
||||
struct pci_saved_state *saved_state;
|
||||
struct pci_saved_state *default_state;
|
||||
u16 revision_id;
|
||||
bool recovery_in_progress;
|
||||
atomic_t fw_available;
|
||||
|
|
@ -1518,7 +1519,7 @@ int cnss_pci_load_and_free_saved_state(struct pci_dev *dev,
|
|||
|
||||
int cnss_msm_pcie_shadow_control(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return msm_pcie_shadow_control(dev, enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_msm_pcie_deregister_event(struct msm_pcie_register_event *reg)
|
||||
|
|
@ -1528,7 +1529,12 @@ int cnss_msm_pcie_deregister_event(struct msm_pcie_register_event *reg)
|
|||
|
||||
int cnss_msm_pcie_recover_config(struct pci_dev *dev)
|
||||
{
|
||||
return msm_pcie_recover_config(dev);
|
||||
if (penv->saved_state)
|
||||
cnss_pci_load_and_free_saved_state(dev, &penv->saved_state);
|
||||
else
|
||||
pci_load_saved_state(dev, penv->default_state);
|
||||
|
||||
pci_restore_state(dev);
|
||||
}
|
||||
|
||||
int cnss_msm_pcie_register_event(struct msm_pcie_register_event *reg)
|
||||
|
|
@ -1661,6 +1667,8 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev,
|
|||
if (penv->pcie_link_state) {
|
||||
pci_save_state(pdev);
|
||||
penv->saved_state = cnss_pci_store_saved_state(pdev);
|
||||
/* Save default config space */
|
||||
penv->default_state = cnss_pci_store_saved_state(pdev);
|
||||
|
||||
ret = cnss_msm_pcie_pm_control(MSM_PCIE_SUSPEND,
|
||||
cnss_get_pci_dev_bus_number(pdev),
|
||||
|
|
@ -1734,6 +1742,9 @@ static void cnss_wlan_pci_remove(struct pci_dev *pdev)
|
|||
if (!penv)
|
||||
return;
|
||||
|
||||
if (penv->default_state)
|
||||
pci_load_and_free_saved_state(penv->pdev, &penv->default_state);
|
||||
|
||||
dev = &penv->pldev->dev;
|
||||
cnss_pcie_reset_platform_ops(dev);
|
||||
device_remove_file(dev, &dev_attr_wlan_setup);
|
||||
|
|
|
|||
|
|
@ -3053,6 +3053,10 @@ static void cnss_init_control_params(struct cnss_plat_data *plat_priv)
|
|||
plat_priv->ctrl_params.qmi_timeout = CNSS_QMI_TIMEOUT_DEFAULT;
|
||||
plat_priv->ctrl_params.bdf_type = CNSS_BDF_TYPE_DEFAULT;
|
||||
plat_priv->ctrl_params.time_sync_period = CNSS_TIME_SYNC_PERIOD_DEFAULT;
|
||||
/* Set adsp_pc_enabled default value to true as ADSP pc is always
|
||||
* enabled by default
|
||||
*/
|
||||
plat_priv->adsp_pc_enabled = true;
|
||||
}
|
||||
|
||||
static void cnss_get_pm_domain_info(struct cnss_plat_data *plat_priv)
|
||||
|
|
|
|||
|
|
@ -505,6 +505,7 @@ struct cnss_plat_data {
|
|||
u32 is_converged_dt;
|
||||
struct device_node *dev_node;
|
||||
u64 feature_list;
|
||||
bool adsp_pc_enabled;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_QCOM
|
||||
|
|
|
|||
|
|
@ -1802,6 +1802,13 @@ static int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv,
|
|||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
int ret = 0;
|
||||
u32 pm_options = PM_OPTIONS_DEFAULT;
|
||||
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
|
||||
|
||||
if (plat_priv->adsp_pc_enabled == control) {
|
||||
cnss_pr_dbg("ADSP power collapse already %s\n",
|
||||
control ? "Enabled" : "Disabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (control)
|
||||
pm_options &= ~MSM_PCIE_CONFIG_NO_DRV_PC;
|
||||
|
|
@ -1814,6 +1821,7 @@ static int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv,
|
|||
return ret;
|
||||
|
||||
cnss_pr_dbg("%s ADSP power collapse\n", control ? "Enable" : "Disable");
|
||||
plat_priv->adsp_pc_enabled = control;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
|
@ -2978,6 +2986,7 @@ int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv)
|
|||
static bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct pci_dev *root_port = pci_find_pcie_root_port(pci_priv->pci_dev);
|
||||
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
|
||||
struct device_node *root_of_node;
|
||||
bool drv_supported = false;
|
||||
|
||||
|
|
@ -2997,6 +3006,9 @@ static bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv)
|
|||
drv_supported ? "supported" : "not supported");
|
||||
pci_priv->drv_supported = drv_supported;
|
||||
|
||||
if (drv_supported)
|
||||
plat_priv->cap.cap_flag |= CNSS_HAS_DRV_SUPPORT;
|
||||
|
||||
return drv_supported;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4041,7 +4041,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work)
|
|||
}
|
||||
vq = hwsim_vqs[HWSIM_VQ_RX];
|
||||
sg_init_one(sg, skb->head, skb_end_offset(skb));
|
||||
err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL);
|
||||
err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_ATOMIC);
|
||||
if (WARN(err, "virtqueue_add_inbuf returned %d\n", err))
|
||||
nlmsg_free(skb);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ enum qpnp_regulator_logical_type {
|
|||
QPNP_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS,
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_ULT_LDO,
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2,
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3,
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_LDO_510,
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS,
|
||||
};
|
||||
|
||||
enum qpnp_regulator_type {
|
||||
|
|
@ -103,6 +106,17 @@ enum qpnp_regulator_subtype {
|
|||
QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL2 = 0x0E,
|
||||
QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL3 = 0x0F,
|
||||
QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10,
|
||||
QPNP_REGULATOR_SUBTYPE_HFSMPS_510 = 0x0A,
|
||||
QPNP_REGULATOR_SUBTYPE_FTSMPS_510 = 0x0B,
|
||||
QPNP_REGULATOR_SUBTYPE_LV_P150_510 = 0x71,
|
||||
QPNP_REGULATOR_SUBTYPE_LV_P300_510 = 0x72,
|
||||
QPNP_REGULATOR_SUBTYPE_LV_P600_510 = 0x73,
|
||||
QPNP_REGULATOR_SUBTYPE_N300_510 = 0x6A,
|
||||
QPNP_REGULATOR_SUBTYPE_N600_510 = 0x6B,
|
||||
QPNP_REGULATOR_SUBTYPE_N1200_510 = 0x6C,
|
||||
QPNP_REGULATOR_SUBTYPE_MV_P50_510 = 0x7A,
|
||||
QPNP_REGULATOR_SUBTYPE_MV_P150_510 = 0x7B,
|
||||
QPNP_REGULATOR_SUBTYPE_MV_P600_510 = 0x7D,
|
||||
};
|
||||
|
||||
/* First common register layout used by older devices */
|
||||
|
|
@ -130,6 +144,11 @@ enum qpnp_common2_regulator_registers {
|
|||
QPNP_COMMON2_REG_STEP_CTRL = 0x61,
|
||||
};
|
||||
|
||||
enum qpnp_common3_regulator_registers {
|
||||
QPNP_COMMON3_REG_STEP_CTRL = 0x3C,
|
||||
};
|
||||
|
||||
|
||||
enum qpnp_ldo_registers {
|
||||
QPNP_LDO_REG_SOFT_START = 0x4C,
|
||||
};
|
||||
|
|
@ -191,6 +210,15 @@ enum qpnp_common2_control_register_index {
|
|||
|
||||
#define QPNP_COMMON2_MODE_MASK 0x07
|
||||
|
||||
/* Third common regulator mode register values */
|
||||
#define QPNP_COMMON3_MODE_BYPASS 2
|
||||
#define QPNP_COMMON3_MODE_RETENTION 3
|
||||
#define QPNP_COMMON3_MODE_LPM 4
|
||||
#define QPNP_COMMON3_MODE_AUTO 6
|
||||
#define QPNP_COMMON3_MODE_HPM 7
|
||||
|
||||
#define QPNP_COMMON3_MODE_MASK 0x07
|
||||
|
||||
/* Common regulator pull down control register layout */
|
||||
#define QPNP_COMMON_PULL_DOWN_ENABLE_MASK 0x80
|
||||
|
||||
|
|
@ -251,6 +279,9 @@ enum qpnp_common2_control_register_index {
|
|||
#define QPNP_FTSMPS2_STEP_MARGIN_NUM 10
|
||||
#define QPNP_FTSMPS2_STEP_MARGIN_DEN 11
|
||||
|
||||
/* slew_rate has units of uV/us. */
|
||||
#define QPNP_COMMON3_FTSMPS3_SLEW_RATE_38p4 38400
|
||||
|
||||
/*
|
||||
* This voltage in uV is returned by get_voltage functions when there is no way
|
||||
* to determine the current voltage level. It is needed because the regulator
|
||||
|
|
@ -451,6 +482,26 @@ static struct qpnp_voltage_range ftsmps426_ranges[] = {
|
|||
VOLTAGE_RANGE(0, 0, 320000, 1352000, 1352000, 4000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_range pldo_510_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 1504000, 1504000, 2000000, 2000000, 8000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_range mv_pldo_510_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 1504000, 1504000, 3544000, 3544000, 8000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_range nldo_510_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_range hfsmps510_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_range ftsmps510_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 300000, 300000, 1372000, 1372000, 4000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_set_points pldo_set_points = SET_POINTS(pldo_ranges);
|
||||
static struct qpnp_voltage_set_points nldo1_set_points
|
||||
= SET_POINTS(nldo1_ranges);
|
||||
|
|
@ -479,6 +530,16 @@ static struct qpnp_voltage_set_points ult_pldo_set_points
|
|||
= SET_POINTS(ult_pldo_ranges);
|
||||
static struct qpnp_voltage_set_points ftsmps426_set_points
|
||||
= SET_POINTS(ftsmps426_ranges);
|
||||
static struct qpnp_voltage_set_points pldo_510_set_points
|
||||
= SET_POINTS(pldo_510_ranges);
|
||||
static struct qpnp_voltage_set_points mv_pldo_510_set_points
|
||||
= SET_POINTS(mv_pldo_510_ranges);
|
||||
static struct qpnp_voltage_set_points nldo_510_set_points
|
||||
= SET_POINTS(nldo_510_ranges);
|
||||
static struct qpnp_voltage_set_points hfsmps510_set_points
|
||||
= SET_POINTS(hfsmps510_ranges);
|
||||
static struct qpnp_voltage_set_points ftsmps510_set_points
|
||||
= SET_POINTS(ftsmps510_ranges);
|
||||
static struct qpnp_voltage_set_points none_set_points;
|
||||
|
||||
static struct qpnp_voltage_set_points *all_set_points[] = {
|
||||
|
|
@ -497,6 +558,11 @@ static struct qpnp_voltage_set_points *all_set_points[] = {
|
|||
&ult_nldo_set_points,
|
||||
&ult_pldo_set_points,
|
||||
&ftsmps426_set_points,
|
||||
&pldo_510_set_points,
|
||||
&mv_pldo_510_set_points,
|
||||
&nldo_510_set_points,
|
||||
&hfsmps510_set_points,
|
||||
&ftsmps510_set_points,
|
||||
};
|
||||
|
||||
/* Determines which label to add to a debug print statement. */
|
||||
|
|
@ -1212,12 +1278,27 @@ static int qpnp_regulator_common2_set_mode(struct regulator_dev *rdev,
|
|||
* ensures that AUTO mode is re-asserted after switching away from
|
||||
* forced HPM if it was configured initially.
|
||||
*/
|
||||
if (mode == REGULATOR_MODE_NORMAL)
|
||||
val = QPNP_COMMON2_MODE_HPM;
|
||||
else if (vreg->init_mode == QPNP_COMMON2_MODE_HPM)
|
||||
val = QPNP_COMMON2_MODE_LPM;
|
||||
else
|
||||
val = vreg->init_mode;
|
||||
if ((vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) ||
|
||||
(vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS) ||
|
||||
(vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_LDO_510)) {
|
||||
if (mode == REGULATOR_MODE_NORMAL)
|
||||
val = QPNP_COMMON3_MODE_HPM;
|
||||
else if (vreg->init_mode == QPNP_COMMON3_MODE_HPM &&
|
||||
vreg->logical_type !=
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3)
|
||||
val = QPNP_COMMON3_MODE_LPM;
|
||||
else if (vreg->init_mode == QPNP_COMMON3_MODE_HPM)
|
||||
val = QPNP_COMMON3_MODE_RETENTION;
|
||||
else
|
||||
val = vreg->init_mode;
|
||||
} else {
|
||||
if (mode == REGULATOR_MODE_NORMAL)
|
||||
val = QPNP_COMMON2_MODE_HPM;
|
||||
else if (vreg->init_mode == QPNP_COMMON2_MODE_HPM)
|
||||
val = QPNP_COMMON2_MODE_LPM;
|
||||
else
|
||||
val = vreg->init_mode;
|
||||
}
|
||||
|
||||
rc = qpnp_vreg_write_optimized(vreg, QPNP_COMMON2_REG_MODE, &val,
|
||||
&vreg->ctrl_reg[QPNP_COMMON2_IDX_MODE], 1);
|
||||
|
|
@ -1335,6 +1416,18 @@ static const char * const qpnp_common2_mode_label[] = {
|
|||
[QPNP_COMMON2_MODE_HPM] = "HPM",
|
||||
};
|
||||
|
||||
static const char * const qpnp_common3_mode_label[] = {
|
||||
[0] = "RSV",
|
||||
[1] = "RSV",
|
||||
[2] = "RSV",
|
||||
[QPNP_COMMON3_MODE_BYPASS] = "BYP",
|
||||
[QPNP_COMMON3_MODE_RETENTION] = "RET",
|
||||
[QPNP_COMMON3_MODE_LPM] = "LPM",
|
||||
[QPNP_COMMON3_MODE_AUTO] = "AUTO",
|
||||
[QPNP_COMMON3_MODE_HPM] = "HPM",
|
||||
};
|
||||
|
||||
|
||||
static void qpnp_vreg_show_state(struct regulator_dev *rdev,
|
||||
enum qpnp_regulator_action action)
|
||||
{
|
||||
|
|
@ -1495,6 +1588,16 @@ static void qpnp_vreg_show_state(struct regulator_dev *rdev,
|
|||
action_label, vreg->rdesc.name, enable_label, uV,
|
||||
mode_label);
|
||||
break;
|
||||
case QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS:
|
||||
case QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3:
|
||||
case QPNP_REGULATOR_LOGICAL_TYPE_LDO_510:
|
||||
mode_reg = vreg->ctrl_reg[QPNP_COMMON_IDX_MODE];
|
||||
mode_label = qpnp_common3_mode_label[mode_reg
|
||||
& QPNP_COMMON3_MODE_MASK];
|
||||
pr_info("%s %-11s: %s, v=%7d uV, mode=%s\n",
|
||||
action_label, vreg->rdesc.name, enable_label, uV,
|
||||
mode_label);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1618,6 +1721,45 @@ static struct regulator_ops qpnp_ftsmps426_ops = {
|
|||
.enable_time = qpnp_regulator_common_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_ops qpnp_hfsmps510_ops = {
|
||||
.enable = qpnp_regulator_common_enable,
|
||||
.disable = qpnp_regulator_common_disable,
|
||||
.is_enabled = qpnp_regulator_common_is_enabled,
|
||||
.set_voltage = qpnp_regulator_common2_set_voltage,
|
||||
.get_voltage = qpnp_regulator_common2_get_voltage,
|
||||
.list_voltage = qpnp_regulator_common_list_voltage,
|
||||
.set_mode = qpnp_regulator_common2_set_mode,
|
||||
.get_mode = qpnp_regulator_common2_get_mode,
|
||||
.get_optimum_mode = qpnp_regulator_common_get_optimum_mode,
|
||||
.enable_time = qpnp_regulator_common_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_ops qpnp_ftsmps510_ops = {
|
||||
.enable = qpnp_regulator_common_enable,
|
||||
.disable = qpnp_regulator_common_disable,
|
||||
.is_enabled = qpnp_regulator_common_is_enabled,
|
||||
.set_voltage = qpnp_regulator_common2_set_voltage,
|
||||
.get_voltage = qpnp_regulator_common2_get_voltage,
|
||||
.list_voltage = qpnp_regulator_common_list_voltage,
|
||||
.set_mode = qpnp_regulator_common2_set_mode,
|
||||
.get_mode = qpnp_regulator_common2_get_mode,
|
||||
.get_optimum_mode = qpnp_regulator_common_get_optimum_mode,
|
||||
.enable_time = qpnp_regulator_common_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_ops qpnp_ldo_510_ops = {
|
||||
.enable = qpnp_regulator_common_enable,
|
||||
.disable = qpnp_regulator_common_disable,
|
||||
.is_enabled = qpnp_regulator_common_is_enabled,
|
||||
.set_voltage = qpnp_regulator_common2_set_voltage,
|
||||
.get_voltage = qpnp_regulator_common2_get_voltage,
|
||||
.list_voltage = qpnp_regulator_common_list_voltage,
|
||||
.set_mode = qpnp_regulator_common2_set_mode,
|
||||
.get_mode = qpnp_regulator_common2_get_mode,
|
||||
.get_optimum_mode = qpnp_regulator_common_get_optimum_mode,
|
||||
.enable_time = qpnp_regulator_common_enable_time,
|
||||
};
|
||||
|
||||
/* Maximum possible digital major revision value */
|
||||
#define INF 0xFF
|
||||
|
||||
|
|
@ -1679,8 +1821,27 @@ static const struct qpnp_regulator_mapping supported_regulators[] = {
|
|||
10000),
|
||||
QPNP_VREG_MAP(ULT_LDO, P50, 0, INF, ULT_LDO, ult_ldo, ult_pldo,
|
||||
5000),
|
||||
QPNP_VREG_MAP(FTS, FTS426, 0, INF, FTSMPS2, ftsmps426, ftsmps426,
|
||||
QPNP_VREG_MAP(FTS, FTS426, 0, INF, FTSMPS2, ftsmps426, ftsmps426,
|
||||
100000),
|
||||
QPNP_VREG_MAP(LDO, LV_P150_510, 0, INF, LDO_510, ldo_510, pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, LV_P300_510, 0, INF, LDO_510, ldo_510, pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, LV_P600_510, 0, INF, LDO_510, ldo_510, pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, MV_P50_510, 0, INF, LDO_510, ldo_510, mv_pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, MV_P150_510, 0, INF, LDO_510, ldo_510, mv_pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, MV_P600_510, 0, INF, LDO_510, ldo_510, mv_pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, N300_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000),
|
||||
QPNP_VREG_MAP(LDO, N600_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000),
|
||||
QPNP_VREG_MAP(LDO, N1200_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000),
|
||||
QPNP_VREG_MAP(BUCK, HFSMPS_510, 0, INF, HFSMPS, hfsmps510, hfsmps510,
|
||||
100000),
|
||||
QPNP_VREG_MAP(FTS, FTSMPS_510, 0, INF, FTSMPS3, ftsmps510, ftsmps510,
|
||||
100000),
|
||||
};
|
||||
|
||||
static int qpnp_regulator_match(struct qpnp_regulator *vreg)
|
||||
|
|
@ -1792,10 +1953,18 @@ static int qpnp_regulator_ftsmps2_init_slew_rate(struct qpnp_regulator *vreg)
|
|||
int i, rc, delay;
|
||||
u8 reg = 0;
|
||||
|
||||
rc = qpnp_vreg_read(vreg, QPNP_COMMON2_REG_STEP_CTRL, ®, 1);
|
||||
if (rc) {
|
||||
vreg_err(vreg, "spmi read failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
if (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) {
|
||||
rc = qpnp_vreg_read(vreg, QPNP_COMMON3_REG_STEP_CTRL, ®, 1);
|
||||
if (rc) {
|
||||
vreg_err(vreg, "spmi read failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
rc = qpnp_vreg_read(vreg, QPNP_COMMON2_REG_STEP_CTRL, ®, 1);
|
||||
if (rc) {
|
||||
vreg_err(vreg, "spmi read failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1817,14 +1986,18 @@ static int qpnp_regulator_ftsmps2_init_slew_rate(struct qpnp_regulator *vreg)
|
|||
delay = (reg & QPNP_FTSMPS2_STEP_CTRL_DELAY_MASK)
|
||||
>> QPNP_FTSMPS2_STEP_CTRL_DELAY_SHIFT;
|
||||
|
||||
/* slew_rate has units of uV/us. */
|
||||
vreg->slew_rate = QPNP_FTSMPS2_CLOCK_RATE * range->step_uV;
|
||||
vreg->slew_rate /= 1000 * (QPNP_FTSMPS2_STEP_DELAY << delay);
|
||||
vreg->slew_rate = vreg->slew_rate * QPNP_FTSMPS2_STEP_MARGIN_NUM
|
||||
/ QPNP_FTSMPS2_STEP_MARGIN_DEN;
|
||||
if (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) {
|
||||
vreg->slew_rate = QPNP_COMMON3_FTSMPS3_SLEW_RATE_38p4 >> delay;
|
||||
} else {
|
||||
/* slew_rate has units of uV/us. */
|
||||
vreg->slew_rate = QPNP_FTSMPS2_CLOCK_RATE * range->step_uV;
|
||||
vreg->slew_rate /= 1000 * (QPNP_FTSMPS2_STEP_DELAY << delay);
|
||||
vreg->slew_rate = vreg->slew_rate * QPNP_FTSMPS2_STEP_MARGIN_NUM
|
||||
/ QPNP_FTSMPS2_STEP_MARGIN_DEN;
|
||||
|
||||
/* Ensure that the slew rate is greater than 0. */
|
||||
vreg->slew_rate = max(vreg->slew_rate, 1);
|
||||
/* Ensure that the slew rate is greater than 0. */
|
||||
vreg->slew_rate = max(vreg->slew_rate, 1);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1905,6 +2078,35 @@ static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg,
|
|||
= QPNP_COMMON2_MODE_LPM;
|
||||
}
|
||||
|
||||
if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3 ||
|
||||
type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS ||
|
||||
type == QPNP_REGULATOR_LOGICAL_TYPE_LDO_510) {
|
||||
if (pdata->hpm_enable == QPNP_REGULATOR_ENABLE)
|
||||
ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
= QPNP_COMMON3_MODE_HPM;
|
||||
else if (pdata->auto_mode_enable == QPNP_REGULATOR_ENABLE
|
||||
&& type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS)
|
||||
ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
= QPNP_COMMON3_MODE_AUTO;
|
||||
else if (pdata->hpm_enable == QPNP_REGULATOR_DISABLE
|
||||
&& ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
== QPNP_COMMON3_MODE_HPM &&
|
||||
type != QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3)
|
||||
ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
= QPNP_COMMON3_MODE_LPM;
|
||||
else if (pdata->hpm_enable == QPNP_REGULATOR_DISABLE
|
||||
&& ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
== QPNP_COMMON3_MODE_HPM)
|
||||
ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
= QPNP_COMMON3_MODE_RETENTION;
|
||||
else if (pdata->auto_mode_enable == QPNP_REGULATOR_DISABLE
|
||||
&& ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
== QPNP_COMMON2_MODE_AUTO &&
|
||||
type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS)
|
||||
ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
= QPNP_COMMON2_MODE_LPM;
|
||||
}
|
||||
|
||||
/* Set up mode pin control. */
|
||||
if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS
|
||||
|| type == QPNP_REGULATOR_LOGICAL_TYPE_LDO)
|
||||
|
|
@ -2068,8 +2270,9 @@ static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg,
|
|||
}
|
||||
}
|
||||
|
||||
/* Calculate the slew rate for FTSMPS2 regulators. */
|
||||
if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2) {
|
||||
/* Calculate the slew rate for FTSMPS2 and FTSMPS3 regulators. */
|
||||
if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2 ||
|
||||
type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) {
|
||||
rc = qpnp_regulator_ftsmps2_init_slew_rate(vreg);
|
||||
if (rc) {
|
||||
vreg_err(vreg, "failed to initialize step rate, rc=%d\n",
|
||||
|
|
|
|||
|
|
@ -445,7 +445,7 @@ static void rproc_rvdev_release(struct device *dev)
|
|||
/**
|
||||
* rproc_handle_vdev() - handle a vdev fw resource
|
||||
* @rproc: the remote processor
|
||||
* @rsc: the vring resource descriptor
|
||||
* ptr: the vring resource descriptor
|
||||
* @avail: size of available data (for sanity checking the image)
|
||||
*
|
||||
* This resource entry requests the host to statically register a virtio
|
||||
|
|
@ -469,9 +469,10 @@ static void rproc_rvdev_release(struct device *dev)
|
|||
*
|
||||
* Returns 0 on success, or an appropriate error code otherwise
|
||||
*/
|
||||
static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
|
||||
static int rproc_handle_vdev(struct rproc *rproc, void *ptr,
|
||||
int offset, int avail)
|
||||
{
|
||||
struct fw_rsc_vdev *rsc = ptr;
|
||||
struct device *dev = &rproc->dev;
|
||||
struct rproc_vdev *rvdev;
|
||||
int i, ret;
|
||||
|
|
@ -587,7 +588,7 @@ void rproc_vdev_release(struct kref *ref)
|
|||
/**
|
||||
* rproc_handle_trace() - handle a shared trace buffer resource
|
||||
* @rproc: the remote processor
|
||||
* @rsc: the trace resource descriptor
|
||||
* @ptr: the trace resource descriptor
|
||||
* @avail: size of available data (for sanity checking the image)
|
||||
*
|
||||
* In case the remote processor dumps trace logs into memory,
|
||||
|
|
@ -600,9 +601,10 @@ void rproc_vdev_release(struct kref *ref)
|
|||
*
|
||||
* Returns 0 on success, or an appropriate error code otherwise
|
||||
*/
|
||||
static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
|
||||
static int rproc_handle_trace(struct rproc *rproc, void *ptr,
|
||||
int offset, int avail)
|
||||
{
|
||||
struct fw_rsc_trace *rsc = ptr;
|
||||
struct rproc_debug_trace *trace;
|
||||
struct device *dev = &rproc->dev;
|
||||
char name[15];
|
||||
|
|
@ -652,7 +654,7 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
|
|||
/**
|
||||
* rproc_handle_devmem() - handle devmem resource entry
|
||||
* @rproc: remote processor handle
|
||||
* @rsc: the devmem resource entry
|
||||
* @ptr: the devmem resource entry
|
||||
* @avail: size of available data (for sanity checking the image)
|
||||
*
|
||||
* Remote processors commonly need to access certain on-chip peripherals.
|
||||
|
|
@ -674,9 +676,10 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
|
|||
* and not allow firmwares to request access to physical addresses that
|
||||
* are outside those ranges.
|
||||
*/
|
||||
static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc,
|
||||
static int rproc_handle_devmem(struct rproc *rproc, void *ptr,
|
||||
int offset, int avail)
|
||||
{
|
||||
struct fw_rsc_devmem *rsc = ptr;
|
||||
struct rproc_mem_entry *mapping;
|
||||
struct device *dev = &rproc->dev;
|
||||
int ret;
|
||||
|
|
@ -853,7 +856,7 @@ static int rproc_release_carveout(struct rproc *rproc,
|
|||
/**
|
||||
* rproc_handle_carveout() - handle phys contig memory allocation requests
|
||||
* @rproc: rproc handle
|
||||
* @rsc: the resource entry
|
||||
* @ptr: the resource entry
|
||||
* @avail: size of available data (for image validation)
|
||||
*
|
||||
* This function will handle firmware requests for allocation of physically
|
||||
|
|
@ -869,9 +872,9 @@ static int rproc_release_carveout(struct rproc *rproc,
|
|||
* pressure is important; it may have a substantial impact on performance.
|
||||
*/
|
||||
static int rproc_handle_carveout(struct rproc *rproc,
|
||||
struct fw_rsc_carveout *rsc,
|
||||
int offset, int avail)
|
||||
void *ptr, int offset, int avail)
|
||||
{
|
||||
struct fw_rsc_carveout *rsc = ptr;
|
||||
struct rproc_mem_entry *carveout;
|
||||
struct device *dev = &rproc->dev;
|
||||
|
||||
|
|
@ -1028,10 +1031,10 @@ EXPORT_SYMBOL(rproc_of_resm_mem_entry_init);
|
|||
* enum fw_resource_type.
|
||||
*/
|
||||
static rproc_handle_resource_t rproc_loading_handlers[RSC_LAST] = {
|
||||
[RSC_CARVEOUT] = (rproc_handle_resource_t)rproc_handle_carveout,
|
||||
[RSC_DEVMEM] = (rproc_handle_resource_t)rproc_handle_devmem,
|
||||
[RSC_TRACE] = (rproc_handle_resource_t)rproc_handle_trace,
|
||||
[RSC_VDEV] = (rproc_handle_resource_t)rproc_handle_vdev,
|
||||
[RSC_CARVEOUT] = rproc_handle_carveout,
|
||||
[RSC_DEVMEM] = rproc_handle_devmem,
|
||||
[RSC_TRACE] = rproc_handle_trace,
|
||||
[RSC_VDEV] = rproc_handle_vdev,
|
||||
};
|
||||
|
||||
/* handle firmware resource entries before booting the remote processor */
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ static void ufs_mtk_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
|
|||
if (!hba->vreg_info.vccq2 || !hba->vreg_info.vcc)
|
||||
return;
|
||||
|
||||
if (lpm & !hba->vreg_info.vcc->enabled)
|
||||
if (lpm && !hba->vreg_info.vcc->enabled)
|
||||
regulator_set_mode(hba->vreg_info.vccq2->reg,
|
||||
REGULATOR_MODE_IDLE);
|
||||
else if (!lpm)
|
||||
|
|
|
|||
|
|
@ -9077,7 +9077,8 @@ int ufshcd_system_suspend(struct ufs_hba *hba)
|
|||
(ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) ==
|
||||
hba->curr_dev_pwr_mode) &&
|
||||
(ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) ==
|
||||
hba->uic_link_state))
|
||||
hba->uic_link_state) &&
|
||||
!hba->dev_info.b_rpm_dev_flush_capable)
|
||||
goto out;
|
||||
|
||||
if (pm_runtime_suspended(hba->dev)) {
|
||||
|
|
@ -9274,6 +9275,7 @@ void ufshcd_remove(struct ufs_hba *hba)
|
|||
ufs_bsg_remove(hba);
|
||||
ufs_sysfs_remove_nodes(hba->dev);
|
||||
scsi_remove_host(hba->host);
|
||||
destroy_workqueue(hba->eh_wq);
|
||||
/* disable interrupts */
|
||||
ufshcd_disable_intr(hba, hba->intr_mask);
|
||||
ufshcd_hba_stop(hba, true);
|
||||
|
|
@ -9546,6 +9548,7 @@ out_remove_scsi_host:
|
|||
exit_gating:
|
||||
ufshcd_exit_clk_scaling(hba);
|
||||
ufshcd_exit_clk_gating(hba);
|
||||
destroy_workqueue(hba->eh_wq);
|
||||
out_disable:
|
||||
hba->is_irq_enabled = false;
|
||||
ufshcd_hba_exit(hba);
|
||||
|
|
|
|||
|
|
@ -1462,6 +1462,10 @@ static inline void ufshcd_vops_device_reset(struct ufs_hba *hba)
|
|||
if (hba->vops && hba->vops->device_reset) {
|
||||
hba->vops->device_reset(hba);
|
||||
ufshcd_set_ufs_dev_active(hba);
|
||||
if (ufshcd_is_wb_allowed(hba)) {
|
||||
hba->wb_enabled = false;
|
||||
hba->wb_buf_flush_enabled = false;
|
||||
}
|
||||
ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,16 @@ config CDSPRM_VTCM_DYNAMIC_DEBUG
|
|||
enabled, the vtcm partition details are sent to the CDSP via rpmsg
|
||||
channel.
|
||||
|
||||
config QCOM_SYSMON_SUBSYSTEM_STATS
|
||||
tristate "Qualcomm Technologies SysMon DSP subsystem stats"
|
||||
depends on QCOM_SMEM
|
||||
help
|
||||
sysMon subsystem stats driver exposes API to query DSP
|
||||
subsystem's load and power statistics stored in SMEM.
|
||||
SMEM region for each DSP subsystem is updated periodically
|
||||
by the respective subsystem. Power stats gets updated after
|
||||
DSP clock change event.
|
||||
|
||||
config QCOM_WDT_CORE
|
||||
tristate "Qualcomm Technologies, Inc. Watchdog Support"
|
||||
depends on ARCH_QCOM
|
||||
|
|
@ -1062,6 +1072,15 @@ config QCOM_WDT_CORE
|
|||
watchdog module must be loaded along with this for watchdog
|
||||
functionality.
|
||||
|
||||
config QCOM_CX_IPEAK
|
||||
tristate "Common driver to handle Cx iPeak limitation"
|
||||
help
|
||||
Cx ipeak HW module is used to limit the current drawn by various
|
||||
subsystem blocks on Cx power rail. Each client needs to set their
|
||||
bit in tcsr register if it is going to cross its own threshold.
|
||||
If all clients are going to cross their thresholds then Cx ipeak
|
||||
hw module will raise an interrupt to cDSP block to throttle cDSP fmax.
|
||||
|
||||
config QCOM_SOC_WATCHDOG
|
||||
tristate "Qualcomm Technologies, Inc. Soc Watchdog"
|
||||
depends on QCOM_WDT_CORE
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ endif
|
|||
obj-$(CONFIG_QTI_SYS_PM_VX) += sys_pm_vx.o
|
||||
obj-$(CONFIG_ICNSS2) += icnss2/
|
||||
obj-$(CONFIG_QTI_PLH_SCMI_CLIENT) += plh_scmi.o
|
||||
obj-$(CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS) += sysmon_subsystem_stats.o
|
||||
obj-$(CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT) += memlat_scmi.o
|
||||
obj-$(CONFIG_QTI_HW_MEMLAT) += rimps_memlat.o
|
||||
obj-$(CONFIG_QTI_HW_MEMLAT_LOG) += rimps_log.o
|
||||
|
|
@ -120,6 +121,7 @@ obj-$(CONFIG_MSM_SLATECOM_INTERFACE) += slatecom_interface.o
|
|||
obj-$(CONFIG_QCOM_AOP_SET_DDR) += aop-set-ddr.o
|
||||
obj-$(CONFIG_CPU_V7) += idle-v7.o
|
||||
obj-$(CONFIG_DUMP_XBL_LOG) += dump_boot_log.o
|
||||
obj-$(CONFIG_QCOM_CX_IPEAK) += cx_ipeak.o
|
||||
# GNSS driver
|
||||
obj-$(CONFIG_GNSS_SIRF) += gnsssirf/
|
||||
obj-$(CONFIG_MSM_SEB) += slate_events_bridge.o
|
||||
|
|
|
|||
545
drivers/soc/qcom/cx_ipeak.c
Normal file
545
drivers/soc/qcom/cx_ipeak.c
Normal file
|
|
@ -0,0 +1,545 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <soc/qcom/cx_ipeak.h>
|
||||
|
||||
#define TCSR_CXIP_LM_VOTE_FEATURE_ENABLE_OFFSET 0x10
|
||||
|
||||
/* v1 register set */
|
||||
#define TCSR_CXIP_LM_VOTE_BYPASS_OFFSET 0x4
|
||||
#define TCSR_CXIP_LM_VOTE_CLEAR_OFFSET 0x8
|
||||
#define TCSR_CXIP_LM_VOTE_SET_OFFSET 0xC
|
||||
#define TCSR_CXIP_LM_TRS_OFFSET 0x24
|
||||
|
||||
/* v2 register set */
|
||||
#define TCSR_CXIP_LM_VOTE_CLIENTx_BYPASS_OFFSET 0x4
|
||||
#define TCSR_CXIP_LM_DANGER_OFFSET 0x24
|
||||
|
||||
#define CXIP_CLIENT_OFFSET 0x1000
|
||||
#define CXIP_CLIENT10_OFFSET 0x3000
|
||||
#define CXIP_VICTIM_OFFSET 0xB000
|
||||
|
||||
#define CXIP_POLL_TIMEOUT_US (50 * 1000)
|
||||
|
||||
#define CXIP_VICTIMS 3
|
||||
#define VICTIM_ENTRIES 3
|
||||
|
||||
struct cx_ipeak_client;
|
||||
|
||||
struct cx_ipeak_core_ops {
|
||||
int (*update)(struct cx_ipeak_client *client, bool vote);
|
||||
struct cx_ipeak_client* (*register_client)(int client_id);
|
||||
};
|
||||
|
||||
static struct cx_ipeak_victims {
|
||||
u32 client_id;
|
||||
u32 victim_id;
|
||||
u32 freq_limit;
|
||||
void *data;
|
||||
cx_ipeak_victim_fn victim_cb;
|
||||
struct cx_ipeak_client *client;
|
||||
} victim_list[CXIP_VICTIMS];
|
||||
|
||||
static struct cx_ipeak_device {
|
||||
struct platform_device *pdev;
|
||||
struct mutex vote_lock;
|
||||
struct mutex throttle_lock;
|
||||
void __iomem *tcsr_vptr;
|
||||
struct cx_ipeak_core_ops *core_ops;
|
||||
u32 victims_count;
|
||||
int danger_intr_num;
|
||||
int safe_intr_num;
|
||||
} device_ipeak;
|
||||
|
||||
struct cx_ipeak_client {
|
||||
u32 vote_count;
|
||||
unsigned int offset;
|
||||
u32 client_id;
|
||||
bool danger_assert;
|
||||
struct cx_ipeak_device *dev;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* cx_ipeak_register() - allocate client structure and fill device private and
|
||||
* offset details.
|
||||
* @dev_node: device node of the client
|
||||
* @client_name: property name of the client
|
||||
*
|
||||
* Allocate client memory and fill the structure with device private and bit
|
||||
*
|
||||
*/
|
||||
struct cx_ipeak_client *cx_ipeak_register(struct device_node *dev_node,
|
||||
const char *client_name)
|
||||
{
|
||||
struct of_phandle_args cx_spec;
|
||||
struct cx_ipeak_client *client = NULL;
|
||||
int ret;
|
||||
|
||||
ret = of_parse_phandle_with_args(dev_node, client_name,
|
||||
"#size-cells", 0, &cx_spec);
|
||||
if (ret)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!of_device_is_available(cx_spec.np))
|
||||
return NULL;
|
||||
|
||||
if (device_ipeak.tcsr_vptr == NULL)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
if (cx_spec.args[0] > 31)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (device_ipeak.core_ops)
|
||||
client = device_ipeak.core_ops->register_client
|
||||
(cx_spec.args[0]);
|
||||
|
||||
client->client_id = cx_spec.args[0];
|
||||
|
||||
return client;
|
||||
}
|
||||
EXPORT_SYMBOL(cx_ipeak_register);
|
||||
|
||||
static struct cx_ipeak_client *cx_ipeak_register_v1(int client_id)
|
||||
{
|
||||
struct cx_ipeak_client *client;
|
||||
unsigned int reg_enable, reg_bypass;
|
||||
void __iomem *vptr = device_ipeak.tcsr_vptr;
|
||||
|
||||
reg_enable = readl_relaxed(device_ipeak.tcsr_vptr +
|
||||
TCSR_CXIP_LM_VOTE_FEATURE_ENABLE_OFFSET);
|
||||
reg_bypass = readl_relaxed(vptr +
|
||||
TCSR_CXIP_LM_VOTE_BYPASS_OFFSET) &
|
||||
BIT(client_id);
|
||||
if (!reg_enable || reg_bypass)
|
||||
return NULL;
|
||||
|
||||
client = kzalloc(sizeof(*client), GFP_KERNEL);
|
||||
if (!client)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
client->offset = BIT(client_id);
|
||||
client->dev = &device_ipeak;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
static struct cx_ipeak_client *cx_ipeak_register_v2(int client_id)
|
||||
{
|
||||
unsigned int reg_bypass, reg_enable;
|
||||
struct cx_ipeak_client *client;
|
||||
unsigned int client_offset = 0;
|
||||
void __iomem *vptr = device_ipeak.tcsr_vptr;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= client_id; i++)
|
||||
client_offset += CXIP_CLIENT_OFFSET;
|
||||
|
||||
if (client_id >= 10)
|
||||
client_offset += CXIP_CLIENT10_OFFSET;
|
||||
|
||||
reg_enable = readl_relaxed(device_ipeak.tcsr_vptr +
|
||||
TCSR_CXIP_LM_VOTE_FEATURE_ENABLE_OFFSET);
|
||||
reg_bypass = readl_relaxed(vptr + client_offset +
|
||||
TCSR_CXIP_LM_VOTE_CLIENTx_BYPASS_OFFSET) &
|
||||
BIT(0);
|
||||
|
||||
if (!reg_enable || reg_bypass)
|
||||
return NULL;
|
||||
|
||||
client = kzalloc(sizeof(*client), GFP_KERNEL);
|
||||
if (!client)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
client->offset = client_offset;
|
||||
client->dev = &device_ipeak;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* cx_ipeak_victim_register - victim registration API to handle
|
||||
* the cx ipeak hw interrupts (danger/safe) to throttle freq.
|
||||
* @client: cx ipeak client
|
||||
* @victim_cb: callback function of victim
|
||||
* @data: data to be passed to victim while handling irq
|
||||
*/
|
||||
int cx_ipeak_victim_register(struct cx_ipeak_client *client,
|
||||
cx_ipeak_victim_fn victim_cb, void *data)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!victim_cb)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < device_ipeak.victims_count; i++)
|
||||
if (client->client_id == victim_list[i].client_id) {
|
||||
victim_list[i].victim_cb = victim_cb;
|
||||
victim_list[i].data = data;
|
||||
victim_list[i].client = client;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL(cx_ipeak_victim_register);
|
||||
|
||||
/**
|
||||
* cx_ipeak_victim_unregister - unregister victim client from
|
||||
* cx_ipeak driver.
|
||||
* @client: cx ipeak client
|
||||
*/
|
||||
|
||||
void cx_ipeak_victim_unregister(struct cx_ipeak_client *client)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < device_ipeak.victims_count; i++)
|
||||
if (client->client_id == victim_list[i].client_id) {
|
||||
victim_list[i].victim_cb = NULL;
|
||||
victim_list[i].data = NULL;
|
||||
victim_list[i].client = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(cx_ipeak_victim_unregister);
|
||||
|
||||
/**
|
||||
* cx_ipeak_update() - Set/Clear client vote for Cx iPeak limit
|
||||
* manager to throttle cDSP.
|
||||
* @client: client handle.
|
||||
* @vote: True to set the vote and False for reset.
|
||||
*
|
||||
* Receives vote from each client and decides whether to throttle cDSP or not.
|
||||
* This function is NOP for the targets which does not support TCSR Cx iPeak.
|
||||
*/
|
||||
int cx_ipeak_update(struct cx_ipeak_client *client, bool vote)
|
||||
{
|
||||
/* Check for client and device availability and proceed */
|
||||
if (!client)
|
||||
return 0;
|
||||
|
||||
if (!client->dev || !client->dev->core_ops || !client->dev->tcsr_vptr)
|
||||
return -EINVAL;
|
||||
|
||||
return client->dev->core_ops->update(client, vote);
|
||||
}
|
||||
EXPORT_SYMBOL(cx_ipeak_update);
|
||||
|
||||
static int cx_ipeak_update_v1(struct cx_ipeak_client *client, bool vote)
|
||||
{
|
||||
unsigned int reg_val;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&client->dev->vote_lock);
|
||||
|
||||
if (vote) {
|
||||
if (client->vote_count == 0) {
|
||||
writel_relaxed(client->offset,
|
||||
client->dev->tcsr_vptr +
|
||||
TCSR_CXIP_LM_VOTE_SET_OFFSET);
|
||||
/*
|
||||
* Do a dummy read to give enough time for TRS register
|
||||
* to become 1 when the last client votes.
|
||||
*/
|
||||
readl_relaxed(client->dev->tcsr_vptr +
|
||||
TCSR_CXIP_LM_TRS_OFFSET);
|
||||
|
||||
ret = readl_poll_timeout(client->dev->tcsr_vptr +
|
||||
TCSR_CXIP_LM_TRS_OFFSET,
|
||||
reg_val, !reg_val, 0,
|
||||
CXIP_POLL_TIMEOUT_US);
|
||||
if (ret) {
|
||||
writel_relaxed(client->offset,
|
||||
client->dev->tcsr_vptr +
|
||||
TCSR_CXIP_LM_VOTE_CLEAR_OFFSET);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
client->vote_count++;
|
||||
} else {
|
||||
if (client->vote_count > 0) {
|
||||
client->vote_count--;
|
||||
if (client->vote_count == 0) {
|
||||
writel_relaxed(client->offset,
|
||||
client->dev->tcsr_vptr +
|
||||
TCSR_CXIP_LM_VOTE_CLEAR_OFFSET);
|
||||
}
|
||||
} else
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
done:
|
||||
mutex_unlock(&client->dev->vote_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cx_ipeak_update_v2(struct cx_ipeak_client *client, bool vote)
|
||||
{
|
||||
u32 reg_val;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&client->dev->vote_lock);
|
||||
|
||||
if (vote) {
|
||||
if (client->vote_count == 0) {
|
||||
writel_relaxed(BIT(0),
|
||||
client->dev->tcsr_vptr +
|
||||
client->offset);
|
||||
|
||||
ret = readl_poll_timeout(
|
||||
client->dev->tcsr_vptr +
|
||||
TCSR_CXIP_LM_DANGER_OFFSET,
|
||||
reg_val, !reg_val ||
|
||||
client->danger_assert,
|
||||
0, CXIP_POLL_TIMEOUT_US);
|
||||
/*
|
||||
* If poll exits due to danger assert condition return
|
||||
* error to client to avoid voting.
|
||||
*/
|
||||
if (client->danger_assert)
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
if (ret) {
|
||||
writel_relaxed(0,
|
||||
client->dev->tcsr_vptr +
|
||||
client->offset);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
client->vote_count++;
|
||||
} else {
|
||||
if (client->vote_count > 0) {
|
||||
client->vote_count--;
|
||||
if (client->vote_count == 0) {
|
||||
writel_relaxed(0,
|
||||
client->dev->tcsr_vptr +
|
||||
client->offset);
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
mutex_unlock(&client->dev->vote_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t cx_ipeak_irq_soft_handler(int irq, void *data)
|
||||
{
|
||||
int i;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
mutex_lock(&device_ipeak.throttle_lock);
|
||||
|
||||
for (i = 0; i < device_ipeak.victims_count; i++) {
|
||||
cx_ipeak_victim_fn victim_cb = victim_list[i].victim_cb;
|
||||
struct cx_ipeak_client *victim_client = victim_list[i].client;
|
||||
|
||||
if (!victim_cb || !victim_client)
|
||||
continue;
|
||||
|
||||
if (irq == device_ipeak.danger_intr_num) {
|
||||
|
||||
victim_client->danger_assert = true;
|
||||
|
||||
/*
|
||||
* To set frequency limit at victim client
|
||||
* side in danger interrupt case
|
||||
*/
|
||||
|
||||
ret = victim_cb(victim_list[i].data,
|
||||
victim_list[i].freq_limit);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&device_ipeak.pdev->dev,
|
||||
"Unable to throttle client:%d freq:%d\n",
|
||||
victim_list[i].client_id,
|
||||
victim_list[i].freq_limit);
|
||||
victim_client->danger_assert = false;
|
||||
ret = IRQ_HANDLED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
writel_relaxed(1, (device_ipeak.tcsr_vptr +
|
||||
CXIP_VICTIM_OFFSET +
|
||||
((victim_list[i].victim_id)*
|
||||
CXIP_CLIENT_OFFSET)));
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
} else if (irq == device_ipeak.safe_intr_num) {
|
||||
victim_client->danger_assert = false;
|
||||
/*
|
||||
* To remove frequency limit at victim client
|
||||
* side in safe interrupt case
|
||||
*/
|
||||
ret = victim_cb(victim_list[i].data, 0);
|
||||
|
||||
if (ret)
|
||||
dev_err(&device_ipeak.pdev->dev, "Unable to remove freq limit client:%d\n",
|
||||
victim_list[i].client_id);
|
||||
|
||||
writel_relaxed(0, (device_ipeak.tcsr_vptr +
|
||||
CXIP_VICTIM_OFFSET +
|
||||
((victim_list[i].victim_id)*
|
||||
CXIP_CLIENT_OFFSET)));
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
done:
|
||||
mutex_unlock(&device_ipeak.throttle_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cx_ipeak_request_irq(struct platform_device *pdev, const char *name,
|
||||
irq_handler_t handler, irq_handler_t thread_fn, void *data)
|
||||
{
|
||||
int ret, num = platform_get_irq_byname(pdev, name);
|
||||
|
||||
if (num < 0)
|
||||
return num;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, num, handler, thread_fn,
|
||||
IRQF_ONESHOT | IRQF_TRIGGER_RISING, name, data);
|
||||
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Unable to get interrupt %s: %d\n",
|
||||
name, ret);
|
||||
|
||||
return ret ? ret : num;
|
||||
}
|
||||
|
||||
/**
|
||||
* cx_ipeak_unregister() - unregister client
|
||||
* @client: client address to free
|
||||
*
|
||||
* Free the client memory
|
||||
*/
|
||||
void cx_ipeak_unregister(struct cx_ipeak_client *client)
|
||||
{
|
||||
kfree(client);
|
||||
}
|
||||
EXPORT_SYMBOL(cx_ipeak_unregister);
|
||||
|
||||
struct cx_ipeak_core_ops core_ops_v1 = {
|
||||
.update = cx_ipeak_update_v1,
|
||||
.register_client = cx_ipeak_register_v1,
|
||||
};
|
||||
|
||||
struct cx_ipeak_core_ops core_ops_v2 = {
|
||||
.update = cx_ipeak_update_v2,
|
||||
.register_client = cx_ipeak_register_v2,
|
||||
};
|
||||
|
||||
static int cx_ipeak_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
int i, ret, count;
|
||||
u32 victim_en;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
device_ipeak.tcsr_vptr = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(device_ipeak.tcsr_vptr))
|
||||
return PTR_ERR(device_ipeak.tcsr_vptr);
|
||||
|
||||
if (of_device_is_compatible(pdev->dev.of_node, "qcom,cx-ipeak-v1"))
|
||||
device_ipeak.core_ops = &core_ops_v1;
|
||||
else if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"qcom,cx-ipeak-v2"))
|
||||
device_ipeak.core_ops = &core_ops_v2;
|
||||
else
|
||||
device_ipeak.core_ops = NULL;
|
||||
|
||||
victim_en = of_property_read_bool(pdev->dev.of_node,
|
||||
"victims_table");
|
||||
|
||||
if (victim_en) {
|
||||
count = of_property_count_u32_elems(pdev->dev.of_node,
|
||||
"victims_table");
|
||||
|
||||
if (((count%VICTIM_ENTRIES) != 0) ||
|
||||
((count/VICTIM_ENTRIES) > CXIP_VICTIMS))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < (count/VICTIM_ENTRIES); i++) {
|
||||
ret = of_property_read_u32_index(pdev->dev.of_node,
|
||||
"victims_table", i*VICTIM_ENTRIES,
|
||||
&victim_list[i].client_id);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_property_read_u32_index(pdev->dev.of_node,
|
||||
"victims_table", (i*VICTIM_ENTRIES) + 1,
|
||||
&victim_list[i].victim_id);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_property_read_u32_index(pdev->dev.of_node,
|
||||
"victims_table", (i*VICTIM_ENTRIES) + 2,
|
||||
&victim_list[i].freq_limit);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
device_ipeak.victims_count++;
|
||||
}
|
||||
|
||||
device_ipeak.danger_intr_num = cx_ipeak_request_irq(pdev,
|
||||
"cx_ipeak_danger", NULL,
|
||||
cx_ipeak_irq_soft_handler, NULL);
|
||||
|
||||
if (device_ipeak.danger_intr_num < 0)
|
||||
return device_ipeak.danger_intr_num;
|
||||
|
||||
device_ipeak.safe_intr_num = cx_ipeak_request_irq(pdev,
|
||||
"cx_ipeak_safe", NULL,
|
||||
cx_ipeak_irq_soft_handler, NULL);
|
||||
|
||||
if (device_ipeak.safe_intr_num < 0)
|
||||
return device_ipeak.safe_intr_num;
|
||||
|
||||
}
|
||||
|
||||
device_ipeak.pdev = pdev;
|
||||
mutex_init(&device_ipeak.vote_lock);
|
||||
mutex_init(&device_ipeak.throttle_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cx_ipeak_match_table[] = {
|
||||
{ .compatible = "qcom,cx-ipeak-v1"},
|
||||
{ .compatible = "qcom,cx-ipeak-v2"},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver cx_ipeak_platform_driver = {
|
||||
.probe = cx_ipeak_probe,
|
||||
.driver = {
|
||||
.name = "cx_ipeak",
|
||||
.of_match_table = cx_ipeak_match_table,
|
||||
.suppress_bind_attrs = true,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init cx_ipeak_init(void)
|
||||
{
|
||||
return platform_driver_register(&cx_ipeak_platform_driver);
|
||||
}
|
||||
|
||||
arch_initcall(cx_ipeak_init);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
@ -26,6 +26,7 @@ static struct icnss_vreg_cfg icnss_adrestea_vreg_list[] = {
|
|||
{"vdd-1.3-rfa", 1304000, 1304000, 0, 0, 0, false, true},
|
||||
{"vdd-3.3-ch1", 3312000, 3312000, 0, 0, 0, false, true},
|
||||
{"vdd-3.3-ch0", 3312000, 3312000, 0, 0, 0, false, true},
|
||||
{"vdd-smps", 984000, 984000, 0, 0, 0, false, true},
|
||||
};
|
||||
|
||||
static struct icnss_clk_cfg icnss_clk_list[] = {
|
||||
|
|
|
|||
|
|
@ -1350,6 +1350,10 @@ int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv,
|
|||
mode == QMI_WLFW_OFF_V01)
|
||||
return 0;
|
||||
|
||||
if (!test_bit(ICNSS_MODE_ON, &priv->state) &&
|
||||
mode == QMI_WLFW_OFF_V01)
|
||||
return 0;
|
||||
|
||||
icnss_pr_dbg("Sending Mode request, state: 0x%lx, mode: %d\n",
|
||||
priv->state, mode);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ static bool is_rpm_controller;
|
|||
static bool has_pend_offline_req;
|
||||
static atomic_long_t totalram_pages_with_offline = ATOMIC_INIT(0);
|
||||
static struct workqueue_struct *migrate_wq;
|
||||
static unsigned long movable_bitmap;
|
||||
|
||||
#define MODULE_CLASS_NAME "mem-offline"
|
||||
#define MIGRATE_TIMEOUT_SEC (20)
|
||||
|
|
@ -752,6 +753,63 @@ static int mem_event_callback(struct notifier_block *self,
|
|||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int update_movable_bitmap(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
struct property *prop;
|
||||
int len, num_cells, num_entries;
|
||||
u64 base, size, end, section_size;
|
||||
u64 movable_start, movable_end;
|
||||
int nr_address_cells, nr_size_cells;
|
||||
const __be32 *pos;
|
||||
|
||||
node = of_find_node_by_name(of_root, "memory");
|
||||
if (!node) {
|
||||
pr_err("mem-offine: memory node not found in DT\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nr_address_cells = of_n_addr_cells(of_root);
|
||||
nr_size_cells = of_n_size_cells(of_root);
|
||||
|
||||
prop = of_find_property(node, "reg", &len);
|
||||
|
||||
num_cells = len / sizeof(__be32);
|
||||
num_entries = num_cells / (nr_address_cells + nr_size_cells);
|
||||
|
||||
pos = prop->value;
|
||||
|
||||
section_size = MIN_MEMORY_BLOCK_SIZE;
|
||||
movable_start = memblock_end_of_DRAM();
|
||||
movable_end = bootloader_memory_limit - 1;
|
||||
|
||||
while (num_entries--) {
|
||||
u64 new_base, new_end;
|
||||
u64 new_start_bitmap, bitmap_size;
|
||||
|
||||
base = of_read_number(pos, nr_address_cells);
|
||||
size = of_read_number(pos + nr_address_cells, nr_size_cells);
|
||||
pos += nr_address_cells + nr_size_cells;
|
||||
end = base + size;
|
||||
|
||||
if (end <= movable_start)
|
||||
continue;
|
||||
|
||||
if (base < movable_start)
|
||||
new_base = movable_start;
|
||||
else
|
||||
new_base = base;
|
||||
new_end = end;
|
||||
|
||||
new_start_bitmap = (new_base - movable_start) / section_size;
|
||||
bitmap_size = (new_end - new_base) / section_size;
|
||||
bitmap_set(&movable_bitmap, new_start_bitmap, bitmap_size);
|
||||
}
|
||||
|
||||
pr_debug("mem-offline: movable_bitmap is %lx\n", movable_bitmap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mem_online_remaining_blocks(void)
|
||||
{
|
||||
unsigned long memblock_end_pfn = __phys_to_pfn(memblock_end_of_DRAM());
|
||||
|
|
@ -760,6 +818,7 @@ static int mem_online_remaining_blocks(void)
|
|||
unsigned int nid;
|
||||
phys_addr_t phys_addr;
|
||||
int fail = 0;
|
||||
int ret;
|
||||
|
||||
block_size = memory_block_size_bytes();
|
||||
sections_per_block = block_size / MIN_MEMORY_BLOCK_SIZE;
|
||||
|
|
@ -771,8 +830,17 @@ static int mem_online_remaining_blocks(void)
|
|||
pr_info("mem-offline: System booted with no zone movable memory blocks. Cannot perform memory offlining\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = update_movable_bitmap();
|
||||
if (ret < 0)
|
||||
return -ENODEV;
|
||||
|
||||
for (memblock = start_section_nr; memblock <= end_section_nr;
|
||||
memblock += sections_per_block) {
|
||||
|
||||
if (!test_bit(memblock - start_section_nr, &movable_bitmap))
|
||||
continue;
|
||||
|
||||
pfn = section_nr_to_pfn(memblock);
|
||||
phys_addr = __pfn_to_phys(pfn);
|
||||
|
||||
|
|
|
|||
89
drivers/soc/qcom/sysmon_subsystem_stats.c
Normal file
89
drivers/soc/qcom/sysmon_subsystem_stats.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/qcom/smem.h>
|
||||
#include <linux/soc/qcom/sysmon_subsystem_stats.h>
|
||||
|
||||
#define SYSMON_SMEM_ID 634
|
||||
#define SYSMON_POWER_STATS_VERSIONID 0x1
|
||||
#define SYSMON_POWER_STATS_FEATUREID 0x3
|
||||
|
||||
/**
|
||||
* sysmon_stats_query_power_residency() - * API to query requested
|
||||
* DSP subsystem power residency.On success, returns power residency
|
||||
* statistics in the given sysmon_smem_power_stats structure.
|
||||
*/
|
||||
int sysmon_stats_query_power_residency(enum dsp_id_t dsp_id,
|
||||
struct sysmon_smem_power_stats *sysmon_power_stats)
|
||||
{
|
||||
u32 featureId;
|
||||
int err = 0;
|
||||
int feature, size_rcvd;
|
||||
size_t size;
|
||||
char *smem_pointer = NULL;
|
||||
int size_of_u32 = sizeof(u32);
|
||||
|
||||
if (!sysmon_power_stats || !dsp_id) {
|
||||
pr_err("%s: Null pointer received/invalid dsp ID\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
smem_pointer = qcom_smem_get(dsp_id, SYSMON_SMEM_ID, &size);
|
||||
|
||||
if (IS_ERR_OR_NULL(smem_pointer) || !size) {
|
||||
pr_err("Failed to fetch data from SMEM for ID %d: %d\n",
|
||||
dsp_id, PTR_ERR(smem_pointer));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
featureId = *(unsigned int *)smem_pointer;
|
||||
|
||||
feature = featureId >> 28;
|
||||
size_rcvd = (featureId >> 16) & 0xFFF;
|
||||
|
||||
while (size != 0) {
|
||||
switch (feature) {
|
||||
|
||||
case SYSMON_POWER_STATS_FEATUREID:
|
||||
|
||||
if (!IS_ERR_OR_NULL(smem_pointer + size_of_u32)) {
|
||||
memcpy(sysmon_power_stats, (smem_pointer + size_of_u32),
|
||||
sizeof(struct sysmon_smem_power_stats));
|
||||
size = 0;
|
||||
} else {
|
||||
pr_err("%s: Requested feature not found\n", __func__);
|
||||
size = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
if (!IS_ERR_OR_NULL(smem_pointer + size_rcvd)
|
||||
&& (size > size_rcvd)) {
|
||||
|
||||
featureId = *(unsigned int *)(smem_pointer + size_rcvd);
|
||||
|
||||
smem_pointer += size_rcvd;
|
||||
size = size - size_rcvd;
|
||||
|
||||
feature = featureId >> 28;
|
||||
size_rcvd = (featureId >> 16) & 0xFFF;
|
||||
} else {
|
||||
pr_err("%s: Requested feature not found\n", __func__);
|
||||
size = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(sysmon_stats_query_power_residency);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Sysmon subsystem Stats driver");
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
/* UART specific GENI registers */
|
||||
#define SE_UART_LOOPBACK_CFG (0x22C)
|
||||
#define SE_GENI_CFG_REG80 (0x240)
|
||||
#define SE_UART_TX_TRANS_CFG (0x25C)
|
||||
#define SE_UART_TX_WORD_LEN (0x268)
|
||||
#define SE_UART_TX_STOP_BIT_LEN (0x26C)
|
||||
|
|
@ -258,6 +259,7 @@ static int msm_geni_serial_runtime_resume(struct device *dev);
|
|||
static int msm_geni_serial_runtime_suspend(struct device *dev);
|
||||
static int msm_geni_serial_get_ver_info(struct uart_port *uport);
|
||||
static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport);
|
||||
static void msm_geni_serial_allow_rx(struct msm_geni_serial_port *port);
|
||||
static int uart_line_id;
|
||||
|
||||
#define GET_DEV_PORT(uport) \
|
||||
|
|
@ -308,6 +310,7 @@ static void msm_geni_update_uart_error_code(struct msm_geni_serial_port *port,
|
|||
static void msm_geni_serial_enable_interrupts(struct uart_port *uport)
|
||||
{
|
||||
unsigned int geni_m_irq_en, geni_s_irq_en;
|
||||
unsigned int geni_dma_tx_irq_en, geni_dma_rx_irq_en;
|
||||
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
|
||||
|
||||
geni_m_irq_en = geni_read_reg_nolog(uport->membase,
|
||||
|
|
@ -326,12 +329,28 @@ static void msm_geni_serial_enable_interrupts(struct uart_port *uport)
|
|||
geni_write_reg_nolog(DMA_RX_IRQ_BITS, uport->membase,
|
||||
SE_DMA_RX_IRQ_EN_SET);
|
||||
}
|
||||
|
||||
if (!uart_console(uport)) {
|
||||
geni_m_irq_en = geni_read_reg_nolog(uport->membase,
|
||||
SE_GENI_M_IRQ_EN);
|
||||
geni_s_irq_en = geni_read_reg_nolog(uport->membase,
|
||||
SE_GENI_S_IRQ_EN);
|
||||
geni_dma_tx_irq_en = geni_read_reg_nolog(uport->membase,
|
||||
SE_DMA_TX_IRQ_EN);
|
||||
geni_dma_rx_irq_en = geni_read_reg_nolog(uport->membase,
|
||||
SE_DMA_RX_IRQ_EN);
|
||||
IPC_LOG_MSG(port->ipc_log_misc,
|
||||
"%s: M_IRQ_EN:0x%x S_IRQ_EN:0x%x TX_IRQ_EN:0x%x RX_IRQ_EN:0x%x\n",
|
||||
__func__, geni_m_irq_en, geni_s_irq_en,
|
||||
geni_dma_tx_irq_en, geni_dma_rx_irq_en);
|
||||
}
|
||||
}
|
||||
|
||||
/* Try disabling interrupts in order to do polling in an atomic contexts. */
|
||||
static bool msm_serial_try_disable_interrupts(struct uart_port *uport)
|
||||
{
|
||||
unsigned int geni_m_irq_en, geni_s_irq_en;
|
||||
unsigned int geni_dma_tx_irq_en, geni_dma_rx_irq_en;
|
||||
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
|
||||
|
||||
/*
|
||||
|
|
@ -356,6 +375,21 @@ static bool msm_serial_try_disable_interrupts(struct uart_port *uport)
|
|||
SE_DMA_RX_IRQ_EN_CLR);
|
||||
}
|
||||
|
||||
if (!uart_console(uport)) {
|
||||
geni_m_irq_en = geni_read_reg_nolog(uport->membase,
|
||||
SE_GENI_M_IRQ_EN);
|
||||
geni_s_irq_en = geni_read_reg_nolog(uport->membase,
|
||||
SE_GENI_S_IRQ_EN);
|
||||
geni_dma_tx_irq_en = geni_read_reg_nolog(uport->membase,
|
||||
SE_DMA_TX_IRQ_EN);
|
||||
geni_dma_rx_irq_en = geni_read_reg_nolog(uport->membase,
|
||||
SE_DMA_RX_IRQ_EN);
|
||||
IPC_LOG_MSG(port->ipc_log_misc,
|
||||
"%s: M_IRQ_EN:0x%x S_IRQ_EN:0x%x TX_IRQ_EN:0x%x RX_IRQ_EN:0x%x\n",
|
||||
__func__, geni_m_irq_en, geni_s_irq_en,
|
||||
geni_dma_tx_irq_en, geni_dma_rx_irq_en);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -375,6 +409,8 @@ static bool geni_wait_for_cmd_done(struct uart_port *uport, bool is_irq_masked)
|
|||
* We need to do polling if spinlock is taken
|
||||
* by framework as we cannot rely on ISR.
|
||||
*/
|
||||
if (!uart_console(uport))
|
||||
IPC_LOG_MSG(msm_port->ipc_log_misc, "%s polling:%d\n", __func__, is_irq_masked);
|
||||
if (is_irq_masked) {
|
||||
/*
|
||||
* Polling is done for 1000 iterrations with
|
||||
|
|
@ -1028,6 +1064,9 @@ static void msm_geni_serial_console_write(struct console *co, const char *s,
|
|||
"%s: tx abort failed 0x%x\n", __func__,
|
||||
geni_read_reg_nolog(uport->membase,
|
||||
SE_GENI_STATUS));
|
||||
msm_geni_serial_allow_rx(port);
|
||||
geni_write_reg(FORCE_DEFAULT, uport->membase,
|
||||
GENI_FORCE_DEFAULT_REG);
|
||||
}
|
||||
|
||||
msm_geni_serial_enable_interrupts(uport);
|
||||
|
|
@ -1181,6 +1220,9 @@ static int msm_geni_serial_prep_dma_tx(struct uart_port *uport)
|
|||
SE_GENI_STATUS));
|
||||
msm_geni_update_uart_error_code(msm_port, UART_ERROR_TX_ABORT_FAIL);
|
||||
}
|
||||
msm_geni_serial_allow_rx(msm_port);
|
||||
geni_write_reg(FORCE_DEFAULT, uport->membase,
|
||||
GENI_FORCE_DEFAULT_REG);
|
||||
}
|
||||
|
||||
if (msm_port->xfer_mode == SE_DMA) {
|
||||
|
|
@ -1225,6 +1267,13 @@ static void msm_geni_serial_start_tx(struct uart_port *uport)
|
|||
unsigned int geni_ios;
|
||||
static unsigned int ios_log_limit;
|
||||
|
||||
/* when start_tx is called with UART clocks OFF return. */
|
||||
if (uart_console(uport) && msm_port->is_clock_off) {
|
||||
IPC_LOG_MSG(msm_port->console_log,
|
||||
"%s. Console in suspend state\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uart_console(uport) && !pm_runtime_active(uport->dev)) {
|
||||
IPC_LOG_MSG(msm_port->ipc_log_misc,
|
||||
"%s.Putting in async RPM vote\n", __func__);
|
||||
|
|
@ -1328,6 +1377,9 @@ static void stop_tx_sequencer(struct uart_port *uport)
|
|||
geni_read_reg_nolog(uport->membase, SE_GENI_STATUS));
|
||||
msm_geni_update_uart_error_code(port, UART_ERROR_TX_ABORT_FAIL);
|
||||
}
|
||||
msm_geni_serial_allow_rx(port);
|
||||
geni_write_reg(FORCE_DEFAULT, uport->membase,
|
||||
GENI_FORCE_DEFAULT_REG);
|
||||
}
|
||||
|
||||
if (port->xfer_mode == SE_DMA) {
|
||||
|
|
@ -1608,6 +1660,9 @@ static int stop_rx_sequencer(struct uart_port *uport)
|
|||
geni_se_dump_dbg_regs(&port->serial_rsc,
|
||||
uport->membase, port->ipc_log_misc);
|
||||
}
|
||||
msm_geni_serial_allow_rx(port);
|
||||
geni_write_reg(FORCE_DEFAULT, uport->membase,
|
||||
GENI_FORCE_DEFAULT_REG);
|
||||
|
||||
if (port->xfer_mode == SE_DMA) {
|
||||
port->s_cmd_done = false;
|
||||
|
|
@ -2168,9 +2223,9 @@ static void msm_geni_serial_handle_isr(struct uart_port *uport,
|
|||
if (m_irq_status || s_irq_status ||
|
||||
dma_tx_status || dma_rx_status)
|
||||
IPC_LOG_MSG(msm_port->ipc_log_irqstatus,
|
||||
"%s: sirq:0x%x mirq:0x%x dma_txirq:0x%x dma_rxirq:0x%x\n",
|
||||
"%s: sirq:0x%x mirq:0x%x dma_txirq:0x%x dma_rxirq:0x%x is_irq_masked:%d\n",
|
||||
__func__, s_irq_status, m_irq_status,
|
||||
dma_tx_status, dma_rx_status);
|
||||
dma_tx_status, dma_rx_status, is_irq_masked);
|
||||
m_cmd_done = handle_tx_dma_xfer(m_irq_status, uport);
|
||||
s_cmd_done = handle_rx_dma_xfer(s_irq_status, uport);
|
||||
}
|
||||
|
|
@ -2351,6 +2406,8 @@ static int msm_geni_serial_port_setup(struct uart_port *uport)
|
|||
SE_GENI_RX_PACKING_CFG0);
|
||||
geni_write_reg_nolog(cfg1, uport->membase,
|
||||
SE_GENI_RX_PACKING_CFG1);
|
||||
geni_write_reg_nolog(0x431c, uport->membase,
|
||||
SE_GENI_CFG_REG80);
|
||||
if (!msm_port->rx_fifo) {
|
||||
ret = -ENOMEM;
|
||||
goto exit_portsetup;
|
||||
|
|
@ -2618,7 +2675,10 @@ static void msm_geni_serial_set_termios(struct uart_port *uport,
|
|||
}
|
||||
|
||||
if (!uart_console(uport)) {
|
||||
int ret = msm_geni_serial_power_on(uport);
|
||||
int ret;
|
||||
|
||||
IPC_LOG_MSG(port->ipc_log_misc, "%s: start\n", __func__);
|
||||
ret = msm_geni_serial_power_on(uport);
|
||||
|
||||
if (ret) {
|
||||
IPC_LOG_MSG(port->ipc_log_misc,
|
||||
|
|
@ -3562,6 +3622,7 @@ static int msm_geni_serial_sys_suspend(struct device *dev)
|
|||
if (uart_console(uport) || port->pm_auto_suspend_disable) {
|
||||
uart_suspend_port((struct uart_driver *)uport->private_data,
|
||||
uport);
|
||||
IPC_LOG_MSG(port->console_log, "%s\n", __func__);
|
||||
} else {
|
||||
struct uart_state *state = uport->state;
|
||||
struct tty_port *tty_port = &state->port;
|
||||
|
|
@ -3593,6 +3654,7 @@ static int msm_geni_serial_sys_resume(struct device *dev)
|
|||
port->pm_auto_suspend_disable) {
|
||||
uart_resume_port((struct uart_driver *)uport->private_data,
|
||||
uport);
|
||||
IPC_LOG_MSG(port->console_log, "%s\n", __func__);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
18
fs/aio.c
18
fs/aio.c
|
|
@ -71,12 +71,6 @@ struct aio_ring {
|
|||
struct io_event io_events[0];
|
||||
}; /* 128 bytes + ring size */
|
||||
|
||||
/*
|
||||
* Plugging is meant to work with larger batches of IOs. If we don't
|
||||
* have more than the below, then don't bother setting up a plug.
|
||||
*/
|
||||
#define AIO_PLUG_THRESHOLD 2
|
||||
|
||||
#define AIO_RING_PAGES 8
|
||||
|
||||
struct kioctx_table {
|
||||
|
|
@ -1932,8 +1926,7 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
|
|||
if (nr > ctx->nr_events)
|
||||
nr = ctx->nr_events;
|
||||
|
||||
if (nr > AIO_PLUG_THRESHOLD)
|
||||
blk_start_plug(&plug);
|
||||
blk_start_plug(&plug);
|
||||
for (i = 0; i < nr; i++) {
|
||||
struct iocb __user *user_iocb;
|
||||
|
||||
|
|
@ -1946,8 +1939,7 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
|
|||
if (ret)
|
||||
break;
|
||||
}
|
||||
if (nr > AIO_PLUG_THRESHOLD)
|
||||
blk_finish_plug(&plug);
|
||||
blk_finish_plug(&plug);
|
||||
|
||||
percpu_ref_put(&ctx->users);
|
||||
return i ? i : ret;
|
||||
|
|
@ -1974,8 +1966,7 @@ COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id,
|
|||
if (nr > ctx->nr_events)
|
||||
nr = ctx->nr_events;
|
||||
|
||||
if (nr > AIO_PLUG_THRESHOLD)
|
||||
blk_start_plug(&plug);
|
||||
blk_start_plug(&plug);
|
||||
for (i = 0; i < nr; i++) {
|
||||
compat_uptr_t user_iocb;
|
||||
|
||||
|
|
@ -1988,8 +1979,7 @@ COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id,
|
|||
if (ret)
|
||||
break;
|
||||
}
|
||||
if (nr > AIO_PLUG_THRESHOLD)
|
||||
blk_finish_plug(&plug);
|
||||
blk_finish_plug(&plug);
|
||||
|
||||
percpu_ref_put(&ctx->users);
|
||||
return i ? i : ret;
|
||||
|
|
|
|||
2
fs/fuse/OWNERS
Normal file
2
fs/fuse/OWNERS
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# include OWNERS from the authoritative android-mainline branch
|
||||
include kernel/common:android-mainline:/fs/fuse/OWNERS
|
||||
|
|
@ -549,7 +549,6 @@ int incfs_read_file_header(struct backing_file_context *bfc,
|
|||
if (!bfc || !first_md_off)
|
||||
return -EFAULT;
|
||||
|
||||
LOCK_REQUIRED(bfc->bc_mutex);
|
||||
bytes_read = incfs_kread(bfc, &fh, sizeof(fh), 0);
|
||||
if (bytes_read < 0)
|
||||
return bytes_read;
|
||||
|
|
|
|||
|
|
@ -30,8 +30,18 @@ static ssize_t corefs_show(struct kobject *kobj,
|
|||
|
||||
static struct kobj_attribute corefs_attr = __ATTR_RO(corefs);
|
||||
|
||||
static ssize_t mounter_context_for_backing_rw_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buff)
|
||||
{
|
||||
return snprintf(buff, PAGE_SIZE, "supported\n");
|
||||
}
|
||||
|
||||
static struct kobj_attribute mounter_context_for_backing_rw_attr =
|
||||
__ATTR_RO(mounter_context_for_backing_rw);
|
||||
|
||||
static struct attribute *attributes[] = {
|
||||
&corefs_attr.attr,
|
||||
&mounter_context_for_backing_rw_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -94,4 +94,9 @@
|
|||
#define CAM_CPAS_RT_OT_FUSE 9
|
||||
#define CAM_CPAS_FUSE_FEATURE_MAX 10
|
||||
|
||||
/* Flash type*/
|
||||
#define CAM_FLASH_TYPE_GPIO 0
|
||||
#define CAM_FLASH_TYPE_I2C 1
|
||||
#define CAM_FLASH_TYPE_PMIC 2
|
||||
|
||||
#endif
|
||||
|
|
|
|||
52
include/linux/msm_kgsl.h
Normal file
52
include/linux/msm_kgsl.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef _MSM_KGSL_H
|
||||
#define _MSM_KGSL_H
|
||||
|
||||
/**
|
||||
* struct kgsl_gpu_freq_stat - Per GPU freq stat struct
|
||||
* @freq: GPU frequency in Hz
|
||||
* @active_time: GPU busy time in usecs
|
||||
* @idle_time: GPU idle time in usec
|
||||
*/
|
||||
struct kgsl_gpu_freq_stat {
|
||||
u32 freq;
|
||||
u64 active_time;
|
||||
u64 idle_time;
|
||||
};
|
||||
|
||||
/**
|
||||
* kgsl_gpu_num_freqs - Get number of available GPU frequencies
|
||||
*
|
||||
* Return: number of available frequencies on success or negative error
|
||||
* on failure
|
||||
*/
|
||||
int kgsl_gpu_num_freqs(void);
|
||||
|
||||
/**
|
||||
* kgsl_gpu_stat - Get per GPU freq stats
|
||||
* @stats: Array of struct kgsl_gpu_freq_stat to hold stats
|
||||
* @numfreq: Number of entries in @stats
|
||||
*
|
||||
* This function will populate @stats with per freq stats.
|
||||
* Number of entries in @stats array must be greater or
|
||||
* equal to value returned by function kgsl_gpu_num_freqs
|
||||
*
|
||||
* Return: 0 on success or negative error on failure
|
||||
*/
|
||||
int kgsl_gpu_stat(struct kgsl_gpu_freq_stat *stats, u32 numfreq);
|
||||
|
||||
/**
|
||||
* kgsl_gpu_frame_count - Get number of frames already processed by GPU
|
||||
* @pid: pid of the process for which frame count is required
|
||||
* @frame_count: pointer to a u64 to store frame count
|
||||
*
|
||||
* Return: zero on success and number of frames processed corresponding
|
||||
* to @pid in @frame_count or negative error on failure
|
||||
*/
|
||||
int kgsl_gpu_frame_count(pid_t pid, u64 *frame_count);
|
||||
|
||||
#endif /* _MSM_KGSL_H */
|
||||
|
||||
62
include/linux/soc/qcom/sysmon_subsystem_stats.h
Normal file
62
include/linux/soc/qcom/sysmon_subsystem_stats.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This header is for sysmon subsystem stats query API's in drivers.
|
||||
*/
|
||||
|
||||
#ifndef __QCOM_SYSMON_SUBSYSTEM_STATS_H__
|
||||
#define __QCOM_SYSMON_SUBSYSTEM_STATS_H__
|
||||
|
||||
/*
|
||||
* @struct sysmon_smem_power_stats_t
|
||||
* @brief Structure type to hold DSP power statistics.
|
||||
*/
|
||||
struct sysmon_smem_power_stats {
|
||||
u32 clk_arr[8];
|
||||
/**< Core clock frequency(KHz) array */
|
||||
|
||||
u32 active_time[8];
|
||||
/**< Active time(seconds) array corresponding to core clock array */
|
||||
|
||||
u32 pc_time;
|
||||
/**< DSP LPM(Low Power Mode) time(seconds) */
|
||||
|
||||
u32 lpi_time;
|
||||
/**< DSP LPI(Low Power Island Mode) time(seconds) */
|
||||
};
|
||||
|
||||
/*
|
||||
* @enum dsp_id_t
|
||||
* @brief Enum to hold SMEM HOST ID for DSP subsystems.
|
||||
*/
|
||||
enum dsp_id_t {
|
||||
ADSP = 2,
|
||||
SLPI,
|
||||
CDSP = 5
|
||||
};
|
||||
|
||||
/**
|
||||
* API to query requested DSP subsystem power residency.
|
||||
* On success, returns power residency statistics in the given
|
||||
* sysmon_smem_power_stats structure.
|
||||
* @arg: DSP_ID
|
||||
.* 2 - ADSP
|
||||
* 3 - SLPI
|
||||
* 5 - CDSP
|
||||
*sysmon_smem_power_stats
|
||||
* u32 clk_arr[8];
|
||||
* u32 active_time[8];
|
||||
* u32 pc_time;
|
||||
* u32 lpi_time;
|
||||
*@return SUCCESS (0) if Query is succssful
|
||||
* FAILURE (Non-zero) if Query could not be processed.
|
||||
*
|
||||
*/
|
||||
|
||||
int sysmon_stats_query_power_residency(enum dsp_id_t dsp_id,
|
||||
struct sysmon_smem_power_stats *sysmon_power_stats);
|
||||
|
||||
#endif
|
||||
|
|
@ -29,6 +29,7 @@ enum cnss_bus_width_type {
|
|||
enum cnss_platform_cap_flag {
|
||||
CNSS_HAS_EXTERNAL_SWREG = 0x01,
|
||||
CNSS_HAS_UART_ACCESS = 0x02,
|
||||
CNSS_HAS_DRV_SUPPORT = 0x04,
|
||||
};
|
||||
|
||||
struct cnss_platform_cap {
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb,
|
|||
int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup);
|
||||
|
||||
struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
|
||||
netdev_features_t features);
|
||||
netdev_features_t features, bool is_ipv6);
|
||||
|
||||
static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb)
|
||||
{
|
||||
|
|
|
|||
55
include/soc/qcom/cx_ipeak.h
Normal file
55
include/soc/qcom/cx_ipeak.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018, 2021 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_COM_CX_IPEAK_H
|
||||
#define __SOC_COM_CX_IPEAK_H
|
||||
|
||||
typedef int (*cx_ipeak_victim_fn)(void *data, u32 freq_limit);
|
||||
|
||||
struct device_node;
|
||||
struct cx_ipeak_client;
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_CX_IPEAK)
|
||||
|
||||
struct cx_ipeak_client *cx_ipeak_register(struct device_node *dev_node,
|
||||
const char *client_name);
|
||||
void cx_ipeak_unregister(struct cx_ipeak_client *client);
|
||||
int cx_ipeak_update(struct cx_ipeak_client *ipeak_client, bool vote);
|
||||
int cx_ipeak_victim_register(struct cx_ipeak_client *client,
|
||||
cx_ipeak_victim_fn victim_cb, void *data);
|
||||
void cx_ipeak_victim_unregister(struct cx_ipeak_client *client);
|
||||
|
||||
#else
|
||||
|
||||
static inline struct cx_ipeak_client *cx_ipeak_register(
|
||||
struct device_node *dev_node,
|
||||
const char *client_name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void cx_ipeak_unregister(struct cx_ipeak_client *client)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int cx_ipeak_update(struct cx_ipeak_client *ipeak_client,
|
||||
bool vote)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cx_ipeak_victim_register(struct cx_ipeak_client *client,
|
||||
cx_ipeak_victim_fn victim_cb, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void cx_ipeak_victim_unregister(struct cx_ipeak_client *client)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /*__SOC_COM_CX_IPEAK_H*/
|
||||
1
kernel/.gitignore
vendored
1
kernel/.gitignore
vendored
|
|
@ -1,6 +1,7 @@
|
|||
#
|
||||
# Generated files
|
||||
#
|
||||
config_data
|
||||
kheaders.md5
|
||||
timeconst.h
|
||||
hz.bc
|
||||
|
|
|
|||
|
|
@ -128,10 +128,15 @@ KCOV_INSTRUMENT_stackleak.o := n
|
|||
|
||||
$(obj)/configs.o: $(obj)/config_data.gz
|
||||
|
||||
targets += config_data.gz
|
||||
$(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE
|
||||
targets += config_data config_data.gz
|
||||
$(obj)/config_data.gz: $(obj)/config_data FORCE
|
||||
$(call if_changed,gzip)
|
||||
|
||||
filechk_cat = cat $<
|
||||
|
||||
$(obj)/config_data: $(KCONFIG_CONFIG) FORCE
|
||||
$(call filechk,cat)
|
||||
|
||||
$(obj)/kheaders.o: $(obj)/kheaders_data.tar.xz
|
||||
|
||||
quiet_cmd_genikh = CHK $(obj)/kheaders_data.tar.xz
|
||||
|
|
|
|||
|
|
@ -3870,6 +3870,9 @@ void scheduler_tick(void)
|
|||
if (curr->sched_class == &fair_sched_class)
|
||||
check_for_migration(rq, curr);
|
||||
|
||||
if (idle_cpu(cpu) && is_reserved(cpu))
|
||||
clear_reserved(cpu);
|
||||
|
||||
trace_android_vh_scheduler_tick(rq);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6302,22 +6302,22 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t
|
|||
static int
|
||||
select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
|
||||
{
|
||||
unsigned long best_cap = 0;
|
||||
unsigned long task_util, best_cap = 0;
|
||||
int cpu, best_cpu = -1;
|
||||
struct cpumask *cpus;
|
||||
|
||||
sync_entity_load_avg(&p->se);
|
||||
|
||||
cpus = this_cpu_cpumask_var_ptr(select_idle_mask);
|
||||
cpumask_and(cpus, sched_domain_span(sd), p->cpus_ptr);
|
||||
|
||||
task_util = uclamp_task_util(p);
|
||||
|
||||
for_each_cpu_wrap(cpu, cpus, target) {
|
||||
unsigned long cpu_cap = capacity_of(cpu);
|
||||
|
||||
if ((!available_idle_cpu(cpu) && !sched_idle_cpu(cpu)) ||
|
||||
cpu_isolated(target))
|
||||
continue;
|
||||
if (task_fits_capacity(p, cpu_cap, cpu))
|
||||
if (fits_capacity(task_util, cpu_cap))
|
||||
return cpu;
|
||||
|
||||
if (cpu_cap > best_cap) {
|
||||
|
|
@ -6329,14 +6329,60 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
|
|||
return best_cpu;
|
||||
}
|
||||
|
||||
static inline bool asym_fits_capacity(int task_util, int cpu)
|
||||
{
|
||||
if (static_branch_unlikely(&sched_asym_cpucapacity))
|
||||
return fits_capacity(task_util, capacity_of(cpu));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try and locate an idle core/thread in the LLC cache domain.
|
||||
*/
|
||||
static int select_idle_sibling(struct task_struct *p, int prev, int target)
|
||||
{
|
||||
struct sched_domain *sd;
|
||||
unsigned long task_util;
|
||||
int i, recent_used_cpu;
|
||||
|
||||
/*
|
||||
* On asymmetric system, update task utilization because we will check
|
||||
* that the task fits with cpu's capacity.
|
||||
*/
|
||||
if (static_branch_unlikely(&sched_asym_cpucapacity)) {
|
||||
sync_entity_load_avg(&p->se);
|
||||
task_util = uclamp_task_util(p);
|
||||
}
|
||||
|
||||
if ((available_idle_cpu(target) || sched_idle_cpu(target)) &&
|
||||
asym_fits_capacity(task_util, target))
|
||||
return target;
|
||||
|
||||
/*
|
||||
* If the previous CPU is cache affine and idle, don't be stupid:
|
||||
*/
|
||||
if (prev != target && cpus_share_cache(prev, target) &&
|
||||
(available_idle_cpu(prev) || sched_idle_cpu(prev)) &&
|
||||
asym_fits_capacity(task_util, prev))
|
||||
return prev;
|
||||
|
||||
/* Check a recently used CPU as a potential idle candidate: */
|
||||
recent_used_cpu = p->recent_used_cpu;
|
||||
if (recent_used_cpu != prev &&
|
||||
recent_used_cpu != target &&
|
||||
cpus_share_cache(recent_used_cpu, target) &&
|
||||
(available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) &&
|
||||
cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) &&
|
||||
asym_fits_capacity(task_util, recent_used_cpu)) {
|
||||
/*
|
||||
* Replace recent_used_cpu with prev as it is a potential
|
||||
* candidate for the next wake:
|
||||
*/
|
||||
p->recent_used_cpu = prev;
|
||||
return recent_used_cpu;
|
||||
}
|
||||
|
||||
/*
|
||||
* For asymmetric CPU capacity systems, our domain of interest is
|
||||
* sd_asym_cpucapacity rather than sd_llc.
|
||||
|
|
@ -6351,39 +6397,10 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
|
|||
* SD_ASYM_CPUCAPACITY. These should follow the usual symmetric
|
||||
* capacity path.
|
||||
*/
|
||||
if (!sd)
|
||||
goto symmetric;
|
||||
|
||||
i = select_idle_capacity(p, sd, target);
|
||||
return ((unsigned)i < nr_cpumask_bits) ? i : target;
|
||||
}
|
||||
|
||||
symmetric:
|
||||
if ((available_idle_cpu(target) || sched_idle_cpu(target)) &&
|
||||
!cpu_isolated(target))
|
||||
return target;
|
||||
|
||||
/*
|
||||
* If the previous CPU is cache affine and idle, don't be stupid:
|
||||
*/
|
||||
if (prev != target && cpus_share_cache(prev, target) &&
|
||||
((available_idle_cpu(prev) || sched_idle_cpu(prev)) &&
|
||||
!cpu_isolated(prev)))
|
||||
return prev;
|
||||
|
||||
/* Check a recently used CPU as a potential idle candidate: */
|
||||
recent_used_cpu = p->recent_used_cpu;
|
||||
if (recent_used_cpu != prev &&
|
||||
recent_used_cpu != target &&
|
||||
cpus_share_cache(recent_used_cpu, target) &&
|
||||
(available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) &&
|
||||
cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr)) {
|
||||
/*
|
||||
* Replace recent_used_cpu with prev as it is a potential
|
||||
* candidate for the next wake:
|
||||
*/
|
||||
p->recent_used_cpu = prev;
|
||||
return recent_used_cpu;
|
||||
if (sd) {
|
||||
i = select_idle_capacity(p, sd, target);
|
||||
return ((unsigned)i < nr_cpumask_bits) ? i : target;
|
||||
}
|
||||
}
|
||||
|
||||
sd = rcu_dereference(per_cpu(sd_llc, target));
|
||||
|
|
|
|||
4
mm/cma.c
4
mm/cma.c
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
struct cma cma_areas[MAX_CMA_AREAS];
|
||||
unsigned cma_area_count;
|
||||
static DEFINE_MUTEX(cma_mutex);
|
||||
|
||||
phys_addr_t cma_get_base(const struct cma *cma)
|
||||
{
|
||||
|
|
@ -508,10 +507,9 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align,
|
|||
mutex_unlock(&cma->lock);
|
||||
|
||||
pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);
|
||||
mutex_lock(&cma_mutex);
|
||||
ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA,
|
||||
GFP_KERNEL | (no_warn ? __GFP_NOWARN : 0));
|
||||
mutex_unlock(&cma_mutex);
|
||||
|
||||
if (ret == 0) {
|
||||
page = pfn_to_page(pfn);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
|
|||
[NETIF_F_GSO_SCTP_BIT] = "tx-sctp-segmentation",
|
||||
[NETIF_F_GSO_ESP_BIT] = "tx-esp-segmentation",
|
||||
[NETIF_F_GSO_UDP_L4_BIT] = "tx-udp-segmentation",
|
||||
[NETIF_F_GSO_FRAGLIST_BIT] = "tx-gso-list",
|
||||
|
||||
[NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc",
|
||||
[NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp",
|
||||
|
|
|
|||
|
|
@ -3649,7 +3649,8 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
|
|||
unsigned int delta_truesize = 0;
|
||||
unsigned int delta_len = 0;
|
||||
struct sk_buff *tail = NULL;
|
||||
struct sk_buff *nskb;
|
||||
struct sk_buff *nskb, *tmp;
|
||||
int err;
|
||||
|
||||
skb_push(skb, -skb_network_offset(skb) + offset);
|
||||
|
||||
|
|
@ -3659,11 +3660,28 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
|
|||
nskb = list_skb;
|
||||
list_skb = list_skb->next;
|
||||
|
||||
err = 0;
|
||||
if (skb_shared(nskb)) {
|
||||
tmp = skb_clone(nskb, GFP_ATOMIC);
|
||||
if (tmp) {
|
||||
consume_skb(nskb);
|
||||
nskb = tmp;
|
||||
err = skb_unclone(nskb, GFP_ATOMIC);
|
||||
} else {
|
||||
err = -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tail)
|
||||
skb->next = nskb;
|
||||
else
|
||||
tail->next = nskb;
|
||||
|
||||
if (unlikely(err)) {
|
||||
nskb->next = list_skb;
|
||||
goto err_linearize;
|
||||
}
|
||||
|
||||
tail = nskb;
|
||||
|
||||
delta_len += nskb->len;
|
||||
|
|
|
|||
|
|
@ -184,8 +184,67 @@ out_unlock:
|
|||
}
|
||||
EXPORT_SYMBOL(skb_udp_tunnel_segment);
|
||||
|
||||
static void __udpv4_gso_segment_csum(struct sk_buff *seg,
|
||||
__be32 *oldip, __be32 *newip,
|
||||
__be16 *oldport, __be16 *newport)
|
||||
{
|
||||
struct udphdr *uh;
|
||||
struct iphdr *iph;
|
||||
|
||||
if (*oldip == *newip && *oldport == *newport)
|
||||
return;
|
||||
|
||||
uh = udp_hdr(seg);
|
||||
iph = ip_hdr(seg);
|
||||
|
||||
if (uh->check) {
|
||||
inet_proto_csum_replace4(&uh->check, seg, *oldip, *newip,
|
||||
true);
|
||||
inet_proto_csum_replace2(&uh->check, seg, *oldport, *newport,
|
||||
false);
|
||||
if (!uh->check)
|
||||
uh->check = CSUM_MANGLED_0;
|
||||
}
|
||||
*oldport = *newport;
|
||||
|
||||
csum_replace4(&iph->check, *oldip, *newip);
|
||||
*oldip = *newip;
|
||||
}
|
||||
|
||||
static struct sk_buff *__udpv4_gso_segment_list_csum(struct sk_buff *segs)
|
||||
{
|
||||
struct sk_buff *seg;
|
||||
struct udphdr *uh, *uh2;
|
||||
struct iphdr *iph, *iph2;
|
||||
|
||||
seg = segs;
|
||||
uh = udp_hdr(seg);
|
||||
iph = ip_hdr(seg);
|
||||
|
||||
if ((udp_hdr(seg)->dest == udp_hdr(seg->next)->dest) &&
|
||||
(udp_hdr(seg)->source == udp_hdr(seg->next)->source) &&
|
||||
(ip_hdr(seg)->daddr == ip_hdr(seg->next)->daddr) &&
|
||||
(ip_hdr(seg)->saddr == ip_hdr(seg->next)->saddr))
|
||||
return segs;
|
||||
|
||||
while ((seg = seg->next)) {
|
||||
uh2 = udp_hdr(seg);
|
||||
iph2 = ip_hdr(seg);
|
||||
|
||||
__udpv4_gso_segment_csum(seg,
|
||||
&iph2->saddr, &iph->saddr,
|
||||
&uh2->source, &uh->source);
|
||||
__udpv4_gso_segment_csum(seg,
|
||||
&iph2->daddr, &iph->daddr,
|
||||
&uh2->dest, &uh->dest);
|
||||
}
|
||||
|
||||
return segs;
|
||||
}
|
||||
|
||||
static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
netdev_features_t features,
|
||||
bool is_ipv6)
|
||||
{
|
||||
unsigned int mss = skb_shinfo(skb)->gso_size;
|
||||
|
||||
|
|
@ -195,11 +254,11 @@ static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb,
|
|||
|
||||
udp_hdr(skb)->len = htons(sizeof(struct udphdr) + mss);
|
||||
|
||||
return skb;
|
||||
return is_ipv6 ? skb : __udpv4_gso_segment_list_csum(skb);
|
||||
}
|
||||
|
||||
struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
|
||||
netdev_features_t features)
|
||||
netdev_features_t features, bool is_ipv6)
|
||||
{
|
||||
struct sock *sk = gso_skb->sk;
|
||||
unsigned int sum_truesize = 0;
|
||||
|
|
@ -211,7 +270,7 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
|
|||
__be16 newlen;
|
||||
|
||||
if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST)
|
||||
return __udp_gso_segment_list(gso_skb, features);
|
||||
return __udp_gso_segment_list(gso_skb, features, is_ipv6);
|
||||
|
||||
mss = skb_shinfo(gso_skb)->gso_size;
|
||||
if (gso_skb->len <= sizeof(*uh) + mss)
|
||||
|
|
@ -325,7 +384,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
|
|||
goto out;
|
||||
|
||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
|
||||
return __udp_gso_segment(skb, features);
|
||||
return __udp_gso_segment(skb, features, false);
|
||||
|
||||
mss = skb_shinfo(skb)->gso_size;
|
||||
if (unlikely(skb->len <= mss))
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
|
|||
goto out;
|
||||
|
||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
|
||||
return __udp_gso_segment(skb, features);
|
||||
return __udp_gso_segment(skb, features, true);
|
||||
|
||||
/* Do software UFO. Complete and fill in the UDP checksum as HW cannot
|
||||
* do checksum of UDP packets sent as multiple IP fragments.
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ static int xfrm_xlate64_attr(struct sk_buff *dst, const struct nlattr *src)
|
|||
case XFRMA_PAD:
|
||||
/* Ignore */
|
||||
return 0;
|
||||
case XFRMA_UNSPEC:
|
||||
case XFRMA_ALG_AUTH:
|
||||
case XFRMA_ALG_CRYPT:
|
||||
case XFRMA_ALG_COMP:
|
||||
|
|
@ -387,7 +388,7 @@ static int xfrm_attr_cpy32(void *dst, size_t *pos, const struct nlattr *src,
|
|||
|
||||
memcpy(nla, src, nla_attr_size(copy_len));
|
||||
nla->nla_len = nla_attr_size(payload);
|
||||
*pos += nla_attr_size(payload);
|
||||
*pos += nla_attr_size(copy_len);
|
||||
nlmsg->nlmsg_len += nla->nla_len;
|
||||
|
||||
memset(dst + *pos, 0, payload - copy_len);
|
||||
|
|
@ -563,7 +564,7 @@ static struct nlmsghdr *xfrm_user_rcv_msg_compat(const struct nlmsghdr *h32,
|
|||
return NULL;
|
||||
|
||||
len += NLMSG_HDRLEN;
|
||||
h64 = kvmalloc(len, GFP_KERNEL | __GFP_ZERO);
|
||||
h64 = kvmalloc(len, GFP_KERNEL);
|
||||
if (!h64)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
|
|
|||
|
|
@ -2381,8 +2381,10 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
|
|||
if (in_compat_syscall()) {
|
||||
struct xfrm_translator *xtr = xfrm_get_translator();
|
||||
|
||||
if (!xtr)
|
||||
if (!xtr) {
|
||||
kfree(data);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = xtr->xlate_user_policy_sockptr(&data, optlen);
|
||||
xfrm_put_translator(xtr);
|
||||
|
|
|
|||
|
|
@ -34,9 +34,6 @@ case "$KBUILD_VERBOSE" in
|
|||
;;
|
||||
esac
|
||||
|
||||
# We need access to CONFIG_ symbols
|
||||
. include/config/auto.conf
|
||||
|
||||
# Generate a new symbol list file
|
||||
$CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh "$new_ksyms_file"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue