mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
Merge branch 'android14-6.1' into android14-6.1-lts
Merge the recent changes in android14-6.1 into android14-6.1-lts to catch up on abi changes and other issues fixed there already. Changes included in here are: *5a912daf87ANDROID: OPP: fix function args mismatch for dev_pm_opp_add in pm_opp.h *bcc435d374ANDROID: GKI: Update KMI symbol list for ASR *9e167c1c27ANDROID: GKI: Export a symbol “next_arg” for honor *4dcae85afdBACKPORT: netem: fix return value if duplicate enqueue fails *f4bcd4ef0fANDROID: 16K: Fixup padding vm_flags bits on VMA splits *9027204d5aANDROID: 16K: Introduce pgsize_migration_inline.h *03b93dc707FROMLIST: binder: fix BINDER_WORK_FROZEN_BINDER debug logs *9c6fdb6bf8BACKPORT: FROMLIST: binder: fix freeze UAF in binder_release_work() *07a43515b0FROMLIST: binder: fix OOB in binder_add_freeze_work() *a26cde4055FROMLIST: binder: fix node UAF in binder_add_freeze_work() *df571cd9f1FROMGIT: virtio_pmem: Check device status before requesting flush *b2a0a8f709ANDROID: GKI: update rockchip symbols sync with kernel update *83e7e0486eANDROID: GKI: Update symbol list for honor *5c7d0d4f4aANDROID: GKI: Update `kernel_aarch64_16k` build config to match `kernel_aarch64` *2cd8ac816dANDROID: ABI: update symbol list for honor *b5ee53c64eANDROID: Allow vendor modules perform more operationson on sock. *e64a80a096ANDROID: GKI: update symbol list file for xiaomi *530ff6a3e6ANDROID: GKI: add vendor hooks android_vh_page_should_be_protected() and android_vh_modify_scan_control(). *41e1c6f937Merge tag 'android14-6.1.99_r00' into android14-6.1 *3b95e54867ANDROID: Update the ABI symbol list *b3a2458fc6ANDROID: mm: add vh for kcompactd_cpu_online() *532fad0092ANDROID: ABI: update symbol list for honor *145b08312dANDROID: vendor_hooks: add hook to perform targeted memory management *c105083ac6ANDROID: ABI: update symbol list for honor *eda4e9fa64ANDROID: mm: add vendor hook in fault and read file *814dd5bfa8ANDROID: Update the ABI symbol list *8a268cb981ANDROID: GKI: Update symbol list for honor *be07389110ANDROID: Allow vendor modules perform operationson on memleak detect *47871c381dANDROID: GKI: Update symbol list for honor *c7b8f95c21ANDROID: Allow vendor modules perform more operations on binder transaction. *d1f3a046a6FROMGIT: f2fs: prevent atomic file from being dirtied before commit *6e5b92a6a1ANDROID: GKI: Add symbol list for exynosauto *b18f8bbc04ANDROID: GKI: Update symbol list for BCMSTB *ff74052448BACKPORT: binder_alloc: Fix sleeping function called from invalid context *75c9b1955bUPSTREAM: bpf: Fix overrunning reservations in ringbuf *fdec2610bfANDROID: gki_config: Disable CONFIG_DEBUG_STACK_USAGE *d02968a023ANDROID: gki_defconfig: Enable CONFIG_SERIAL_8250_BCM7271 *a752cdd96fBACKPORT: serial: 8250_bcm7271: improve bcm7271 8250 port *04212acc42ANDROID: GKI: Add initial symbol list for honor *27310ed6b6ANDROID: binder: fix KMI issues due to frozen notification *2f43c68d05FROMGIT: binder: frozen notification binder_features flag *eda0570485BACKPORT: FROMGIT: binder: frozen notification *822682e75dANDROID: KVM: arm64: Fix cpu type for tracing HVCs *c7596f093dANDROID: gki_defconfig: Enable CONFIG_RTC_HCTOSYS for x86 *d1af8906d9ANDROID: GKI: Update symbol list for vivo *9eca8763c1ANDROID: vendor_hooks: add hooks for exting task's swp_entrys *03a4ae5d99ANDROID: gki_defconfig: Enable Broadcom SoCs *ef0ea14d63ANDROID: ABI: Update xiaomi symbol list *eabf8327edANDROID: Update the ABI symbol list *f88293625bUPSTREAM: PM: domains: Add helper functions to attach/detach multiple PM domains *7b1e2d9798UPSTREAM: OPP: Fix -Wunsequenced in _of_add_opp_table_v1() *c33dbb3b87UPSTREAM: firmware: arm_scmi: Specify the performance level when adding an OPP *47933171f3BACKPORT: firmware: arm_scmi: Simplify error path in scmi_dvfs_device_opps_add() *b50a013d33BACKPORT: OPP: Extend support for the opp-level beyond required-opps *9ba5e19e0dUPSTREAM: OPP: Extend dev_pm_opp_data with a level *adf41f4737BACKPORT: OPP: Add dev_pm_opp_add_dynamic() to allow more flexibility *9c1597d2e4UPSTREAM: dt-bindings: power: Clarify performance capabilities of power-domains *dda942f010UPSTREAM: dt-bindings: firmware: arm,scmi: Extend bindings for protocol@13 *ff18572d05UPSTREAM: dt-bindings: arm: cpus: Add a power-domain-name for a performance-domain *5c0092ff97UPSTREAM: PM: domains: Allow genpd providers to manage OPP tables directly by its FW *c638aef4e9UPSTREAM: cpufreq: scmi: Add support to parse domain-id using #power-domain-cells *0ccb8d6efaUPSTREAM: cpufreq: scmi: Avoid one OF parsing in scmi_get_sharing_cpus() *1a6e883184UPSTREAM: firmware: arm_scmi: Drop redundant ->device_domain_id() from perf ops *3aa5b5408fUPSTREAM: firmware: arm_scmi: Align perf ops to use domain-id as in-parameter *49da9f2745UPSTREAM: cpufreq: scmi: Prepare to move OF parsing of domain-id to cpufreq *742d32f206BACKPORT: firmware: arm_scmi: Extend perf protocol ops to get information of a domain *b99f37e4a6BACKPORT: firmware: arm_scmi: Extend perf protocol ops to get number of domains *09ab235661ANDROID: vendor_hooks: export shrink_slab *8a0fa49a77UPSTREAM: erofs: fix out-of-bound access when z_erofs_gbuf_growsize() partially fails *7c5c6b6397UPSTREAM: netfilter: ipset: Fix race between namespace cleanup and gc in the list:set type *a1895da8bdANDROID: GKI: Add initial sunxi symbol list *b5e374dda9FROMLIST: usb: typec: fix up incorrectly backported "usb: typec: tcpm: unregister existing source caps before re-registration" *841cae8810UPSTREAM: net: sched: sch_multiq: fix possible OOB write in multiq_tune() *3bb5a64ae9ANDROID: Update the ABI symbol list *6cbdf0e239ANDROID: Update the ABI symbol list *25641a61baANDROID: GKI: Update symbol list for mtk *82b9eb64ebFROMGIT: KVM: arm64: Ensure TLBI uses correct VMID after changing context *9920d2584eFROMGIT: KVM: arm64: Invalidate EL1&0 TLB entries for all VMIDs in nvhe hyp init *1a48a88fcbFROMGIT: BACKPORT: KVM: arm64: Don't pass a TLBI level hint when zapping table entries *02fcfc12fcMerge tag 'android14-6.1.93_r00' into android14-6.1 *42515e9246ANDROID: sched: Add android_vh_set_task_comm *0f23336b97BACKPORT: UPSTREAM: sched: Move psi_account_irqtime() out of update_rq_clock_task() hotpath *370ea8bc2eFROMLIST: binder: fix UAF caused by offsets overwrite *f8f9a197f4ANDROID: binder: fix KMI-break due to proc->dmap *a55053f3a8UPSTREAM: binder: fix descriptor lookup for context manager *c5f1e68340BACKPORT: binder: use bitmap for faster descriptor lookup *514bdc80b9UPSTREAM: perf/core: Fix potential NULL deref *faf32723dcBACKPORT: scsi: ufs: core: Fix ufshcd_abort_one racing issue *4d735ca7bbBACKPORT: scsi: ufs: core: Fix ufshcd_clear_cmd racing issue Change-Id: Ib03de3ba63c1e5c7fc2782fefe352aaa5d234ba1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -120,6 +120,7 @@ filegroup(
|
|||||||
"android/abi_gki_aarch64_qcom",
|
"android/abi_gki_aarch64_qcom",
|
||||||
"android/abi_gki_aarch64_rockchip",
|
"android/abi_gki_aarch64_rockchip",
|
||||||
"android/abi_gki_aarch64_sony",
|
"android/abi_gki_aarch64_sony",
|
||||||
|
"android/abi_gki_aarch64_sunxi",
|
||||||
"android/abi_gki_aarch64_telechips",
|
"android/abi_gki_aarch64_telechips",
|
||||||
"android/abi_gki_aarch64_tuxera",
|
"android/abi_gki_aarch64_tuxera",
|
||||||
"android/abi_gki_aarch64_type_visibility",
|
"android/abi_gki_aarch64_type_visibility",
|
||||||
@@ -144,8 +145,14 @@ define_common_kernels(target_configs = {
|
|||||||
"make_goals": _GKI_AARCH64_MAKE_GOALS,
|
"make_goals": _GKI_AARCH64_MAKE_GOALS,
|
||||||
},
|
},
|
||||||
"kernel_aarch64_16k": {
|
"kernel_aarch64_16k": {
|
||||||
"kmi_symbol_list_strict_mode": False,
|
"kmi_symbol_list_strict_mode": True,
|
||||||
"module_implicit_outs": get_gki_modules_list("arm64"),
|
"module_implicit_outs": get_gki_modules_list("arm64"),
|
||||||
|
"kmi_symbol_list": "android/abi_gki_aarch64",
|
||||||
|
"rewrite_absolute_paths_in_config": True,
|
||||||
|
"kmi_symbol_list_add_only": True,
|
||||||
|
"additional_kmi_symbol_lists": [":aarch64_additional_kmi_symbol_lists"],
|
||||||
|
"protected_exports_list": "android/abi_gki_protected_exports_aarch64",
|
||||||
|
"protected_modules_list": "android/gki_aarch64_protected_modules",
|
||||||
"make_goals": _GKI_AARCH64_MAKE_GOALS,
|
"make_goals": _GKI_AARCH64_MAKE_GOALS,
|
||||||
},
|
},
|
||||||
"kernel_aarch64_debug": {
|
"kernel_aarch64_debug": {
|
||||||
|
|||||||
@@ -296,7 +296,9 @@ properties:
|
|||||||
power-domains property.
|
power-domains property.
|
||||||
|
|
||||||
For PSCI based platforms, the name corresponding to the index of the PSCI
|
For PSCI based platforms, the name corresponding to the index of the PSCI
|
||||||
PM domain provider, must be "psci".
|
PM domain provider, must be "psci". For SCMI based platforms, the name
|
||||||
|
corresponding to the index of an SCMI performance domain provider, must be
|
||||||
|
"perf".
|
||||||
|
|
||||||
qcom,saw:
|
qcom,saw:
|
||||||
$ref: '/schemas/types.yaml#/definitions/phandle'
|
$ref: '/schemas/types.yaml#/definitions/phandle'
|
||||||
|
|||||||
@@ -120,8 +120,15 @@ properties:
|
|||||||
'#clock-cells':
|
'#clock-cells':
|
||||||
const: 1
|
const: 1
|
||||||
|
|
||||||
required:
|
'#power-domain-cells':
|
||||||
- '#clock-cells'
|
const: 1
|
||||||
|
|
||||||
|
oneOf:
|
||||||
|
- required:
|
||||||
|
- '#clock-cells'
|
||||||
|
|
||||||
|
- required:
|
||||||
|
- '#power-domain-cells'
|
||||||
|
|
||||||
protocol@14:
|
protocol@14:
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ maintainers:
|
|||||||
|
|
||||||
description: |+
|
description: |+
|
||||||
System on chip designs are often divided into multiple PM domains that can be
|
System on chip designs are often divided into multiple PM domains that can be
|
||||||
used for power gating of selected IP blocks for power saving by reduced leakage
|
used for power gating of selected IP blocks for power saving by reduced
|
||||||
current.
|
leakage current. Moreover, in some cases the similar PM domains may also be
|
||||||
|
capable of scaling performance for a group of IP blocks.
|
||||||
|
|
||||||
This device tree binding can be used to bind PM domain consumer devices with
|
This device tree binding can be used to bind PM domain consumer devices with
|
||||||
their PM domains provided by PM domain providers. A PM domain provider can be
|
their PM domains provided by PM domain providers. A PM domain provider can be
|
||||||
@@ -25,7 +26,7 @@ description: |+
|
|||||||
|
|
||||||
properties:
|
properties:
|
||||||
$nodename:
|
$nodename:
|
||||||
pattern: "^(power-controller|power-domain)([@-].*)?$"
|
pattern: "^(power-controller|power-domain|performance-domain)([@-].*)?$"
|
||||||
|
|
||||||
domain-idle-states:
|
domain-idle-states:
|
||||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||||
@@ -47,11 +48,11 @@ properties:
|
|||||||
items:
|
items:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
description:
|
description:
|
||||||
Phandles to the OPP tables of power domains provided by a power domain
|
Phandles to the OPP tables of power domains that are capable of scaling
|
||||||
provider. If the provider provides a single power domain only or all
|
performance, provided by a power domain provider. If the provider provides
|
||||||
the power domains provided by the provider have identical OPP tables,
|
a single power domain only or all the power domains provided by the
|
||||||
then this shall contain a single phandle. Refer to ../opp/opp-v2-base.yaml
|
provider have identical OPP tables, then this shall contain a single
|
||||||
for more information.
|
phandle. Refer to ../opp/opp-v2-base.yaml for more information.
|
||||||
|
|
||||||
"#power-domain-cells":
|
"#power-domain-cells":
|
||||||
description:
|
description:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -41,3 +41,17 @@
|
|||||||
# required by asr_drm.ko
|
# required by asr_drm.ko
|
||||||
clk_set_rate_exclusive
|
clk_set_rate_exclusive
|
||||||
clk_rate_exclusive_put
|
clk_rate_exclusive_put
|
||||||
|
|
||||||
|
# required by mercury.ko
|
||||||
|
media_device_register_entity
|
||||||
|
media_device_unregister_entity
|
||||||
|
v4l2_ctrl_get_menu
|
||||||
|
v4l2_ctrl_type_op_equal
|
||||||
|
v4l2_ctrl_type_op_init
|
||||||
|
v4l2_ctrl_type_op_log
|
||||||
|
v4l2_m2m_buf_done_and_job_finish
|
||||||
|
v4l2_m2m_last_buf
|
||||||
|
|
||||||
|
# required by jpu_heap.ko
|
||||||
|
kmem_cache_size
|
||||||
|
memset16
|
||||||
|
|||||||
@@ -355,7 +355,6 @@
|
|||||||
nr_cpu_ids
|
nr_cpu_ids
|
||||||
ns_capable
|
ns_capable
|
||||||
of_address_to_resource
|
of_address_to_resource
|
||||||
of_alias_get_id
|
|
||||||
of_clk_get_by_name
|
of_clk_get_by_name
|
||||||
of_count_phandle_with_args
|
of_count_phandle_with_args
|
||||||
of_device_get_match_data
|
of_device_get_match_data
|
||||||
@@ -422,7 +421,6 @@
|
|||||||
__platform_driver_register
|
__platform_driver_register
|
||||||
platform_driver_unregister
|
platform_driver_unregister
|
||||||
platform_get_irq
|
platform_get_irq
|
||||||
platform_get_irq_byname
|
|
||||||
platform_get_irq_byname_optional
|
platform_get_irq_byname_optional
|
||||||
platform_get_irq_optional
|
platform_get_irq_optional
|
||||||
platform_get_resource
|
platform_get_resource
|
||||||
@@ -747,18 +745,6 @@
|
|||||||
vlan_vid_add
|
vlan_vid_add
|
||||||
vlan_vid_del
|
vlan_vid_del
|
||||||
|
|
||||||
# required by 8250_bcm7271.ko
|
|
||||||
serial8250_do_set_termios
|
|
||||||
serial8250_do_shutdown
|
|
||||||
serial8250_do_startup
|
|
||||||
serial8250_get_port
|
|
||||||
serial8250_handle_irq
|
|
||||||
serial8250_register_8250_port
|
|
||||||
serial8250_resume_port
|
|
||||||
serial8250_suspend_port
|
|
||||||
serial8250_unregister_port
|
|
||||||
uart_write_wakeup
|
|
||||||
|
|
||||||
# required by ahci_brcm.ko
|
# required by ahci_brcm.ko
|
||||||
phy_calibrate
|
phy_calibrate
|
||||||
|
|
||||||
@@ -797,6 +783,7 @@
|
|||||||
dma_sync_single_for_cpu
|
dma_sync_single_for_cpu
|
||||||
of_get_ethdev_address
|
of_get_ethdev_address
|
||||||
of_platform_populate
|
of_platform_populate
|
||||||
|
platform_get_irq_byname
|
||||||
__skb_pad
|
__skb_pad
|
||||||
synchronize_irq
|
synchronize_irq
|
||||||
|
|
||||||
@@ -1069,6 +1056,7 @@
|
|||||||
netif_schedule_queue
|
netif_schedule_queue
|
||||||
netif_set_real_num_rx_queues
|
netif_set_real_num_rx_queues
|
||||||
netif_set_real_num_tx_queues
|
netif_set_real_num_tx_queues
|
||||||
|
of_alias_get_id
|
||||||
of_get_compatible_child
|
of_get_compatible_child
|
||||||
of_phy_find_device
|
of_phy_find_device
|
||||||
phy_attach
|
phy_attach
|
||||||
|
|||||||
@@ -612,6 +612,8 @@
|
|||||||
seq_putc
|
seq_putc
|
||||||
seq_puts
|
seq_puts
|
||||||
seq_read
|
seq_read
|
||||||
|
serdev_device_write
|
||||||
|
serdev_device_write_wakeup
|
||||||
set_cpus_allowed_ptr
|
set_cpus_allowed_ptr
|
||||||
set_normalized_timespec64
|
set_normalized_timespec64
|
||||||
sg_alloc_table
|
sg_alloc_table
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
__tracepoint_android_vh_get_page_wmark
|
__tracepoint_android_vh_get_page_wmark
|
||||||
__tracepoint_android_vh_page_add_new_anon_rmap
|
__tracepoint_android_vh_page_add_new_anon_rmap
|
||||||
__tracepoint_android_vh_do_shrink_slab
|
__tracepoint_android_vh_do_shrink_slab
|
||||||
|
__tracepoint_android_vh_should_fault_around
|
||||||
|
__traceiter_android_vh_should_fault_around
|
||||||
__tracepoint_android_vh_shrink_slab_bypass
|
__tracepoint_android_vh_shrink_slab_bypass
|
||||||
__tracepoint_android_vh_mutex_init
|
__tracepoint_android_vh_mutex_init
|
||||||
__tracepoint_android_vh_file_is_tiny_bypass
|
__tracepoint_android_vh_file_is_tiny_bypass
|
||||||
@@ -14,6 +16,33 @@
|
|||||||
__traceiter_android_vh_shrink_slab_bypass
|
__traceiter_android_vh_shrink_slab_bypass
|
||||||
__traceiter_android_vh_mutex_init
|
__traceiter_android_vh_mutex_init
|
||||||
__traceiter_android_vh_file_is_tiny_bypass
|
__traceiter_android_vh_file_is_tiny_bypass
|
||||||
|
__tracepoint_android_vh_do_read_fault
|
||||||
|
__tracepoint_android_vh_filemap_read
|
||||||
|
__tracepoint_android_vh_filemap_map_pages
|
||||||
|
__traceiter_android_vh_do_read_fault
|
||||||
|
__traceiter_android_vh_filemap_read
|
||||||
|
__traceiter_android_vh_filemap_map_pages
|
||||||
__traceiter_android_vh_modify_scan_control
|
__traceiter_android_vh_modify_scan_control
|
||||||
__traceiter_android_vh_should_continue_reclaim
|
__traceiter_android_vh_should_continue_reclaim
|
||||||
__traceiter_android_vh_tune_fault_around_bytes
|
__traceiter_android_vh_tune_fault_around_bytes
|
||||||
|
binder_alloc_copy_from_buffer
|
||||||
|
kfree
|
||||||
|
__kmalloc
|
||||||
|
mod_node_page_state
|
||||||
|
page_cache_sync_ra
|
||||||
|
proc_create
|
||||||
|
profile_event_register
|
||||||
|
profile_event_unregister
|
||||||
|
drop_super
|
||||||
|
si_swapinfo
|
||||||
|
__show_mem
|
||||||
|
single_open
|
||||||
|
sock_from_file
|
||||||
|
task_cputime_adjusted
|
||||||
|
tcp_sync_mss
|
||||||
|
netdev_get_name
|
||||||
|
tcp_send_active_reset
|
||||||
|
tcp_done
|
||||||
|
udp4_lib_lookup
|
||||||
|
udp6_lib_lookup
|
||||||
|
next_arg
|
||||||
|
|||||||
@@ -554,6 +554,8 @@
|
|||||||
devm_request_threaded_irq
|
devm_request_threaded_irq
|
||||||
__devm_reset_control_get
|
__devm_reset_control_get
|
||||||
devm_reset_controller_register
|
devm_reset_controller_register
|
||||||
|
devm_rproc_add
|
||||||
|
devm_rproc_alloc
|
||||||
devm_rtc_allocate_device
|
devm_rtc_allocate_device
|
||||||
devm_rtc_nvmem_register
|
devm_rtc_nvmem_register
|
||||||
__devm_rtc_register_device
|
__devm_rtc_register_device
|
||||||
|
|||||||
@@ -576,6 +576,7 @@
|
|||||||
dma_direct_free
|
dma_direct_free
|
||||||
dmaengine_unmap_put
|
dmaengine_unmap_put
|
||||||
dma_fence_add_callback
|
dma_fence_add_callback
|
||||||
|
dma_fence_allocate_private_stub
|
||||||
dma_fence_array_create
|
dma_fence_array_create
|
||||||
dma_fence_array_ops
|
dma_fence_array_ops
|
||||||
dma_fence_context_alloc
|
dma_fence_context_alloc
|
||||||
@@ -1359,6 +1360,7 @@
|
|||||||
mbox_controller_unregister
|
mbox_controller_unregister
|
||||||
mbox_free_channel
|
mbox_free_channel
|
||||||
mbox_request_channel
|
mbox_request_channel
|
||||||
|
mbox_request_channel_byname
|
||||||
mbox_send_message
|
mbox_send_message
|
||||||
memchr
|
memchr
|
||||||
memchr_inv
|
memchr_inv
|
||||||
@@ -2307,6 +2309,7 @@
|
|||||||
teo_cpu_get_util_threshold
|
teo_cpu_get_util_threshold
|
||||||
teo_cpu_set_util_threshold
|
teo_cpu_set_util_threshold
|
||||||
thermal_cdev_update
|
thermal_cdev_update
|
||||||
|
thermal_cooling_device_register
|
||||||
thermal_cooling_device_unregister
|
thermal_cooling_device_unregister
|
||||||
thermal_of_cooling_device_register
|
thermal_of_cooling_device_register
|
||||||
thermal_pressure
|
thermal_pressure
|
||||||
@@ -2371,6 +2374,7 @@
|
|||||||
__traceiter_android_rvh_set_user_nice
|
__traceiter_android_rvh_set_user_nice
|
||||||
__traceiter_android_rvh_set_user_nice_locked
|
__traceiter_android_rvh_set_user_nice_locked
|
||||||
__traceiter_android_rvh_tick_entry
|
__traceiter_android_rvh_tick_entry
|
||||||
|
__traceiter_android_rvh_try_to_wake_up_success
|
||||||
__traceiter_android_rvh_typec_tcpci_get_vbus
|
__traceiter_android_rvh_typec_tcpci_get_vbus
|
||||||
__traceiter_android_rvh_uclamp_eff_get
|
__traceiter_android_rvh_uclamp_eff_get
|
||||||
__traceiter_android_rvh_ufs_complete_init
|
__traceiter_android_rvh_ufs_complete_init
|
||||||
@@ -2399,12 +2403,14 @@
|
|||||||
__traceiter_android_vh_meminfo_proc_show
|
__traceiter_android_vh_meminfo_proc_show
|
||||||
__traceiter_android_vh_mm_compaction_begin
|
__traceiter_android_vh_mm_compaction_begin
|
||||||
__traceiter_android_vh_mm_compaction_end
|
__traceiter_android_vh_mm_compaction_end
|
||||||
|
__traceiter_android_vh_mm_kcompactd_cpu_online
|
||||||
__traceiter_android_vh_prio_inheritance
|
__traceiter_android_vh_prio_inheritance
|
||||||
__traceiter_android_vh_prio_restore
|
__traceiter_android_vh_prio_restore
|
||||||
__traceiter_android_vh_resume_end
|
__traceiter_android_vh_resume_end
|
||||||
__traceiter_android_vh_rmqueue
|
__traceiter_android_vh_rmqueue
|
||||||
__traceiter_android_vh_scheduler_tick
|
__traceiter_android_vh_scheduler_tick
|
||||||
__traceiter_android_vh_setscheduler_uclamp
|
__traceiter_android_vh_setscheduler_uclamp
|
||||||
|
__traceiter_android_vh_set_task_comm
|
||||||
__traceiter_android_vh_si_meminfo_adjust
|
__traceiter_android_vh_si_meminfo_adjust
|
||||||
__traceiter_android_vh_sound_usb_support_cpu_suspend
|
__traceiter_android_vh_sound_usb_support_cpu_suspend
|
||||||
__traceiter_android_vh_sysrq_crash
|
__traceiter_android_vh_sysrq_crash
|
||||||
@@ -2426,6 +2432,7 @@
|
|||||||
__traceiter_android_vh_ufs_update_sysfs
|
__traceiter_android_vh_ufs_update_sysfs
|
||||||
__traceiter_android_vh_usb_dev_resume
|
__traceiter_android_vh_usb_dev_resume
|
||||||
__traceiter_android_vh_use_amu_fie
|
__traceiter_android_vh_use_amu_fie
|
||||||
|
__traceiter_android_vh_vmscan_kswapd_done
|
||||||
__traceiter_clock_set_rate
|
__traceiter_clock_set_rate
|
||||||
__traceiter_cma_alloc_finish
|
__traceiter_cma_alloc_finish
|
||||||
__traceiter_cma_alloc_start
|
__traceiter_cma_alloc_start
|
||||||
@@ -2444,6 +2451,7 @@
|
|||||||
__traceiter_mmap_lock_start_locking
|
__traceiter_mmap_lock_start_locking
|
||||||
__traceiter_mm_vmscan_direct_reclaim_begin
|
__traceiter_mm_vmscan_direct_reclaim_begin
|
||||||
__traceiter_mm_vmscan_direct_reclaim_end
|
__traceiter_mm_vmscan_direct_reclaim_end
|
||||||
|
__traceiter_mm_vmscan_kswapd_wake
|
||||||
__traceiter_pelt_cfs_tp
|
__traceiter_pelt_cfs_tp
|
||||||
__traceiter_pelt_dl_tp
|
__traceiter_pelt_dl_tp
|
||||||
__traceiter_pelt_irq_tp
|
__traceiter_pelt_irq_tp
|
||||||
@@ -2501,6 +2509,7 @@
|
|||||||
__tracepoint_android_rvh_set_user_nice
|
__tracepoint_android_rvh_set_user_nice
|
||||||
__tracepoint_android_rvh_set_user_nice_locked
|
__tracepoint_android_rvh_set_user_nice_locked
|
||||||
__tracepoint_android_rvh_tick_entry
|
__tracepoint_android_rvh_tick_entry
|
||||||
|
__tracepoint_android_rvh_try_to_wake_up_success
|
||||||
__tracepoint_android_rvh_typec_tcpci_get_vbus
|
__tracepoint_android_rvh_typec_tcpci_get_vbus
|
||||||
__tracepoint_android_rvh_uclamp_eff_get
|
__tracepoint_android_rvh_uclamp_eff_get
|
||||||
__tracepoint_android_rvh_ufs_complete_init
|
__tracepoint_android_rvh_ufs_complete_init
|
||||||
@@ -2529,12 +2538,14 @@
|
|||||||
__tracepoint_android_vh_meminfo_proc_show
|
__tracepoint_android_vh_meminfo_proc_show
|
||||||
__tracepoint_android_vh_mm_compaction_begin
|
__tracepoint_android_vh_mm_compaction_begin
|
||||||
__tracepoint_android_vh_mm_compaction_end
|
__tracepoint_android_vh_mm_compaction_end
|
||||||
|
__tracepoint_android_vh_mm_kcompactd_cpu_online
|
||||||
__tracepoint_android_vh_prio_inheritance
|
__tracepoint_android_vh_prio_inheritance
|
||||||
__tracepoint_android_vh_prio_restore
|
__tracepoint_android_vh_prio_restore
|
||||||
__tracepoint_android_vh_resume_end
|
__tracepoint_android_vh_resume_end
|
||||||
__tracepoint_android_vh_rmqueue
|
__tracepoint_android_vh_rmqueue
|
||||||
__tracepoint_android_vh_scheduler_tick
|
__tracepoint_android_vh_scheduler_tick
|
||||||
__tracepoint_android_vh_setscheduler_uclamp
|
__tracepoint_android_vh_setscheduler_uclamp
|
||||||
|
__tracepoint_android_vh_set_task_comm
|
||||||
__tracepoint_android_vh_si_meminfo_adjust
|
__tracepoint_android_vh_si_meminfo_adjust
|
||||||
__tracepoint_android_vh_sound_usb_support_cpu_suspend
|
__tracepoint_android_vh_sound_usb_support_cpu_suspend
|
||||||
__tracepoint_android_vh_sysrq_crash
|
__tracepoint_android_vh_sysrq_crash
|
||||||
@@ -2556,6 +2567,7 @@
|
|||||||
__tracepoint_android_vh_ufs_update_sysfs
|
__tracepoint_android_vh_ufs_update_sysfs
|
||||||
__tracepoint_android_vh_usb_dev_resume
|
__tracepoint_android_vh_usb_dev_resume
|
||||||
__tracepoint_android_vh_use_amu_fie
|
__tracepoint_android_vh_use_amu_fie
|
||||||
|
__tracepoint_android_vh_vmscan_kswapd_done
|
||||||
__tracepoint_clock_set_rate
|
__tracepoint_clock_set_rate
|
||||||
__tracepoint_cma_alloc_finish
|
__tracepoint_cma_alloc_finish
|
||||||
__tracepoint_cma_alloc_start
|
__tracepoint_cma_alloc_start
|
||||||
@@ -2574,6 +2586,7 @@
|
|||||||
__tracepoint_mmap_lock_start_locking
|
__tracepoint_mmap_lock_start_locking
|
||||||
__tracepoint_mm_vmscan_direct_reclaim_begin
|
__tracepoint_mm_vmscan_direct_reclaim_begin
|
||||||
__tracepoint_mm_vmscan_direct_reclaim_end
|
__tracepoint_mm_vmscan_direct_reclaim_end
|
||||||
|
__tracepoint_mm_vmscan_kswapd_wake
|
||||||
__tracepoint_pelt_cfs_tp
|
__tracepoint_pelt_cfs_tp
|
||||||
__tracepoint_pelt_dl_tp
|
__tracepoint_pelt_dl_tp
|
||||||
__tracepoint_pelt_irq_tp
|
__tracepoint_pelt_irq_tp
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
__arch_copy_from_user
|
__arch_copy_from_user
|
||||||
__arch_copy_to_user
|
__arch_copy_to_user
|
||||||
arch_freq_scale
|
arch_freq_scale
|
||||||
|
arch_invalidate_pmem
|
||||||
arch_timer_read_counter
|
arch_timer_read_counter
|
||||||
argv_free
|
argv_free
|
||||||
argv_split
|
argv_split
|
||||||
|
|||||||
@@ -200,6 +200,7 @@
|
|||||||
devm_clk_bulk_get
|
devm_clk_bulk_get
|
||||||
devm_clk_bulk_get_all
|
devm_clk_bulk_get_all
|
||||||
devm_clk_get
|
devm_clk_get
|
||||||
|
devm_clk_get_enabled
|
||||||
devm_clk_get_optional
|
devm_clk_get_optional
|
||||||
devm_clk_hw_register
|
devm_clk_hw_register
|
||||||
devm_clk_register
|
devm_clk_register
|
||||||
@@ -252,6 +253,7 @@
|
|||||||
__devm_regmap_init_i2c
|
__devm_regmap_init_i2c
|
||||||
__devm_regmap_init_mmio_clk
|
__devm_regmap_init_mmio_clk
|
||||||
devm_regulator_bulk_get
|
devm_regulator_bulk_get
|
||||||
|
devm_regulator_bulk_get_enable
|
||||||
devm_regulator_get
|
devm_regulator_get
|
||||||
devm_regulator_get_optional
|
devm_regulator_get_optional
|
||||||
devm_regulator_register
|
devm_regulator_register
|
||||||
@@ -1975,6 +1977,7 @@
|
|||||||
scsi_remove_device
|
scsi_remove_device
|
||||||
scsi_remove_host
|
scsi_remove_host
|
||||||
scsi_rescan_device
|
scsi_rescan_device
|
||||||
|
scsi_resume_device
|
||||||
scsi_schedule_eh
|
scsi_schedule_eh
|
||||||
scsi_sense_desc_find
|
scsi_sense_desc_find
|
||||||
scsi_set_sense_field_pointer
|
scsi_set_sense_field_pointer
|
||||||
|
|||||||
55
android/abi_gki_aarch64_sunxi
Normal file
55
android/abi_gki_aarch64_sunxi
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
[abi_symbol_list]
|
||||||
|
arp_create
|
||||||
|
clk_unregister_gate
|
||||||
|
clk_unregister_fixed_factor
|
||||||
|
dev_mc_add
|
||||||
|
dev_mc_del
|
||||||
|
dma_get_any_slave_channel
|
||||||
|
dmam_pool_create
|
||||||
|
drm_client_buffer_vmap
|
||||||
|
drm_client_framebuffer_create
|
||||||
|
drm_gem_fb_create_with_funcs
|
||||||
|
drm_property_add_enum
|
||||||
|
drm_vblank_work_init
|
||||||
|
drm_vblank_work_schedule
|
||||||
|
drm_vblank_work_cancel_sync
|
||||||
|
drm_vblank_work_flush
|
||||||
|
drm_warn_on_modeset_not_all_locked
|
||||||
|
fat_time_fat2unix
|
||||||
|
fat_time_unix2fat
|
||||||
|
gpiochip_line_is_irq
|
||||||
|
hwspin_lock_register
|
||||||
|
hwspin_lock_unregister
|
||||||
|
init_on_alloc
|
||||||
|
iio_map_array_register
|
||||||
|
iio_map_array_unregister
|
||||||
|
ioport_resource
|
||||||
|
irq_setup_alt_chip
|
||||||
|
ir_raw_event_store
|
||||||
|
ir_raw_event_handle
|
||||||
|
of_io_request_and_map
|
||||||
|
of_clk_hw_register
|
||||||
|
pinctrl_gpio_set_config
|
||||||
|
phy_queue_state_machine
|
||||||
|
phy_speed_to_str
|
||||||
|
rc_map_register
|
||||||
|
rc_map_unregister
|
||||||
|
rc_keydown
|
||||||
|
reset_control_status
|
||||||
|
skb_append
|
||||||
|
snd_dmaengine_pcm_close_release_chan
|
||||||
|
snd_dmaengine_pcm_get_chan
|
||||||
|
snd_dmaengine_pcm_open
|
||||||
|
snd_dmaengine_pcm_pointer
|
||||||
|
snd_dmaengine_pcm_trigger
|
||||||
|
spi_unregister_device
|
||||||
|
v4l2_ctrl_cluster
|
||||||
|
v4l2_g_ctrl
|
||||||
|
v4l2_i2c_new_subdev
|
||||||
|
vb2_dma_contig_set_max_seg_size
|
||||||
|
__media_entity_setup_link
|
||||||
|
__traceiter_dwc3_readl
|
||||||
|
__traceiter_dwc3_writel
|
||||||
|
__tracepoint_dwc3_readl
|
||||||
|
__tracepoint_dwc3_writel
|
||||||
|
|
||||||
@@ -3,3 +3,6 @@
|
|||||||
# for type visibility
|
# for type visibility
|
||||||
ANDROID_GKI_struct_dwc3
|
ANDROID_GKI_struct_dwc3
|
||||||
ANDROID_GKI_struct_kernel_all_info
|
ANDROID_GKI_struct_kernel_all_info
|
||||||
|
|
||||||
|
# symbol no longer needed
|
||||||
|
serial8250_handle_irq
|
||||||
|
|||||||
@@ -408,6 +408,8 @@
|
|||||||
__traceiter_android_vh_mmap_region
|
__traceiter_android_vh_mmap_region
|
||||||
__traceiter_android_vh_mutex_wait_finish
|
__traceiter_android_vh_mutex_wait_finish
|
||||||
__traceiter_android_vh_mutex_wait_start
|
__traceiter_android_vh_mutex_wait_start
|
||||||
|
__traceiter_android_vh_oom_swapmem_gather_finish
|
||||||
|
__traceiter_android_vh_oom_swapmem_gather_init
|
||||||
__traceiter_android_vh_percpu_rwsem_down_read
|
__traceiter_android_vh_percpu_rwsem_down_read
|
||||||
__traceiter_android_vh_percpu_rwsem_up_write
|
__traceiter_android_vh_percpu_rwsem_up_write
|
||||||
__traceiter_android_vh_printk_hotplug
|
__traceiter_android_vh_printk_hotplug
|
||||||
@@ -428,6 +430,9 @@
|
|||||||
__traceiter_android_vh_shmem_swapin_folio
|
__traceiter_android_vh_shmem_swapin_folio
|
||||||
__traceiter_android_vh_show_resume_epoch_val
|
__traceiter_android_vh_show_resume_epoch_val
|
||||||
__traceiter_android_vh_show_suspend_epoch_val
|
__traceiter_android_vh_show_suspend_epoch_val
|
||||||
|
__traceiter_android_vh_swapmem_gather_add_bypass
|
||||||
|
__traceiter_android_vh_swapmem_gather_finish
|
||||||
|
__traceiter_android_vh_swapmem_gather_init
|
||||||
__traceiter_android_vh_sysrq_crash
|
__traceiter_android_vh_sysrq_crash
|
||||||
__traceiter_android_vh_timer_calc_index
|
__traceiter_android_vh_timer_calc_index
|
||||||
__traceiter_android_vh_try_to_freeze_todo
|
__traceiter_android_vh_try_to_freeze_todo
|
||||||
@@ -513,6 +518,8 @@
|
|||||||
__tracepoint_android_rvh_is_cpu_allowed
|
__tracepoint_android_rvh_is_cpu_allowed
|
||||||
__tracepoint_android_rvh_migrate_queued_task
|
__tracepoint_android_rvh_migrate_queued_task
|
||||||
__tracepoint_android_rvh_new_task_stats
|
__tracepoint_android_rvh_new_task_stats
|
||||||
|
__tracepoint_android_vh_oom_swapmem_gather_finish
|
||||||
|
__tracepoint_android_vh_oom_swapmem_gather_init
|
||||||
__tracepoint_android_rvh_panic_unhandled
|
__tracepoint_android_rvh_panic_unhandled
|
||||||
__tracepoint_android_rvh_percpu_rwsem_wait_complete
|
__tracepoint_android_rvh_percpu_rwsem_wait_complete
|
||||||
__tracepoint_android_rvh_pick_next_entity
|
__tracepoint_android_rvh_pick_next_entity
|
||||||
@@ -546,6 +553,9 @@
|
|||||||
__tracepoint_android_rvh_setscheduler
|
__tracepoint_android_rvh_setscheduler
|
||||||
__tracepoint_android_rvh_shmem_get_folio
|
__tracepoint_android_rvh_shmem_get_folio
|
||||||
__tracepoint_android_rvh_show_max_freq
|
__tracepoint_android_rvh_show_max_freq
|
||||||
|
__tracepoint_android_vh_swapmem_gather_add_bypass
|
||||||
|
__tracepoint_android_vh_swapmem_gather_finish
|
||||||
|
__tracepoint_android_vh_swapmem_gather_init
|
||||||
__tracepoint_android_rvh_tick_entry
|
__tracepoint_android_rvh_tick_entry
|
||||||
__tracepoint_android_rvh_try_to_wake_up
|
__tracepoint_android_rvh_try_to_wake_up
|
||||||
__tracepoint_android_rvh_try_to_wake_up_success
|
__tracepoint_android_rvh_try_to_wake_up_success
|
||||||
|
|||||||
@@ -373,6 +373,9 @@
|
|||||||
pci_sriov_set_totalvfs
|
pci_sriov_set_totalvfs
|
||||||
pci_num_vf
|
pci_num_vf
|
||||||
|
|
||||||
|
# required by shrink memory module
|
||||||
|
shrink_slab
|
||||||
|
|
||||||
#required by cifs.ko
|
#required by cifs.ko
|
||||||
add_swap_extent
|
add_swap_extent
|
||||||
asn1_ber_decoder
|
asn1_ber_decoder
|
||||||
@@ -459,6 +462,13 @@
|
|||||||
__fs_parse
|
__fs_parse
|
||||||
__filemap_get_folio
|
__filemap_get_folio
|
||||||
|
|
||||||
|
#required by mem_reclaim_ctl.ko
|
||||||
|
__traceiter_android_vh_page_should_be_protected
|
||||||
|
__tracepoint_android_vh_page_should_be_protected
|
||||||
|
__traceiter_android_vh_page_referenced_check_bypass
|
||||||
|
__tracepoint_android_vh_page_referenced_check_bypass
|
||||||
|
__page_mapcount
|
||||||
|
|
||||||
#required by mi_async_reclaim.ko
|
#required by mi_async_reclaim.ko
|
||||||
__traceiter_android_vh_handle_trylock_failed_folio
|
__traceiter_android_vh_handle_trylock_failed_folio
|
||||||
__tracepoint_android_vh_handle_trylock_failed_folio
|
__tracepoint_android_vh_handle_trylock_failed_folio
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ bt_err_ratelimited
|
|||||||
bt_info
|
bt_info
|
||||||
bt_procfs_cleanup
|
bt_procfs_cleanup
|
||||||
bt_procfs_init
|
bt_procfs_init
|
||||||
|
bt_sock_alloc
|
||||||
bt_sock_ioctl
|
bt_sock_ioctl
|
||||||
bt_sock_link
|
bt_sock_link
|
||||||
bt_sock_poll
|
bt_sock_poll
|
||||||
|
|||||||
@@ -402,7 +402,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
|
|||||||
CONFIG_SERIAL_8250_NR_UARTS=32
|
CONFIG_SERIAL_8250_NR_UARTS=32
|
||||||
CONFIG_SERIAL_8250_RUNTIME_UARTS=0
|
CONFIG_SERIAL_8250_RUNTIME_UARTS=0
|
||||||
CONFIG_SERIAL_8250_DW=y
|
CONFIG_SERIAL_8250_DW=y
|
||||||
# CONFIG_SERIAL_8250_BCM7271 is not set
|
|
||||||
CONFIG_SERIAL_OF_PLATFORM=y
|
CONFIG_SERIAL_OF_PLATFORM=y
|
||||||
CONFIG_SERIAL_AMBA_PL011=y
|
CONFIG_SERIAL_AMBA_PL011=y
|
||||||
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
||||||
@@ -732,6 +731,7 @@ CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
|
|||||||
CONFIG_TRACE_MMIO_ACCESS=y
|
CONFIG_TRACE_MMIO_ACCESS=y
|
||||||
CONFIG_CRC_CCITT=y
|
CONFIG_CRC_CCITT=y
|
||||||
CONFIG_XZ_DEC=y
|
CONFIG_XZ_DEC=y
|
||||||
|
CONFIG_DMA_RESTRICTED_POOL=y
|
||||||
CONFIG_DMA_CMA=y
|
CONFIG_DMA_CMA=y
|
||||||
CONFIG_PRINTK_TIME=y
|
CONFIG_PRINTK_TIME=y
|
||||||
CONFIG_PRINTK_CALLER=y
|
CONFIG_PRINTK_CALLER=y
|
||||||
@@ -751,7 +751,6 @@ CONFIG_UBSAN_LOCAL_BOUNDS=y
|
|||||||
CONFIG_PAGE_OWNER=y
|
CONFIG_PAGE_OWNER=y
|
||||||
CONFIG_PAGE_PINNER=y
|
CONFIG_PAGE_PINNER=y
|
||||||
CONFIG_PER_VMA_LOCK_STATS=y
|
CONFIG_PER_VMA_LOCK_STATS=y
|
||||||
CONFIG_DEBUG_STACK_USAGE=y
|
|
||||||
CONFIG_DEBUG_MEMORY_INIT=y
|
CONFIG_DEBUG_MEMORY_INIT=y
|
||||||
CONFIG_KASAN=y
|
CONFIG_KASAN=y
|
||||||
CONFIG_KASAN_HW_TAGS=y
|
CONFIG_KASAN_HW_TAGS=y
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ void *rb_reserve_trace_entry(struct hyp_rb_per_cpu *cpu_buffer, unsigned long le
|
|||||||
int __pkvm_load_tracing(unsigned long pack_va, size_t pack_size);
|
int __pkvm_load_tracing(unsigned long pack_va, size_t pack_size);
|
||||||
void __pkvm_teardown_tracing(void);
|
void __pkvm_teardown_tracing(void);
|
||||||
int __pkvm_enable_tracing(bool enable);
|
int __pkvm_enable_tracing(bool enable);
|
||||||
int __pkvm_rb_swap_reader_page(int cpu);
|
int __pkvm_rb_swap_reader_page(unsigned int cpu);
|
||||||
int __pkvm_rb_update_footers(int cpu);
|
int __pkvm_rb_update_footers(unsigned int cpu);
|
||||||
int __pkvm_enable_event(unsigned short id, bool enable);
|
int __pkvm_enable_event(unsigned short id, bool enable);
|
||||||
|
|
||||||
#define HYP_EVENT(__name, __proto, __struct, __assign, __printk) \
|
#define HYP_EVENT(__name, __proto, __struct, __assign, __printk) \
|
||||||
@@ -94,12 +94,12 @@ static inline void __pkvm_teardown_tracing(void) { }
|
|||||||
|
|
||||||
static inline int __pkvm_enable_tracing(bool enable) { return -ENODEV; }
|
static inline int __pkvm_enable_tracing(bool enable) { return -ENODEV; }
|
||||||
|
|
||||||
static inline int __pkvm_rb_swap_reader_page(int cpu)
|
static inline int __pkvm_rb_swap_reader_page(unsigned int cpu)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int __pkvm_rb_update_footers(int cpu)
|
static inline int __pkvm_rb_update_footers(unsigned int cpu)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ alternative_else_nop_endif
|
|||||||
|
|
||||||
/* Invalidate the stale TLBs from Bootloader */
|
/* Invalidate the stale TLBs from Bootloader */
|
||||||
tlbi alle2
|
tlbi alle2
|
||||||
tlbi vmalls12e1
|
tlbi alle1
|
||||||
dsb sy
|
dsb sy
|
||||||
|
|
||||||
mov_q x0, INIT_SCTLR_EL2_MMU_ON
|
mov_q x0, INIT_SCTLR_EL2_MMU_ON
|
||||||
|
|||||||
@@ -1241,14 +1241,14 @@ static void handle___pkvm_enable_tracing(struct kvm_cpu_context *host_ctxt)
|
|||||||
|
|
||||||
static void handle___pkvm_rb_swap_reader_page(struct kvm_cpu_context *host_ctxt)
|
static void handle___pkvm_rb_swap_reader_page(struct kvm_cpu_context *host_ctxt)
|
||||||
{
|
{
|
||||||
DECLARE_REG(int, cpu, host_ctxt, 1);
|
DECLARE_REG(unsigned int, cpu, host_ctxt, 1);
|
||||||
|
|
||||||
cpu_reg(host_ctxt, 1) = __pkvm_rb_swap_reader_page(cpu);
|
cpu_reg(host_ctxt, 1) = __pkvm_rb_swap_reader_page(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle___pkvm_rb_update_footers(struct kvm_cpu_context *host_ctxt)
|
static void handle___pkvm_rb_update_footers(struct kvm_cpu_context *host_ctxt)
|
||||||
{
|
{
|
||||||
DECLARE_REG(int, cpu, host_ctxt, 1);
|
DECLARE_REG(unsigned int, cpu, host_ctxt, 1);
|
||||||
|
|
||||||
cpu_reg(host_ctxt, 1) = __pkvm_rb_update_footers(cpu);
|
cpu_reg(host_ctxt, 1) = __pkvm_rb_update_footers(cpu);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,10 +106,10 @@ static void exit_vmid_context(struct tlb_inv_context *cxt)
|
|||||||
else
|
else
|
||||||
__load_host_stage2();
|
__load_host_stage2();
|
||||||
|
|
||||||
if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
|
/* Ensure write of the old VMID */
|
||||||
/* Ensure write of the old VMID */
|
isb();
|
||||||
isb();
|
|
||||||
|
|
||||||
|
if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
|
||||||
if (!(cxt->sctlr & SCTLR_ELx_M)) {
|
if (!(cxt->sctlr & SCTLR_ELx_M)) {
|
||||||
write_sysreg_el1(cxt->sctlr, SYS_SCTLR);
|
write_sysreg_el1(cxt->sctlr, SYS_SCTLR);
|
||||||
isb();
|
isb();
|
||||||
|
|||||||
@@ -485,7 +485,7 @@ static void rb_teardown_bpage_backing(void)
|
|||||||
hyp_buffer_pages_backing.size = 0;
|
hyp_buffer_pages_backing.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __pkvm_rb_update_footers(int cpu)
|
int __pkvm_rb_update_footers(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct hyp_rb_per_cpu *cpu_buffer;
|
struct hyp_rb_per_cpu *cpu_buffer;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -508,9 +508,9 @@ int __pkvm_rb_update_footers(int cpu)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __pkvm_rb_swap_reader_page(int cpu)
|
int __pkvm_rb_swap_reader_page(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct hyp_rb_per_cpu *cpu_buffer = per_cpu_ptr(&trace_rb, cpu);
|
struct hyp_rb_per_cpu *cpu_buffer;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (cpu >= hyp_nr_cpus)
|
if (cpu >= hyp_nr_cpus)
|
||||||
|
|||||||
@@ -420,7 +420,7 @@ static int hyp_unmap_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
|
|||||||
|
|
||||||
kvm_clear_pte(ptep);
|
kvm_clear_pte(ptep);
|
||||||
dsb(ishst);
|
dsb(ishst);
|
||||||
__tlbi_level(vae2is, __TLBI_VADDR(addr, 0), level);
|
__tlbi_level(vae2is, __TLBI_VADDR(addr, 0), 0);
|
||||||
} else {
|
} else {
|
||||||
if (end - addr < granule)
|
if (end - addr < granule)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -661,10 +661,15 @@ static bool stage2_pte_needs_update(struct kvm_pgtable *pgt,
|
|||||||
static void stage2_clear_pte(kvm_pte_t *ptep, struct kvm_s2_mmu *mmu, u64 addr,
|
static void stage2_clear_pte(kvm_pte_t *ptep, struct kvm_s2_mmu *mmu, u64 addr,
|
||||||
u32 level)
|
u32 level)
|
||||||
{
|
{
|
||||||
if (!kvm_pte_valid(*ptep))
|
kvm_pte_t pte = *ptep;
|
||||||
|
|
||||||
|
if (!kvm_pte_valid(pte))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
kvm_clear_pte(ptep);
|
kvm_clear_pte(ptep);
|
||||||
|
|
||||||
|
if (kvm_pte_table(pte, level))
|
||||||
|
level = 0;
|
||||||
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, addr, level);
|
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, addr, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -512,7 +512,6 @@ CONFIG_LEDS_TRIGGER_TIMER=y
|
|||||||
CONFIG_LEDS_TRIGGER_TRANSIENT=y
|
CONFIG_LEDS_TRIGGER_TRANSIENT=y
|
||||||
CONFIG_EDAC=y
|
CONFIG_EDAC=y
|
||||||
CONFIG_RTC_CLASS=y
|
CONFIG_RTC_CLASS=y
|
||||||
# CONFIG_RTC_HCTOSYS is not set
|
|
||||||
CONFIG_DMABUF_HEAPS=y
|
CONFIG_DMABUF_HEAPS=y
|
||||||
CONFIG_DMABUF_SYSFS_STATS=y
|
CONFIG_DMABUF_SYSFS_STATS=y
|
||||||
CONFIG_DMABUF_HEAPS_DEFERRED_FREE=y
|
CONFIG_DMABUF_HEAPS_DEFERRED_FREE=y
|
||||||
@@ -665,7 +664,6 @@ CONFIG_UBSAN_LOCAL_BOUNDS=y
|
|||||||
# CONFIG_UBSAN_ENUM is not set
|
# CONFIG_UBSAN_ENUM is not set
|
||||||
CONFIG_PAGE_OWNER=y
|
CONFIG_PAGE_OWNER=y
|
||||||
CONFIG_PER_VMA_LOCK_STATS=y
|
CONFIG_PER_VMA_LOCK_STATS=y
|
||||||
CONFIG_DEBUG_STACK_USAGE=y
|
|
||||||
CONFIG_DEBUG_MEMORY_INIT=y
|
CONFIG_DEBUG_MEMORY_INIT=y
|
||||||
CONFIG_KFENCE=y
|
CONFIG_KFENCE=y
|
||||||
CONFIG_KFENCE_SAMPLE_INTERVAL=500
|
CONFIG_KFENCE_SAMPLE_INTERVAL=500
|
||||||
|
|||||||
@@ -1236,6 +1236,63 @@ static struct binder_ref *binder_get_ref_olocked(struct binder_proc *proc,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find the smallest unused descriptor the "slow way" */
|
||||||
|
static u32 slow_desc_lookup_olocked(struct binder_proc *proc, u32 offset)
|
||||||
|
{
|
||||||
|
struct binder_ref *ref;
|
||||||
|
struct rb_node *n;
|
||||||
|
u32 desc;
|
||||||
|
|
||||||
|
desc = offset;
|
||||||
|
for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n)) {
|
||||||
|
ref = rb_entry(n, struct binder_ref, rb_node_desc);
|
||||||
|
if (ref->data.desc > desc)
|
||||||
|
break;
|
||||||
|
desc = ref->data.desc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find an available reference descriptor ID. The proc->outer_lock might
|
||||||
|
* be released in the process, in which case -EAGAIN is returned and the
|
||||||
|
* @desc should be considered invalid.
|
||||||
|
*/
|
||||||
|
static int get_ref_desc_olocked(struct binder_proc *proc,
|
||||||
|
struct binder_node *node,
|
||||||
|
u32 *desc)
|
||||||
|
{
|
||||||
|
struct dbitmap *dmap = &proc_wrapper(proc)->dmap;
|
||||||
|
unsigned int nbits, offset;
|
||||||
|
unsigned long *new, bit;
|
||||||
|
|
||||||
|
/* 0 is reserved for the context manager */
|
||||||
|
offset = (node == proc->context->binder_context_mgr_node) ? 0 : 1;
|
||||||
|
|
||||||
|
if (!dbitmap_enabled(dmap)) {
|
||||||
|
*desc = slow_desc_lookup_olocked(proc, offset);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dbitmap_acquire_next_zero_bit(dmap, offset, &bit) == 0) {
|
||||||
|
*desc = bit;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The dbitmap is full and needs to grow. The proc->outer_lock
|
||||||
|
* is briefly released to allocate the new bitmap safely.
|
||||||
|
*/
|
||||||
|
nbits = dbitmap_grow_nbits(dmap);
|
||||||
|
binder_proc_unlock(proc);
|
||||||
|
new = bitmap_zalloc(nbits, GFP_KERNEL);
|
||||||
|
binder_proc_lock(proc);
|
||||||
|
dbitmap_grow(dmap, new, nbits);
|
||||||
|
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* binder_get_ref_for_node_olocked() - get the ref associated with given node
|
* binder_get_ref_for_node_olocked() - get the ref associated with given node
|
||||||
* @proc: binder_proc that owns the ref
|
* @proc: binder_proc that owns the ref
|
||||||
@@ -1259,12 +1316,14 @@ static struct binder_ref *binder_get_ref_for_node_olocked(
|
|||||||
struct binder_node *node,
|
struct binder_node *node,
|
||||||
struct binder_ref *new_ref)
|
struct binder_ref *new_ref)
|
||||||
{
|
{
|
||||||
struct binder_context *context = proc->context;
|
|
||||||
struct rb_node **p = &proc->refs_by_node.rb_node;
|
|
||||||
struct rb_node *parent = NULL;
|
|
||||||
struct binder_ref *ref;
|
struct binder_ref *ref;
|
||||||
struct rb_node *n;
|
struct rb_node *parent;
|
||||||
|
struct rb_node **p;
|
||||||
|
u32 desc;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
p = &proc->refs_by_node.rb_node;
|
||||||
|
parent = NULL;
|
||||||
while (*p) {
|
while (*p) {
|
||||||
parent = *p;
|
parent = *p;
|
||||||
ref = rb_entry(parent, struct binder_ref, rb_node_node);
|
ref = rb_entry(parent, struct binder_ref, rb_node_node);
|
||||||
@@ -1279,6 +1338,10 @@ static struct binder_ref *binder_get_ref_for_node_olocked(
|
|||||||
if (!new_ref)
|
if (!new_ref)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* might release the proc->outer_lock */
|
||||||
|
if (get_ref_desc_olocked(proc, node, &desc) == -EAGAIN)
|
||||||
|
goto retry;
|
||||||
|
|
||||||
binder_stats_created(BINDER_STAT_REF);
|
binder_stats_created(BINDER_STAT_REF);
|
||||||
new_ref->data.debug_id = atomic_inc_return(&binder_last_id);
|
new_ref->data.debug_id = atomic_inc_return(&binder_last_id);
|
||||||
new_ref->proc = proc;
|
new_ref->proc = proc;
|
||||||
@@ -1286,14 +1349,7 @@ static struct binder_ref *binder_get_ref_for_node_olocked(
|
|||||||
rb_link_node(&new_ref->rb_node_node, parent, p);
|
rb_link_node(&new_ref->rb_node_node, parent, p);
|
||||||
rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);
|
rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);
|
||||||
|
|
||||||
new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 1;
|
new_ref->data.desc = desc;
|
||||||
for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
|
|
||||||
ref = rb_entry(n, struct binder_ref, rb_node_desc);
|
|
||||||
if (ref->data.desc > new_ref->data.desc)
|
|
||||||
break;
|
|
||||||
new_ref->data.desc = ref->data.desc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = &proc->refs_by_desc.rb_node;
|
p = &proc->refs_by_desc.rb_node;
|
||||||
while (*p) {
|
while (*p) {
|
||||||
parent = *p;
|
parent = *p;
|
||||||
@@ -1323,6 +1379,7 @@ static struct binder_ref *binder_get_ref_for_node_olocked(
|
|||||||
|
|
||||||
static void binder_cleanup_ref_olocked(struct binder_ref *ref)
|
static void binder_cleanup_ref_olocked(struct binder_ref *ref)
|
||||||
{
|
{
|
||||||
|
struct dbitmap *dmap = &proc_wrapper(ref->proc)->dmap;
|
||||||
bool delete_node = false;
|
bool delete_node = false;
|
||||||
|
|
||||||
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
|
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
|
||||||
@@ -1330,6 +1387,8 @@ static void binder_cleanup_ref_olocked(struct binder_ref *ref)
|
|||||||
ref->proc->pid, ref->data.debug_id, ref->data.desc,
|
ref->proc->pid, ref->data.debug_id, ref->data.desc,
|
||||||
ref->node->debug_id);
|
ref->node->debug_id);
|
||||||
|
|
||||||
|
if (dbitmap_enabled(dmap))
|
||||||
|
dbitmap_clear_bit(dmap, ref->data.desc);
|
||||||
rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc);
|
rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc);
|
||||||
rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node);
|
rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node);
|
||||||
|
|
||||||
@@ -1360,6 +1419,10 @@ static void binder_cleanup_ref_olocked(struct binder_ref *ref)
|
|||||||
binder_dequeue_work(ref->proc, &ref->death->work);
|
binder_dequeue_work(ref->proc, &ref->death->work);
|
||||||
binder_stats_deleted(BINDER_STAT_DEATH);
|
binder_stats_deleted(BINDER_STAT_DEATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ref->freeze)
|
||||||
|
binder_dequeue_work(ref->proc, &ref->freeze->work);
|
||||||
|
|
||||||
binder_stats_deleted(BINDER_STAT_REF);
|
binder_stats_deleted(BINDER_STAT_REF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1489,9 +1552,30 @@ static void binder_free_ref(struct binder_ref *ref)
|
|||||||
if (ref->node)
|
if (ref->node)
|
||||||
binder_free_node(ref->node);
|
binder_free_node(ref->node);
|
||||||
kfree(ref->death);
|
kfree(ref->death);
|
||||||
|
kfree(ref->freeze);
|
||||||
kfree(ref);
|
kfree(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* shrink descriptor bitmap if needed */
|
||||||
|
static void try_shrink_dmap(struct binder_proc *proc)
|
||||||
|
{
|
||||||
|
struct dbitmap *dmap = &proc_wrapper(proc)->dmap;
|
||||||
|
unsigned long *new;
|
||||||
|
int nbits;
|
||||||
|
|
||||||
|
binder_proc_lock(proc);
|
||||||
|
nbits = dbitmap_shrink_nbits(dmap);
|
||||||
|
binder_proc_unlock(proc);
|
||||||
|
|
||||||
|
if (!nbits)
|
||||||
|
return;
|
||||||
|
|
||||||
|
new = bitmap_zalloc(nbits, GFP_KERNEL);
|
||||||
|
binder_proc_lock(proc);
|
||||||
|
dbitmap_shrink(dmap, new, nbits);
|
||||||
|
binder_proc_unlock(proc);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* binder_update_ref_for_handle() - inc/dec the ref for given handle
|
* binder_update_ref_for_handle() - inc/dec the ref for given handle
|
||||||
* @proc: proc containing the ref
|
* @proc: proc containing the ref
|
||||||
@@ -1528,8 +1612,10 @@ static int binder_update_ref_for_handle(struct binder_proc *proc,
|
|||||||
*rdata = ref->data;
|
*rdata = ref->data;
|
||||||
binder_proc_unlock(proc);
|
binder_proc_unlock(proc);
|
||||||
|
|
||||||
if (delete_ref)
|
if (delete_ref) {
|
||||||
binder_free_ref(ref);
|
binder_free_ref(ref);
|
||||||
|
try_shrink_dmap(proc);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err_no_ref:
|
err_no_ref:
|
||||||
@@ -3564,6 +3650,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|||||||
*/
|
*/
|
||||||
copy_size = object_offset - user_offset;
|
copy_size = object_offset - user_offset;
|
||||||
if (copy_size && (user_offset > object_offset ||
|
if (copy_size && (user_offset > object_offset ||
|
||||||
|
object_offset > tr->data_size ||
|
||||||
binder_alloc_copy_user_to_buffer(
|
binder_alloc_copy_user_to_buffer(
|
||||||
&target_proc->alloc,
|
&target_proc->alloc,
|
||||||
t->buffer, user_offset,
|
t->buffer, user_offset,
|
||||||
@@ -3986,6 +4073,154 @@ err_invalid_target_handle:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
binder_request_freeze_notification(struct binder_proc *proc,
|
||||||
|
struct binder_thread *thread,
|
||||||
|
struct binder_handle_cookie *handle_cookie)
|
||||||
|
{
|
||||||
|
struct binder_ref_freeze *freeze;
|
||||||
|
struct binder_ref *ref;
|
||||||
|
bool is_frozen;
|
||||||
|
|
||||||
|
freeze = kzalloc(sizeof(*freeze), GFP_KERNEL);
|
||||||
|
if (!freeze)
|
||||||
|
return -ENOMEM;
|
||||||
|
binder_proc_lock(proc);
|
||||||
|
ref = binder_get_ref_olocked(proc, handle_cookie->handle, false);
|
||||||
|
if (!ref) {
|
||||||
|
binder_user_error("%d:%d BC_REQUEST_FREEZE_NOTIFICATION invalid ref %d\n",
|
||||||
|
proc->pid, thread->pid, handle_cookie->handle);
|
||||||
|
binder_proc_unlock(proc);
|
||||||
|
kfree(freeze);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
binder_node_lock(ref->node);
|
||||||
|
|
||||||
|
if (ref->freeze || !ref->node->proc) {
|
||||||
|
binder_user_error("%d:%d invalid BC_REQUEST_FREEZE_NOTIFICATION %s\n",
|
||||||
|
proc->pid, thread->pid,
|
||||||
|
ref->freeze ? "already set" : "dead node");
|
||||||
|
binder_node_unlock(ref->node);
|
||||||
|
binder_proc_unlock(proc);
|
||||||
|
kfree(freeze);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
binder_inner_proc_lock(ref->node->proc);
|
||||||
|
is_frozen = ref->node->proc->is_frozen;
|
||||||
|
binder_inner_proc_unlock(ref->node->proc);
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&freeze->work.entry);
|
||||||
|
freeze->cookie = handle_cookie->cookie;
|
||||||
|
freeze->work.type = BINDER_WORK_FROZEN_BINDER;
|
||||||
|
freeze->is_frozen = is_frozen;
|
||||||
|
|
||||||
|
ref->freeze = freeze;
|
||||||
|
|
||||||
|
binder_inner_proc_lock(proc);
|
||||||
|
binder_enqueue_work_ilocked(&ref->freeze->work, &proc->todo);
|
||||||
|
binder_wakeup_proc_ilocked(proc);
|
||||||
|
binder_inner_proc_unlock(proc);
|
||||||
|
|
||||||
|
binder_node_unlock(ref->node);
|
||||||
|
binder_proc_unlock(proc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
binder_clear_freeze_notification(struct binder_proc *proc,
|
||||||
|
struct binder_thread *thread,
|
||||||
|
struct binder_handle_cookie *handle_cookie)
|
||||||
|
{
|
||||||
|
struct binder_ref_freeze *freeze;
|
||||||
|
struct binder_ref *ref;
|
||||||
|
|
||||||
|
binder_proc_lock(proc);
|
||||||
|
ref = binder_get_ref_olocked(proc, handle_cookie->handle, false);
|
||||||
|
if (!ref) {
|
||||||
|
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION invalid ref %d\n",
|
||||||
|
proc->pid, thread->pid, handle_cookie->handle);
|
||||||
|
binder_proc_unlock(proc);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
binder_node_lock(ref->node);
|
||||||
|
|
||||||
|
if (!ref->freeze) {
|
||||||
|
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION freeze notification not active\n",
|
||||||
|
proc->pid, thread->pid);
|
||||||
|
binder_node_unlock(ref->node);
|
||||||
|
binder_proc_unlock(proc);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
freeze = ref->freeze;
|
||||||
|
binder_inner_proc_lock(proc);
|
||||||
|
if (freeze->cookie != handle_cookie->cookie) {
|
||||||
|
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION freeze notification cookie mismatch %016llx != %016llx\n",
|
||||||
|
proc->pid, thread->pid, (u64)freeze->cookie,
|
||||||
|
(u64)handle_cookie->cookie);
|
||||||
|
binder_inner_proc_unlock(proc);
|
||||||
|
binder_node_unlock(ref->node);
|
||||||
|
binder_proc_unlock(proc);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
ref->freeze = NULL;
|
||||||
|
/*
|
||||||
|
* Take the existing freeze object and overwrite its work type. There are three cases here:
|
||||||
|
* 1. No pending notification. In this case just add the work to the queue.
|
||||||
|
* 2. A notification was sent and is pending an ack from userspace. Once an ack arrives, we
|
||||||
|
* should resend with the new work type.
|
||||||
|
* 3. A notification is pending to be sent. Since the work is already in the queue, nothing
|
||||||
|
* needs to be done here.
|
||||||
|
*/
|
||||||
|
freeze->work.type = BINDER_WORK_CLEAR_FREEZE_NOTIFICATION;
|
||||||
|
if (list_empty(&freeze->work.entry)) {
|
||||||
|
binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
|
||||||
|
binder_wakeup_proc_ilocked(proc);
|
||||||
|
} else if (freeze->sent) {
|
||||||
|
freeze->resend = true;
|
||||||
|
}
|
||||||
|
binder_inner_proc_unlock(proc);
|
||||||
|
binder_node_unlock(ref->node);
|
||||||
|
binder_proc_unlock(proc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
binder_freeze_notification_done(struct binder_proc *proc,
|
||||||
|
struct binder_thread *thread,
|
||||||
|
binder_uintptr_t cookie)
|
||||||
|
{
|
||||||
|
struct binder_ref_freeze *freeze = NULL;
|
||||||
|
struct binder_work *w;
|
||||||
|
|
||||||
|
binder_inner_proc_lock(proc);
|
||||||
|
list_for_each_entry(w, &proc_wrapper(proc)->delivered_freeze, entry) {
|
||||||
|
struct binder_ref_freeze *tmp_freeze =
|
||||||
|
container_of(w, struct binder_ref_freeze, work);
|
||||||
|
|
||||||
|
if (tmp_freeze->cookie == cookie) {
|
||||||
|
freeze = tmp_freeze;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!freeze) {
|
||||||
|
binder_user_error("%d:%d BC_FREEZE_NOTIFICATION_DONE %016llx not found\n",
|
||||||
|
proc->pid, thread->pid, (u64)cookie);
|
||||||
|
binder_inner_proc_unlock(proc);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
binder_dequeue_work_ilocked(&freeze->work);
|
||||||
|
freeze->sent = false;
|
||||||
|
if (freeze->resend) {
|
||||||
|
freeze->resend = false;
|
||||||
|
binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
|
||||||
|
binder_wakeup_proc_ilocked(proc);
|
||||||
|
}
|
||||||
|
binder_inner_proc_unlock(proc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* binder_free_buf() - free the specified buffer
|
* binder_free_buf() - free the specified buffer
|
||||||
* @proc: binder proc that owns buffer
|
* @proc: binder proc that owns buffer
|
||||||
@@ -4480,6 +4715,44 @@ static int binder_thread_write(struct binder_proc *proc,
|
|||||||
binder_inner_proc_unlock(proc);
|
binder_inner_proc_unlock(proc);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case BC_REQUEST_FREEZE_NOTIFICATION: {
|
||||||
|
struct binder_handle_cookie handle_cookie;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (copy_from_user(&handle_cookie, ptr, sizeof(handle_cookie)))
|
||||||
|
return -EFAULT;
|
||||||
|
ptr += sizeof(handle_cookie);
|
||||||
|
error = binder_request_freeze_notification(proc, thread,
|
||||||
|
&handle_cookie);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case BC_CLEAR_FREEZE_NOTIFICATION: {
|
||||||
|
struct binder_handle_cookie handle_cookie;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (copy_from_user(&handle_cookie, ptr, sizeof(handle_cookie)))
|
||||||
|
return -EFAULT;
|
||||||
|
ptr += sizeof(handle_cookie);
|
||||||
|
error = binder_clear_freeze_notification(proc, thread, &handle_cookie);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case BC_FREEZE_NOTIFICATION_DONE: {
|
||||||
|
binder_uintptr_t cookie;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
ptr += sizeof(cookie);
|
||||||
|
error = binder_freeze_notification_done(proc, thread, cookie);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
pr_err("%d:%d unknown command %u\n",
|
pr_err("%d:%d unknown command %u\n",
|
||||||
proc->pid, thread->pid, cmd);
|
proc->pid, thread->pid, cmd);
|
||||||
@@ -4881,6 +5154,45 @@ skip:
|
|||||||
if (cmd == BR_DEAD_BINDER)
|
if (cmd == BR_DEAD_BINDER)
|
||||||
goto done; /* DEAD_BINDER notifications can cause transactions */
|
goto done; /* DEAD_BINDER notifications can cause transactions */
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case BINDER_WORK_FROZEN_BINDER: {
|
||||||
|
struct binder_ref_freeze *freeze;
|
||||||
|
struct binder_frozen_state_info info;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
freeze = container_of(w, struct binder_ref_freeze, work);
|
||||||
|
info.is_frozen = freeze->is_frozen;
|
||||||
|
info.cookie = freeze->cookie;
|
||||||
|
freeze->sent = true;
|
||||||
|
binder_enqueue_work_ilocked(w, &proc_wrapper(proc)->delivered_freeze);
|
||||||
|
binder_inner_proc_unlock(proc);
|
||||||
|
|
||||||
|
if (put_user(BR_FROZEN_BINDER, (uint32_t __user *)ptr))
|
||||||
|
return -EFAULT;
|
||||||
|
ptr += sizeof(uint32_t);
|
||||||
|
if (copy_to_user(ptr, &info, sizeof(info)))
|
||||||
|
return -EFAULT;
|
||||||
|
ptr += sizeof(info);
|
||||||
|
binder_stat_br(proc, thread, BR_FROZEN_BINDER);
|
||||||
|
goto done; /* BR_FROZEN_BINDER notifications can cause transactions */
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: {
|
||||||
|
struct binder_ref_freeze *freeze =
|
||||||
|
container_of(w, struct binder_ref_freeze, work);
|
||||||
|
binder_uintptr_t cookie = freeze->cookie;
|
||||||
|
|
||||||
|
binder_inner_proc_unlock(proc);
|
||||||
|
kfree(freeze);
|
||||||
|
if (put_user(BR_CLEAR_FREEZE_NOTIFICATION_DONE, (uint32_t __user *)ptr))
|
||||||
|
return -EFAULT;
|
||||||
|
ptr += sizeof(uint32_t);
|
||||||
|
if (put_user(cookie, (binder_uintptr_t __user *)ptr))
|
||||||
|
return -EFAULT;
|
||||||
|
ptr += sizeof(binder_uintptr_t);
|
||||||
|
binder_stat_br(proc, thread, BR_CLEAR_FREEZE_NOTIFICATION_DONE);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
binder_inner_proc_unlock(proc);
|
binder_inner_proc_unlock(proc);
|
||||||
pr_err("%d:%d: bad work type %d\n",
|
pr_err("%d:%d: bad work type %d\n",
|
||||||
@@ -5163,7 +5475,6 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc)
|
|||||||
|
|
||||||
static void binder_free_proc(struct binder_proc *proc)
|
static void binder_free_proc(struct binder_proc *proc)
|
||||||
{
|
{
|
||||||
struct binder_proc_wrap *proc_wrap;
|
|
||||||
struct binder_device *device;
|
struct binder_device *device;
|
||||||
|
|
||||||
BUG_ON(!list_empty(&proc->todo));
|
BUG_ON(!list_empty(&proc->todo));
|
||||||
@@ -5180,9 +5491,9 @@ static void binder_free_proc(struct binder_proc *proc)
|
|||||||
put_task_struct(proc->tsk);
|
put_task_struct(proc->tsk);
|
||||||
put_cred(proc->cred);
|
put_cred(proc->cred);
|
||||||
binder_stats_deleted(BINDER_STAT_PROC);
|
binder_stats_deleted(BINDER_STAT_PROC);
|
||||||
|
dbitmap_free(&proc_wrapper(proc)->dmap);
|
||||||
trace_android_vh_binder_free_proc(proc);
|
trace_android_vh_binder_free_proc(proc);
|
||||||
proc_wrap = binder_proc_wrap_entry(proc);
|
kfree(proc_wrapper(proc));
|
||||||
kfree(proc_wrap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void binder_free_thread(struct binder_thread *thread)
|
static void binder_free_thread(struct binder_thread *thread)
|
||||||
@@ -5502,6 +5813,57 @@ static bool binder_txns_pending_ilocked(struct binder_proc *proc)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
|
||||||
|
{
|
||||||
|
struct binder_node *prev = NULL;
|
||||||
|
struct rb_node *n;
|
||||||
|
struct binder_ref *ref;
|
||||||
|
|
||||||
|
binder_inner_proc_lock(proc);
|
||||||
|
for (n = rb_first(&proc->nodes); n; n = rb_next(n)) {
|
||||||
|
struct binder_node *node;
|
||||||
|
|
||||||
|
node = rb_entry(n, struct binder_node, rb_node);
|
||||||
|
binder_inc_node_tmpref_ilocked(node);
|
||||||
|
binder_inner_proc_unlock(proc);
|
||||||
|
if (prev)
|
||||||
|
binder_put_node(prev);
|
||||||
|
binder_node_lock(node);
|
||||||
|
hlist_for_each_entry(ref, &node->refs, node_entry) {
|
||||||
|
/*
|
||||||
|
* Need the node lock to synchronize
|
||||||
|
* with new notification requests and the
|
||||||
|
* inner lock to synchronize with queued
|
||||||
|
* freeze notifications.
|
||||||
|
*/
|
||||||
|
binder_inner_proc_lock(ref->proc);
|
||||||
|
if (!ref->freeze) {
|
||||||
|
binder_inner_proc_unlock(ref->proc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ref->freeze->work.type = BINDER_WORK_FROZEN_BINDER;
|
||||||
|
if (list_empty(&ref->freeze->work.entry)) {
|
||||||
|
ref->freeze->is_frozen = is_frozen;
|
||||||
|
binder_enqueue_work_ilocked(&ref->freeze->work, &ref->proc->todo);
|
||||||
|
binder_wakeup_proc_ilocked(ref->proc);
|
||||||
|
} else {
|
||||||
|
if (ref->freeze->sent && ref->freeze->is_frozen != is_frozen)
|
||||||
|
ref->freeze->resend = true;
|
||||||
|
ref->freeze->is_frozen = is_frozen;
|
||||||
|
}
|
||||||
|
binder_inner_proc_unlock(ref->proc);
|
||||||
|
}
|
||||||
|
prev = node;
|
||||||
|
binder_node_unlock(node);
|
||||||
|
binder_inner_proc_lock(proc);
|
||||||
|
if (proc->is_dead)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
binder_inner_proc_unlock(proc);
|
||||||
|
if (prev)
|
||||||
|
binder_put_node(prev);
|
||||||
|
}
|
||||||
|
|
||||||
static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
||||||
struct binder_proc *target_proc)
|
struct binder_proc *target_proc)
|
||||||
{
|
{
|
||||||
@@ -5513,6 +5875,7 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
|||||||
target_proc->async_recv = false;
|
target_proc->async_recv = false;
|
||||||
target_proc->is_frozen = false;
|
target_proc->is_frozen = false;
|
||||||
binder_inner_proc_unlock(target_proc);
|
binder_inner_proc_unlock(target_proc);
|
||||||
|
binder_add_freeze_work(target_proc, false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5545,6 +5908,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
|||||||
binder_inner_proc_lock(target_proc);
|
binder_inner_proc_lock(target_proc);
|
||||||
target_proc->is_frozen = false;
|
target_proc->is_frozen = false;
|
||||||
binder_inner_proc_unlock(target_proc);
|
binder_inner_proc_unlock(target_proc);
|
||||||
|
} else {
|
||||||
|
binder_add_freeze_work(target_proc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -5903,6 +6268,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
proc = &proc_wrap->proc;
|
proc = &proc_wrap->proc;
|
||||||
|
|
||||||
|
dbitmap_init(&proc_wrapper(proc)->dmap);
|
||||||
spin_lock_init(&proc->inner_lock);
|
spin_lock_init(&proc->inner_lock);
|
||||||
spin_lock_init(&proc->outer_lock);
|
spin_lock_init(&proc->outer_lock);
|
||||||
get_task_struct(current->group_leader);
|
get_task_struct(current->group_leader);
|
||||||
@@ -5934,6 +6300,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
|||||||
binder_stats_created(BINDER_STAT_PROC);
|
binder_stats_created(BINDER_STAT_PROC);
|
||||||
proc->pid = current->group_leader->pid;
|
proc->pid = current->group_leader->pid;
|
||||||
INIT_LIST_HEAD(&proc->delivered_death);
|
INIT_LIST_HEAD(&proc->delivered_death);
|
||||||
|
INIT_LIST_HEAD(&proc_wrapper(proc)->delivered_freeze);
|
||||||
INIT_LIST_HEAD(&proc->waiting_threads);
|
INIT_LIST_HEAD(&proc->waiting_threads);
|
||||||
filp->private_data = proc;
|
filp->private_data = proc;
|
||||||
|
|
||||||
@@ -6314,6 +6681,9 @@ static void print_binder_work_ilocked(struct seq_file *m,
|
|||||||
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
|
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
|
||||||
seq_printf(m, "%shas cleared death notification\n", prefix);
|
seq_printf(m, "%shas cleared death notification\n", prefix);
|
||||||
break;
|
break;
|
||||||
|
case BINDER_WORK_FROZEN_BINDER:
|
||||||
|
seq_printf(m, "%shas frozen binder\n", prefix);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
seq_printf(m, "%sunknown work: type %d\n", prefix, w->type);
|
seq_printf(m, "%sunknown work: type %d\n", prefix, w->type);
|
||||||
break;
|
break;
|
||||||
@@ -6520,7 +6890,7 @@ static const char * const binder_objstat_strings[] = {
|
|||||||
"ref",
|
"ref",
|
||||||
"death",
|
"death",
|
||||||
"transaction",
|
"transaction",
|
||||||
"transaction_complete"
|
"transaction_complete",
|
||||||
};
|
};
|
||||||
|
|
||||||
static void print_binder_stats(struct seq_file *m, const char *prefix,
|
static void print_binder_stats(struct seq_file *m, const char *prefix,
|
||||||
|
|||||||
@@ -955,9 +955,9 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
|
|||||||
__free_page(alloc->pages[i].page_ptr);
|
__free_page(alloc->pages[i].page_ptr);
|
||||||
page_count++;
|
page_count++;
|
||||||
}
|
}
|
||||||
kfree(alloc->pages);
|
|
||||||
}
|
}
|
||||||
binder_alloc_unlock(alloc);
|
binder_alloc_unlock(alloc);
|
||||||
|
kfree(alloc->pages);
|
||||||
if (alloc->mm)
|
if (alloc->mm)
|
||||||
mmdrop(alloc->mm);
|
mmdrop(alloc->mm);
|
||||||
|
|
||||||
@@ -1315,4 +1315,4 @@ int binder_alloc_copy_from_buffer(struct binder_alloc *alloc,
|
|||||||
return binder_alloc_do_buffer_copy(alloc, false, buffer, buffer_offset,
|
return binder_alloc_do_buffer_copy(alloc, false, buffer, buffer_offset,
|
||||||
dest, bytes);
|
dest, bytes);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(binder_alloc_copy_from_buffer);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <linux/uidgid.h>
|
#include <linux/uidgid.h>
|
||||||
#include <uapi/linux/android/binderfs.h>
|
#include <uapi/linux/android/binderfs.h>
|
||||||
#include "binder_alloc.h"
|
#include "binder_alloc.h"
|
||||||
|
#include "dbitmap.h"
|
||||||
|
|
||||||
struct binder_context {
|
struct binder_context {
|
||||||
struct binder_node *binder_context_mgr_node;
|
struct binder_node *binder_context_mgr_node;
|
||||||
@@ -158,6 +159,10 @@ struct binder_work {
|
|||||||
BINDER_WORK_DEAD_BINDER,
|
BINDER_WORK_DEAD_BINDER,
|
||||||
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
|
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
|
||||||
BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
|
BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
|
||||||
|
#ifndef __GENKSYMS__
|
||||||
|
BINDER_WORK_FROZEN_BINDER,
|
||||||
|
BINDER_WORK_CLEAR_FREEZE_NOTIFICATION,
|
||||||
|
#endif
|
||||||
} type;
|
} type;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -279,6 +284,14 @@ struct binder_ref_death {
|
|||||||
binder_uintptr_t cookie;
|
binder_uintptr_t cookie;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct binder_ref_freeze {
|
||||||
|
struct binder_work work;
|
||||||
|
binder_uintptr_t cookie;
|
||||||
|
bool is_frozen:1;
|
||||||
|
bool sent:1;
|
||||||
|
bool resend:1;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct binder_ref_data - binder_ref counts and id
|
* struct binder_ref_data - binder_ref counts and id
|
||||||
* @debug_id: unique ID for the ref
|
* @debug_id: unique ID for the ref
|
||||||
@@ -311,6 +324,8 @@ struct binder_ref_data {
|
|||||||
* @node indicates the node must be freed
|
* @node indicates the node must be freed
|
||||||
* @death: pointer to death notification (ref_death) if requested
|
* @death: pointer to death notification (ref_death) if requested
|
||||||
* (protected by @node->lock)
|
* (protected by @node->lock)
|
||||||
|
* @freeze: pointer to freeze notification (ref_freeze) if requested
|
||||||
|
* (protected by @node->lock)
|
||||||
*
|
*
|
||||||
* Structure to track references from procA to target node (on procB). This
|
* Structure to track references from procA to target node (on procB). This
|
||||||
* structure is unsafe to access without holding @proc->outer_lock.
|
* structure is unsafe to access without holding @proc->outer_lock.
|
||||||
@@ -327,6 +342,7 @@ struct binder_ref {
|
|||||||
struct binder_proc *proc;
|
struct binder_proc *proc;
|
||||||
struct binder_node *node;
|
struct binder_node *node;
|
||||||
struct binder_ref_death *death;
|
struct binder_ref_death *death;
|
||||||
|
struct binder_ref_freeze *freeze;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -443,7 +459,6 @@ struct binder_proc {
|
|||||||
bool sync_recv;
|
bool sync_recv;
|
||||||
bool async_recv;
|
bool async_recv;
|
||||||
wait_queue_head_t freeze_wait;
|
wait_queue_head_t freeze_wait;
|
||||||
|
|
||||||
struct list_head todo;
|
struct list_head todo;
|
||||||
struct binder_stats stats;
|
struct binder_stats stats;
|
||||||
struct list_head delivered_death;
|
struct list_head delivered_death;
|
||||||
@@ -461,27 +476,38 @@ struct binder_proc {
|
|||||||
bool oneway_spam_detection_enabled;
|
bool oneway_spam_detection_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct binder_proc_wrap - wrapper to preserve KMI in binder_proc
|
||||||
|
* @proc: binder_proc being wrapped
|
||||||
|
* @dmap: dbitmap to manage available reference descriptors
|
||||||
|
* (protected by @proc.outer_lock)
|
||||||
|
* @lock: protects @proc->alloc fields
|
||||||
|
* @delivered_freeze: list of delivered freeze notification
|
||||||
|
* (protected by @inner_lock)
|
||||||
|
*/
|
||||||
struct binder_proc_wrap {
|
struct binder_proc_wrap {
|
||||||
struct binder_proc proc;
|
struct binder_proc proc;
|
||||||
|
struct dbitmap dmap;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
struct list_head delivered_freeze;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline
|
||||||
|
struct binder_proc_wrap *proc_wrapper(struct binder_proc *proc)
|
||||||
|
{
|
||||||
|
return container_of(proc, struct binder_proc_wrap, proc);
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct binder_proc *
|
static inline struct binder_proc *
|
||||||
binder_proc_entry(struct binder_alloc *alloc)
|
binder_proc_entry(struct binder_alloc *alloc)
|
||||||
{
|
{
|
||||||
return container_of(alloc, struct binder_proc, alloc);
|
return container_of(alloc, struct binder_proc, alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct binder_proc_wrap *
|
|
||||||
binder_proc_wrap_entry(struct binder_proc *proc)
|
|
||||||
{
|
|
||||||
return container_of(proc, struct binder_proc_wrap, proc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct binder_proc_wrap *
|
static inline struct binder_proc_wrap *
|
||||||
binder_alloc_to_proc_wrap(struct binder_alloc *alloc)
|
binder_alloc_to_proc_wrap(struct binder_alloc *alloc)
|
||||||
{
|
{
|
||||||
return binder_proc_wrap_entry(binder_proc_entry(alloc));
|
return proc_wrapper(binder_proc_entry(alloc));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void binder_alloc_lock_init(struct binder_alloc *alloc)
|
static inline void binder_alloc_lock_init(struct binder_alloc *alloc)
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ enum binderfs_stats_mode {
|
|||||||
struct binder_features {
|
struct binder_features {
|
||||||
bool oneway_spam_detection;
|
bool oneway_spam_detection;
|
||||||
bool extended_error;
|
bool extended_error;
|
||||||
|
bool freeze_notification;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct constant_table binderfs_param_stats[] = {
|
static const struct constant_table binderfs_param_stats[] = {
|
||||||
@@ -76,6 +77,7 @@ static const struct fs_parameter_spec binderfs_fs_parameters[] = {
|
|||||||
static struct binder_features binder_features = {
|
static struct binder_features binder_features = {
|
||||||
.oneway_spam_detection = true,
|
.oneway_spam_detection = true,
|
||||||
.extended_error = true,
|
.extended_error = true,
|
||||||
|
.freeze_notification = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct binderfs_info *BINDERFS_SB(const struct super_block *sb)
|
static inline struct binderfs_info *BINDERFS_SB(const struct super_block *sb)
|
||||||
@@ -610,6 +612,12 @@ static int init_binder_features(struct super_block *sb)
|
|||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
|
|
||||||
|
dentry = binderfs_create_file(dir, "freeze_notification",
|
||||||
|
&binder_features_fops,
|
||||||
|
&binder_features.freeze_notification);
|
||||||
|
if (IS_ERR(dentry))
|
||||||
|
return PTR_ERR(dentry);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
168
drivers/android/dbitmap.h
Normal file
168
drivers/android/dbitmap.h
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Google LLC
|
||||||
|
*
|
||||||
|
* dbitmap - dynamically sized bitmap library.
|
||||||
|
*
|
||||||
|
* Used by the binder driver to optimize the allocation of the smallest
|
||||||
|
* available descriptor ID. Each bit in the bitmap represents the state
|
||||||
|
* of an ID.
|
||||||
|
*
|
||||||
|
* A dbitmap can grow or shrink as needed. This part has been designed
|
||||||
|
* considering that users might need to briefly release their locks in
|
||||||
|
* order to allocate memory for the new bitmap. These operations then,
|
||||||
|
* are verified to determine if the grow or shrink is sill valid.
|
||||||
|
*
|
||||||
|
* This library does not provide protection against concurrent access
|
||||||
|
* by itself. Binder uses the proc->outer_lock for this purpose.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LINUX_DBITMAP_H
|
||||||
|
#define _LINUX_DBITMAP_H
|
||||||
|
#include <linux/bitmap.h>
|
||||||
|
|
||||||
|
#define NBITS_MIN BITS_PER_TYPE(unsigned long)
|
||||||
|
|
||||||
|
struct dbitmap {
|
||||||
|
unsigned int nbits;
|
||||||
|
unsigned long *map;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int dbitmap_enabled(struct dbitmap *dmap)
|
||||||
|
{
|
||||||
|
return !!dmap->nbits;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dbitmap_free(struct dbitmap *dmap)
|
||||||
|
{
|
||||||
|
dmap->nbits = 0;
|
||||||
|
kfree(dmap->map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the nbits that a dbitmap can shrink to, 0 if not possible. */
|
||||||
|
static inline unsigned int dbitmap_shrink_nbits(struct dbitmap *dmap)
|
||||||
|
{
|
||||||
|
unsigned int bit;
|
||||||
|
|
||||||
|
if (dmap->nbits <= NBITS_MIN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine if the bitmap can shrink based on the position of
|
||||||
|
* its last set bit. If the bit is within the first quarter of
|
||||||
|
* the bitmap then shrinking is possible. In this case, the
|
||||||
|
* bitmap should shrink to half its current size.
|
||||||
|
*/
|
||||||
|
bit = find_last_bit(dmap->map, dmap->nbits);
|
||||||
|
if (bit < (dmap->nbits >> 2))
|
||||||
|
return dmap->nbits >> 1;
|
||||||
|
|
||||||
|
/* find_last_bit() returns dmap->nbits when no bits are set. */
|
||||||
|
if (bit == dmap->nbits)
|
||||||
|
return NBITS_MIN;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Replace the internal bitmap with a new one of different size */
|
||||||
|
static inline void
|
||||||
|
dbitmap_replace(struct dbitmap *dmap, unsigned long *new, unsigned int nbits)
|
||||||
|
{
|
||||||
|
bitmap_copy(new, dmap->map, min(dmap->nbits, nbits));
|
||||||
|
kfree(dmap->map);
|
||||||
|
dmap->map = new;
|
||||||
|
dmap->nbits = nbits;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
dbitmap_shrink(struct dbitmap *dmap, unsigned long *new, unsigned int nbits)
|
||||||
|
{
|
||||||
|
if (!new)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify that shrinking to @nbits is still possible. The @new
|
||||||
|
* bitmap might have been allocated without locks, so this call
|
||||||
|
* could now be outdated. In this case, free @new and move on.
|
||||||
|
*/
|
||||||
|
if (!dbitmap_enabled(dmap) || dbitmap_shrink_nbits(dmap) != nbits) {
|
||||||
|
kfree(new);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbitmap_replace(dmap, new, nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the nbits that a dbitmap can grow to. */
|
||||||
|
static inline unsigned int dbitmap_grow_nbits(struct dbitmap *dmap)
|
||||||
|
{
|
||||||
|
return dmap->nbits << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
dbitmap_grow(struct dbitmap *dmap, unsigned long *new, unsigned int nbits)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Verify that growing to @nbits is still possible. The @new
|
||||||
|
* bitmap might have been allocated without locks, so this call
|
||||||
|
* could now be outdated. In this case, free @new and move on.
|
||||||
|
*/
|
||||||
|
if (!dbitmap_enabled(dmap) || nbits <= dmap->nbits) {
|
||||||
|
kfree(new);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for ENOMEM after confirming the grow operation is still
|
||||||
|
* required. This ensures we only disable the dbitmap when it's
|
||||||
|
* necessary. Once the dbitmap is disabled, binder will fallback
|
||||||
|
* to slow_desc_lookup_olocked().
|
||||||
|
*/
|
||||||
|
if (!new) {
|
||||||
|
dbitmap_free(dmap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbitmap_replace(dmap, new, nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finds and sets the next zero bit in the bitmap. Upon success @bit
|
||||||
|
* is populated with the index and 0 is returned. Otherwise, -ENOSPC
|
||||||
|
* is returned to indicate that a dbitmap_grow() is needed.
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
dbitmap_acquire_next_zero_bit(struct dbitmap *dmap, unsigned long offset,
|
||||||
|
unsigned long *bit)
|
||||||
|
{
|
||||||
|
unsigned long n;
|
||||||
|
|
||||||
|
n = find_next_zero_bit(dmap->map, dmap->nbits, offset);
|
||||||
|
if (n == dmap->nbits)
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
|
*bit = n;
|
||||||
|
set_bit(n, dmap->map);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
dbitmap_clear_bit(struct dbitmap *dmap, unsigned long bit)
|
||||||
|
{
|
||||||
|
clear_bit(bit, dmap->map);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dbitmap_init(struct dbitmap *dmap)
|
||||||
|
{
|
||||||
|
dmap->map = bitmap_zalloc(NBITS_MIN, GFP_KERNEL);
|
||||||
|
if (!dmap->map) {
|
||||||
|
dmap->nbits = 0;
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
dmap->nbits = NBITS_MIN;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -276,6 +276,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_gfp_zone_flags);
|
|||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_readahead_gfp_mask);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_set_readahead_gfp_mask);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alter_mutex_list_add);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alter_mutex_list_add);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_unlock_slowpath);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_unlock_slowpath);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_should_fault_around);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_wake_finish);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_wake_finish);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_fault_around_bytes);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_fault_around_bytes);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_adjust_alloc_flags);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_adjust_alloc_flags);
|
||||||
@@ -377,6 +378,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_alloc_pages_may_oom_exit);
|
|||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_vmscan_kswapd_done);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_vmscan_kswapd_done);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_compaction_begin);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_compaction_begin);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_compaction_end);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_compaction_end);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_kcompactd_cpu_online);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_bus_iommu_probe);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_bus_iommu_probe);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rmqueue);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rmqueue);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_resume_begin);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_resume_begin);
|
||||||
@@ -442,3 +444,13 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_folio_trylock_clear);
|
|||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_folio_trylock_set);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_folio_trylock_set);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_trylock_failed_folio);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_trylock_failed_folio);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_hibernate_state);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_hibernate_state);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_should_be_protected);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_referenced_check_bypass);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swapmem_gather_init);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swapmem_gather_add_bypass);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swapmem_gather_finish);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_oom_swapmem_gather_init);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_oom_swapmem_gather_finish);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_do_read_fault);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_filemap_read);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_filemap_map_pages);
|
||||||
|
|||||||
@@ -167,6 +167,115 @@ struct device *dev_pm_domain_attach_by_name(struct device *dev,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
|
EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dev_pm_domain_attach_list - Associate a device with its PM domains.
|
||||||
|
* @dev: The device used to lookup the PM domains for.
|
||||||
|
* @data: The data used for attaching to the PM domains.
|
||||||
|
* @list: An out-parameter with an allocated list of attached PM domains.
|
||||||
|
*
|
||||||
|
* This function helps to attach a device to its multiple PM domains. The
|
||||||
|
* caller, which is typically a driver's probe function, may provide a list of
|
||||||
|
* names for the PM domains that we should try to attach the device to, but it
|
||||||
|
* may also provide an empty list, in case the attach should be done for all of
|
||||||
|
* the available PM domains.
|
||||||
|
*
|
||||||
|
* Callers must ensure proper synchronization of this function with power
|
||||||
|
* management callbacks.
|
||||||
|
*
|
||||||
|
* Returns the number of attached PM domains or a negative error code in case of
|
||||||
|
* a failure. Note that, to detach the list of PM domains, the driver shall call
|
||||||
|
* dev_pm_domain_detach_list(), typically during the remove phase.
|
||||||
|
*/
|
||||||
|
int dev_pm_domain_attach_list(struct device *dev,
|
||||||
|
const struct dev_pm_domain_attach_data *data,
|
||||||
|
struct dev_pm_domain_list **list)
|
||||||
|
{
|
||||||
|
struct device_node *np = dev->of_node;
|
||||||
|
struct dev_pm_domain_list *pds;
|
||||||
|
struct device *pd_dev = NULL;
|
||||||
|
int ret, i, num_pds = 0;
|
||||||
|
bool by_id = true;
|
||||||
|
u32 pd_flags = data ? data->pd_flags : 0;
|
||||||
|
u32 link_flags = pd_flags & PD_FLAG_NO_DEV_LINK ? 0 :
|
||||||
|
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
|
||||||
|
|
||||||
|
if (dev->pm_domain)
|
||||||
|
return -EEXIST;
|
||||||
|
|
||||||
|
/* For now this is limited to OF based platforms. */
|
||||||
|
if (!np)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (data && data->pd_names) {
|
||||||
|
num_pds = data->num_pd_names;
|
||||||
|
by_id = false;
|
||||||
|
} else {
|
||||||
|
num_pds = of_count_phandle_with_args(np, "power-domains",
|
||||||
|
"#power-domain-cells");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_pds <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pds = devm_kzalloc(dev, sizeof(*pds), GFP_KERNEL);
|
||||||
|
if (!pds)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
pds->pd_devs = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_devs),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!pds->pd_devs)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
pds->pd_links = devm_kcalloc(dev, num_pds, sizeof(*pds->pd_links),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!pds->pd_links)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (link_flags && pd_flags & PD_FLAG_DEV_LINK_ON)
|
||||||
|
link_flags |= DL_FLAG_RPM_ACTIVE;
|
||||||
|
|
||||||
|
for (i = 0; i < num_pds; i++) {
|
||||||
|
if (by_id)
|
||||||
|
pd_dev = dev_pm_domain_attach_by_id(dev, i);
|
||||||
|
else
|
||||||
|
pd_dev = dev_pm_domain_attach_by_name(dev,
|
||||||
|
data->pd_names[i]);
|
||||||
|
if (IS_ERR_OR_NULL(pd_dev)) {
|
||||||
|
ret = pd_dev ? PTR_ERR(pd_dev) : -ENODEV;
|
||||||
|
goto err_attach;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link_flags) {
|
||||||
|
struct device_link *link;
|
||||||
|
|
||||||
|
link = device_link_add(dev, pd_dev, link_flags);
|
||||||
|
if (!link) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err_link;
|
||||||
|
}
|
||||||
|
|
||||||
|
pds->pd_links[i] = link;
|
||||||
|
}
|
||||||
|
|
||||||
|
pds->pd_devs[i] = pd_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
pds->num_pds = num_pds;
|
||||||
|
*list = pds;
|
||||||
|
return num_pds;
|
||||||
|
|
||||||
|
err_link:
|
||||||
|
dev_pm_domain_detach(pd_dev, true);
|
||||||
|
err_attach:
|
||||||
|
while (--i >= 0) {
|
||||||
|
if (pds->pd_links[i])
|
||||||
|
device_link_del(pds->pd_links[i]);
|
||||||
|
dev_pm_domain_detach(pds->pd_devs[i], true);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dev_pm_domain_attach_list);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dev_pm_domain_detach - Detach a device from its PM domain.
|
* dev_pm_domain_detach - Detach a device from its PM domain.
|
||||||
* @dev: Device to detach.
|
* @dev: Device to detach.
|
||||||
@@ -187,6 +296,31 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
|
EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dev_pm_domain_detach_list - Detach a list of PM domains.
|
||||||
|
* @list: The list of PM domains to detach.
|
||||||
|
*
|
||||||
|
* This function reverse the actions from dev_pm_domain_attach_list().
|
||||||
|
* Typically it should be invoked during the remove phase from drivers.
|
||||||
|
*
|
||||||
|
* Callers must ensure proper synchronization of this function with power
|
||||||
|
* management callbacks.
|
||||||
|
*/
|
||||||
|
void dev_pm_domain_detach_list(struct dev_pm_domain_list *list)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < list->num_pds; i++) {
|
||||||
|
if (list->pd_links[i])
|
||||||
|
device_link_del(list->pd_links[i]);
|
||||||
|
dev_pm_domain_detach(list->pd_devs[i], true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dev_pm_domain_detach_list);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dev_pm_domain_start - Start the device through its PM domain.
|
* dev_pm_domain_start - Start the device through its PM domain.
|
||||||
* @dev: Device to start.
|
* @dev: Device to start.
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ static const struct genpd_lock_ops genpd_spin_ops = {
|
|||||||
#define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
|
#define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
|
||||||
#define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
|
#define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
|
||||||
#define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
|
#define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
|
||||||
|
#define genpd_is_opp_table_fw(genpd) (genpd->flags & GENPD_FLAG_OPP_TABLE_FW)
|
||||||
|
|
||||||
static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
|
static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
|
||||||
const struct generic_pm_domain *genpd)
|
const struct generic_pm_domain *genpd)
|
||||||
@@ -2319,7 +2320,7 @@ int of_genpd_add_provider_simple(struct device_node *np,
|
|||||||
genpd->dev.of_node = np;
|
genpd->dev.of_node = np;
|
||||||
|
|
||||||
/* Parse genpd OPP table */
|
/* Parse genpd OPP table */
|
||||||
if (genpd->set_performance_state) {
|
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
|
||||||
ret = dev_pm_opp_of_add_table(&genpd->dev);
|
ret = dev_pm_opp_of_add_table(&genpd->dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return dev_err_probe(&genpd->dev, ret, "Failed to add OPP table\n");
|
return dev_err_probe(&genpd->dev, ret, "Failed to add OPP table\n");
|
||||||
@@ -2334,7 +2335,7 @@ int of_genpd_add_provider_simple(struct device_node *np,
|
|||||||
|
|
||||||
ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
|
ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (genpd->set_performance_state) {
|
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
|
||||||
dev_pm_opp_put_opp_table(genpd->opp_table);
|
dev_pm_opp_put_opp_table(genpd->opp_table);
|
||||||
dev_pm_opp_of_remove_table(&genpd->dev);
|
dev_pm_opp_of_remove_table(&genpd->dev);
|
||||||
}
|
}
|
||||||
@@ -2378,7 +2379,7 @@ int of_genpd_add_provider_onecell(struct device_node *np,
|
|||||||
genpd->dev.of_node = np;
|
genpd->dev.of_node = np;
|
||||||
|
|
||||||
/* Parse genpd OPP table */
|
/* Parse genpd OPP table */
|
||||||
if (genpd->set_performance_state) {
|
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
|
||||||
ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i);
|
ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err_probe(&genpd->dev, ret,
|
dev_err_probe(&genpd->dev, ret,
|
||||||
@@ -2414,7 +2415,7 @@ error:
|
|||||||
genpd->provider = NULL;
|
genpd->provider = NULL;
|
||||||
genpd->has_provider = false;
|
genpd->has_provider = false;
|
||||||
|
|
||||||
if (genpd->set_performance_state) {
|
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
|
||||||
dev_pm_opp_put_opp_table(genpd->opp_table);
|
dev_pm_opp_put_opp_table(genpd->opp_table);
|
||||||
dev_pm_opp_of_remove_table(&genpd->dev);
|
dev_pm_opp_of_remove_table(&genpd->dev);
|
||||||
}
|
}
|
||||||
@@ -2446,7 +2447,7 @@ void of_genpd_del_provider(struct device_node *np)
|
|||||||
if (gpd->provider == &np->fwnode) {
|
if (gpd->provider == &np->fwnode) {
|
||||||
gpd->has_provider = false;
|
gpd->has_provider = false;
|
||||||
|
|
||||||
if (!gpd->set_performance_state)
|
if (genpd_is_opp_table_fw(gpd) || !gpd->set_performance_state)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dev_pm_opp_put_opp_table(gpd->opp_table);
|
dev_pm_opp_put_opp_table(gpd->opp_table);
|
||||||
|
|||||||
@@ -70,15 +70,35 @@ static unsigned int scmi_cpufreq_fast_switch(struct cpufreq_policy *policy,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int scmi_cpu_domain_id(struct device *cpu_dev)
|
||||||
scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
|
|
||||||
{
|
{
|
||||||
int cpu, domain, tdomain;
|
struct device_node *np = cpu_dev->of_node;
|
||||||
struct device *tcpu_dev;
|
struct of_phandle_args domain_id;
|
||||||
|
int index;
|
||||||
|
|
||||||
domain = perf_ops->device_domain_id(cpu_dev);
|
if (of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0,
|
||||||
if (domain < 0)
|
&domain_id)) {
|
||||||
return domain;
|
/* Find the corresponding index for power-domain "perf". */
|
||||||
|
index = of_property_match_string(np, "power-domain-names",
|
||||||
|
"perf");
|
||||||
|
if (index < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (of_parse_phandle_with_args(np, "power-domains",
|
||||||
|
"#power-domain-cells", index,
|
||||||
|
&domain_id))
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain_id.args[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
scmi_get_sharing_cpus(struct device *cpu_dev, int domain,
|
||||||
|
struct cpumask *cpumask)
|
||||||
|
{
|
||||||
|
int cpu, tdomain;
|
||||||
|
struct device *tcpu_dev;
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
if (cpu == cpu_dev->id)
|
if (cpu == cpu_dev->id)
|
||||||
@@ -88,7 +108,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
|
|||||||
if (!tcpu_dev)
|
if (!tcpu_dev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tdomain = perf_ops->device_domain_id(tcpu_dev);
|
tdomain = scmi_cpu_domain_id(tcpu_dev);
|
||||||
if (tdomain == domain)
|
if (tdomain == domain)
|
||||||
cpumask_set_cpu(cpu, cpumask);
|
cpumask_set_cpu(cpu, cpumask);
|
||||||
}
|
}
|
||||||
@@ -104,7 +124,7 @@ scmi_get_cpu_power(struct device *cpu_dev, unsigned long *power,
|
|||||||
unsigned long Hz;
|
unsigned long Hz;
|
||||||
int ret, domain;
|
int ret, domain;
|
||||||
|
|
||||||
domain = perf_ops->device_domain_id(cpu_dev);
|
domain = scmi_cpu_domain_id(cpu_dev);
|
||||||
if (domain < 0)
|
if (domain < 0)
|
||||||
return domain;
|
return domain;
|
||||||
|
|
||||||
@@ -126,7 +146,7 @@ scmi_get_cpu_power(struct device *cpu_dev, unsigned long *power,
|
|||||||
|
|
||||||
static int scmi_cpufreq_init(struct cpufreq_policy *policy)
|
static int scmi_cpufreq_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
int ret, nr_opp;
|
int ret, nr_opp, domain;
|
||||||
unsigned int latency;
|
unsigned int latency;
|
||||||
struct device *cpu_dev;
|
struct device *cpu_dev;
|
||||||
struct scmi_data *priv;
|
struct scmi_data *priv;
|
||||||
@@ -138,6 +158,10 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
domain = scmi_cpu_domain_id(cpu_dev);
|
||||||
|
if (domain < 0)
|
||||||
|
return domain;
|
||||||
|
|
||||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||||
if (!priv)
|
if (!priv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -148,7 +172,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Obtain CPUs that share SCMI performance controls */
|
/* Obtain CPUs that share SCMI performance controls */
|
||||||
ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus);
|
ret = scmi_get_sharing_cpus(cpu_dev, domain, policy->cpus);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_warn(cpu_dev, "failed to get sharing cpumask\n");
|
dev_warn(cpu_dev, "failed to get sharing cpumask\n");
|
||||||
goto out_free_cpumask;
|
goto out_free_cpumask;
|
||||||
@@ -176,7 +200,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
|
|||||||
*/
|
*/
|
||||||
nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
|
nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
|
||||||
if (nr_opp <= 0) {
|
if (nr_opp <= 0) {
|
||||||
ret = perf_ops->device_opps_add(ph, cpu_dev);
|
ret = perf_ops->device_opps_add(ph, cpu_dev, domain);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_warn(cpu_dev, "failed to add opps to the device\n");
|
dev_warn(cpu_dev, "failed to add opps to the device\n");
|
||||||
goto out_free_cpumask;
|
goto out_free_cpumask;
|
||||||
@@ -209,7 +233,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->cpu_dev = cpu_dev;
|
priv->cpu_dev = cpu_dev;
|
||||||
priv->domain_id = perf_ops->device_domain_id(cpu_dev);
|
priv->domain_id = domain;
|
||||||
|
|
||||||
policy->driver_data = priv;
|
policy->driver_data = priv;
|
||||||
policy->freq_table = freq_table;
|
policy->freq_table = freq_table;
|
||||||
@@ -217,14 +241,14 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
|
|||||||
/* SCMI allows DVFS request for any domain from any CPU */
|
/* SCMI allows DVFS request for any domain from any CPU */
|
||||||
policy->dvfs_possible_from_any_cpu = true;
|
policy->dvfs_possible_from_any_cpu = true;
|
||||||
|
|
||||||
latency = perf_ops->transition_latency_get(ph, cpu_dev);
|
latency = perf_ops->transition_latency_get(ph, domain);
|
||||||
if (!latency)
|
if (!latency)
|
||||||
latency = CPUFREQ_ETERNAL;
|
latency = CPUFREQ_ETERNAL;
|
||||||
|
|
||||||
policy->cpuinfo.transition_latency = latency;
|
policy->cpuinfo.transition_latency = latency;
|
||||||
|
|
||||||
policy->fast_switch_possible =
|
policy->fast_switch_possible =
|
||||||
perf_ops->fast_switch_possible(ph, cpu_dev);
|
perf_ops->fast_switch_possible(ph, domain);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ struct scmi_msg_resp_perf_describe_levels {
|
|||||||
|
|
||||||
struct perf_dom_info {
|
struct perf_dom_info {
|
||||||
bool set_limits;
|
bool set_limits;
|
||||||
bool set_perf;
|
|
||||||
bool perf_limit_notify;
|
bool perf_limit_notify;
|
||||||
bool perf_level_notify;
|
bool perf_level_notify;
|
||||||
bool perf_fastchannels;
|
bool perf_fastchannels;
|
||||||
@@ -132,7 +131,7 @@ struct perf_dom_info {
|
|||||||
u32 sustained_freq_khz;
|
u32 sustained_freq_khz;
|
||||||
u32 sustained_perf_level;
|
u32 sustained_perf_level;
|
||||||
unsigned long mult_factor;
|
unsigned long mult_factor;
|
||||||
char name[SCMI_MAX_STR_SIZE];
|
struct scmi_perf_domain_info info;
|
||||||
struct scmi_opp opp[MAX_OPPS];
|
struct scmi_opp opp[MAX_OPPS];
|
||||||
struct scmi_fc_info *fc_info;
|
struct scmi_fc_info *fc_info;
|
||||||
};
|
};
|
||||||
@@ -209,7 +208,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
|
|||||||
flags = le32_to_cpu(attr->flags);
|
flags = le32_to_cpu(attr->flags);
|
||||||
|
|
||||||
dom_info->set_limits = SUPPORTS_SET_LIMITS(flags);
|
dom_info->set_limits = SUPPORTS_SET_LIMITS(flags);
|
||||||
dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags);
|
dom_info->info.set_perf = SUPPORTS_SET_PERF_LVL(flags);
|
||||||
dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags);
|
dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags);
|
||||||
dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags);
|
dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags);
|
||||||
dom_info->perf_fastchannels = SUPPORTS_PERF_FASTCHANNELS(flags);
|
dom_info->perf_fastchannels = SUPPORTS_PERF_FASTCHANNELS(flags);
|
||||||
@@ -225,7 +224,8 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
|
|||||||
dom_info->mult_factor =
|
dom_info->mult_factor =
|
||||||
(dom_info->sustained_freq_khz * 1000UL)
|
(dom_info->sustained_freq_khz * 1000UL)
|
||||||
/ dom_info->sustained_perf_level;
|
/ dom_info->sustained_perf_level;
|
||||||
strscpy(dom_info->name, attr->name, SCMI_SHORT_NAME_MAX_SIZE);
|
strscpy(dom_info->info.name, attr->name,
|
||||||
|
SCMI_SHORT_NAME_MAX_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ph->xops->xfer_put(ph, t);
|
ph->xops->xfer_put(ph, t);
|
||||||
@@ -237,7 +237,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
|
|||||||
if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 &&
|
if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 &&
|
||||||
SUPPORTS_EXTENDED_NAMES(flags))
|
SUPPORTS_EXTENDED_NAMES(flags))
|
||||||
ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET, domain,
|
ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET, domain,
|
||||||
dom_info->name, SCMI_MAX_STR_SIZE);
|
dom_info->info.name, SCMI_MAX_STR_SIZE);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -333,6 +333,36 @@ scmi_perf_describe_levels_get(const struct scmi_protocol_handle *ph, u32 domain,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int scmi_perf_num_domains_get(const struct scmi_protocol_handle *ph)
|
||||||
|
{
|
||||||
|
struct scmi_perf_info *pi = ph->get_priv(ph);
|
||||||
|
|
||||||
|
return pi->num_domains;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct perf_dom_info *
|
||||||
|
scmi_perf_domain_lookup(const struct scmi_protocol_handle *ph, u32 domain)
|
||||||
|
{
|
||||||
|
struct scmi_perf_info *pi = ph->get_priv(ph);
|
||||||
|
|
||||||
|
if (domain >= pi->num_domains)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
return pi->dom_info + domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct scmi_perf_domain_info *
|
||||||
|
scmi_perf_info_get(const struct scmi_protocol_handle *ph, u32 domain)
|
||||||
|
{
|
||||||
|
struct perf_dom_info *dom;
|
||||||
|
|
||||||
|
dom = scmi_perf_domain_lookup(ph, domain);
|
||||||
|
if (IS_ERR(dom))
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
return &dom->info;
|
||||||
|
}
|
||||||
|
|
||||||
static int scmi_perf_mb_limits_set(const struct scmi_protocol_handle *ph,
|
static int scmi_perf_mb_limits_set(const struct scmi_protocol_handle *ph,
|
||||||
u32 domain, u32 max_perf, u32 min_perf)
|
u32 domain, u32 max_perf, u32 min_perf)
|
||||||
{
|
{
|
||||||
@@ -356,17 +386,6 @@ static int scmi_perf_mb_limits_set(const struct scmi_protocol_handle *ph,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct perf_dom_info *
|
|
||||||
scmi_perf_domain_lookup(const struct scmi_protocol_handle *ph, u32 domain)
|
|
||||||
{
|
|
||||||
struct scmi_perf_info *pi = ph->get_priv(ph);
|
|
||||||
|
|
||||||
if (domain >= pi->num_domains)
|
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
|
|
||||||
return pi->dom_info + domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph,
|
static int scmi_perf_limits_set(const struct scmi_protocol_handle *ph,
|
||||||
u32 domain, u32 max_perf, u32 min_perf)
|
u32 domain, u32 max_perf, u32 min_perf)
|
||||||
{
|
{
|
||||||
@@ -579,62 +598,43 @@ static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
|
|||||||
*p_fc = fc;
|
*p_fc = fc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Device specific ops */
|
|
||||||
static int scmi_dev_domain_id(struct device *dev)
|
|
||||||
{
|
|
||||||
struct of_phandle_args clkspec;
|
|
||||||
|
|
||||||
if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells",
|
|
||||||
0, &clkspec))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return clkspec.args[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
|
static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
|
||||||
struct device *dev)
|
struct device *dev, u32 domain)
|
||||||
{
|
{
|
||||||
int idx, ret, domain;
|
int idx, ret;
|
||||||
unsigned long freq;
|
unsigned long freq;
|
||||||
struct scmi_opp *opp;
|
struct dev_pm_opp_data data = {};
|
||||||
struct perf_dom_info *dom;
|
struct perf_dom_info *dom;
|
||||||
|
|
||||||
domain = scmi_dev_domain_id(dev);
|
|
||||||
if (domain < 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
dom = scmi_perf_domain_lookup(ph, domain);
|
dom = scmi_perf_domain_lookup(ph, domain);
|
||||||
if (IS_ERR(dom))
|
if (IS_ERR(dom))
|
||||||
return PTR_ERR(dom);
|
return PTR_ERR(dom);
|
||||||
|
|
||||||
for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
|
for (idx = 0; idx < dom->opp_count; idx++) {
|
||||||
freq = opp->perf * dom->mult_factor;
|
freq = dom->opp[idx].perf * dom->mult_factor;
|
||||||
|
|
||||||
ret = dev_pm_opp_add(dev, freq, 0);
|
data.level = dom->opp[idx].perf;
|
||||||
|
data.freq = freq;
|
||||||
|
|
||||||
|
ret = dev_pm_opp_add_dynamic(dev, &data);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_warn(dev, "failed to add opp %luHz\n", freq);
|
dev_warn(dev, "failed to add opp %luHz\n", freq);
|
||||||
|
dev_pm_opp_remove_all_dynamic(dev);
|
||||||
while (idx-- > 0) {
|
|
||||||
freq = (--opp)->perf * dom->mult_factor;
|
|
||||||
dev_pm_opp_remove(dev, freq);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev_dbg(dev, "[%d][%s]:: Registered OPP[%d] %lu\n",
|
||||||
|
domain, dom->info.name, idx, freq);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
scmi_dvfs_transition_latency_get(const struct scmi_protocol_handle *ph,
|
scmi_dvfs_transition_latency_get(const struct scmi_protocol_handle *ph,
|
||||||
struct device *dev)
|
u32 domain)
|
||||||
{
|
{
|
||||||
int domain;
|
|
||||||
struct perf_dom_info *dom;
|
struct perf_dom_info *dom;
|
||||||
|
|
||||||
domain = scmi_dev_domain_id(dev);
|
|
||||||
if (domain < 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
dom = scmi_perf_domain_lookup(ph, domain);
|
dom = scmi_perf_domain_lookup(ph, domain);
|
||||||
if (IS_ERR(dom))
|
if (IS_ERR(dom))
|
||||||
return PTR_ERR(dom);
|
return PTR_ERR(dom);
|
||||||
@@ -701,15 +701,10 @@ static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph,
|
static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph,
|
||||||
struct device *dev)
|
u32 domain)
|
||||||
{
|
{
|
||||||
int domain;
|
|
||||||
struct perf_dom_info *dom;
|
struct perf_dom_info *dom;
|
||||||
|
|
||||||
domain = scmi_dev_domain_id(dev);
|
|
||||||
if (domain < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
dom = scmi_perf_domain_lookup(ph, domain);
|
dom = scmi_perf_domain_lookup(ph, domain);
|
||||||
if (IS_ERR(dom))
|
if (IS_ERR(dom))
|
||||||
return false;
|
return false;
|
||||||
@@ -726,11 +721,12 @@ scmi_power_scale_get(const struct scmi_protocol_handle *ph)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct scmi_perf_proto_ops perf_proto_ops = {
|
static const struct scmi_perf_proto_ops perf_proto_ops = {
|
||||||
|
.num_domains_get = scmi_perf_num_domains_get,
|
||||||
|
.info_get = scmi_perf_info_get,
|
||||||
.limits_set = scmi_perf_limits_set,
|
.limits_set = scmi_perf_limits_set,
|
||||||
.limits_get = scmi_perf_limits_get,
|
.limits_get = scmi_perf_limits_get,
|
||||||
.level_set = scmi_perf_level_set,
|
.level_set = scmi_perf_level_set,
|
||||||
.level_get = scmi_perf_level_get,
|
.level_get = scmi_perf_level_get,
|
||||||
.device_domain_id = scmi_dev_domain_id,
|
|
||||||
.transition_latency_get = scmi_dvfs_transition_latency_get,
|
.transition_latency_get = scmi_dvfs_transition_latency_get,
|
||||||
.device_opps_add = scmi_dvfs_device_opps_add,
|
.device_opps_add = scmi_dvfs_device_opps_add,
|
||||||
.freq_set = scmi_dvfs_freq_set,
|
.freq_set = scmi_dvfs_freq_set,
|
||||||
|
|||||||
@@ -44,6 +44,15 @@ static int virtio_pmem_flush(struct nd_region *nd_region)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int err, err1;
|
int err, err1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't bother to submit the request to the device if the device is
|
||||||
|
* not activated.
|
||||||
|
*/
|
||||||
|
if (vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_NEEDS_RESET) {
|
||||||
|
dev_info(&vdev->dev, "virtio pmem device needs a reset\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
|
req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
|
||||||
if (!req_data)
|
if (!req_data)
|
||||||
|
|||||||
@@ -1011,6 +1011,28 @@ static int _set_required_opps(struct device *dev,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _set_opp_level(struct device *dev, struct opp_table *opp_table,
|
||||||
|
struct dev_pm_opp *opp)
|
||||||
|
{
|
||||||
|
unsigned int level = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (opp) {
|
||||||
|
if (!opp->level)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
level = opp->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request a new performance state through the device's PM domain. */
|
||||||
|
ret = dev_pm_genpd_set_performance_state(dev, level);
|
||||||
|
if (ret)
|
||||||
|
dev_err(dev, "Failed to set performance state %u (%d)\n", level,
|
||||||
|
ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void _find_current_opp(struct device *dev, struct opp_table *opp_table)
|
static void _find_current_opp(struct device *dev, struct opp_table *opp_table)
|
||||||
{
|
{
|
||||||
struct dev_pm_opp *opp = ERR_PTR(-ENODEV);
|
struct dev_pm_opp *opp = ERR_PTR(-ENODEV);
|
||||||
@@ -1058,8 +1080,13 @@ static int _disable_opp_table(struct device *dev, struct opp_table *opp_table)
|
|||||||
if (opp_table->regulators)
|
if (opp_table->regulators)
|
||||||
regulator_disable(opp_table->regulators[0]);
|
regulator_disable(opp_table->regulators[0]);
|
||||||
|
|
||||||
|
ret = _set_opp_level(dev, opp_table, NULL);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
ret = _set_required_opps(dev, opp_table, NULL, false);
|
ret = _set_required_opps(dev, opp_table, NULL, false);
|
||||||
|
|
||||||
|
out:
|
||||||
opp_table->enabled = false;
|
opp_table->enabled = false;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1102,6 +1129,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = _set_opp_level(dev, opp_table, opp);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = _set_opp_bw(opp_table, opp, dev);
|
ret = _set_opp_bw(opp_table, opp, dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Failed to set bw: %d\n", ret);
|
dev_err(dev, "Failed to set bw: %d\n", ret);
|
||||||
@@ -1145,6 +1176,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = _set_opp_level(dev, opp_table, opp);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = _set_required_opps(dev, opp_table, opp, false);
|
ret = _set_required_opps(dev, opp_table, opp, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Failed to set required opps: %d\n", ret);
|
dev_err(dev, "Failed to set required opps: %d\n", ret);
|
||||||
@@ -1914,8 +1949,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
|
|||||||
* _opp_add_v1() - Allocate a OPP based on v1 bindings.
|
* _opp_add_v1() - Allocate a OPP based on v1 bindings.
|
||||||
* @opp_table: OPP table
|
* @opp_table: OPP table
|
||||||
* @dev: device for which we do this operation
|
* @dev: device for which we do this operation
|
||||||
* @freq: Frequency in Hz for this OPP
|
* @data: The OPP data for the OPP to add
|
||||||
* @u_volt: Voltage in uVolts for this OPP
|
|
||||||
* @dynamic: Dynamically added OPPs.
|
* @dynamic: Dynamically added OPPs.
|
||||||
*
|
*
|
||||||
* This function adds an opp definition to the opp table and returns status.
|
* This function adds an opp definition to the opp table and returns status.
|
||||||
@@ -1933,10 +1967,10 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
|
|||||||
* -ENOMEM Memory allocation failure
|
* -ENOMEM Memory allocation failure
|
||||||
*/
|
*/
|
||||||
int _opp_add_v1(struct opp_table *opp_table, struct device *dev,
|
int _opp_add_v1(struct opp_table *opp_table, struct device *dev,
|
||||||
unsigned long freq, long u_volt, bool dynamic)
|
struct dev_pm_opp_data *data, bool dynamic)
|
||||||
{
|
{
|
||||||
struct dev_pm_opp *new_opp;
|
struct dev_pm_opp *new_opp;
|
||||||
unsigned long tol;
|
unsigned long tol, u_volt = data->u_volt;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!assert_single_clk(opp_table))
|
if (!assert_single_clk(opp_table))
|
||||||
@@ -1947,7 +1981,8 @@ int _opp_add_v1(struct opp_table *opp_table, struct device *dev,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* populate the opp table */
|
/* populate the opp table */
|
||||||
new_opp->rates[0] = freq;
|
new_opp->rates[0] = data->freq;
|
||||||
|
new_opp->level = data->level;
|
||||||
tol = u_volt * opp_table->voltage_tolerance_v1 / 100;
|
tol = u_volt * opp_table->voltage_tolerance_v1 / 100;
|
||||||
new_opp->supplies[0].u_volt = u_volt;
|
new_opp->supplies[0].u_volt = u_volt;
|
||||||
new_opp->supplies[0].u_volt_min = u_volt - tol;
|
new_opp->supplies[0].u_volt_min = u_volt - tol;
|
||||||
@@ -2731,10 +2766,9 @@ unlock:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dev_pm_opp_add() - Add an OPP table from a table definitions
|
* dev_pm_opp_add_dynamic() - Add an OPP table from a table definitions
|
||||||
* @dev: device for which we do this operation
|
* @dev: The device for which we do this operation
|
||||||
* @freq: Frequency in Hz for this OPP
|
* @data: The OPP data for the OPP to add
|
||||||
* @u_volt: Voltage in uVolts for this OPP
|
|
||||||
*
|
*
|
||||||
* This function adds an opp definition to the opp table and returns status.
|
* This function adds an opp definition to the opp table and returns status.
|
||||||
* The opp is made available by default and it can be controlled using
|
* The opp is made available by default and it can be controlled using
|
||||||
@@ -2747,7 +2781,7 @@ unlock:
|
|||||||
* Duplicate OPPs (both freq and volt are same) and !opp->available
|
* Duplicate OPPs (both freq and volt are same) and !opp->available
|
||||||
* -ENOMEM Memory allocation failure
|
* -ENOMEM Memory allocation failure
|
||||||
*/
|
*/
|
||||||
int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
|
int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *data)
|
||||||
{
|
{
|
||||||
struct opp_table *opp_table;
|
struct opp_table *opp_table;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -2759,12 +2793,24 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
|
|||||||
/* Fix regulator count for dynamic OPPs */
|
/* Fix regulator count for dynamic OPPs */
|
||||||
opp_table->regulator_count = 1;
|
opp_table->regulator_count = 1;
|
||||||
|
|
||||||
ret = _opp_add_v1(opp_table, dev, freq, u_volt, true);
|
ret = _opp_add_v1(opp_table, dev, data, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_pm_opp_put_opp_table(opp_table);
|
dev_pm_opp_put_opp_table(opp_table);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dev_pm_opp_add_dynamic);
|
||||||
|
|
||||||
|
int dev_pm_opp_add(struct device *dev, unsigned long freq,
|
||||||
|
unsigned long u_volt)
|
||||||
|
{
|
||||||
|
struct dev_pm_opp_data data = {
|
||||||
|
.freq = freq,
|
||||||
|
.u_volt = u_volt,
|
||||||
|
};
|
||||||
|
|
||||||
|
return dev_pm_opp_add_dynamic(dev, &data);
|
||||||
|
}
|
||||||
EXPORT_SYMBOL_GPL(dev_pm_opp_add);
|
EXPORT_SYMBOL_GPL(dev_pm_opp_add);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1108,11 +1108,15 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
|
|||||||
while (nr) {
|
while (nr) {
|
||||||
unsigned long freq = be32_to_cpup(val++) * 1000;
|
unsigned long freq = be32_to_cpup(val++) * 1000;
|
||||||
unsigned long volt = be32_to_cpup(val++);
|
unsigned long volt = be32_to_cpup(val++);
|
||||||
|
struct dev_pm_opp_data data = {
|
||||||
|
.freq = freq,
|
||||||
|
.u_volt = volt,
|
||||||
|
};
|
||||||
|
|
||||||
ret = _opp_add_v1(opp_table, dev, freq, volt, false);
|
ret = _opp_add_v1(opp_table, dev, &data, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
|
dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
|
||||||
__func__, freq, ret);
|
__func__, data.freq, ret);
|
||||||
goto remove_static_opp;
|
goto remove_static_opp;
|
||||||
}
|
}
|
||||||
nr -= 2;
|
nr -= 2;
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table);
|
|||||||
void _opp_free(struct dev_pm_opp *opp);
|
void _opp_free(struct dev_pm_opp *opp);
|
||||||
int _opp_compare_key(struct opp_table *opp_table, struct dev_pm_opp *opp1, struct dev_pm_opp *opp2);
|
int _opp_compare_key(struct opp_table *opp_table, struct dev_pm_opp *opp1, struct dev_pm_opp *opp2);
|
||||||
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
|
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
|
||||||
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic);
|
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, struct dev_pm_opp_data *data, bool dynamic);
|
||||||
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
|
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
|
||||||
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
|
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
|
||||||
void _put_opp_list_kref(struct opp_table *opp_table);
|
void _put_opp_list_kref(struct opp_table *opp_table);
|
||||||
|
|||||||
@@ -1059,7 +1059,7 @@ static int brcmuart_probe(struct platform_device *pdev)
|
|||||||
dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not ");
|
dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not ");
|
||||||
|
|
||||||
memset(&up, 0, sizeof(up));
|
memset(&up, 0, sizeof(up));
|
||||||
up.port.type = PORT_16550A;
|
up.port.type = PORT_BCM7271;
|
||||||
up.port.uartclk = clk_rate;
|
up.port.uartclk = clk_rate;
|
||||||
up.port.dev = dev;
|
up.port.dev = dev;
|
||||||
up.port.mapbase = mapbase;
|
up.port.mapbase = mapbase;
|
||||||
@@ -1073,8 +1073,6 @@ static int brcmuart_probe(struct platform_device *pdev)
|
|||||||
| UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
| UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
||||||
up.port.dev = dev;
|
up.port.dev = dev;
|
||||||
up.port.private_data = priv;
|
up.port.private_data = priv;
|
||||||
up.capabilities = UART_CAP_FIFO | UART_CAP_AFE;
|
|
||||||
up.port.fifosize = 32;
|
|
||||||
|
|
||||||
/* Check for a fixed line number */
|
/* Check for a fixed line number */
|
||||||
ret = of_alias_get_id(np, "serial");
|
ret = of_alias_get_id(np, "serial");
|
||||||
|
|||||||
@@ -314,6 +314,14 @@ static const struct serial8250_config uart_config[] = {
|
|||||||
.rxtrig_bytes = {1, 4, 8, 14},
|
.rxtrig_bytes = {1, 4, 8, 14},
|
||||||
.flags = UART_CAP_FIFO,
|
.flags = UART_CAP_FIFO,
|
||||||
},
|
},
|
||||||
|
[PORT_BCM7271] = {
|
||||||
|
.name = "Broadcom BCM7271 UART",
|
||||||
|
.fifo_size = 32,
|
||||||
|
.tx_loadsz = 32,
|
||||||
|
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01,
|
||||||
|
.rxtrig_bytes = {1, 8, 16, 30},
|
||||||
|
.flags = UART_CAP_FIFO | UART_CAP_AFE,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Uart divisor latch read */
|
/* Uart divisor latch read */
|
||||||
|
|||||||
@@ -105,16 +105,15 @@ EXPORT_SYMBOL_GPL(ufshcd_mcq_config_mac);
|
|||||||
* @hba: per adapter instance
|
* @hba: per adapter instance
|
||||||
* @req: pointer to the request to be issued
|
* @req: pointer to the request to be issued
|
||||||
*
|
*
|
||||||
* Returns the hardware queue instance on which the request would
|
* Return: the hardware queue instance on which the request will be or has
|
||||||
* be queued.
|
* been queued. %NULL if the request has already been freed.
|
||||||
*/
|
*/
|
||||||
struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba,
|
struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba,
|
||||||
struct request *req)
|
struct request *req)
|
||||||
{
|
{
|
||||||
u32 utag = blk_mq_unique_tag(req);
|
struct blk_mq_hw_ctx *hctx = READ_ONCE(req->mq_hctx);
|
||||||
u32 hwq = blk_mq_unique_tag_to_hwq(utag);
|
|
||||||
|
|
||||||
return &hba->uhq[hwq];
|
return hctx ? &hba->uhq[hctx->queue_num] : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -521,6 +520,8 @@ int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag)
|
|||||||
if (!cmd)
|
if (!cmd)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd));
|
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd));
|
||||||
|
if (!hwq)
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
hwq = hba->dev_cmd_queue;
|
hwq = hba->dev_cmd_queue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6489,6 +6489,8 @@ static bool ufshcd_abort_all(struct ufs_hba *hba)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd));
|
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd));
|
||||||
|
if (!hwq)
|
||||||
|
return 0;
|
||||||
spin_lock_irqsave(&hwq->cq_lock, flags);
|
spin_lock_irqsave(&hwq->cq_lock, flags);
|
||||||
if (ufshcd_cmd_inflight(lrbp->cmd))
|
if (ufshcd_cmd_inflight(lrbp->cmd))
|
||||||
ufshcd_release_scsi_cmd(hba, lrbp);
|
ufshcd_release_scsi_cmd(hba, lrbp);
|
||||||
|
|||||||
@@ -2453,7 +2453,7 @@ static int tcpm_register_sink_caps(struct tcpm_port *port)
|
|||||||
{
|
{
|
||||||
struct usb_power_delivery_desc desc = { port->negotiated_rev };
|
struct usb_power_delivery_desc desc = { port->negotiated_rev };
|
||||||
struct usb_power_delivery_capabilities_desc caps = { };
|
struct usb_power_delivery_capabilities_desc caps = { };
|
||||||
struct usb_power_delivery_capabilities *cap = port->partner_source_caps;
|
struct usb_power_delivery_capabilities *cap;
|
||||||
|
|
||||||
if (!port->partner_pd)
|
if (!port->partner_pd)
|
||||||
port->partner_pd = usb_power_delivery_register(NULL, &desc);
|
port->partner_pd = usb_power_delivery_register(NULL, &desc);
|
||||||
@@ -2463,11 +2463,6 @@ static int tcpm_register_sink_caps(struct tcpm_port *port)
|
|||||||
memcpy(caps.pdo, port->sink_caps, sizeof(u32) * port->nr_sink_caps);
|
memcpy(caps.pdo, port->sink_caps, sizeof(u32) * port->nr_sink_caps);
|
||||||
caps.role = TYPEC_SINK;
|
caps.role = TYPEC_SINK;
|
||||||
|
|
||||||
if (cap) {
|
|
||||||
usb_power_delivery_unregister_capabilities(cap);
|
|
||||||
port->partner_source_caps = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps);
|
cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps);
|
||||||
if (IS_ERR(cap))
|
if (IS_ERR(cap))
|
||||||
return PTR_ERR(cap);
|
return PTR_ERR(cap);
|
||||||
|
|||||||
@@ -111,7 +111,8 @@ int z_erofs_gbuf_growsize(unsigned int nrpages)
|
|||||||
out:
|
out:
|
||||||
if (i < z_erofs_gbuf_count && tmp_pages) {
|
if (i < z_erofs_gbuf_count && tmp_pages) {
|
||||||
for (j = 0; j < nrpages; ++j)
|
for (j = 0; j < nrpages; ++j)
|
||||||
if (tmp_pages[j] && tmp_pages[j] != gbuf->pages[j])
|
if (tmp_pages[j] && (j >= gbuf->nrpages ||
|
||||||
|
tmp_pages[j] != gbuf->pages[j]))
|
||||||
__free_page(tmp_pages[j]);
|
__free_page(tmp_pages[j]);
|
||||||
kfree(tmp_pages);
|
kfree(tmp_pages);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <trace/events/sched.h>
|
#include <trace/events/sched.h>
|
||||||
|
#include <trace/hooks/sched.h>
|
||||||
|
|
||||||
static int bprm_creds_from_file(struct linux_binprm *bprm);
|
static int bprm_creds_from_file(struct linux_binprm *bprm);
|
||||||
|
|
||||||
@@ -1238,6 +1239,7 @@ void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
|
|||||||
task_lock(tsk);
|
task_lock(tsk);
|
||||||
trace_task_rename(tsk, buf);
|
trace_task_rename(tsk, buf);
|
||||||
strscpy_pad(tsk->comm, buf, sizeof(tsk->comm));
|
strscpy_pad(tsk->comm, buf, sizeof(tsk->comm));
|
||||||
|
trace_android_vh_set_task_comm(tsk);
|
||||||
task_unlock(tsk);
|
task_unlock(tsk);
|
||||||
perf_event_comm(tsk, exec);
|
perf_event_comm(tsk, exec);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -798,6 +798,7 @@ enum {
|
|||||||
FI_ALIGNED_WRITE, /* enable aligned write */
|
FI_ALIGNED_WRITE, /* enable aligned write */
|
||||||
FI_COW_FILE, /* indicate COW file */
|
FI_COW_FILE, /* indicate COW file */
|
||||||
FI_ATOMIC_COMMITTED, /* indicate atomic commit completed except disk sync */
|
FI_ATOMIC_COMMITTED, /* indicate atomic commit completed except disk sync */
|
||||||
|
FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */
|
||||||
FI_ATOMIC_REPLACE, /* indicate atomic replace */
|
FI_ATOMIC_REPLACE, /* indicate atomic replace */
|
||||||
FI_MAX, /* max flag, never be used */
|
FI_MAX, /* max flag, never be used */
|
||||||
};
|
};
|
||||||
@@ -3001,7 +3002,6 @@ static inline void __mark_inode_dirty_flag(struct inode *inode,
|
|||||||
case FI_INLINE_DOTS:
|
case FI_INLINE_DOTS:
|
||||||
case FI_PIN_FILE:
|
case FI_PIN_FILE:
|
||||||
case FI_COMPRESS_RELEASED:
|
case FI_COMPRESS_RELEASED:
|
||||||
case FI_ATOMIC_COMMITTED:
|
|
||||||
f2fs_mark_inode_dirty_sync(inode, true);
|
f2fs_mark_inode_dirty_sync(inode, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
|
|||||||
if (f2fs_inode_dirtied(inode, sync))
|
if (f2fs_inode_dirtied(inode, sync))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (f2fs_is_atomic_file(inode)) {
|
||||||
|
set_inode_flag(inode, FI_ATOMIC_DIRTIED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mark_inode_dirty_sync(inode);
|
mark_inode_dirty_sync(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -199,6 +199,10 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean)
|
|||||||
clear_inode_flag(inode, FI_ATOMIC_COMMITTED);
|
clear_inode_flag(inode, FI_ATOMIC_COMMITTED);
|
||||||
clear_inode_flag(inode, FI_ATOMIC_REPLACE);
|
clear_inode_flag(inode, FI_ATOMIC_REPLACE);
|
||||||
clear_inode_flag(inode, FI_ATOMIC_FILE);
|
clear_inode_flag(inode, FI_ATOMIC_FILE);
|
||||||
|
if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) {
|
||||||
|
clear_inode_flag(inode, FI_ATOMIC_DIRTIED);
|
||||||
|
f2fs_mark_inode_dirty_sync(inode, true);
|
||||||
|
}
|
||||||
stat_dec_atomic_inode(inode);
|
stat_dec_atomic_inode(inode);
|
||||||
|
|
||||||
F2FS_I(inode)->atomic_write_task = NULL;
|
F2FS_I(inode)->atomic_write_task = NULL;
|
||||||
@@ -368,6 +372,10 @@ out:
|
|||||||
} else {
|
} else {
|
||||||
sbi->committed_atomic_block += fi->atomic_write_cnt;
|
sbi->committed_atomic_block += fi->atomic_write_cnt;
|
||||||
set_inode_flag(inode, FI_ATOMIC_COMMITTED);
|
set_inode_flag(inode, FI_ATOMIC_COMMITTED);
|
||||||
|
if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) {
|
||||||
|
clear_inode_flag(inode, FI_ATOMIC_DIRTIED);
|
||||||
|
f2fs_mark_inode_dirty_sync(inode, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__complete_revoke_list(inode, &revoke_list, ret ? true : false);
|
__complete_revoke_list(inode, &revoke_list, ret ? true : false);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <linux/sizes.h>
|
#include <linux/sizes.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/pgtable.h>
|
#include <linux/pgtable.h>
|
||||||
|
#include <linux/pgsize_migration_inline.h>
|
||||||
#include <linux/kasan.h>
|
#include <linux/kasan.h>
|
||||||
#include <linux/page_pinner.h>
|
#include <linux/page_pinner.h>
|
||||||
#include <linux/memremap.h>
|
#include <linux/memremap.h>
|
||||||
@@ -834,6 +835,8 @@ static inline void vm_flags_reset(struct vm_area_struct *vma,
|
|||||||
vm_flags_t flags)
|
vm_flags_t flags)
|
||||||
{
|
{
|
||||||
vma_assert_write_locked(vma);
|
vma_assert_write_locked(vma);
|
||||||
|
/* Preserve padding flags */
|
||||||
|
flags = vma_pad_fixup_flags(vma, flags);
|
||||||
vm_flags_init(vma, flags);
|
vm_flags_init(vma, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -841,6 +844,8 @@ static inline void vm_flags_reset_once(struct vm_area_struct *vma,
|
|||||||
vm_flags_t flags)
|
vm_flags_t flags)
|
||||||
{
|
{
|
||||||
vma_assert_write_locked(vma);
|
vma_assert_write_locked(vma);
|
||||||
|
/* Preserve padding flags */
|
||||||
|
flags = vma_pad_fixup_flags(vma, flags);
|
||||||
WRITE_ONCE(ACCESS_PRIVATE(vma, __vm_flags), flags);
|
WRITE_ONCE(ACCESS_PRIVATE(vma, __vm_flags), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,35 +13,9 @@
|
|||||||
* page size in Android.
|
* page size in Android.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/mm.h>
|
#include <linux/pgsize_migration_inline.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/sizes.h>
|
#include <linux/mm.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* vm_flags representation of VMA padding pages.
|
|
||||||
*
|
|
||||||
* This allows the kernel to identify the portion of an ELF LOAD segment VMA
|
|
||||||
* that is padding.
|
|
||||||
*
|
|
||||||
* 4 high bits of vm_flags [63,60] are used to represent ELF segment padding
|
|
||||||
* up to 60kB, which is sufficient for ELFs of both 16kB and 64kB segment
|
|
||||||
* alignment (p_align).
|
|
||||||
*
|
|
||||||
* The representation is illustrated below.
|
|
||||||
*
|
|
||||||
* 63 62 61 60
|
|
||||||
* _________ _________ _________ _________
|
|
||||||
* | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|
|
||||||
* | of 4kB | of 4kB | of 4kB | of 4kB |
|
|
||||||
* | chunks | chunks | chunks | chunks |
|
|
||||||
* |_________|_________|_________|_________|
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define VM_PAD_WIDTH 4
|
|
||||||
#define VM_PAD_SHIFT (BITS_PER_LONG - VM_PAD_WIDTH)
|
|
||||||
#define VM_TOTAL_PAD_PAGES ((1ULL << VM_PAD_WIDTH) - 1)
|
|
||||||
#define VM_PAD_MASK (VM_TOTAL_PAD_PAGES << VM_PAD_SHIFT)
|
|
||||||
#define VMA_PAD_START(vma) (vma->vm_end - (vma_pad_pages(vma) << PAGE_SHIFT))
|
|
||||||
|
|
||||||
#if PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT)
|
#if PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT)
|
||||||
extern void vma_set_pad_pages(struct vm_area_struct *vma,
|
extern void vma_set_pad_pages(struct vm_area_struct *vma,
|
||||||
@@ -63,9 +37,6 @@ extern void show_map_pad_vma(struct vm_area_struct *vma,
|
|||||||
extern void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
|
extern void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
|
||||||
unsigned long addr, int new_below);
|
unsigned long addr, int new_below);
|
||||||
|
|
||||||
extern unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
|
|
||||||
unsigned long newflags);
|
|
||||||
|
|
||||||
extern bool is_mergable_pad_vma(struct vm_area_struct *vma,
|
extern bool is_mergable_pad_vma(struct vm_area_struct *vma,
|
||||||
unsigned long vm_flags);
|
unsigned long vm_flags);
|
||||||
|
|
||||||
@@ -107,12 +78,6 @@ static inline void split_pad_vma(struct vm_area_struct *vma, struct vm_area_stru
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
|
|
||||||
unsigned long newflags)
|
|
||||||
{
|
|
||||||
return newflags;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool is_mergable_pad_vma(struct vm_area_struct *vma,
|
static inline bool is_mergable_pad_vma(struct vm_area_struct *vma,
|
||||||
unsigned long vm_flags)
|
unsigned long vm_flags)
|
||||||
{
|
{
|
||||||
|
|||||||
67
include/linux/pgsize_migration_inline.h
Normal file
67
include/linux/pgsize_migration_inline.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef _LINUX_PAGE_SIZE_MIGRATION_INLINE_H
|
||||||
|
#define _LINUX_PAGE_SIZE_MIGRATION_INLINE_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Page Size Migration
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024, Google LLC.
|
||||||
|
* Author: Kalesh Singh <kaleshsingh@goole.com>
|
||||||
|
*
|
||||||
|
* This file contains inline APIs for mitigations to ensure
|
||||||
|
* app compatibility during the transition from 4kB to 16kB
|
||||||
|
* page size in Android.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/mm_types.h>
|
||||||
|
#include <linux/sizes.h>
|
||||||
|
|
||||||
|
#include <asm/page.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vm_flags representation of VMA padding pages.
|
||||||
|
*
|
||||||
|
* This allows the kernel to identify the portion of an ELF LOAD segment VMA
|
||||||
|
* that is padding.
|
||||||
|
*
|
||||||
|
* 4 high bits of vm_flags [63,60] are used to represent ELF segment padding
|
||||||
|
* up to 60kB, which is sufficient for ELFs of both 16kB and 64kB segment
|
||||||
|
* alignment (p_align).
|
||||||
|
*
|
||||||
|
* The representation is illustrated below.
|
||||||
|
*
|
||||||
|
* 63 62 61 60
|
||||||
|
* _________ _________ _________ _________
|
||||||
|
* | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|
||||||
|
* | of 4kB | of 4kB | of 4kB | of 4kB |
|
||||||
|
* | chunks | chunks | chunks | chunks |
|
||||||
|
* |_________|_________|_________|_________|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VM_PAD_WIDTH 4
|
||||||
|
#define VM_PAD_SHIFT (BITS_PER_LONG - VM_PAD_WIDTH)
|
||||||
|
#define VM_TOTAL_PAD_PAGES ((1ULL << VM_PAD_WIDTH) - 1)
|
||||||
|
#define VM_PAD_MASK (VM_TOTAL_PAD_PAGES << VM_PAD_SHIFT)
|
||||||
|
#define VMA_PAD_START(vma) (vma->vm_end - (vma_pad_pages(vma) << PAGE_SHIFT))
|
||||||
|
|
||||||
|
#if PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT)
|
||||||
|
/*
|
||||||
|
* Sets the correct padding bits / flags for a VMA split.
|
||||||
|
*/
|
||||||
|
static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
|
||||||
|
unsigned long newflags)
|
||||||
|
{
|
||||||
|
if (newflags & VM_PAD_MASK)
|
||||||
|
return (newflags & ~VM_PAD_MASK) | (vma->vm_flags & VM_PAD_MASK);
|
||||||
|
else
|
||||||
|
return newflags;
|
||||||
|
}
|
||||||
|
#else /* PAGE_SIZE != SZ_4K || !defined(CONFIG_64BIT) */
|
||||||
|
static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
|
||||||
|
unsigned long newflags)
|
||||||
|
{
|
||||||
|
return newflags;
|
||||||
|
}
|
||||||
|
#endif /* PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT) */
|
||||||
|
|
||||||
|
#endif /* _LINUX_PAGE_SIZE_MIGRATION_INLINE_H */
|
||||||
@@ -18,6 +18,33 @@
|
|||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flags to control the behaviour when attaching a device to its PM domains.
|
||||||
|
*
|
||||||
|
* PD_FLAG_NO_DEV_LINK: As the default behaviour creates a device-link
|
||||||
|
* for every PM domain that gets attached, this
|
||||||
|
* flag can be used to skip that.
|
||||||
|
*
|
||||||
|
* PD_FLAG_DEV_LINK_ON: Add the DL_FLAG_RPM_ACTIVE to power-on the
|
||||||
|
* supplier and its PM domain when creating the
|
||||||
|
* device-links.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define PD_FLAG_NO_DEV_LINK BIT(0)
|
||||||
|
#define PD_FLAG_DEV_LINK_ON BIT(1)
|
||||||
|
|
||||||
|
struct dev_pm_domain_attach_data {
|
||||||
|
const char * const *pd_names;
|
||||||
|
const u32 num_pd_names;
|
||||||
|
const u32 pd_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dev_pm_domain_list {
|
||||||
|
struct device **pd_devs;
|
||||||
|
struct device_link **pd_links;
|
||||||
|
u32 num_pds;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags to control the behaviour of a genpd.
|
* Flags to control the behaviour of a genpd.
|
||||||
*
|
*
|
||||||
@@ -60,6 +87,10 @@
|
|||||||
* GENPD_FLAG_MIN_RESIDENCY: Enable the genpd governor to consider its
|
* GENPD_FLAG_MIN_RESIDENCY: Enable the genpd governor to consider its
|
||||||
* components' next wakeup when determining the
|
* components' next wakeup when determining the
|
||||||
* optimal idle state.
|
* optimal idle state.
|
||||||
|
*
|
||||||
|
* GENPD_FLAG_OPP_TABLE_FW: The genpd provider supports performance states,
|
||||||
|
* but its corresponding OPP tables are not
|
||||||
|
* described in DT, but are given directly by FW.
|
||||||
*/
|
*/
|
||||||
#define GENPD_FLAG_PM_CLK (1U << 0)
|
#define GENPD_FLAG_PM_CLK (1U << 0)
|
||||||
#define GENPD_FLAG_IRQ_SAFE (1U << 1)
|
#define GENPD_FLAG_IRQ_SAFE (1U << 1)
|
||||||
@@ -68,6 +99,7 @@
|
|||||||
#define GENPD_FLAG_CPU_DOMAIN (1U << 4)
|
#define GENPD_FLAG_CPU_DOMAIN (1U << 4)
|
||||||
#define GENPD_FLAG_RPM_ALWAYS_ON (1U << 5)
|
#define GENPD_FLAG_RPM_ALWAYS_ON (1U << 5)
|
||||||
#define GENPD_FLAG_MIN_RESIDENCY (1U << 6)
|
#define GENPD_FLAG_MIN_RESIDENCY (1U << 6)
|
||||||
|
#define GENPD_FLAG_OPP_TABLE_FW (1U << 7)
|
||||||
|
|
||||||
enum gpd_status {
|
enum gpd_status {
|
||||||
GENPD_STATE_ON = 0, /* PM domain is on */
|
GENPD_STATE_ON = 0, /* PM domain is on */
|
||||||
@@ -415,7 +447,11 @@ struct device *dev_pm_domain_attach_by_id(struct device *dev,
|
|||||||
unsigned int index);
|
unsigned int index);
|
||||||
struct device *dev_pm_domain_attach_by_name(struct device *dev,
|
struct device *dev_pm_domain_attach_by_name(struct device *dev,
|
||||||
const char *name);
|
const char *name);
|
||||||
|
int dev_pm_domain_attach_list(struct device *dev,
|
||||||
|
const struct dev_pm_domain_attach_data *data,
|
||||||
|
struct dev_pm_domain_list **list);
|
||||||
void dev_pm_domain_detach(struct device *dev, bool power_off);
|
void dev_pm_domain_detach(struct device *dev, bool power_off);
|
||||||
|
void dev_pm_domain_detach_list(struct dev_pm_domain_list *list);
|
||||||
int dev_pm_domain_start(struct device *dev);
|
int dev_pm_domain_start(struct device *dev);
|
||||||
void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd);
|
void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd);
|
||||||
#else
|
#else
|
||||||
@@ -433,7 +469,14 @@ static inline struct device *dev_pm_domain_attach_by_name(struct device *dev,
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
static inline int dev_pm_domain_attach_list(struct device *dev,
|
||||||
|
const struct dev_pm_domain_attach_data *data,
|
||||||
|
struct dev_pm_domain_list **list)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
|
static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
|
||||||
|
static inline void dev_pm_domain_detach_list(struct dev_pm_domain_list *list) {}
|
||||||
static inline int dev_pm_domain_start(struct device *dev)
|
static inline int dev_pm_domain_start(struct device *dev)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -92,6 +92,18 @@ struct dev_pm_opp_config {
|
|||||||
struct device ***virt_devs;
|
struct device ***virt_devs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct dev_pm_opp_data - The data to use to initialize an OPP.
|
||||||
|
* @level: The performance level for the OPP.
|
||||||
|
* @freq: The clock rate in Hz for the OPP.
|
||||||
|
* @u_volt: The voltage in uV for the OPP.
|
||||||
|
*/
|
||||||
|
struct dev_pm_opp_data {
|
||||||
|
unsigned int level;
|
||||||
|
unsigned long freq;
|
||||||
|
unsigned long u_volt;
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(CONFIG_PM_OPP)
|
#if defined(CONFIG_PM_OPP)
|
||||||
|
|
||||||
struct opp_table *dev_pm_opp_get_opp_table(struct device *dev);
|
struct opp_table *dev_pm_opp_get_opp_table(struct device *dev);
|
||||||
@@ -140,8 +152,9 @@ struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
|
|||||||
|
|
||||||
void dev_pm_opp_put(struct dev_pm_opp *opp);
|
void dev_pm_opp_put(struct dev_pm_opp *opp);
|
||||||
|
|
||||||
int dev_pm_opp_add(struct device *dev, unsigned long freq,
|
int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp);
|
||||||
unsigned long u_volt);
|
int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt);
|
||||||
|
|
||||||
void dev_pm_opp_remove(struct device *dev, unsigned long freq);
|
void dev_pm_opp_remove(struct device *dev, unsigned long freq);
|
||||||
void dev_pm_opp_remove_all_dynamic(struct device *dev);
|
void dev_pm_opp_remove_all_dynamic(struct device *dev);
|
||||||
|
|
||||||
@@ -291,8 +304,14 @@ static inline struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
|
|||||||
|
|
||||||
static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {}
|
static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {}
|
||||||
|
|
||||||
static inline int dev_pm_opp_add(struct device *dev, unsigned long freq,
|
static inline int
|
||||||
unsigned long u_volt)
|
dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,15 +100,21 @@ struct scmi_clk_proto_ops {
|
|||||||
ANDROID_KABI_RESERVE(1);
|
ANDROID_KABI_RESERVE(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct scmi_perf_domain_info {
|
||||||
|
char name[SCMI_MAX_STR_SIZE];
|
||||||
|
bool set_perf;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct scmi_perf_proto_ops - represents the various operations provided
|
* struct scmi_perf_proto_ops - represents the various operations provided
|
||||||
* by SCMI Performance Protocol
|
* by SCMI Performance Protocol
|
||||||
*
|
*
|
||||||
|
* @num_domains_get: gets the number of supported performance domains
|
||||||
|
* @info_get: get the information of a performance domain
|
||||||
* @limits_set: sets limits on the performance level of a domain
|
* @limits_set: sets limits on the performance level of a domain
|
||||||
* @limits_get: gets limits on the performance level of a domain
|
* @limits_get: gets limits on the performance level of a domain
|
||||||
* @level_set: sets the performance level of a domain
|
* @level_set: sets the performance level of a domain
|
||||||
* @level_get: gets the performance level of a domain
|
* @level_get: gets the performance level of a domain
|
||||||
* @device_domain_id: gets the scmi domain id for a given device
|
|
||||||
* @transition_latency_get: gets the DVFS transition latency for a given device
|
* @transition_latency_get: gets the DVFS transition latency for a given device
|
||||||
* @device_opps_add: adds all the OPPs for a given device
|
* @device_opps_add: adds all the OPPs for a given device
|
||||||
* @freq_set: sets the frequency for a given device using sustained frequency
|
* @freq_set: sets the frequency for a given device using sustained frequency
|
||||||
@@ -123,6 +129,9 @@ struct scmi_clk_proto_ops {
|
|||||||
* or in some other (abstract) scale
|
* or in some other (abstract) scale
|
||||||
*/
|
*/
|
||||||
struct scmi_perf_proto_ops {
|
struct scmi_perf_proto_ops {
|
||||||
|
int (*num_domains_get)(const struct scmi_protocol_handle *ph);
|
||||||
|
const struct scmi_perf_domain_info __must_check *(*info_get)
|
||||||
|
(const struct scmi_protocol_handle *ph, u32 domain);
|
||||||
int (*limits_set)(const struct scmi_protocol_handle *ph, u32 domain,
|
int (*limits_set)(const struct scmi_protocol_handle *ph, u32 domain,
|
||||||
u32 max_perf, u32 min_perf);
|
u32 max_perf, u32 min_perf);
|
||||||
int (*limits_get)(const struct scmi_protocol_handle *ph, u32 domain,
|
int (*limits_get)(const struct scmi_protocol_handle *ph, u32 domain,
|
||||||
@@ -131,11 +140,10 @@ struct scmi_perf_proto_ops {
|
|||||||
u32 level, bool poll);
|
u32 level, bool poll);
|
||||||
int (*level_get)(const struct scmi_protocol_handle *ph, u32 domain,
|
int (*level_get)(const struct scmi_protocol_handle *ph, u32 domain,
|
||||||
u32 *level, bool poll);
|
u32 *level, bool poll);
|
||||||
int (*device_domain_id)(struct device *dev);
|
|
||||||
int (*transition_latency_get)(const struct scmi_protocol_handle *ph,
|
int (*transition_latency_get)(const struct scmi_protocol_handle *ph,
|
||||||
struct device *dev);
|
u32 domain);
|
||||||
int (*device_opps_add)(const struct scmi_protocol_handle *ph,
|
int (*device_opps_add)(const struct scmi_protocol_handle *ph,
|
||||||
struct device *dev);
|
struct device *dev, u32 domain);
|
||||||
int (*freq_set)(const struct scmi_protocol_handle *ph, u32 domain,
|
int (*freq_set)(const struct scmi_protocol_handle *ph, u32 domain,
|
||||||
unsigned long rate, bool poll);
|
unsigned long rate, bool poll);
|
||||||
int (*freq_get)(const struct scmi_protocol_handle *ph, u32 domain,
|
int (*freq_get)(const struct scmi_protocol_handle *ph, u32 domain,
|
||||||
@@ -143,7 +151,7 @@ struct scmi_perf_proto_ops {
|
|||||||
int (*est_power_get)(const struct scmi_protocol_handle *ph, u32 domain,
|
int (*est_power_get)(const struct scmi_protocol_handle *ph, u32 domain,
|
||||||
unsigned long *rate, unsigned long *power);
|
unsigned long *rate, unsigned long *power);
|
||||||
bool (*fast_switch_possible)(const struct scmi_protocol_handle *ph,
|
bool (*fast_switch_possible)(const struct scmi_protocol_handle *ph,
|
||||||
struct device *dev);
|
u32 domain);
|
||||||
enum scmi_power_scale (*power_scale_get)(const struct scmi_protocol_handle *ph);
|
enum scmi_power_scale (*power_scale_get)(const struct scmi_protocol_handle *ph);
|
||||||
|
|
||||||
ANDROID_KABI_RESERVE(1);
|
ANDROID_KABI_RESERVE(1);
|
||||||
|
|||||||
@@ -145,6 +145,9 @@ DECLARE_HOOK(android_vh_mm_compaction_begin,
|
|||||||
DECLARE_HOOK(android_vh_mm_compaction_end,
|
DECLARE_HOOK(android_vh_mm_compaction_end,
|
||||||
TP_PROTO(struct compact_control *cc, long vendor_ret),
|
TP_PROTO(struct compact_control *cc, long vendor_ret),
|
||||||
TP_ARGS(cc, vendor_ret));
|
TP_ARGS(cc, vendor_ret));
|
||||||
|
DECLARE_HOOK(android_vh_mm_kcompactd_cpu_online,
|
||||||
|
TP_PROTO(int cpu),
|
||||||
|
TP_ARGS(cpu));
|
||||||
DECLARE_HOOK(android_vh_free_unref_page_bypass,
|
DECLARE_HOOK(android_vh_free_unref_page_bypass,
|
||||||
TP_PROTO(struct page *page, int order, int migratetype, bool *bypass),
|
TP_PROTO(struct page *page, int order, int migratetype, bool *bypass),
|
||||||
TP_ARGS(page, order, migratetype, bypass));
|
TP_ARGS(page, order, migratetype, bypass));
|
||||||
@@ -208,6 +211,9 @@ DECLARE_HOOK(android_vh_look_around,
|
|||||||
DECLARE_HOOK(android_vh_mm_alloc_pages_direct_reclaim_enter,
|
DECLARE_HOOK(android_vh_mm_alloc_pages_direct_reclaim_enter,
|
||||||
TP_PROTO(unsigned int order),
|
TP_PROTO(unsigned int order),
|
||||||
TP_ARGS(order));
|
TP_ARGS(order));
|
||||||
|
DECLARE_HOOK(android_vh_should_fault_around,
|
||||||
|
TP_PROTO(struct vm_fault *vmf, bool *should_around),
|
||||||
|
TP_ARGS(vmf, should_around));
|
||||||
DECLARE_HOOK(android_vh_mm_alloc_pages_direct_reclaim_exit,
|
DECLARE_HOOK(android_vh_mm_alloc_pages_direct_reclaim_exit,
|
||||||
TP_PROTO(unsigned long did_some_progress, int retry_times),
|
TP_PROTO(unsigned long did_some_progress, int retry_times),
|
||||||
TP_ARGS(did_some_progress, retry_times));
|
TP_ARGS(did_some_progress, retry_times));
|
||||||
@@ -246,6 +252,36 @@ DECLARE_HOOK(android_vh_shmem_swapin_folio,
|
|||||||
DECLARE_HOOK(android_vh_madvise_cold_or_pageout_page,
|
DECLARE_HOOK(android_vh_madvise_cold_or_pageout_page,
|
||||||
TP_PROTO(bool pageout, struct page *page),
|
TP_PROTO(bool pageout, struct page *page),
|
||||||
TP_ARGS(pageout, page));
|
TP_ARGS(pageout, page));
|
||||||
|
DECLARE_HOOK(android_vh_page_should_be_protected,
|
||||||
|
TP_PROTO(struct folio *folio, unsigned long nr_scanned,
|
||||||
|
s8 priority, u64 *ext, int *should_protect),
|
||||||
|
TP_ARGS(folio, nr_scanned, priority, ext, should_protect));
|
||||||
|
|
||||||
|
DECLARE_HOOK(android_vh_swapmem_gather_init,
|
||||||
|
TP_PROTO(struct mm_struct *mm),
|
||||||
|
TP_ARGS(mm));
|
||||||
|
DECLARE_HOOK(android_vh_swapmem_gather_add_bypass,
|
||||||
|
TP_PROTO(struct mm_struct *mm, swp_entry_t entry, bool *bypass),
|
||||||
|
TP_ARGS(mm, entry, bypass));
|
||||||
|
DECLARE_HOOK(android_vh_swapmem_gather_finish,
|
||||||
|
TP_PROTO(struct mm_struct *mm),
|
||||||
|
TP_ARGS(mm));
|
||||||
|
DECLARE_HOOK(android_vh_oom_swapmem_gather_init,
|
||||||
|
TP_PROTO(struct mm_struct *mm),
|
||||||
|
TP_ARGS(mm));
|
||||||
|
DECLARE_HOOK(android_vh_oom_swapmem_gather_finish,
|
||||||
|
TP_PROTO(struct mm_struct *mm),
|
||||||
|
TP_ARGS(mm));
|
||||||
|
DECLARE_HOOK(android_vh_do_read_fault,
|
||||||
|
TP_PROTO(struct vm_fault *vmf, unsigned long fault_around_bytes),
|
||||||
|
TP_ARGS(vmf, fault_around_bytes));
|
||||||
|
DECLARE_HOOK(android_vh_filemap_read,
|
||||||
|
TP_PROTO(struct file *file, loff_t pos, size_t size),
|
||||||
|
TP_ARGS(file, pos, size));
|
||||||
|
DECLARE_HOOK(android_vh_filemap_map_pages,
|
||||||
|
TP_PROTO(struct file *file, pgoff_t first_pgoff,
|
||||||
|
pgoff_t last_pgoff, vm_fault_t ret),
|
||||||
|
TP_ARGS(file, first_pgoff, last_pgoff, ret));
|
||||||
#endif /* _TRACE_HOOK_MM_H */
|
#endif /* _TRACE_HOOK_MM_H */
|
||||||
|
|
||||||
/* This part must be outside protection */
|
/* This part must be outside protection */
|
||||||
|
|||||||
@@ -458,6 +458,10 @@ DECLARE_HOOK(android_vh_prio_restore,
|
|||||||
TP_PROTO(int saved_prio),
|
TP_PROTO(int saved_prio),
|
||||||
TP_ARGS(saved_prio));
|
TP_ARGS(saved_prio));
|
||||||
|
|
||||||
|
DECLARE_HOOK(android_vh_set_task_comm,
|
||||||
|
TP_PROTO(struct task_struct *p),
|
||||||
|
TP_ARGS(p));
|
||||||
|
|
||||||
#endif /* _TRACE_HOOK_SCHED_H */
|
#endif /* _TRACE_HOOK_SCHED_H */
|
||||||
/* This part must be outside protection */
|
/* This part must be outside protection */
|
||||||
#include <trace/define_trace.h>
|
#include <trace/define_trace.h>
|
||||||
|
|||||||
@@ -69,6 +69,9 @@ DECLARE_HOOK(android_vh_do_folio_trylock,
|
|||||||
TP_PROTO(struct folio *folio, struct rw_semaphore *sem,
|
TP_PROTO(struct folio *folio, struct rw_semaphore *sem,
|
||||||
bool *got_lock, bool *skip),
|
bool *got_lock, bool *skip),
|
||||||
TP_ARGS(folio, sem, got_lock, skip));
|
TP_ARGS(folio, sem, got_lock, skip));
|
||||||
|
DECLARE_HOOK(android_vh_page_referenced_check_bypass,
|
||||||
|
TP_PROTO(struct folio *folio, unsigned long nr_to_scan, int lru, bool *bypass),
|
||||||
|
TP_ARGS(folio, nr_to_scan, lru, bypass));
|
||||||
#endif /* _TRACE_HOOK_VMSCAN_H */
|
#endif /* _TRACE_HOOK_VMSCAN_H */
|
||||||
/* This part must be outside protection */
|
/* This part must be outside protection */
|
||||||
#include <trace/define_trace.h>
|
#include <trace/define_trace.h>
|
||||||
|
|||||||
@@ -284,6 +284,12 @@ struct binder_frozen_status_info {
|
|||||||
__u32 async_recv;
|
__u32 async_recv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct binder_frozen_state_info {
|
||||||
|
binder_uintptr_t cookie;
|
||||||
|
__u32 is_frozen;
|
||||||
|
__u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
/* struct binder_extened_error - extended error information
|
/* struct binder_extened_error - extended error information
|
||||||
* @id: identifier for the failed operation
|
* @id: identifier for the failed operation
|
||||||
* @command: command as defined by binder_driver_return_protocol
|
* @command: command as defined by binder_driver_return_protocol
|
||||||
@@ -508,6 +514,17 @@ enum binder_driver_return_protocol {
|
|||||||
* asynchronous transaction makes the allocated async buffer size exceed
|
* asynchronous transaction makes the allocated async buffer size exceed
|
||||||
* detection threshold. No parameters.
|
* detection threshold. No parameters.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
BR_FROZEN_BINDER = _IOR('r', 21, struct binder_frozen_state_info),
|
||||||
|
/*
|
||||||
|
* The cookie and a boolean (is_frozen) that indicates whether the process
|
||||||
|
* transitioned into a frozen or an unfrozen state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
BR_CLEAR_FREEZE_NOTIFICATION_DONE = _IOR('r', 22, binder_uintptr_t),
|
||||||
|
/*
|
||||||
|
* void *: cookie
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
enum binder_driver_command_protocol {
|
enum binder_driver_command_protocol {
|
||||||
@@ -591,6 +608,25 @@ enum binder_driver_command_protocol {
|
|||||||
/*
|
/*
|
||||||
* binder_transaction_data_sg: the sent command.
|
* binder_transaction_data_sg: the sent command.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
BC_REQUEST_FREEZE_NOTIFICATION =
|
||||||
|
_IOW('c', 19, struct binder_handle_cookie),
|
||||||
|
/*
|
||||||
|
* int: handle
|
||||||
|
* void *: cookie
|
||||||
|
*/
|
||||||
|
|
||||||
|
BC_CLEAR_FREEZE_NOTIFICATION = _IOW('c', 20,
|
||||||
|
struct binder_handle_cookie),
|
||||||
|
/*
|
||||||
|
* int: handle
|
||||||
|
* void *: cookie
|
||||||
|
*/
|
||||||
|
|
||||||
|
BC_FREEZE_NOTIFICATION_DONE = _IOW('c', 21, binder_uintptr_t),
|
||||||
|
/*
|
||||||
|
* void *: cookie
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _UAPI_LINUX_BINDER_H */
|
#endif /* _UAPI_LINUX_BINDER_H */
|
||||||
|
|||||||
@@ -144,6 +144,9 @@
|
|||||||
/* Blackfin bf5xx */
|
/* Blackfin bf5xx */
|
||||||
#define PORT_BFIN 75
|
#define PORT_BFIN 75
|
||||||
|
|
||||||
|
/* Broadcom BCM7271 UART */
|
||||||
|
#define PORT_BCM7271 76
|
||||||
|
|
||||||
/* Broadcom SB1250, etc. SOC */
|
/* Broadcom SB1250, etc. SOC */
|
||||||
#define PORT_SB1250_DUART 77
|
#define PORT_SB1250_DUART 77
|
||||||
|
|
||||||
|
|||||||
@@ -13328,7 +13328,8 @@ static int inherit_group(struct perf_event *parent_event,
|
|||||||
!perf_get_aux_event(child_ctr, leader))
|
!perf_get_aux_event(child_ctr, leader))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
leader->group_generation = parent_event->group_generation;
|
if (leader)
|
||||||
|
leader->group_generation = parent_event->group_generation;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -721,7 +721,6 @@ static void update_rq_clock_task(struct rq *rq, s64 delta)
|
|||||||
|
|
||||||
rq->prev_irq_time += irq_delta;
|
rq->prev_irq_time += irq_delta;
|
||||||
delta -= irq_delta;
|
delta -= irq_delta;
|
||||||
psi_account_irqtime(rq->curr, irq_delta);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
|
#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
|
||||||
if (static_key_false((¶virt_steal_rq_enabled))) {
|
if (static_key_false((¶virt_steal_rq_enabled))) {
|
||||||
@@ -5679,7 +5678,7 @@ void scheduler_tick(void)
|
|||||||
{
|
{
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
struct rq *rq = cpu_rq(cpu);
|
struct rq *rq = cpu_rq(cpu);
|
||||||
struct task_struct *curr = rq->curr;
|
struct task_struct *curr;
|
||||||
struct rq_flags rf;
|
struct rq_flags rf;
|
||||||
unsigned long thermal_pressure;
|
unsigned long thermal_pressure;
|
||||||
u64 resched_latency;
|
u64 resched_latency;
|
||||||
@@ -5691,6 +5690,9 @@ void scheduler_tick(void)
|
|||||||
|
|
||||||
rq_lock(rq, &rf);
|
rq_lock(rq, &rf);
|
||||||
|
|
||||||
|
curr = rq->curr;
|
||||||
|
psi_account_irqtime(rq, curr, NULL);
|
||||||
|
|
||||||
update_rq_clock(rq);
|
update_rq_clock(rq);
|
||||||
trace_android_rvh_tick_entry(rq);
|
trace_android_rvh_tick_entry(rq);
|
||||||
|
|
||||||
@@ -6736,6 +6738,7 @@ static void __sched notrace __schedule(unsigned int sched_mode)
|
|||||||
++*switch_count;
|
++*switch_count;
|
||||||
|
|
||||||
migrate_disable_switch(rq, prev);
|
migrate_disable_switch(rq, prev);
|
||||||
|
psi_account_irqtime(rq, prev, next);
|
||||||
psi_sched_switch(prev, next, !task_on_rq_queued(prev));
|
psi_sched_switch(prev, next, !task_on_rq_queued(prev));
|
||||||
|
|
||||||
trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev, next, prev_state);
|
trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev, next, prev_state);
|
||||||
|
|||||||
@@ -737,6 +737,7 @@ static void psi_group_change(struct psi_group *group, int cpu,
|
|||||||
enum psi_states s;
|
enum psi_states s;
|
||||||
u32 state_mask;
|
u32 state_mask;
|
||||||
|
|
||||||
|
lockdep_assert_rq_held(cpu_rq(cpu));
|
||||||
groupc = per_cpu_ptr(group->pcpu, cpu);
|
groupc = per_cpu_ptr(group->pcpu, cpu);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -955,19 +956,31 @@ void psi_task_switch(struct task_struct *prev, struct task_struct *next,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
|
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
|
||||||
void psi_account_irqtime(struct task_struct *task, u32 delta)
|
static DEFINE_PER_CPU(u64, psi_irq_time);
|
||||||
|
void psi_account_irqtime(struct rq *rq, struct task_struct *curr, struct task_struct *prev)
|
||||||
{
|
{
|
||||||
int cpu = task_cpu(task);
|
int cpu = task_cpu(curr);
|
||||||
struct psi_group *group;
|
struct psi_group *group;
|
||||||
struct psi_group_cpu *groupc;
|
struct psi_group_cpu *groupc;
|
||||||
u64 now;
|
u64 now, irq, *psi_time;
|
||||||
|
s64 delta;
|
||||||
|
|
||||||
if (!task->pid)
|
if (!curr->pid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lockdep_assert_rq_held(rq);
|
||||||
|
group = task_psi_group(curr);
|
||||||
|
if (prev && task_psi_group(prev) == group)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
now = cpu_clock(cpu);
|
now = cpu_clock(cpu);
|
||||||
|
irq = irq_time_read(cpu);
|
||||||
|
psi_time = &per_cpu(psi_irq_time, cpu);
|
||||||
|
delta = (s64)(irq - *psi_time);
|
||||||
|
if (delta < 0)
|
||||||
|
return;
|
||||||
|
*psi_time = irq;
|
||||||
|
|
||||||
group = task_psi_group(task);
|
|
||||||
do {
|
do {
|
||||||
if (!group->enabled)
|
if (!group->enabled)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -110,8 +110,12 @@ __schedstats_from_se(struct sched_entity *se)
|
|||||||
void psi_task_change(struct task_struct *task, int clear, int set);
|
void psi_task_change(struct task_struct *task, int clear, int set);
|
||||||
void psi_task_switch(struct task_struct *prev, struct task_struct *next,
|
void psi_task_switch(struct task_struct *prev, struct task_struct *next,
|
||||||
bool sleep);
|
bool sleep);
|
||||||
void psi_account_irqtime(struct task_struct *task, u32 delta);
|
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
|
||||||
|
void psi_account_irqtime(struct rq *rq, struct task_struct *curr, struct task_struct *prev);
|
||||||
|
#else
|
||||||
|
static inline void psi_account_irqtime(struct rq *rq, struct task_struct *curr,
|
||||||
|
struct task_struct *prev) {}
|
||||||
|
#endif /*CONFIG_IRQ_TIME_ACCOUNTING */
|
||||||
/*
|
/*
|
||||||
* PSI tracks state that persists across sleeps, such as iowaits and
|
* PSI tracks state that persists across sleeps, such as iowaits and
|
||||||
* memory stalls. As a result, it has to distinguish between sleeps,
|
* memory stalls. As a result, it has to distinguish between sleeps,
|
||||||
@@ -206,7 +210,8 @@ static inline void psi_ttwu_dequeue(struct task_struct *p) {}
|
|||||||
static inline void psi_sched_switch(struct task_struct *prev,
|
static inline void psi_sched_switch(struct task_struct *prev,
|
||||||
struct task_struct *next,
|
struct task_struct *next,
|
||||||
bool sleep) {}
|
bool sleep) {}
|
||||||
static inline void psi_account_irqtime(struct task_struct *task, u32 delta) {}
|
static inline void psi_account_irqtime(struct rq *rq, struct task_struct *curr,
|
||||||
|
struct task_struct *prev) {}
|
||||||
#endif /* CONFIG_PSI */
|
#endif /* CONFIG_PSI */
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_INFO
|
#ifdef CONFIG_SCHED_INFO
|
||||||
|
|||||||
@@ -115,3 +115,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_update_blocked_fair);
|
|||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_update_rt_rq_load_avg);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_update_rt_rq_load_avg);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_prio_inheritance);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_prio_inheritance);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_prio_restore);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_prio_restore);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_task_comm);
|
||||||
|
|||||||
@@ -44,3 +44,4 @@ void __show_mem(unsigned int filter, nodemask_t *nodemask, int max_zone_idx)
|
|||||||
#endif
|
#endif
|
||||||
trace_android_vh_show_mem(filter, nodemask);
|
trace_android_vh_show_mem(filter, nodemask);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(__show_mem);
|
||||||
|
|||||||
@@ -3070,6 +3070,7 @@ static int kcompactd_cpu_online(unsigned int cpu)
|
|||||||
if (pgdat->kcompactd)
|
if (pgdat->kcompactd)
|
||||||
set_cpus_allowed_ptr(pgdat->kcompactd, mask);
|
set_cpus_allowed_ptr(pgdat->kcompactd, mask);
|
||||||
}
|
}
|
||||||
|
trace_android_vh_mm_kcompactd_cpu_online(cpu);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2736,6 +2736,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter,
|
|||||||
|
|
||||||
iov_iter_truncate(iter, inode->i_sb->s_maxbytes);
|
iov_iter_truncate(iter, inode->i_sb->s_maxbytes);
|
||||||
folio_batch_init(&fbatch);
|
folio_batch_init(&fbatch);
|
||||||
|
trace_android_vh_filemap_read(filp, iocb->ki_pos, iov_iter_count(iter));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
cond_resched();
|
cond_resched();
|
||||||
@@ -3438,11 +3439,13 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
|
|||||||
struct page *page;
|
struct page *page;
|
||||||
unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss);
|
unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss);
|
||||||
vm_fault_t ret = 0;
|
vm_fault_t ret = 0;
|
||||||
|
pgoff_t first_pgoff = 0;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
folio = first_map_page(mapping, &xas, end_pgoff);
|
folio = first_map_page(mapping, &xas, end_pgoff);
|
||||||
if (!folio)
|
if (!folio)
|
||||||
goto out;
|
goto out;
|
||||||
|
first_pgoff = xas.xa_index;
|
||||||
|
|
||||||
if (filemap_map_pmd(vmf, &folio->page)) {
|
if (filemap_map_pmd(vmf, &folio->page)) {
|
||||||
ret = VM_FAULT_NOPAGE;
|
ret = VM_FAULT_NOPAGE;
|
||||||
@@ -3498,6 +3501,8 @@ unlock:
|
|||||||
out:
|
out:
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
WRITE_ONCE(file->f_ra.mmap_miss, mmap_miss);
|
WRITE_ONCE(file->f_ra.mmap_miss, mmap_miss);
|
||||||
|
trace_android_vh_filemap_map_pages(file, first_pgoff, last_pgoff, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(filemap_map_pages);
|
EXPORT_SYMBOL(filemap_map_pages);
|
||||||
|
|||||||
13
mm/memory.c
13
mm/memory.c
@@ -81,6 +81,7 @@
|
|||||||
#include <linux/set_memory.h>
|
#include <linux/set_memory.h>
|
||||||
|
|
||||||
#include <trace/events/kmem.h>
|
#include <trace/events/kmem.h>
|
||||||
|
#include <trace/hooks/mm.h>
|
||||||
|
|
||||||
#undef CREATE_TRACE_POINTS
|
#undef CREATE_TRACE_POINTS
|
||||||
#include <trace/hooks/mm.h>
|
#include <trace/hooks/mm.h>
|
||||||
@@ -1426,6 +1427,7 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
|
|||||||
pte_t *start_pte;
|
pte_t *start_pte;
|
||||||
pte_t *pte;
|
pte_t *pte;
|
||||||
swp_entry_t entry;
|
swp_entry_t entry;
|
||||||
|
bool bypass = false;
|
||||||
|
|
||||||
tlb_change_page_size(tlb, PAGE_SIZE);
|
tlb_change_page_size(tlb, PAGE_SIZE);
|
||||||
again:
|
again:
|
||||||
@@ -1498,6 +1500,9 @@ again:
|
|||||||
if (!should_zap_cows(details))
|
if (!should_zap_cows(details))
|
||||||
continue;
|
continue;
|
||||||
rss[MM_SWAPENTS]--;
|
rss[MM_SWAPENTS]--;
|
||||||
|
trace_android_vh_swapmem_gather_add_bypass(mm, entry, &bypass);
|
||||||
|
if (bypass)
|
||||||
|
goto skip;
|
||||||
if (unlikely(!free_swap_and_cache(entry)))
|
if (unlikely(!free_swap_and_cache(entry)))
|
||||||
print_bad_pte(vma, addr, ptent, NULL);
|
print_bad_pte(vma, addr, ptent, NULL);
|
||||||
} else if (is_migration_entry(entry)) {
|
} else if (is_migration_entry(entry)) {
|
||||||
@@ -1517,6 +1522,7 @@ again:
|
|||||||
/* We should have covered all the swap entry types */
|
/* We should have covered all the swap entry types */
|
||||||
WARN_ON_ONCE(1);
|
WARN_ON_ONCE(1);
|
||||||
}
|
}
|
||||||
|
skip:
|
||||||
pte_clear_not_present_full(mm, addr, pte, tlb->fullmm);
|
pte_clear_not_present_full(mm, addr, pte, tlb->fullmm);
|
||||||
zap_install_uffd_wp_if_needed(vma, addr, pte, details, ptent);
|
zap_install_uffd_wp_if_needed(vma, addr, pte, details, ptent);
|
||||||
} while (pte++, addr += PAGE_SIZE, addr != end);
|
} while (pte++, addr += PAGE_SIZE, addr != end);
|
||||||
@@ -4658,6 +4664,7 @@ static vm_fault_t do_fault_around(struct vm_fault *vmf)
|
|||||||
/* Return true if we should do read fault-around, false otherwise */
|
/* Return true if we should do read fault-around, false otherwise */
|
||||||
static inline bool should_fault_around(struct vm_fault *vmf)
|
static inline bool should_fault_around(struct vm_fault *vmf)
|
||||||
{
|
{
|
||||||
|
bool should_around = true;
|
||||||
/* No ->map_pages? No way to fault around... */
|
/* No ->map_pages? No way to fault around... */
|
||||||
if (!vmf->vma->vm_ops->map_pages)
|
if (!vmf->vma->vm_ops->map_pages)
|
||||||
return false;
|
return false;
|
||||||
@@ -4665,6 +4672,10 @@ static inline bool should_fault_around(struct vm_fault *vmf)
|
|||||||
if (uffd_disable_fault_around(vmf->vma))
|
if (uffd_disable_fault_around(vmf->vma))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
trace_android_vh_should_fault_around(vmf, &should_around);
|
||||||
|
if (!should_around)
|
||||||
|
return false;
|
||||||
|
|
||||||
return fault_around_bytes >> PAGE_SHIFT > 1;
|
return fault_around_bytes >> PAGE_SHIFT > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4685,6 +4696,8 @@ static vm_fault_t do_read_fault(struct vm_fault *vmf)
|
|||||||
ret = do_fault_around(vmf);
|
ret = do_fault_around(vmf);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
} else {
|
||||||
|
trace_android_vh_do_read_fault(vmf, fault_around_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = vmf_can_call_fault(vmf);
|
ret = vmf_can_call_fault(vmf);
|
||||||
|
|||||||
@@ -459,7 +459,7 @@ success:
|
|||||||
if ((newflags & VM_LOCKED) && (oldflags & VM_LOCKED)) {
|
if ((newflags & VM_LOCKED) && (oldflags & VM_LOCKED)) {
|
||||||
/* No work to do, and mlocking twice would be wrong */
|
/* No work to do, and mlocking twice would be wrong */
|
||||||
vma_start_write(vma);
|
vma_start_write(vma);
|
||||||
vm_flags_reset(vma, vma_pad_fixup_flags(vma, newflags));
|
vm_flags_reset(vma, newflags);
|
||||||
} else {
|
} else {
|
||||||
mlock_vma_pages_range(vma, start, end, newflags);
|
mlock_vma_pages_range(vma, start, end, newflags);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3329,9 +3329,11 @@ void exit_mmap(struct mm_struct *mm)
|
|||||||
lru_add_drain();
|
lru_add_drain();
|
||||||
flush_cache_mm(mm);
|
flush_cache_mm(mm);
|
||||||
tlb_gather_mmu_fullmm(&tlb, mm);
|
tlb_gather_mmu_fullmm(&tlb, mm);
|
||||||
|
trace_android_vh_swapmem_gather_init(mm);
|
||||||
/* update_hiwater_rss(mm) here? but nobody should be looking */
|
/* update_hiwater_rss(mm) here? but nobody should be looking */
|
||||||
/* Use ULONG_MAX here to ensure all VMAs in the mm are unmapped */
|
/* Use ULONG_MAX here to ensure all VMAs in the mm are unmapped */
|
||||||
unmap_vmas(&tlb, &mm->mm_mt, vma, 0, ULONG_MAX, vma->vm_end, ULONG_MAX, false);
|
unmap_vmas(&tlb, &mm->mm_mt, vma, 0, ULONG_MAX, vma->vm_end, ULONG_MAX, false);
|
||||||
|
trace_android_vh_swapmem_gather_finish(mm);
|
||||||
mmap_read_unlock(mm);
|
mmap_read_unlock(mm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -633,7 +633,7 @@ success:
|
|||||||
* held in write mode.
|
* held in write mode.
|
||||||
*/
|
*/
|
||||||
vma_start_write(vma);
|
vma_start_write(vma);
|
||||||
vm_flags_reset(vma, vma_pad_fixup_flags(vma, newflags));
|
vm_flags_reset(vma, newflags);
|
||||||
/*
|
/*
|
||||||
* We want to check manually if we can change individual PTEs writable
|
* We want to check manually if we can change individual PTEs writable
|
||||||
* if we can't do that automatically for all PTEs in a mapping. For
|
* if we can't do that automatically for all PTEs in a mapping. For
|
||||||
|
|||||||
@@ -53,6 +53,9 @@
|
|||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include <trace/events/oom.h>
|
#include <trace/events/oom.h>
|
||||||
|
|
||||||
|
#undef CREATE_TRACE_POINTS
|
||||||
|
#include <trace/hooks/mm.h>
|
||||||
|
|
||||||
static int sysctl_panic_on_oom;
|
static int sysctl_panic_on_oom;
|
||||||
static int sysctl_oom_kill_allocating_task;
|
static int sysctl_oom_kill_allocating_task;
|
||||||
static int sysctl_oom_dump_tasks = 1;
|
static int sysctl_oom_dump_tasks = 1;
|
||||||
@@ -525,6 +528,7 @@ bool __oom_reap_task_mm(struct mm_struct *mm)
|
|||||||
*/
|
*/
|
||||||
set_bit(MMF_UNSTABLE, &mm->flags);
|
set_bit(MMF_UNSTABLE, &mm->flags);
|
||||||
|
|
||||||
|
trace_android_vh_oom_swapmem_gather_init(mm);
|
||||||
for_each_vma(vmi, vma) {
|
for_each_vma(vmi, vma) {
|
||||||
if (vma->vm_flags & (VM_HUGETLB|VM_PFNMAP))
|
if (vma->vm_flags & (VM_HUGETLB|VM_PFNMAP))
|
||||||
continue;
|
continue;
|
||||||
@@ -557,6 +561,7 @@ bool __oom_reap_task_mm(struct mm_struct *mm)
|
|||||||
tlb_finish_mmu(&tlb);
|
tlb_finish_mmu(&tlb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
trace_android_vh_oom_swapmem_gather_finish(mm);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ unsigned long vma_pad_pages(struct vm_area_struct *vma)
|
|||||||
if (!is_pgsize_migration_enabled())
|
if (!is_pgsize_migration_enabled())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return vma->vm_flags >> VM_PAD_SHIFT;
|
return (vma->vm_flags & VM_PAD_MASK) >> VM_PAD_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __always_inline bool str_has_suffix(const char *str, const char *suffix)
|
static __always_inline bool str_has_suffix(const char *str, const char *suffix)
|
||||||
@@ -413,8 +413,8 @@ void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
|
|||||||
|
|
||||||
nr_vma2_pages = vma_pages(second);
|
nr_vma2_pages = vma_pages(second);
|
||||||
|
|
||||||
if (nr_vma2_pages >= nr_pad_pages) { /* Case 1 & 3*/
|
if (nr_vma2_pages >= nr_pad_pages) { /* Case 1 & 3 */
|
||||||
vm_flags_clear(first, VM_PAD_MASK);
|
vma_set_pad_pages(first, 0);
|
||||||
vma_set_pad_pages(second, nr_pad_pages);
|
vma_set_pad_pages(second, nr_pad_pages);
|
||||||
} else { /* Case 2 */
|
} else { /* Case 2 */
|
||||||
vma_set_pad_pages(first, nr_pad_pages - nr_vma2_pages);
|
vma_set_pad_pages(first, nr_pad_pages - nr_vma2_pages);
|
||||||
@@ -422,18 +422,6 @@ void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Sets the correct padding bits / flags for a VMA split.
|
|
||||||
*/
|
|
||||||
unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
|
|
||||||
unsigned long newflags)
|
|
||||||
{
|
|
||||||
if (newflags & VM_PAD_MASK)
|
|
||||||
return (newflags & ~VM_PAD_MASK) | (vma->vm_flags & VM_PAD_MASK);
|
|
||||||
else
|
|
||||||
return newflags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Merging of padding VMAs is uncommon, as padding is only allowed
|
* Merging of padding VMAs is uncommon, as padding is only allowed
|
||||||
* from the linker context.
|
* from the linker context.
|
||||||
|
|||||||
24
mm/vmscan.c
24
mm/vmscan.c
@@ -994,7 +994,7 @@ static unsigned long shrink_slab_memcg(gfp_t gfp_mask, int nid,
|
|||||||
*
|
*
|
||||||
* Returns the number of reclaimed slab objects.
|
* Returns the number of reclaimed slab objects.
|
||||||
*/
|
*/
|
||||||
static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
|
unsigned long shrink_slab(gfp_t gfp_mask, int nid,
|
||||||
struct mem_cgroup *memcg,
|
struct mem_cgroup *memcg,
|
||||||
int priority)
|
int priority)
|
||||||
{
|
{
|
||||||
@@ -1047,6 +1047,8 @@ out:
|
|||||||
return freed;
|
return freed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL_GPL(shrink_slab);
|
||||||
|
|
||||||
static void drop_slab_node(int nid)
|
static void drop_slab_node(int nid)
|
||||||
{
|
{
|
||||||
unsigned long freed;
|
unsigned long freed;
|
||||||
@@ -1478,6 +1480,10 @@ static enum folio_references folio_check_references(struct folio *folio,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
bool trylock_failed = false;
|
bool trylock_failed = false;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ANDROID_VENDOR_OEM_DATA
|
||||||
|
trace_android_vh_page_should_be_protected(folio, sc->nr_scanned,
|
||||||
|
sc->priority, &sc->android_vendor_data1, &ret);
|
||||||
|
#endif
|
||||||
trace_android_vh_check_folio_look_around_ref(folio, &ret);
|
trace_android_vh_check_folio_look_around_ref(folio, &ret);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2647,6 +2653,8 @@ static void shrink_active_list(unsigned long nr_to_scan,
|
|||||||
unsigned nr_rotated = 0;
|
unsigned nr_rotated = 0;
|
||||||
int file = is_file_lru(lru);
|
int file = is_file_lru(lru);
|
||||||
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
|
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
|
||||||
|
int should_protect = 0;
|
||||||
|
bool bypass = false;
|
||||||
|
|
||||||
lru_add_drain();
|
lru_add_drain();
|
||||||
|
|
||||||
@@ -2683,6 +2691,19 @@ static void shrink_active_list(unsigned long nr_to_scan,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ANDROID_VENDOR_OEM_DATA
|
||||||
|
trace_android_vh_page_should_be_protected(folio, sc->nr_scanned,
|
||||||
|
sc->priority, &sc->android_vendor_data1, &should_protect);
|
||||||
|
#endif
|
||||||
|
if (unlikely(should_protect)) {
|
||||||
|
nr_rotated += folio_nr_pages(folio);
|
||||||
|
list_add(&folio->lru, &l_active);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_android_vh_page_referenced_check_bypass(folio, nr_to_scan, lru, &bypass);
|
||||||
|
if (bypass)
|
||||||
|
goto skip_folio_referenced;
|
||||||
trace_android_vh_folio_trylock_set(folio);
|
trace_android_vh_folio_trylock_set(folio);
|
||||||
/* Referenced or rmap lock contention: rotate */
|
/* Referenced or rmap lock contention: rotate */
|
||||||
if (folio_referenced(folio, 0, sc->target_mem_cgroup,
|
if (folio_referenced(folio, 0, sc->target_mem_cgroup,
|
||||||
@@ -2704,6 +2725,7 @@ static void shrink_active_list(unsigned long nr_to_scan,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
trace_android_vh_folio_trylock_clear(folio);
|
trace_android_vh_folio_trylock_clear(folio);
|
||||||
|
skip_folio_referenced:
|
||||||
folio_clear_active(folio); /* we are de-activating */
|
folio_clear_active(folio); /* we are de-activating */
|
||||||
folio_set_workingset(folio);
|
folio_set_workingset(folio);
|
||||||
list_add(&folio->lru, &l_inactive);
|
list_add(&folio->lru, &l_inactive);
|
||||||
|
|||||||
@@ -927,6 +927,7 @@ out:
|
|||||||
up_read(&devnet_rename_sem);
|
up_read(&devnet_rename_sem);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(netdev_get_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dev_getbyhwaddr_rcu - find a device by its hardware address
|
* dev_getbyhwaddr_rcu - find a device by its hardware address
|
||||||
|
|||||||
@@ -3487,6 +3487,7 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority)
|
|||||||
*/
|
*/
|
||||||
trace_tcp_send_reset(sk, NULL);
|
trace_tcp_send_reset(sk, NULL);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tcp_send_active_reset);
|
||||||
|
|
||||||
/* Send a crossed SYN-ACK during socket establishment.
|
/* Send a crossed SYN-ACK during socket establishment.
|
||||||
* WARNING: This routine must only be called when we have already sent
|
* WARNING: This routine must only be called when we have already sent
|
||||||
|
|||||||
@@ -437,12 +437,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|||||||
struct netem_sched_data *q = qdisc_priv(sch);
|
struct netem_sched_data *q = qdisc_priv(sch);
|
||||||
/* We don't fill cb now as skb_unshare() may invalidate it */
|
/* We don't fill cb now as skb_unshare() may invalidate it */
|
||||||
struct netem_skb_cb *cb;
|
struct netem_skb_cb *cb;
|
||||||
struct sk_buff *skb2;
|
struct sk_buff *skb2 = NULL;
|
||||||
struct sk_buff *segs = NULL;
|
struct sk_buff *segs = NULL;
|
||||||
unsigned int prev_len = qdisc_pkt_len(skb);
|
unsigned int prev_len = qdisc_pkt_len(skb);
|
||||||
int count = 1;
|
int count = 1;
|
||||||
int rc = NET_XMIT_SUCCESS;
|
|
||||||
int rc_drop = NET_XMIT_DROP;
|
|
||||||
|
|
||||||
/* Do not fool qdisc_drop_all() */
|
/* Do not fool qdisc_drop_all() */
|
||||||
skb->prev = NULL;
|
skb->prev = NULL;
|
||||||
@@ -471,19 +469,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|||||||
skb_orphan_partial(skb);
|
skb_orphan_partial(skb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we need to duplicate packet, then re-insert at top of the
|
* If we need to duplicate packet, then clone it before
|
||||||
* qdisc tree, since parent queuer expects that only one
|
* original is modified.
|
||||||
* skb will be queued.
|
|
||||||
*/
|
*/
|
||||||
if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
|
if (count > 1)
|
||||||
struct Qdisc *rootq = qdisc_root_bh(sch);
|
skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||||
u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
|
|
||||||
|
|
||||||
q->duplicate = 0;
|
|
||||||
rootq->enqueue(skb2, rootq, to_free);
|
|
||||||
q->duplicate = dupsave;
|
|
||||||
rc_drop = NET_XMIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Randomized packet corruption.
|
* Randomized packet corruption.
|
||||||
@@ -495,7 +485,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|||||||
if (skb_is_gso(skb)) {
|
if (skb_is_gso(skb)) {
|
||||||
skb = netem_segment(skb, sch, to_free);
|
skb = netem_segment(skb, sch, to_free);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return rc_drop;
|
goto finish_segs;
|
||||||
|
|
||||||
segs = skb->next;
|
segs = skb->next;
|
||||||
skb_mark_not_on_list(skb);
|
skb_mark_not_on_list(skb);
|
||||||
qdisc_skb_cb(skb)->pkt_len = skb->len;
|
qdisc_skb_cb(skb)->pkt_len = skb->len;
|
||||||
@@ -521,7 +512,24 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|||||||
/* re-link segs, so that qdisc_drop_all() frees them all */
|
/* re-link segs, so that qdisc_drop_all() frees them all */
|
||||||
skb->next = segs;
|
skb->next = segs;
|
||||||
qdisc_drop_all(skb, sch, to_free);
|
qdisc_drop_all(skb, sch, to_free);
|
||||||
return rc_drop;
|
if (skb2)
|
||||||
|
__qdisc_drop(skb2, to_free);
|
||||||
|
return NET_XMIT_DROP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If doing duplication then re-insert at top of the
|
||||||
|
* qdisc tree, since parent queuer expects that only one
|
||||||
|
* skb will be queued.
|
||||||
|
*/
|
||||||
|
if (skb2) {
|
||||||
|
struct Qdisc *rootq = qdisc_root_bh(sch);
|
||||||
|
u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
|
||||||
|
|
||||||
|
q->duplicate = 0;
|
||||||
|
rootq->enqueue(skb2, rootq, to_free);
|
||||||
|
q->duplicate = dupsave;
|
||||||
|
skb2 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
qdisc_qstats_backlog_inc(sch, skb);
|
qdisc_qstats_backlog_inc(sch, skb);
|
||||||
@@ -592,9 +600,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_segs:
|
finish_segs:
|
||||||
|
if (skb2)
|
||||||
|
__qdisc_drop(skb2, to_free);
|
||||||
|
|
||||||
if (segs) {
|
if (segs) {
|
||||||
unsigned int len, last_len;
|
unsigned int len, last_len;
|
||||||
int nb;
|
int rc, nb;
|
||||||
|
|
||||||
len = skb ? skb->len : 0;
|
len = skb ? skb->len : 0;
|
||||||
nb = skb ? 1 : 0;
|
nb = skb ? 1 : 0;
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ static int __do_binderfs_test(struct __test_metadata *_metadata)
|
|||||||
static const char * const binder_features[] = {
|
static const char * const binder_features[] = {
|
||||||
"oneway_spam_detection",
|
"oneway_spam_detection",
|
||||||
"extended_error",
|
"extended_error",
|
||||||
|
"freeze_notification",
|
||||||
};
|
};
|
||||||
|
|
||||||
change_mountns(_metadata);
|
change_mountns(_metadata);
|
||||||
|
|||||||
Reference in New Issue
Block a user