Merge branch 'android12-5.10' into android12-5.10-lts

Sync up with android12-5.10 for the following commits:

d0782c9411 Merge tag 'android12-5.10.160_r00' into android12-5.10
e12e360999 ANDROID: usb: f_accessory: Check buffer size when initialised via composite
ca53b8f1b4 BACKPORT: mm: make minimum slab alignment a runtime property
b10e8ec405 BACKPORT: printk: stop including cache.h from printk.h
ce6cc743ca UPSTREAM: kasan: fix a missing header include of static_keys.h
3519fc246d BACKPORT: kasan: split kasan_*enabled() functions into a separate header
56583c9472 UPSTREAM: usb: gadget: f_fs: Ensure ep0req is dequeued before free_request
b44330f50c UPSTREAM: usb: gadget: f_fs: Prevent race during ffs_ep0_queue_wait
d53fb78733 UPSTREAM: usb: dwc3: gadget: conditionally remove requests
75a4f0b5e1 UPSTREAM: usb: dwc3: ep0: Properly handle setup_packet_pending scenario in data stage
767a360826 UPSTREAM: usb: dwc3: gadget: Fix IN endpoint max packet size allocation
7b90f7b05e UPSTREAM: usb: dwc3: gadget: Delay issuing End Transfer
4678fabb6e UPSTREAM: usb: dwc3: gadget: Only End Transfer for ep0 data phase
a79e848e52 UPSTREAM: usb: dwc3: ep0: Don't prepare beyond Setup stage
802b4745f7 UPSTREAM: usb: dwc3: gadget: move cmd_endtransfer to extra function
33b5613a43 UPSTREAM: usb: dwc3: gadget: ep_queue simplify isoc start condition
d099b9a70e UPSTREAM: usb: dwc3: gadget: Skip reading GEVNTSIZn
15b61c98d6 UPSTREAM: usb: dwc3: gadget: Ignore Update Transfer cmd params
0761373d2f UPSTREAM: usb: dwc3: gadget: Skip checking Update Transfer status
7d1d982f57 UPSTREAM: pstore: Properly assign mem_type property
c83ab50b6e BACKPORT: ext4: fix use-after-free in ext4_rename_dir_prepare
ab89185ddb ANDROID: GKI: rockchip: Update symbols
6e50bbff17 BACKPORT: f2fs: let's avoid panic if extent_tree is not created
39b8fee3c0 BACKPORT: f2fs: should use a temp extent_info for lookup
937ed4edda BACKPORT: f2fs: don't mix to use union values in extent_info
073b997b02 BACKPORT: f2fs: initialize extent_cache parameter
aa064914fd BACKPORT: f2fs: add block_age-based extent cache
d6ba4dceab BACKPORT: f2fs: allocate the extent_cache by default
72e9dd90cf BACKPORT: f2fs: refactor extent_cache to support for read and more
561e9febb3 BACKPORT: f2fs: remove unnecessary __init_extent_tree
bf3cafe7f1 BACKPORT: f2fs: move internal functions into extent_cache.c
b29b3bd7e1 BACKPORT: f2fs: specify extent cache for read explicitly
02cb04cb05 BACKPORT: f2fs: add "c_len" into trace_f2fs_update_extent_tree_range for compressed file
f6b4d18df0 BACKPORT: f2fs: fix race condition on setting FI_NO_EXTENT flag
3112d6f502 BACKPORT: f2fs: extent cache: support unaligned extent
25280f263d UPSTREAM: io_uring: kill goto error handling in io_sqpoll_wait_sq()
7c31ae524c ANDROID: allmodconfig: disable WERROR
824c55581d UPSTREAM: Enable '-Werror' by default for all kernel builds
447ba7ae75 ANDROID: GKI: VIVO: Add a symbol to symbol list
91e4675508 ANDROID: fips140: add crypto_memneq() back to the module
b460d3c09a ANDROID: GKI: rockchip: Update module fragment and symbol list
91e760f1f2 ANDROID: GKI: rockchip: Enable symbols for HDMIRX
1960d4cfad ANDROID: GKI: rockchip: Enable symbols for Ethernet
529351c4c8 ANDROID: Re-enable fast mremap and fix UAF with SPF
c67f268c84 Revert "ANDROID: Make SPF aware of fast mremaps"
1351459097 ANDROID: GKI: Update symbols to symbol list
fe60669d03 ANDROID: fips140: add dump_jitterentropy command to fips140_lab_util
6d015667ce UPSTREAM: io_uring: add missing item types for splice request
ad1f2eebad ANDROID: GKI: update xiaomi symbol list
f677efbea1 Revert "Revert "ANDROID: vendor_hooks:vendor hook for mmput""
a43cd1f2bb Revert "Revert "ANDROID: vendor_hooks:vendor hook for __alloc_pages_slowpath.""
9e6fb5ac72 ANDROID: GKI: rockchip: Add symbol clk_hw_set_parent
7bc2b8c400 UPSTREAM: usb: dwc3: core: Add error log when core soft reset failed
05a8f2c4d2 FROMLIST: fuse: give wakeup hints to the scheduler
134c1aae43 ANDROID: Make SPF aware of fast mremaps
16c03440df ANDROID: GKI: enable mulitcolor-led
4aa3cab588 UPSTREAM: HID: playstation: support updated DualSense rumble mode.
63b2567f9d UPSTREAM: HID: playstation: add initial DualSense Edge controller support
a3ea8fbc1f UPSTREAM: HID: playstation: stop DualSense output work on remove.
a301358cb5 UPSTREAM: HID: playstation: convert to use dev_groups
62964653b7 UPSTREAM: HID: playstation: fix return from dualsense_player_led_set_brightness()
f7901b46a2 UPSTREAM: HID: playstation: expose DualSense player LEDs through LED class.
a70e598cef UPSTREAM: leds: add new LED_FUNCTION_PLAYER for player LEDs for game controllers.
e1cd3ffe47 UPSTREAM: HID: playstation: expose DualSense lightbar through a multi-color LED.
65654da06d UPSTREAM: Documentation: leds: standartizing LED names
d37e563bff ANDROID: usb: gadget: uvc: remove duplicate code in unbind
8ad88eae4b ANDROID: dma-buf: Fix build breakage with !CONFIG_DMABUF_SYSFS_STATS
ce18af9b5d ANDROID: dma-buf: don't re-purpose kobject as work_struct
eddb2f39cd UPSTREAM: drm/amdgpu: temporarily disable broken Clang builds due to blown stack-frame
e2a4080d04 BACKPORT: Kconfig.debug: provide a little extra FRAME_WARN leeway when KASAN is enabled
98671fcc32 UPSTREAM: bpf: Ensure correct locking around vulnerable function find_vpid()
01b3d953ac BACKPORT: UPSTREAM: usb: typec: ucsi: Wait for the USB role switches
37725ca62e UPSTREAM: HID: roccat: Fix use-after-free in roccat_read()
8f0752d06e ANDROID: arm64: mm: perform clean & invalidation in __dma_map_area
d55aeb4029 BACKPORT: ANDROID: dma-buf: heaps: replace mutex lock with spinlock
9ef4727680 Merge tag 'android12-5.10.149_r00' into android12-5.10
ac30bb6084 UPSTREAM: binder: Gracefully handle BINDER_TYPE_FDA objects with num_fds=0
befa134c53 UPSTREAM: binder: Address corner cases in deferred copy and fixup
8494d73eeb UPSTREAM: binder: fix pointer cast warning
3e7e7f4b10 UPSTREAM: binder: defer copies of pre-patched txn data
58fd89db0d UPSTREAM: binder: read pre-translated fds from sender buffer
92a864d9db UPSTREAM: binder: avoid potential data leakage when copying txn
d95f5e3da7 ANDROID: khugepaged: fix mixing declarations warning in retract_page_tables
aaf03dd58c ANDROID: mm: fix build issue in spf when CONFIG_USERFAULTFD=n
1c828eb3da ANDROID: mm: disable speculative page faults for CONFIG_NUMA
1900436df5 ANDROID: mm: fix invalid backport in speculative page fault path
0f43357d37 ANDROID: disable page table moves when speculative page faults are enabled
d65d4a0538 ANDROID: mm: assert that mmap_lock is taken exclusively in vm_write_begin
bfdcf47ca3 ANDROID: mm: remove sequence counting when mmap_lock is not exclusively owned
5ed391bd8a ANDROID: mm/khugepaged: add missing vm_write_{begin|end}
59d4d125b7 BACKPORT: FROMLIST: mm: implement speculative handling in filemap_fault()
2bb39b9121 ANDROID: mm: prevent reads of unstable pmd during speculation
4b388752ac ANDROID: mm: prevent speculative page fault handling for in do_swap_page()
0560f5f7b3 ANDROID: mm: prevent speculative page fault handling for userfaults
1169f70f8f ANDROID: mm: skip pte_alloc during speculative page fault
d84fac9795 FROMGIT: mm/madvise: fix madvise_pageout for private file mappings
c7eb32a49f ANDROID: GKI: Update symbols to symbol list
dcdb7eadfd Revert "FROMGIT: mm/vmalloc: Add override for lazy vunmap"
450a37133d Revert "FROMGIT: arm64: Work around Cortex-A510 erratum 2454944"
015859081a UPSTREAM: efi: capsule-loader: Fix use-after-free in efi_capsule_write
02e1387801 FROMGIT: arm64: Work around Cortex-A510 erratum 2454944
abb277d9f1 FROMGIT: mm/vmalloc: Add override for lazy vunmap
68d4b5fef2 BACKPORT: mm/page_alloc: always initialize memory map for the holes
a8997cb185 UPSTREAM: usb: dwc3: gadget: Submit endxfer command if delayed during disconnect
910e9e6049 UPSTREAM: usb: dwc3: Fix ep0 handling when getting reset while doing control transfer
e0243d1991 UPSTREAM: mm/damon/core: initialize damon_target->list in damon_new_target()
82b904105a UPSTREAM: usb: typec: ucsi: Remove incorrect warning
5f1257b5ff UPSTREAM: xhci: Don't show warning for reinit on known broken suspend
2df2e2c084 UPSTREAM: mm/damon: validate if the pmd entry is present before accessing
ed91943b48 UPSTREAM: mm/damon/dbgfs: fix memory leak when using debugfs_lookup()
3093f8b52c UPSTREAM: mm/damon/dbgfs: avoid duplicate context directory creation
3f23bb2255 UPSTREAM: crypto: lib - remove unneeded selection of XOR_BLOCKS
bf4603f495 UPSTREAM: pinctrl: sunxi: Fix name for A100 R_PIO
a0630a0536 UPSTREAM: cgroup: Add missing cpus_read_lock() to cgroup_attach_task_all()
2a11f678f6 BACKPORT: usb: gadget: f_uac2: fix superspeed transfer
347d7198a6 BACKPORT: usb: dwc3: qcom: fix runtime PM wakeup
af723545ed UPSTREAM: KVM: arm64: Reject 32bit user PSTATE on asymmetric systems
8407a5ca14 UPSTREAM: KVM: arm64: Treat PMCR_EL1.LC as RES1 on asymmetric systems
f1bf5340cd UPSTREAM: Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm regression
fdc033d445 UPSTREAM: mm: fix page leak with multiple threads mapping the same page
5b71c43f5c UPSTREAM: PM: domains: Ensure genpd_debugfs_dir exists before remove
0805a01852 UPSTREAM: usb: gadget: uvc: fix changing interface name via configfs
a7ee7101fb BACKPORT: dma-mapping: Fix build error unused-value
c3b65245e6 UPSTREAM: tools/vm/slabinfo: Handle files in debugfs
0b21c99c83 UPSTREAM: mm/damon: use set_huge_pte_at() to make huge pte old
5084953c40 UPSTREAM: usb: gadget: f_mass_storage: Make CD-ROM emulation works with Windows OS
7878f98355 UPSTREAM: blk-mq: don't touch ->tagset in blk_mq_get_sq_hctx
eb8869415a UPSTREAM: PM: domains: Fix initialization of genpd's next_wakeup
4e1bf78ac0 BACKPORT: f2fs: don't use casefolded comparison for "." and ".."
afa5490fba UPSTREAM: regulator: scmi: Fix refcount leak in scmi_regulator_probe
521b2c5661 UPSTREAM: block/mq-deadline: Set the fifo_time member also if inserting at head
e3b4c69c57 BACKPORT: Revert "mm/cma.c: remove redundant cma_mutex lock"
1199a5f80d UPSTREAM: module.h: simplify MODULE_IMPORT_NS
18e0efa7c0 UPSTREAM: iommu/mediatek: Add mutex for m4u_group and m4u_dom in data
adec2c4a36 UPSTREAM: iommu/mediatek: Remove clk_disable in mtk_iommu_remove
f70c5827f9 UPSTREAM: iommu/mediatek: Fix 2 HW sharing pgtable issue
ec3e1bddde UPSTREAM: mm: hugetlb: add missing cache flushing in hugetlb_unshare_all_pmds()
b54d7c828a UPSTREAM: selftests/damon: add damon to selftests root Makefile
250f35d78b FROMGIT: f2fs: allow to read node block after shutdown
da05d408ee BACKPORT: f2fs: do not submit NEW_ADDR to read node block
34c9208c28 BACKPORT: ext4,f2fs: fix readahead of verity data
c5589c7eec ANDROID: dma-buf: Add vendor hook for deferred dmabuf sysfs stats release
425e7c7e0e ANDROID: dm-user: Remove bio recount in I/O path
2f29ec11e3 ANDROID: abi_gki_aarch64_qcom: Add wait_on_page_bit
506e6890de UPSTREAM: drm/meson: Fix overflow implicit truncation warnings
af8a0d5f2f UPSTREAM: irqchip/tegra: Fix overflow implicit truncation warnings
3d129ea9b5 UPSTREAM: video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write
34055de440 UPSTREAM: irqchip/gic-v4: Wait for GICR_VPENDBASER.Dirty to clear before descheduling
2357d700f8 UPSTREAM: mm: kfence: fix missing objcg housekeeping for SLAB
329b0783c6 UPSTREAM: clk: Fix clk_hw_get_clk() when dev is NULL
3c6f11550b UPSTREAM: arm64: kasan: fix include error in MTE functions
9bb85986aa UPSTREAM: arm64: prevent instrumentation of bp hardening callbacks
ae9da95de3 UPSTREAM: PM: domains: Fix sleep-in-atomic bug caused by genpd_debug_remove()
f55885db0c UPSTREAM: mm: fix use-after-free bug when mm->mmap is reused after being freed
83ed3e2c4a BACKPORT: vsprintf: Fix %pK with kptr_restrict == 0
712eaeb09c UPSTREAM: net: preserve skb_end_offset() in skb_unclone_keeptruesize()
0455741716 BACKPORT: net: add skb_set_end_offset() helper
bbb0dfa377 UPSTREAM: arm64: Correct wrong label in macro __init_el2_gicv3
8318510708 UPSTREAM: KVM: arm64: Stop handle_exit() from handling HVC twice when an SError occurs
62e7b5a95c UPSTREAM: KVM: arm64: Avoid consuming a stale esr value when SError occur
a5642af234 BACKPORT: arm64: Enable Cortex-A510 erratum 2051678 by default
c5027380a1 UPSTREAM: usb: typec: tcpm: Do not disconnect when receiving VSAFE0V
044793f5af UPSTREAM: usb: typec: tcpci: don't touch CC line if it's Vconn source
3630e052b5 UPSTREAM: dt-bindings: memory: mtk-smi: Correct minItems to 2 for the gals clocks
451971e07f BACKPORT: dt-bindings: memory: mtk-smi: No need mediatek,larb-id for mt8167
f120d14123 BACKPORT: dt-bindings: memory: mtk-smi: Rename clock to clocks
64eedcefd4 UPSTREAM: KVM: arm64: Use shadow SPSR_EL1 when injecting exceptions on !VHE
6c2c1020b4 UPSTREAM: block: fix async_depth sysfs interface for mq-deadline
01a7ade4e5 UPSTREAM: dma-buf: cma_heap: Fix mutex locking section
8d34761975 UPSTREAM: scsi: ufs: ufs-mediatek: Fix error checking in ufs_mtk_init_va09_pwr_ctrl()
b3609875ce UPSTREAM: f2fs: include non-compressed blocks in compr_written_block
8599a67e73 UPSTREAM: kasan: fix Kconfig check of CC_HAS_WORKING_NOSANITIZE_ADDRESS
a9370f7ce9 UPSTREAM: dma-buf: DMABUF_SYSFS_STATS should depend on DMA_SHARED_BUFFER
b85a4aed4e UPSTREAM: mmflags.h: add missing __GFP_ZEROTAGS and __GFP_SKIP_KASAN_POISON names
3586ade72b BACKPORT: scsi: ufs: Optimize serialization of setup_xfer_req() calls
ab992b1bb8 UPSTREAM: Kbuild: lto: fix module versionings mismatch in GNU make 3.X
fcc95f9aa8 UPSTREAM: clk: versatile: Depend on HAS_IOMEM
7a81ba1e08 BACKPORT: arm64: meson: select COMMON_CLK
0e74b64011 UPSTREAM: kbuild: do not include include/config/auto.conf from adjust_autoksyms.sh
a2afe6cc0f UPSTREAM: inet: fully convert sk->sk_rx_dst to RCU rules
bbba68efda ANDROID: Update symbol list for mtk
30f7ef6517 FROMLIST: binder: fix UAF of alloc->vma in race with munmap()
b1f03eefb3 ANDROID: GKI: Update symbol list for mtk tablet projects
3813ca3253 UPSTREAM: af_key: Do not call xfrm_probe_algs in parallel
4e5c3aad56 UPSTREAM: mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()
89fc774058 UPSTREAM: mm: Force TLB flush for PFNMAP mappings before unlink_file_vma()
af70ef5bfd FROMGIT: f2fs: let's avoid to get cp_rwsem twice by f2fs_evict_inode by d_invalidate
356801e2ff ANDROID: abi_gki_aarch64_qcom: whitelist some vm symbols

Change-Id: Ife50bfa4481374091f863e0d0720846d1ecec025
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman 2023-01-23 12:33:47 +00:00
commit bf760358ea
143 changed files with 5420 additions and 2426 deletions

View file

@ -514,3 +514,17 @@ Date: July 2021
Contact: "Daeho Jeong" <daehojeong@google.com>
Description: You can control for which gc mode the "gc_reclaimed_segments" node shows.
Refer to the description of the modes in "gc_reclaimed_segments".
What: /sys/fs/f2fs/<disk>/hot_data_age_threshold
Date: November 2022
Contact: "Ping Xiong" <xiongping1@xiaomi.com>
Description: When DATA SEPARATION is on, it controls the age threshold to indicate
the data blocks as hot. By default it was initialized as 262144 blocks
(equals to 1GB).
What: /sys/fs/f2fs/<disk>/warm_data_age_threshold
Date: November 2022
Contact: "Ping Xiong" <xiongping1@xiaomi.com>
Description: When DATA SEPARATION is on, it controls the age threshold to indicate
the data blocks as warm. By default it was initialized as 2621440 blocks
(equals to 10GB).

View file

@ -3416,8 +3416,7 @@
difficult since unequal pointers can no longer be
compared. However, if this command-line option is
specified, then all normal pointers will have their true
value printed. Pointers printed via %pK may still be
hashed. This option should only be specified when
value printed. This option should only be specified when
debugging the kernel. Please do not use on production
kernels.

View file

@ -82,10 +82,9 @@ allOf:
- mediatek,mt2701-smi-common
then:
properties:
clock:
items:
minItems: 3
maxItems: 3
clocks:
minItems: 3
maxItems: 3
clock-names:
items:
- const: apb
@ -101,10 +100,9 @@ allOf:
then:
properties:
clock:
items:
minItems: 4
maxItems: 4
clocks:
minItems: 4
maxItems: 4
clock-names:
items:
- const: apb
@ -114,10 +112,9 @@ allOf:
else: # for gen2 HW that don't have gals
properties:
clock:
items:
minItems: 2
maxItems: 2
clocks:
minItems: 2
maxItems: 2
clock-names:
items:
- const: apb

View file

@ -77,11 +77,11 @@ allOf:
then:
properties:
clock:
items:
minItems: 3
maxItems: 3
clocks:
minItems: 2
maxItems: 3
clock-names:
minItems: 2
items:
- const: apb
- const: smi
@ -89,10 +89,9 @@ allOf:
else:
properties:
clock:
items:
minItems: 2
maxItems: 2
clocks:
minItems: 2
maxItems: 2
clock-names:
items:
- const: apb
@ -106,7 +105,6 @@ allOf:
- mediatek,mt2701-smi-larb
- mediatek,mt2712-smi-larb
- mediatek,mt6779-smi-larb
- mediatek,mt8167-smi-larb
then:
required:

View file

@ -300,6 +300,10 @@ inlinecrypt When possible, encrypt/decrypt the contents of encrypted
Documentation/block/inline-encryption.rst.
atgc Enable age-threshold garbage collection, it provides high
effectiveness and efficiency on background GC.
age_extent_cache Enable an age extent cache based on rb-tree. It records
data block update frequency of the extent per inode, in
order to provide better temperature hints for data block
allocation.
======================== ============================================================
Debugfs Entries

View file

@ -0,0 +1,72 @@
-*- org -*-
It is somehow important to provide consistent interface to the
userland. LED devices have one problem there, and that is naming of
directories in /sys/class/leds. It would be nice if userland would
just know right "name" for given LED function, but situation got more
complex.
Anyway, if backwards compatibility is not an issue, new code should
use one of the "good" names from this list, and you should extend the
list where applicable.
Legacy names are listed, too; in case you are writing application that
wants to use particular feature, you should probe for good name, first,
but then try the legacy ones, too.
Notice there's a list of functions in include/dt-bindings/leds/common.h .
* Gamepads and joysticks
Game controllers may feature LEDs to indicate a player number. This is commonly
used on game consoles in which multiple controllers can be connected to a system.
The "player LEDs" are then programmed with a pattern to indicate a particular
player. For example, a game controller with 4 LEDs, may be programmed with "x---"
to indicate player 1, "-x--" to indicate player 2 etcetera where "x" means on.
Input drivers can utilize the LED class to expose the individual player LEDs
of a game controller using the function "player".
Note: tracking and management of Player IDs is the responsibility of user space,
though drivers may pick a default value.
Good: "input*:*:player-{1,2,3,4,5}
* Keyboards
Good: "input*:*:capslock"
Good: "input*:*:scrolllock"
Good: "input*:*:numlock"
Legacy: "shift-key-light" (Motorola Droid 4, capslock)
Set of common keyboard LEDs, going back to PC AT or so.
Legacy: "tpacpi::thinklight" (IBM/Lenovo Thinkpads)
Legacy: "lp5523:kb{1,2,3,4,5,6}" (Nokia N900)
Frontlight/backlight of main keyboard.
Legacy: "button-backlight" (Motorola Droid 4)
Some phones have touch buttons below screen; it is different from main
keyboard. And this is their backlight.
* Sound subsystem
Good: "platform:*:mute"
Good: "platform:*:micmute"
LEDs on notebook body, indicating that sound input / output is muted.
* System notification
Legacy: "status-led:{red,green,blue}" (Motorola Droid 4)
Legacy: "lp5523:{r,g,b}" (Nokia N900)
Phones usually have multi-color status LED.
* Power management
Good: "platform:*:charging" (allwinner sun50i)
* Screen
Good: ":backlight" (Motorola Droid 4)

View file

@ -796,6 +796,9 @@ stackp-flags-$(CONFIG_STACKPROTECTOR_STRONG) := -fstack-protector-strong
KBUILD_CFLAGS += $(stackp-flags-y)
KBUILD_CFLAGS-$(CONFIG_WERROR) += -Werror
KBUILD_CFLAGS += $(KBUILD_CFLAGS-y)
ifdef CONFIG_CC_IS_CLANG
KBUILD_CPPFLAGS += -Qunused-arguments
KBUILD_CFLAGS += -Wno-format-invalid-specifier

File diff suppressed because it is too large Load diff

View file

@ -412,6 +412,7 @@
devm_kasprintf
devm_kfree
devm_kmalloc
devm_led_classdev_flash_register_ext
devm_led_classdev_register_ext
devm_led_classdev_unregister
devm_mbox_controller_register
@ -1149,7 +1150,9 @@
kvmalloc_node
led_classdev_flash_register_ext
led_classdev_flash_unregister
led_colors
led_get_flash_fault
led_set_brightness
led_set_brightness_sync
led_set_flash_brightness
led_set_flash_timeout
@ -1159,6 +1162,7 @@
led_update_brightness
led_update_flash_brightness
linear_range_get_max_value
linear_range_get_selector_high
linear_range_get_value
__list_add_valid
__list_del_entry_valid
@ -1704,6 +1708,7 @@
regulator_enable
regulator_enable_regmap
regulator_get
regulator_get_bypass_regmap
regulator_get_current_limit_regmap
regulator_get_mode
regulator_get_optional
@ -1721,6 +1726,7 @@
regulator_notifier_call_chain
regulator_put
regulator_set_active_discharge_regmap
regulator_set_bypass_regmap
regulator_set_current_limit
regulator_set_current_limit_regmap
regulator_set_load
@ -2973,6 +2979,7 @@
platform_find_device_by_driver
pm_wq
power_supply_is_system_supplied
power_supply_register_no_ws
power_supply_unreg_notifier
prepare_to_wait
printk_deferred

View file

@ -5,6 +5,7 @@
add_device_randomness
add_memory
add_memory_subsection
address_space_init_once
add_swap_extent
add_taint
add_timer
@ -64,6 +65,8 @@
bio_add_pc_page
bio_alloc_bioset
bio_associate_blkg_from_css
__bio_crypt_clone
bio_crypt_set_ctx
bio_endio
bio_put
bio_reset
@ -89,6 +92,7 @@
blk_execute_rq_nowait
blk_get_request
blk_mq_free_request
blk_mq_queue_inflight
blk_mq_rq_cpu
blk_mq_sched_mark_restart_hctx
blk_mq_start_request
@ -2006,6 +2010,7 @@
preempt_schedule_notrace
prepare_to_wait
prepare_to_wait_event
prepare_to_wait_exclusive
print_hex_dump
printk
printk_deferred
@ -2047,11 +2052,14 @@
qcom_smem_state_update_bits
queue_delayed_work_on
queue_work_on
radix_tree_delete_item
radix_tree_gang_lookup
radix_tree_insert
radix_tree_iter_delete
radix_tree_lookup
radix_tree_lookup_slot
radix_tree_next_chunk
radix_tree_replace_slot
radix_tree_preload
___ratelimit
rational_best_approximation
@ -2289,6 +2297,7 @@
rtc_update_irq
rtc_valid_tm
rtnl_is_locked
__rtnl_link_register
__rtnl_link_unregister
rtnl_lock
rtnl_unlock

View file

@ -129,6 +129,7 @@
cgroup_path_ns
cgroup_taskset_first
cgroup_taskset_next
check_move_unevictable_pages
__check_object_size
check_preempt_curr
check_zeroed_user
@ -1659,6 +1660,7 @@
page_endio
page_mapping
__page_pinner_migration_failed
__pagevec_release
panic
panic_notifier_list
panic_timeout
@ -2581,7 +2583,6 @@
__traceiter_android_vh_jiffies_update
__traceiter_android_vh_logbuf
__traceiter_android_vh_logbuf_pr_cont
__tracepoint_android_vh_madvise_cold_or_pageout
__traceiter_android_vh_printk_hotplug
__traceiter_android_vh_rproc_recovery
__traceiter_android_vh_rproc_recovery_set
@ -2703,6 +2704,7 @@
__tracepoint_android_vh_jiffies_update
__tracepoint_android_vh_logbuf
__tracepoint_android_vh_logbuf_pr_cont
__tracepoint_android_vh_madvise_cold_or_pageout
__tracepoint_android_vh_oom_check_panic
__tracepoint_android_vh_printk_hotplug
__tracepoint_android_vh_process_killed
@ -3026,6 +3028,7 @@
wait_for_completion_interruptible_timeout
wait_for_completion_killable
wait_for_completion_timeout
wait_on_page_bit
__wait_rcu_gp
wait_woken
__wake_up

View file

@ -22,6 +22,8 @@
bdget_disk
bdput
_bin2bcd
__bitmap_and
__bitmap_andnot
blk_cleanup_queue
blk_execute_rq_nowait
blk_mq_free_request
@ -80,10 +82,13 @@
__cfi_slowpath
__check_object_size
__class_create
class_create_file_ns
class_destroy
class_for_each_device
__class_register
class_remove_file_ns
class_unregister
__ClearPageMovable
clk_bulk_disable
clk_bulk_enable
clk_bulk_prepare
@ -98,6 +103,7 @@
clk_hw_get_flags
clk_hw_get_name
clk_hw_get_parent
clk_hw_get_parent_by_index
clk_hw_get_rate
__clk_mux_determine_rate
clk_notifier_register
@ -119,6 +125,7 @@
__const_udelay
consume_skb
cpu_bit_bitmap
cpufreq_cpu_get
__cpufreq_driver_target
cpufreq_generic_suspend
cpufreq_register_governor
@ -167,18 +174,19 @@
crypto_unregister_shash
crypto_unregister_template
__crypto_xor
_ctype
debugfs_attr_read
debugfs_attr_write
debugfs_create_dir
debugfs_create_file
debugfs_create_regset32
debugfs_remove
debugfs_rename
default_llseek
delayed_work_timer_fn
del_gendisk
del_timer
del_timer_sync
desc_to_gpio
destroy_workqueue
dev_close
dev_driver_string
@ -187,6 +195,7 @@
devfreq_add_governor
devfreq_recommended_opp
devfreq_register_opp_notifier
devfreq_remove_governor
devfreq_resume_device
devfreq_suspend_device
devfreq_unregister_opp_notifier
@ -199,6 +208,7 @@
device_del
device_destroy
device_get_child_node_count
device_get_match_data
device_get_named_child_node
device_get_next_child_node
device_initialize
@ -214,6 +224,7 @@
device_remove_file
device_set_wakeup_capable
device_set_wakeup_enable
device_unregister
device_wakeup_enable
_dev_info
__dev_kfree_skb_any
@ -227,6 +238,7 @@
devm_devfreq_add_device
devm_devfreq_event_add_edev
devm_devfreq_register_opp_notifier
devm_device_add_group
devm_extcon_dev_allocate
devm_extcon_dev_register
devm_free_irq
@ -284,6 +296,7 @@
devm_snd_soc_register_component
devm_usb_get_phy
_dev_notice
dev_open
dev_pm_domain_detach
dev_pm_opp_find_freq_ceil
dev_pm_opp_find_freq_floor
@ -298,6 +311,7 @@
dev_pm_opp_register_set_opp_helper
dev_pm_opp_set_rate
dev_pm_opp_set_regulators
dev_pm_opp_set_supported_hw
dev_pm_opp_unregister_set_opp_helper
dev_printk
devres_add
@ -360,8 +374,8 @@
driver_register
driver_unregister
drm_add_edid_modes
drm_add_modes_noedid
drm_atomic_get_crtc_state
drm_atomic_get_new_bridge_state
drm_atomic_get_new_connector_for_encoder
drm_atomic_helper_bridge_destroy_state
drm_atomic_helper_bridge_duplicate_state
@ -379,8 +393,12 @@
drm_compat_ioctl
drm_connector_attach_encoder
drm_connector_cleanup
drm_connector_has_possible_encoder
drm_connector_init
drm_connector_init_with_ddc
drm_connector_list_iter_begin
drm_connector_list_iter_end
drm_connector_list_iter_next
drm_connector_unregister
drm_connector_update_edid_property
__drm_dbg
@ -398,7 +416,9 @@
drm_dp_aux_register
drm_dp_aux_unregister
drm_dp_bw_code_to_link_rate
drm_dp_channel_eq_ok
drm_dp_dpcd_read
drm_dp_dpcd_read_link_status
drm_dp_dpcd_write
drm_dp_get_phy_test_pattern
drm_dp_link_rate_to_bw_code
@ -468,6 +488,8 @@
enable_irq
eth_mac_addr
eth_platform_get_mac_address
ethtool_op_get_link
ethtool_op_get_ts_info
eth_type_trans
eth_validate_addr
event_triggers_call
@ -479,6 +501,7 @@
extcon_set_state_sync
extcon_unregister_notifier
failure_tracking
fasync_helper
fd_install
find_next_bit
find_next_zero_bit
@ -539,6 +562,7 @@
gpiod_get_value_cansleep
gpiod_set_consumer_name
gpiod_set_raw_value
gpiod_set_raw_value_cansleep
gpiod_set_value
gpiod_set_value_cansleep
gpiod_to_irq
@ -568,6 +592,7 @@
hrtimer_start_range_ns
i2c_adapter_type
i2c_add_adapter
i2c_add_numbered_adapter
i2c_del_adapter
i2c_del_driver
i2c_get_adapter
@ -583,6 +608,9 @@
i2c_smbus_xfer
i2c_transfer
i2c_transfer_buffer_flags
ida_alloc_range
ida_destroy
ida_free
idr_alloc
idr_destroy
idr_find
@ -637,7 +665,6 @@
irq_find_mapping
irq_get_irq_data
irq_modify_status
irq_of_parse_and_map
irq_set_affinity_hint
irq_set_chained_handler_and_data
irq_set_chip
@ -645,6 +672,7 @@
irq_set_chip_data
irq_set_irq_type
irq_set_irq_wake
irq_to_desc
is_vmalloc_addr
jiffies
jiffies_to_msecs
@ -660,6 +688,7 @@
kfree_const
kfree_sensitive
kfree_skb
kill_fasync
kimage_voffset
__kmalloc
kmalloc_caches
@ -681,6 +710,10 @@
kstrtouint_from_user
kstrtoull
kthread_create_on_node
kthread_create_worker
kthread_destroy_worker
kthread_flush_worker
kthread_queue_work
kthread_should_stop
kthread_stop
ktime_get
@ -698,11 +731,15 @@
__list_add_valid
__list_del_entry_valid
__local_bh_enable_ip
__lock_page
__log_post_read_mmio
__log_read_mmio
__log_write_mmio
lzo1x_decompress_safe
mdiobus_alloc_size
mdiobus_free
mdiobus_read
mdiobus_unregister
mdiobus_write
media_create_pad_link
media_device_init
@ -717,7 +754,6 @@
media_pipeline_start
media_pipeline_stop
memcpy
__memcpy_fromio
memdup_user
memmove
memset
@ -736,7 +772,9 @@
mipi_dsi_host_unregister
misc_deregister
misc_register
mmc_cqe_request_done
mmc_of_parse
mmc_request_done
__mmdrop
mod_delayed_work_on
mod_timer
@ -752,10 +790,14 @@
mutex_lock_interruptible
mutex_trylock
mutex_unlock
napi_gro_receive
__netdev_alloc_skb
netdev_err
netdev_info
netdev_update_features
netdev_warn
netif_carrier_off
netif_carrier_on
netif_rx
netif_rx_ni
netif_tx_wake_queue
@ -788,6 +830,7 @@
of_device_is_available
of_device_is_compatible
of_drm_find_bridge
of_drm_find_panel
of_find_compatible_node
of_find_device_by_node
of_find_i2c_device_by_node
@ -806,6 +849,7 @@
of_get_parent
of_get_property
of_get_regulator_init_data
of_graph_get_endpoint_by_regs
of_graph_get_next_endpoint
of_graph_get_remote_node
of_graph_get_remote_port_parent
@ -849,6 +893,7 @@
perf_trace_buf_alloc
perf_trace_run_bpf_submit
pfn_valid
phy_attached_info
phy_configure
phy_drivers_register
phy_drivers_unregister
@ -887,6 +932,7 @@
platform_driver_unregister
platform_get_irq
platform_get_irq_byname
platform_get_irq_optional
platform_get_resource
platform_get_resource_byname
platform_irq_count
@ -913,6 +959,7 @@
power_supply_changed
power_supply_class
power_supply_get_battery_info
power_supply_get_by_name
power_supply_get_by_phandle
power_supply_get_drvdata
power_supply_get_property
@ -936,6 +983,7 @@
put_disk
__put_page
__put_task_struct
put_unused_fd
pwm_adjust_config
pwm_apply_state
queue_delayed_work_on
@ -946,6 +994,7 @@
_raw_spin_lock_bh
_raw_spin_lock_irq
_raw_spin_lock_irqsave
_raw_spin_trylock
_raw_spin_unlock
_raw_spin_unlock_bh
_raw_spin_unlock_irq
@ -964,6 +1013,7 @@
__register_chrdev
register_chrdev_region
register_inetaddr_notifier
register_netdev
register_netdevice
register_netdevice_notifier
register_pm_notifier
@ -1037,6 +1087,7 @@
scsi_ioctl_block_when_processing_errors
sdev_prefix_printk
sdhci_add_host
sdhci_execute_tuning
sdhci_get_property
sdhci_pltfm_clk_get_max_clock
sdhci_pltfm_free
@ -1052,6 +1103,7 @@
seq_puts
seq_read
set_page_dirty_lock
__SetPageMovable
sg_alloc_table
sg_alloc_table_from_pages
sg_free_table
@ -1068,6 +1120,7 @@
simple_strtoul
single_open
single_release
skb_add_rx_frag
skb_clone
skb_copy
skb_copy_bits
@ -1084,6 +1137,7 @@
skcipher_walk_virt
snd_pcm_format_width
snd_soc_add_component_controls
snd_soc_add_dai_controls
snd_soc_card_jack_new
snd_soc_component_read
snd_soc_component_set_jack
@ -1116,6 +1170,7 @@
snd_soc_pm_ops
snd_soc_put_enum_double
snd_soc_put_volsw
snd_soc_register_component
snd_soc_unregister_component
snprintf
sort
@ -1125,6 +1180,7 @@
sscanf
__stack_chk_fail
__stack_chk_guard
strcasecmp
strchr
strcmp
strcpy
@ -1146,6 +1202,7 @@
sync_file_create
sync_file_get_fence
synchronize_irq
synchronize_net
synchronize_rcu
syscon_node_to_regmap
syscon_regmap_lookup_by_phandle
@ -1158,6 +1215,7 @@
sysfs_remove_link
sysfs_streq
system_freezable_wq
system_highpri_wq
system_long_wq
system_power_efficient_wq
system_state
@ -1190,9 +1248,11 @@
typec_switch_register
typec_switch_unregister
__udelay
unlock_page
__unregister_chrdev
unregister_chrdev_region
unregister_inetaddr_notifier
unregister_netdev
unregister_netdevice_notifier
unregister_netdevice_queue
unregister_reboot_notifier
@ -1388,7 +1448,6 @@
# required by bcmdhd.ko
alloc_etherdev_mqs
complete_and_exit
dev_open
down_interruptible
down_timeout
iwe_stream_add_event
@ -1399,9 +1458,6 @@
mmc_set_data_timeout
mmc_sw_reset
mmc_wait_for_req
netdev_update_features
netif_napi_add
__netif_napi_del
netif_set_xps_queue
__netlink_kernel_create
netlink_kernel_release
@ -1410,7 +1466,6 @@
__nlmsg_put
_raw_read_lock_bh
_raw_read_unlock_bh
register_netdev
sched_set_fifo_low
sdio_claim_host
sdio_disable_func
@ -1444,16 +1499,15 @@
strcat
strspn
sys_tz
unregister_netdev
unregister_pm_notifier
wireless_send_event
# required by bifrost_kbase.ko
__arch_clear_user
__bitmap_andnot
__bitmap_equal
__bitmap_or
__bitmap_weight
__bitmap_xor
cache_line_size
clear_page
complete_all
@ -1503,7 +1557,6 @@
simple_open
strcspn
system_freezing_cnt
system_highpri_wq
_totalram_pages
__traceiter_gpu_mem_total
trace_output_call
@ -1515,9 +1568,6 @@
vmalloc_user
vmf_insert_pfn_prot
# required by bq25700_charger.ko
power_supply_get_by_name
# required by cdc-wdm.ko
cdc_parse_cdc_header
@ -1535,8 +1585,6 @@
# required by cfg80211.ko
bpf_trace_run10
_ctype
debugfs_rename
dev_change_net_namespace
__dev_get_by_index
dev_get_by_index
@ -1569,7 +1617,6 @@
rfkill_blocked
rfkill_pause_polling
rfkill_resume_polling
skb_add_rx_frag
__sock_create
sock_release
unregister_pernet_device
@ -1596,7 +1643,6 @@
# required by clk-rockchip-regmap.ko
clk_hw_get_num_parents
clk_hw_get_parent_by_index
divider_recalc_rate
divider_round_rate_parent
@ -1608,6 +1654,7 @@
__clk_get_hw
clk_hw_register_composite
clk_hw_round_rate
clk_hw_set_parent
clk_mux_ops
clk_mux_ro_ops
clk_register_divider_table
@ -1627,11 +1674,6 @@
# required by cm3218.ko
i2c_smbus_write_word_data
# required by cma_heap.ko
cma_get_name
dma_heap_get_drvdata
dma_heap_put
# required by cpufreq-dt.ko
cpufreq_enable_boost_support
cpufreq_freq_attr_scaling_available_freqs
@ -1666,7 +1708,6 @@
# required by cqhci.ko
devm_blk_ksm_init
mmc_cqe_request_done
# required by cryptodev.ko
crypto_ahash_final
@ -1677,7 +1718,11 @@
sg_last
unregister_sysctl_table
# required by cw221x_battery.ko
power_supply_is_system_supplied
# required by display-connector.ko
drm_atomic_get_new_bridge_state
drm_probe_ddc
# required by dm9601.ko
@ -1695,7 +1740,6 @@
# required by dw-hdmi.ko
drm_connector_attach_max_bpc_property
drm_default_rgb_quant_range
of_graph_get_endpoint_by_regs
# required by dw-mipi-dsi.ko
drm_panel_bridge_add_typed
@ -1721,14 +1765,12 @@
mmc_regulator_set_ocr
mmc_regulator_set_vqmmc
mmc_remove_host
mmc_request_done
sdio_signal_irq
sg_miter_next
sg_miter_start
sg_miter_stop
# required by dw_wdt.ko
platform_get_irq_optional
watchdog_init_timeout
watchdog_register_device
watchdog_set_restart_priority
@ -1739,7 +1781,6 @@
bitmap_find_next_zero_area_off
__bitmap_set
phy_reset
_raw_spin_trylock
usb_add_gadget_udc
usb_del_gadget_udc
usb_ep_set_maxpacket_limit
@ -1758,9 +1799,15 @@
usb_speed_string
usb_wakeup_enabled_descendants
# required by dwmac-rockchip.ko
csum_tcpudp_nofold
ip_send_check
of_get_phy_mode
# required by fusb302.ko
extcon_get_extcon_dev
fwnode_create_software_node
sched_set_fifo
tcpm_cc_change
tcpm_pd_hard_reset
tcpm_pd_receive
@ -1812,6 +1859,7 @@
i2c_verify_client
# required by i2c-gpio.ko
desc_to_gpio
i2c_bit_add_numbered_bus
# required by i2c-hid.ko
@ -1822,7 +1870,6 @@
hid_parse_report
# required by i2c-mux.ko
i2c_add_numbered_adapter
__i2c_transfer
rt_mutex_lock
rt_mutex_trylock
@ -1880,7 +1927,6 @@
dev_fetch_sw_netstats
dev_queue_xmit
ether_setup
ethtool_op_get_link
get_random_u32
__hw_addr_init
__hw_addr_sync
@ -1889,10 +1935,7 @@
kernel_param_unlock
kfree_skb_list
ktime_get_seconds
napi_gro_receive
netdev_set_default_ethtool_ops
netif_carrier_off
netif_carrier_on
netif_receive_skb
netif_receive_skb_list
netif_tx_stop_all_queues
@ -1918,7 +1961,6 @@
skb_queue_head
skb_queue_purge
skb_queue_tail
synchronize_net
unregister_inet6addr_notifier
unregister_netdevice_many
@ -1955,9 +1997,6 @@
dev_pm_qos_expose_latency_tolerance
dev_pm_qos_hide_latency_tolerance
dev_pm_qos_update_user_latency_tolerance
ida_alloc_range
ida_destroy
ida_free
init_srcu_struct
memchr_inv
param_ops_ulong
@ -2049,7 +2088,6 @@
__arm_smccc_hvc
bus_for_each_dev
device_register
device_unregister
free_pages_exact
memremap
memunmap
@ -2076,6 +2114,7 @@
# required by pcie-dw-rockchip.ko
cpumask_next_and
debugfs_create_devm_seqfile
dw_pcie_find_ext_capability
dw_pcie_host_init
dw_pcie_link_up
@ -2106,7 +2145,6 @@
extcon_sync
# required by phy-rockchip-inno-usb3.ko
strcasecmp
usb_add_phy
# required by phy-rockchip-samsung-hdptx-hdmi.ko
@ -2153,10 +2191,25 @@
clk_bulk_put
of_genpd_add_provider_onecell
panic
param_get_bool
param_set_bool
pm_clk_add_clk
pm_genpd_add_subdomain
pm_genpd_init
pm_genpd_remove
pm_wq
# required by pps_core.ko
kobject_get
# required by ptp.ko
kthread_cancel_delayed_work_sync
kthread_delayed_work_timer_fn
kthread_mod_delayed_work
kthread_queue_delayed_work
ktime_get_snapshot
posix_clock_register
posix_clock_unregister
# required by pwm-regulator.ko
regulator_map_voltage_iterate
@ -2173,6 +2226,13 @@
pwm_free
pwm_request
# required by pwrseq_simple.ko
bitmap_alloc
devm_gpiod_get_array
gpiod_set_array_value_cansleep
mmc_pwrseq_register
mmc_pwrseq_unregister
# required by reboot-mode.ko
devres_release
kernel_kobj
@ -2186,6 +2246,7 @@
alloc_iova_fast
dma_fence_wait_timeout
free_iova_fast
idr_alloc_cyclic
kstrdup_quotable_cmdline
mmput
@ -2194,9 +2255,6 @@
irq_domain_xlate_onetwocell
irq_set_parent
# required by rk628_dsi.ko
of_drm_find_panel
# required by rk805-pwrkey.ko
devm_request_any_context_irq
@ -2221,6 +2279,10 @@
# required by rk860x-regulator.ko
regulator_suspend_enable
# required by rk_cma_heap.ko
dma_heap_get_drvdata
dma_heap_put
# required by rk_crypto.ko
crypto_ahash_digest
crypto_dequeue_request
@ -2249,8 +2311,15 @@
# required by rk_ircut.ko
drain_workqueue
# required by rk_system_heap.ko
deferred_free
dmabuf_page_pool_alloc
dmabuf_page_pool_create
dmabuf_page_pool_destroy
dmabuf_page_pool_free
swiotlb_max_segment
# required by rk_vcodec.ko
devfreq_remove_governor
devm_iounmap
dev_pm_domain_attach
dev_pm_opp_get_freq
@ -2260,9 +2329,7 @@
__fdget
iommu_device_unregister
iommu_dma_reserve_iova
kthread_flush_worker
__kthread_init_worker
kthread_queue_work
kthread_worker_fn
of_device_alloc
of_dma_configure_id
@ -2287,7 +2354,18 @@
# required by rockchip-cpufreq.ko
cpufreq_unregister_notifier
dev_pm_opp_put_prop_name
dev_pm_opp_set_supported_hw
# required by rockchip-hdmirx.ko
cec_s_phys_addr_from_edid
cpu_latency_qos_remove_request
device_create_with_groups
of_reserved_mem_device_release
v4l2_ctrl_log_status
v4l2_ctrl_subscribe_event
v4l2_find_dv_timings_cap
v4l2_src_change_event_subscribe
vb2_dma_contig_memops
vb2_fop_read
# required by rockchip-rng.ko
devm_hwrng_register
@ -2296,8 +2374,10 @@
# required by rockchip_bus.ko
cpu_topology
# required by rockchip_debug.ko
nr_irqs
# required by rockchip_dmc.ko
cpufreq_cpu_get
cpufreq_cpu_put
cpufreq_quick_get
devfreq_event_disable_edev
@ -2330,7 +2410,6 @@
regulator_get_linear_step
# required by rockchip_pwm_remotectl.ko
irq_to_desc
__tasklet_hi_schedule
# required by rockchip_saradc.ko
@ -2368,6 +2447,7 @@
drm_atomic_commit
drm_atomic_get_connector_state
drm_atomic_get_plane_state
drm_atomic_helper_bridge_propagate_bus_fmt
drm_atomic_helper_check
drm_atomic_helper_check_plane_state
drm_atomic_helper_cleanup_planes
@ -2398,8 +2478,9 @@
drm_atomic_set_mode_for_crtc
drm_atomic_state_alloc
__drm_atomic_state_free
drm_bridge_chain_mode_set
drm_bridge_get_edid
drm_connector_has_possible_encoder
drm_connector_attach_content_protection_property
drm_connector_list_iter_begin
drm_connector_list_iter_end
drm_connector_list_iter_next
@ -2416,9 +2497,7 @@
drm_crtc_vblank_put
drm_debugfs_create_files
drm_do_get_edid
drm_dp_channel_eq_ok
drm_dp_clock_recovery_ok
drm_dp_dpcd_read_link_status
drm_dp_get_adjust_request_pre_emphasis
drm_dp_get_adjust_request_voltage
drm_dp_read_desc
@ -2450,6 +2529,7 @@
drm_gem_unmap_dma_buf
drm_get_format_info
drm_get_format_name
drm_hdcp_update_content_protection
drm_helper_mode_fill_fb_struct
drm_kms_helper_poll_enable
drm_kms_helper_poll_fini
@ -2475,6 +2555,7 @@
drm_mode_prune_invalid
drm_mode_set_crtcinfo
drm_modeset_lock_all
drm_modeset_unlock
drm_modeset_unlock_all
drm_mode_sort
drm_mode_validate_size
@ -2488,6 +2569,7 @@
drm_plane_create_zpos_property
drm_prime_get_contiguous_size
__drm_printfn_seq_file
drm_property_blob_put
drm_property_create
drm_property_create_bitmask
drm_property_create_bool
@ -2495,6 +2577,8 @@
drm_property_create_object
drm_property_create_range
drm_property_destroy
drm_property_lookup_blob
drm_property_replace_blob
__drm_puts_seq_file
drm_rect_calc_hscale
drm_self_refresh_helper_cleanup
@ -2536,23 +2620,18 @@
sdhci_cqe_irq
sdhci_dumpregs
sdhci_enable_clk
sdhci_execute_tuning
sdhci_pltfm_unregister
sdhci_set_power_and_bus_voltage
sdhci_set_uhs_signaling
sdhci_setup_host
# required by sdhci-of-dwcmshc.ko
device_get_match_data
devm_clk_bulk_get_optional
dma_get_required_mask
sdhci_adma_write_desc
sdhci_remove_host
sdhci_request
# required by sensor_dev.ko
class_create_file_ns
class_remove_file_ns
sdhci_reset_tuning
# required by sg.ko
blk_get_request
@ -2561,10 +2640,8 @@
blk_verify_command
cdev_alloc
class_interface_unregister
fasync_helper
get_sg_io_hdr
import_iovec
kill_fasync
put_sg_io_hdr
_raw_read_lock_irqsave
_raw_read_unlock_irqrestore
@ -2592,12 +2669,7 @@
# required by smsc95xx.ko
csum_partial
ethtool_op_get_ts_info
mdiobus_alloc_size
mdiobus_free
__mdiobus_register
mdiobus_unregister
phy_attached_info
phy_connect_direct
phy_disconnect
phy_ethtool_get_link_ksettings
@ -2615,9 +2687,6 @@
# required by snd-soc-es8316.ko
snd_pcm_hw_constraint_list
# required by snd-soc-es8326.ko
snd_soc_register_component
# required by snd-soc-hdmi-codec.ko
snd_ctl_add
snd_ctl_new1
@ -2626,7 +2695,7 @@
snd_pcm_fill_iec958_consumer
snd_pcm_fill_iec958_consumer_hw_params
snd_pcm_hw_constraint_eld
snd_pcm_stop_xrun
snd_pcm_stop
# required by snd-soc-rk817.ko
snd_soc_component_exit_regmap
@ -2637,7 +2706,8 @@
# required by snd-soc-rockchip-i2s-tdm.ko
clk_is_match
snd_soc_add_dai_controls
pm_runtime_forbid
snd_pcm_stop_xrun
# required by snd-soc-rockchip-i2s.ko
of_prop_next_string
@ -2647,8 +2717,10 @@
snd_soc_jack_add_zones
snd_soc_jack_get_type
# required by snd-soc-rockchip-spdif.ko
snd_pcm_create_iec958_consumer_hw_params
# required by snd-soc-rt5640.ko
gpiod_set_raw_value_cansleep
regmap_register_patch
snd_soc_dapm_force_bias_level
@ -2676,19 +2748,75 @@
spi_setup
stream_open
# required by stmmac-platform.ko
device_get_phy_mode
of_get_mac_address
of_phy_is_fixed_link
platform_get_irq_byname_optional
# required by stmmac.ko
devm_alloc_etherdev_mqs
dql_completed
dql_reset
ethtool_convert_legacy_u32_to_link_mode
ethtool_convert_link_mode_to_legacy_u32
flow_block_cb_setup_simple
flow_rule_match_basic
flow_rule_match_ipv4_addrs
flow_rule_match_ports
mdiobus_get_phy
__napi_alloc_skb
napi_complete_done
napi_disable
__napi_schedule
napi_schedule_prep
netdev_alert
netdev_pick_tx
netdev_rss_key_fill
netif_device_attach
netif_device_detach
netif_napi_add
__netif_napi_del
netif_schedule_queue
netif_set_real_num_rx_queues
netif_set_real_num_tx_queues
of_mdiobus_register
page_pool_alloc_pages
page_pool_create
page_pool_destroy
page_pool_put_page
page_pool_release_page
phy_init_eee
phylink_connect_phy
phylink_create
phylink_destroy
phylink_disconnect_phy
phylink_ethtool_get_eee
phylink_ethtool_get_pauseparam
phylink_ethtool_get_wol
phylink_ethtool_ksettings_get
phylink_ethtool_ksettings_set
phylink_ethtool_nway_reset
phylink_ethtool_set_eee
phylink_ethtool_set_pauseparam
phylink_ethtool_set_wol
phylink_get_eee_err
phylink_mac_change
phylink_mii_ioctl
phylink_of_phy_connect
phylink_set_port_modes
phylink_speed_down
phylink_speed_up
phylink_start
phylink_stop
pm_wakeup_dev_event
reset_control_reset
skb_tstamp_tx
# required by sw_sync.ko
dma_fence_free
dma_fence_signal_locked
__get_task_comm
put_unused_fd
# required by system_heap.ko
deferred_free
dmabuf_page_pool_alloc
dmabuf_page_pool_create
dmabuf_page_pool_destroy
dmabuf_page_pool_free
swiotlb_max_segment
# required by tcpci_husb311.ko
tcpci_get_tcpm_port
@ -2712,6 +2840,7 @@
# required by timer-rockchip.ko
clockevents_config_and_register
irq_of_parse_and_map
# required by tps65132-regulator.ko
regulator_set_active_discharge_regmap
@ -2792,6 +2921,7 @@
# required by video_rkisp.ko
media_device_cleanup
__memcpy_fromio
__memcpy_toio
param_ops_ullong
v4l2_pipeline_link_notify
@ -2831,7 +2961,6 @@
# required by zsmalloc.ko
alloc_anon_inode
__ClearPageMovable
contig_page_data
dec_zone_page_state
inc_zone_page_state
@ -2840,11 +2969,8 @@
kern_mount
kern_unmount
kill_anon_super
__lock_page
page_mapping
_raw_read_lock
_raw_read_unlock
_raw_write_lock
_raw_write_unlock
__SetPageMovable
unlock_page

View file

@ -277,6 +277,7 @@
del_gendisk
del_timer
del_timer_sync
dentry_path_raw
desc_to_gpio
destroy_workqueue
dev_coredumpv

View file

@ -200,3 +200,11 @@
wakeup_sources_read_unlock
wakeup_sources_walk_start
wakeup_sources_walk_next
#required by mi_mempool.ko module
__traceiter_android_vh_mmput
__tracepoint_android_vh_mmput
__traceiter_android_vh_alloc_pages_reclaim_bypass
__tracepoint_android_vh_alloc_pages_reclaim_bypass
__traceiter_android_vh_alloc_pages_failure_bypass
__tracepoint_android_vh_alloc_pages_failure_bypass

View file

@ -687,6 +687,7 @@ config ARM64_ERRATUM_1508412
config ARM64_ERRATUM_2051678
bool "Cortex-A510: 2051678: disable Hardware Update of the page table's dirty bit"
default y
help
This options adds the workaround for ARM Cortex-A510 erratum ARM64_ERRATUM_2051678.
Affected Coretex-A510 might not respect the ordering rules for

View file

@ -152,6 +152,7 @@ config ARCH_MEDIATEK
config ARCH_MESON
bool "Amlogic Platforms"
select COMMON_CLK
help
This enables support for the arm64 based Amlogic SoCs
such as the s905, S905X/D, S912, A113X/D or S905X/D2

View file

@ -513,6 +513,7 @@ CONFIG_MMC_CRYPTO=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_LEDS_CLASS_FLASH=y
CONFIG_LEDS_CLASS_MULTICOLOR=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_EDAC=y

View file

@ -50,10 +50,16 @@ CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_RK1000_TVE=m
CONFIG_DRM_RK630_TVE=m
CONFIG_DRM_ROCKCHIP=m
CONFIG_DRM_ROCKCHIP_RK618=m
CONFIG_DRM_ROCKCHIP_RK628=m
CONFIG_DRM_ROHM_BU18XL82=m
CONFIG_DRM_SII902X=m
CONFIG_DTC_SYMBOLS=y
# CONFIG_DWMAC_GENERIC is not set
# CONFIG_DWMAC_IPQ806X is not set
# CONFIG_DWMAC_QCOM_ETHQOS is not set
# CONFIG_DWMAC_SUN8I is not set
# CONFIG_DWMAC_SUNXI is not set
CONFIG_DW_WATCHDOG=m
CONFIG_GPIO_ROCKCHIP=m
CONFIG_GREENASIA_FF=y
@ -146,6 +152,7 @@ CONFIG_MALI_BIFROST_EXPERT=y
CONFIG_MALI_CSF_SUPPORT=y
CONFIG_MALI_PLATFORM_NAME="rk"
CONFIG_MALI_PWRSOFT_765=y
CONFIG_MFD_RK618=m
CONFIG_MFD_RK628=m
CONFIG_MFD_RK630_I2C=m
CONFIG_MFD_RK806_SPI=m
@ -186,6 +193,7 @@ CONFIG_PROXIMITY_DEVICE=m
CONFIG_PS_STK3410=m
CONFIG_PS_UCS14620=m
CONFIG_PWM_ROCKCHIP=m
CONFIG_PWRSEQ_SIMPLE=m
CONFIG_REGULATOR_ACT8865=m
CONFIG_REGULATOR_FAN53555=m
CONFIG_REGULATOR_GPIO=m
@ -236,6 +244,7 @@ CONFIG_ROCKCHIP_PM_DOMAINS=m
CONFIG_ROCKCHIP_PVTM=m
CONFIG_ROCKCHIP_REMOTECTL=m
CONFIG_ROCKCHIP_REMOTECTL_PWM=m
CONFIG_ROCKCHIP_MULTI_RGA=m
CONFIG_ROCKCHIP_RGB=y
CONFIG_ROCKCHIP_RKNPU=m
CONFIG_ROCKCHIP_SARADC=m
@ -278,6 +287,7 @@ CONFIG_SND_SOC_RT5640=m
CONFIG_SND_SOC_SPDIF=m
CONFIG_SPI_ROCKCHIP=m
CONFIG_SPI_SPIDEV=m
CONFIG_STMMAC_ETH=m
CONFIG_SW_SYNC=m
CONFIG_SYSCON_REBOOT_MODE=m
CONFIG_TEE=m
@ -328,8 +338,8 @@ CONFIG_VIDEO_RK628_BT1120=m
CONFIG_VIDEO_RK628_CSI=m
CONFIG_VIDEO_RK_IRCUT=m
CONFIG_VIDEO_ROCKCHIP_CIF=m
CONFIG_VIDEO_ROCKCHIP_HDMIRX=m
CONFIG_VIDEO_ROCKCHIP_ISP=m
CONFIG_VIDEO_ROCKCHIP_ISPP=m
CONFIG_VIDEO_S5K3L6XX=m
CONFIG_VIDEO_S5KJN1=m
CONFIG_VIDEO_SGM3784=m

View file

@ -6,6 +6,7 @@
#define __ASM_CACHE_H
#include <asm/cputype.h>
#include <asm/mte-def.h>
#define CTR_L1IP_SHIFT 14
#define CTR_L1IP_MASK 3
@ -49,15 +50,21 @@
*/
#define ARCH_DMA_MINALIGN (128)
#ifdef CONFIG_KASAN_SW_TAGS
#define ARCH_SLAB_MINALIGN (1ULL << KASAN_SHADOW_SCALE_SHIFT)
#elif defined(CONFIG_KASAN_HW_TAGS)
#define ARCH_SLAB_MINALIGN MTE_GRANULE_SIZE
#endif
#ifndef __ASSEMBLY__
#include <linux/bitops.h>
#include <linux/kasan-enabled.h>
#ifdef CONFIG_KASAN_SW_TAGS
#define ARCH_SLAB_MINALIGN (1ULL << KASAN_SHADOW_SCALE_SHIFT)
#elif defined(CONFIG_KASAN_HW_TAGS)
static inline unsigned int arch_slab_minalign(void)
{
return kasan_hw_tags_enabled() ? MTE_GRANULE_SIZE :
__alignof__(unsigned long long);
}
#define arch_slab_minalign() arch_slab_minalign()
#endif
#define ICACHEF_ALIASING 0
#define ICACHEF_VPIPT 1

View file

@ -107,7 +107,7 @@
msr_s SYS_ICC_SRE_EL2, x0
isb // Make sure SRE is now set
mrs_s x0, SYS_ICC_SRE_EL2 // Read SRE back,
tbz x0, #0, 1f // and check that it sticks
tbz x0, #0, .Lskip_gicv3_\@ // and check that it sticks
msr_s SYS_ICH_HCR_EL2, xzr // Reset ICC_HCR_EL2 to defaults
.Lskip_gicv3_\@:
.endm

View file

@ -780,6 +780,10 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu);
#define kvm_vcpu_has_pmu(vcpu) \
(test_bit(KVM_ARM_VCPU_PMU_V3, (vcpu)->arch.features))
#define kvm_supports_32bit_el0() \
(system_supports_32bit_el0() && \
!static_branch_unlikely(&arm64_mismatched_32bit_el0))
int kvm_trng_call(struct kvm_vcpu *vcpu);
#ifdef CONFIG_KVM
extern phys_addr_t hyp_mem_base;

View file

@ -5,6 +5,8 @@
#ifndef __ASM_MTE_KASAN_H
#define __ASM_MTE_KASAN_H
#include <asm/compiler.h>
#include <asm/cputype.h>
#include <asm/mte-def.h>
#ifndef __ASSEMBLY__

View file

@ -10,6 +10,7 @@
#include <asm/alternative.h>
#include <asm/cmpxchg.h>
#include <asm/stack_pointer.h>
#include <asm/sysreg.h>
static inline void set_my_cpu_offset(unsigned long off)
{

View file

@ -67,7 +67,8 @@ struct bp_hardening_data {
DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
static inline void arm64_apply_bp_hardening(void)
/* Called during entry so must be __always_inline */
static __always_inline void arm64_apply_bp_hardening(void)
{
struct bp_hardening_data *d;

View file

@ -233,17 +233,20 @@ static void install_bp_hardening_cb(bp_hardening_cb_t fn)
__this_cpu_write(bp_hardening_data.slot, HYP_VECTOR_SPECTRE_DIRECT);
}
static void call_smc_arch_workaround_1(void)
/* Called during entry so must be noinstr */
static noinstr void call_smc_arch_workaround_1(void)
{
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
}
static void call_hvc_arch_workaround_1(void)
/* Called during entry so must be noinstr */
static noinstr void call_hvc_arch_workaround_1(void)
{
arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
}
static void qcom_link_stack_sanitisation(void)
/* Called during entry so must be noinstr */
static noinstr void qcom_link_stack_sanitisation(void)
{
u64 tmp;

View file

@ -695,8 +695,7 @@ static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
if (likely(!vcpu_mode_is_32bit(vcpu)))
return false;
return !system_supports_32bit_el0() ||
static_branch_unlikely(&arm64_mismatched_32bit_el0);
return !kvm_supports_32bit_el0();
}
/**

View file

@ -225,7 +225,7 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
u64 mode = (*(u64 *)valp) & PSR_AA32_MODE_MASK;
switch (mode) {
case PSR_AA32_MODE_USR:
if (!system_supports_32bit_el0())
if (!kvm_supports_32bit_el0())
return -EINVAL;
break;
case PSR_AA32_MODE_FIQ:

View file

@ -240,6 +240,14 @@ int handle_exit(struct kvm_vcpu *vcpu, int exception_index)
{
struct kvm_run *run = vcpu->run;
if (ARM_SERROR_PENDING(exception_index)) {
/*
* The SError is handled by handle_exit_early(). If the guest
* survives it will re-execute the original instruction.
*/
return 1;
}
exception_index = ARM_EXCEPTION_CODE(exception_index);
switch (exception_index) {

View file

@ -38,7 +38,10 @@ static inline void __vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, u64 val)
{
write_sysreg_el1(val, SYS_SPSR);
if (has_vhe())
write_sysreg_el1(val, SYS_SPSR);
else
__vcpu_sys_reg(vcpu, SPSR_EL1) = val;
}
static void __vcpu_write_spsr_abt(struct kvm_vcpu *vcpu, u64 val)

View file

@ -423,7 +423,8 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
if (ARM_SERROR_PENDING(*exit_code)) {
if (ARM_SERROR_PENDING(*exit_code) &&
ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) {
u8 esr_ec = kvm_vcpu_trap_get_class(vcpu);
/*

View file

@ -618,7 +618,7 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
*/
val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
| (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E);
if (!system_supports_32bit_el0())
if (!kvm_supports_32bit_el0())
val |= ARMV8_PMU_PMCR_LC;
__vcpu_sys_reg(vcpu, r->reg) = val;
}
@ -667,7 +667,7 @@ static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
val = __vcpu_sys_reg(vcpu, PMCR_EL0);
val &= ~ARMV8_PMU_PMCR_MASK;
val |= p->regval & ARMV8_PMU_PMCR_MASK;
if (!system_supports_32bit_el0())
if (!kvm_supports_32bit_el0())
val |= ARMV8_PMU_PMCR_LC;
__vcpu_sys_reg(vcpu, PMCR_EL0) = val;
kvm_pmu_handle_pmcr(vcpu, val);

View file

@ -228,6 +228,8 @@ SYM_FUNC_END_PI(__dma_flush_area)
* - dir - DMA direction
*/
SYM_FUNC_START_PI(__dma_map_area)
cmp w2, #DMA_FROM_DEVICE
b.eq __dma_flush_area
b __dma_clean_area
SYM_FUNC_END_PI(__dma_map_area)

View file

@ -6,9 +6,9 @@
#include <linux/bitops.h>
#include <asm/segment.h>
#include <linux/cache.h>
#include <asm/ptrace.h>
#include <asm/current.h>
#include <asm/cache.h>
#include <abi/reg_ops.h>
#include <abi/regdef.h>
#include <abi/switch_context.h>

View file

@ -162,7 +162,8 @@ extern int page_is_ram(unsigned long pfn);
# define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
# else /* CONFIG_MMU */
# define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT)
# define pfn_valid(pfn) ((pfn) < (max_mapnr + ARCH_PFN_OFFSET))
# define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && \
(pfn) < (max_mapnr + ARCH_PFN_OFFSET))
# endif /* CONFIG_MMU */
# endif /* __ASSEMBLY__ */

View file

@ -464,6 +464,7 @@ CONFIG_MMC_CRYPTO=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_LEDS_CLASS_FLASH=y
CONFIG_LEDS_CLASS_MULTICOLOR=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_EDAC=y

View file

@ -1675,8 +1675,7 @@ static bool blk_mq_has_sqsched(struct request_queue *q)
*/
static struct blk_mq_hw_ctx *blk_mq_get_sq_hctx(struct request_queue *q)
{
struct blk_mq_hw_ctx *hctx;
struct blk_mq_ctx *ctx = blk_mq_get_ctx(q);
/*
* If the IO scheduler does not respect hardware queues when
* dispatching, we just don't bother with multiple HW queues and
@ -1684,8 +1683,8 @@ static struct blk_mq_hw_ctx *blk_mq_get_sq_hctx(struct request_queue *q)
* just causes lock contention inside the scheduler and pointless cache
* bouncing.
*/
hctx = blk_mq_map_queue_type(q, HCTX_TYPE_DEFAULT,
raw_smp_processor_id());
struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, 0, ctx);
if (!blk_mq_hctx_stopped(hctx))
return hctx;
return NULL;

View file

@ -749,6 +749,7 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
per_prio = &dd->per_prio[prio];
if (at_head) {
list_add(&rq->queuelist, &per_prio->dispatch);
rq->fifo_time = jiffies;
} else {
deadline_add_rq_rb(per_prio, rq);
@ -866,7 +867,7 @@ SHOW_JIFFIES(deadline_write_expire_show, dd->fifo_expire[DD_WRITE]);
SHOW_JIFFIES(deadline_aging_expire_show, dd->aging_expire);
SHOW_INT(deadline_writes_starved_show, dd->writes_starved);
SHOW_INT(deadline_front_merges_show, dd->front_merges);
SHOW_INT(deadline_async_depth_show, dd->front_merges);
SHOW_INT(deadline_async_depth_show, dd->async_depth);
SHOW_INT(deadline_fifo_batch_show, dd->fifo_batch);
#undef SHOW_INT
#undef SHOW_JIFFIES
@ -896,7 +897,7 @@ STORE_JIFFIES(deadline_write_expire_store, &dd->fifo_expire[DD_WRITE], 0, INT_MA
STORE_JIFFIES(deadline_aging_expire_store, &dd->aging_expire, 0, INT_MAX);
STORE_INT(deadline_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX);
STORE_INT(deadline_front_merges_store, &dd->front_merges, 0, 1);
STORE_INT(deadline_async_depth_store, &dd->front_merges, 1, INT_MAX);
STORE_INT(deadline_async_depth_store, &dd->async_depth, 1, INT_MAX);
STORE_INT(deadline_fifo_batch_store, &dd->fifo_batch, 0, INT_MAX);
#undef STORE_FUNCTION
#undef STORE_INT

View file

@ -9,6 +9,7 @@ function update_config() {
-d CPU_BIG_ENDIAN \
-d DYNAMIC_FTRACE \
-e UNWINDER_FRAME_POINTER \
-d WERROR \
(cd ${OUT_DIR} && \
make O=${OUT_DIR} $archsubarch CROSS_COMPILE=${CROSS_COMPILE} "${TOOL_ARGS[@]}" ${MAKE_ARGS} olddefconfig)

View file

@ -214,7 +214,7 @@ crypto-fips-objs := drbg.o ecb.o cbc.o ctr.o cts.o gcm.o xts.o hmac.o cmac.o \
gf128mul.o aes_generic.o lib-crypto-aes.o \
jitterentropy.o jitterentropy-kcapi.o \
sha1_generic.o sha256_generic.o sha512_generic.o \
lib-sha1.o lib-crypto-sha256.o
lib-memneq.o lib-sha1.o lib-crypto-sha256.o
crypto-fips-objs := $(foreach o,$(crypto-fips-objs),$(o:.o=-fips.o))
# get the arch to add its objects to $(crypto-fips-objs)

View file

@ -1774,15 +1774,21 @@ static void binder_cleanup_transaction(struct binder_transaction *t,
/**
* binder_get_object() - gets object and checks for valid metadata
* @proc: binder_proc owning the buffer
* @u: sender's user pointer to base of buffer
* @buffer: binder_buffer that we're parsing.
* @offset: offset in the @buffer at which to validate an object.
* @object: struct binder_object to read into
*
* Return: If there's a valid metadata object at @offset in @buffer, the
* Copy the binder object at the given offset into @object. If @u is
* provided then the copy is from the sender's buffer. If not, then
* it is copied from the target's @buffer.
*
* Return: If there's a valid metadata object at @offset, the
* size of that object. Otherwise, it returns zero. The object
* is read into the struct binder_object pointed to by @object.
*/
static size_t binder_get_object(struct binder_proc *proc,
const void __user *u,
struct binder_buffer *buffer,
unsigned long offset,
struct binder_object *object)
@ -1792,10 +1798,16 @@ static size_t binder_get_object(struct binder_proc *proc,
size_t object_size = 0;
read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
offset, read_size))
if (offset > buffer->data_size || read_size < sizeof(*hdr))
return 0;
if (u) {
if (copy_from_user(object, u + offset, read_size))
return 0;
} else {
if (binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
offset, read_size))
return 0;
}
/* Ok, now see if we read a complete object. */
hdr = &object->hdr;
@ -1868,7 +1880,7 @@ static struct binder_buffer_object *binder_validate_ptr(
b, buffer_offset,
sizeof(object_offset)))
return NULL;
object_size = binder_get_object(proc, b, object_offset, object);
object_size = binder_get_object(proc, NULL, b, object_offset, object);
if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
return NULL;
if (object_offsetp)
@ -1933,7 +1945,8 @@ static bool binder_validate_fixup(struct binder_proc *proc,
unsigned long buffer_offset;
struct binder_object last_object;
struct binder_buffer_object *last_bbo;
size_t object_size = binder_get_object(proc, b, last_obj_offset,
size_t object_size = binder_get_object(proc, NULL, b,
last_obj_offset,
&last_object);
if (object_size != sizeof(*last_bbo))
return false;
@ -2048,7 +2061,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
buffer, buffer_offset,
sizeof(object_offset)))
object_size = binder_get_object(proc, buffer,
object_size = binder_get_object(proc, NULL, buffer,
object_offset, &object);
if (object_size == 0) {
pr_err("transaction release %d bad object at offset %lld, size %zd\n",
@ -2389,16 +2402,266 @@ err_fd_not_accepted:
return ret;
}
static int binder_translate_fd_array(struct binder_fd_array_object *fda,
/**
* struct binder_ptr_fixup - data to be fixed-up in target buffer
* @offset offset in target buffer to fixup
* @skip_size bytes to skip in copy (fixup will be written later)
* @fixup_data data to write at fixup offset
* @node list node
*
* This is used for the pointer fixup list (pf) which is created and consumed
* during binder_transaction() and is only accessed locally. No
* locking is necessary.
*
* The list is ordered by @offset.
*/
struct binder_ptr_fixup {
binder_size_t offset;
size_t skip_size;
binder_uintptr_t fixup_data;
struct list_head node;
};
/**
* struct binder_sg_copy - scatter-gather data to be copied
* @offset offset in target buffer
* @sender_uaddr user address in source buffer
* @length bytes to copy
* @node list node
*
* This is used for the sg copy list (sgc) which is created and consumed
* during binder_transaction() and is only accessed locally. No
* locking is necessary.
*
* The list is ordered by @offset.
*/
struct binder_sg_copy {
binder_size_t offset;
const void __user *sender_uaddr;
size_t length;
struct list_head node;
};
/**
* binder_do_deferred_txn_copies() - copy and fixup scatter-gather data
* @alloc: binder_alloc associated with @buffer
* @buffer: binder buffer in target process
* @sgc_head: list_head of scatter-gather copy list
* @pf_head: list_head of pointer fixup list
*
* Processes all elements of @sgc_head, applying fixups from @pf_head
* and copying the scatter-gather data from the source process' user
* buffer to the target's buffer. It is expected that the list creation
* and processing all occurs during binder_transaction() so these lists
* are only accessed in local context.
*
* Return: 0=success, else -errno
*/
static int binder_do_deferred_txn_copies(struct binder_alloc *alloc,
struct binder_buffer *buffer,
struct list_head *sgc_head,
struct list_head *pf_head)
{
int ret = 0;
struct binder_sg_copy *sgc, *tmpsgc;
struct binder_ptr_fixup *tmppf;
struct binder_ptr_fixup *pf =
list_first_entry_or_null(pf_head, struct binder_ptr_fixup,
node);
list_for_each_entry_safe(sgc, tmpsgc, sgc_head, node) {
size_t bytes_copied = 0;
while (bytes_copied < sgc->length) {
size_t copy_size;
size_t bytes_left = sgc->length - bytes_copied;
size_t offset = sgc->offset + bytes_copied;
/*
* We copy up to the fixup (pointed to by pf)
*/
copy_size = pf ? min(bytes_left, (size_t)pf->offset - offset)
: bytes_left;
if (!ret && copy_size)
ret = binder_alloc_copy_user_to_buffer(
alloc, buffer,
offset,
sgc->sender_uaddr + bytes_copied,
copy_size);
bytes_copied += copy_size;
if (copy_size != bytes_left) {
BUG_ON(!pf);
/* we stopped at a fixup offset */
if (pf->skip_size) {
/*
* we are just skipping. This is for
* BINDER_TYPE_FDA where the translated
* fds will be fixed up when we get
* to target context.
*/
bytes_copied += pf->skip_size;
} else {
/* apply the fixup indicated by pf */
if (!ret)
ret = binder_alloc_copy_to_buffer(
alloc, buffer,
pf->offset,
&pf->fixup_data,
sizeof(pf->fixup_data));
bytes_copied += sizeof(pf->fixup_data);
}
list_del(&pf->node);
kfree(pf);
pf = list_first_entry_or_null(pf_head,
struct binder_ptr_fixup, node);
}
}
list_del(&sgc->node);
kfree(sgc);
}
list_for_each_entry_safe(pf, tmppf, pf_head, node) {
BUG_ON(pf->skip_size == 0);
list_del(&pf->node);
kfree(pf);
}
BUG_ON(!list_empty(sgc_head));
return ret > 0 ? -EINVAL : ret;
}
/**
* binder_cleanup_deferred_txn_lists() - free specified lists
* @sgc_head: list_head of scatter-gather copy list
* @pf_head: list_head of pointer fixup list
*
* Called to clean up @sgc_head and @pf_head if there is an
* error.
*/
static void binder_cleanup_deferred_txn_lists(struct list_head *sgc_head,
struct list_head *pf_head)
{
struct binder_sg_copy *sgc, *tmpsgc;
struct binder_ptr_fixup *pf, *tmppf;
list_for_each_entry_safe(sgc, tmpsgc, sgc_head, node) {
list_del(&sgc->node);
kfree(sgc);
}
list_for_each_entry_safe(pf, tmppf, pf_head, node) {
list_del(&pf->node);
kfree(pf);
}
}
/**
* binder_defer_copy() - queue a scatter-gather buffer for copy
* @sgc_head: list_head of scatter-gather copy list
* @offset: binder buffer offset in target process
* @sender_uaddr: user address in source process
* @length: bytes to copy
*
* Specify a scatter-gather block to be copied. The actual copy must
* be deferred until all the needed fixups are identified and queued.
* Then the copy and fixups are done together so un-translated values
* from the source are never visible in the target buffer.
*
* We are guaranteed that repeated calls to this function will have
* monotonically increasing @offset values so the list will naturally
* be ordered.
*
* Return: 0=success, else -errno
*/
static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset,
const void __user *sender_uaddr, size_t length)
{
struct binder_sg_copy *bc = kzalloc(sizeof(*bc), GFP_KERNEL);
if (!bc)
return -ENOMEM;
bc->offset = offset;
bc->sender_uaddr = sender_uaddr;
bc->length = length;
INIT_LIST_HEAD(&bc->node);
/*
* We are guaranteed that the deferred copies are in-order
* so just add to the tail.
*/
list_add_tail(&bc->node, sgc_head);
return 0;
}
/**
* binder_add_fixup() - queue a fixup to be applied to sg copy
* @pf_head: list_head of binder ptr fixup list
* @offset: binder buffer offset in target process
* @fixup: bytes to be copied for fixup
* @skip_size: bytes to skip when copying (fixup will be applied later)
*
* Add the specified fixup to a list ordered by @offset. When copying
* the scatter-gather buffers, the fixup will be copied instead of
* data from the source buffer. For BINDER_TYPE_FDA fixups, the fixup
* will be applied later (in target process context), so we just skip
* the bytes specified by @skip_size. If @skip_size is 0, we copy the
* value in @fixup.
*
* This function is called *mostly* in @offset order, but there are
* exceptions. Since out-of-order inserts are relatively uncommon,
* we insert the new element by searching backward from the tail of
* the list.
*
* Return: 0=success, else -errno
*/
static int binder_add_fixup(struct list_head *pf_head, binder_size_t offset,
binder_uintptr_t fixup, size_t skip_size)
{
struct binder_ptr_fixup *pf = kzalloc(sizeof(*pf), GFP_KERNEL);
struct binder_ptr_fixup *tmppf;
if (!pf)
return -ENOMEM;
pf->offset = offset;
pf->fixup_data = fixup;
pf->skip_size = skip_size;
INIT_LIST_HEAD(&pf->node);
/* Fixups are *mostly* added in-order, but there are some
* exceptions. Look backwards through list for insertion point.
*/
list_for_each_entry_reverse(tmppf, pf_head, node) {
if (tmppf->offset < pf->offset) {
list_add(&pf->node, &tmppf->node);
return 0;
}
}
/*
* if we get here, then the new offset is the lowest so
* insert at the head
*/
list_add(&pf->node, pf_head);
return 0;
}
static int binder_translate_fd_array(struct list_head *pf_head,
struct binder_fd_array_object *fda,
const void __user *sender_ubuffer,
struct binder_buffer_object *parent,
struct binder_buffer_object *sender_uparent,
struct binder_transaction *t,
struct binder_thread *thread,
struct binder_transaction *in_reply_to)
{
binder_size_t fdi, fd_buf_size;
binder_size_t fda_offset;
const void __user *sender_ufda_base;
struct binder_proc *proc = thread->proc;
struct binder_proc *target_proc = t->to_proc;
int ret;
if (fda->num_fds == 0)
return 0;
fd_buf_size = sizeof(u32) * fda->num_fds;
if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
@ -2422,19 +2685,25 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
*/
fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) +
fda->parent_offset;
if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32))) {
sender_ufda_base = (void __user *)(uintptr_t)sender_uparent->buffer +
fda->parent_offset;
if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32)) ||
!IS_ALIGNED((unsigned long)sender_ufda_base, sizeof(u32))) {
binder_user_error("%d:%d parent offset not aligned correctly.\n",
proc->pid, thread->pid);
return -EINVAL;
}
ret = binder_add_fixup(pf_head, fda_offset, 0, fda->num_fds * sizeof(u32));
if (ret)
return ret;
for (fdi = 0; fdi < fda->num_fds; fdi++) {
u32 fd;
int ret;
binder_size_t offset = fda_offset + fdi * sizeof(fd);
binder_size_t sender_uoffset = fdi * sizeof(fd);
ret = binder_alloc_copy_from_buffer(&target_proc->alloc,
&fd, t->buffer,
offset, sizeof(fd));
ret = copy_from_user(&fd, sender_ufda_base + sender_uoffset, sizeof(fd));
if (!ret)
ret = binder_translate_fd(fd, offset, t, thread,
in_reply_to);
@ -2444,7 +2713,8 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
return 0;
}
static int binder_fixup_parent(struct binder_transaction *t,
static int binder_fixup_parent(struct list_head *pf_head,
struct binder_transaction *t,
struct binder_thread *thread,
struct binder_buffer_object *bp,
binder_size_t off_start_offset,
@ -2490,14 +2760,7 @@ static int binder_fixup_parent(struct binder_transaction *t,
}
buffer_offset = bp->parent_offset +
(uintptr_t)parent->buffer - (uintptr_t)b->user_data;
if (binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
&bp->buffer, sizeof(bp->buffer))) {
binder_user_error("%d:%d got transaction with invalid parent offset\n",
proc->pid, thread->pid);
return -EINVAL;
}
return 0;
return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0);
}
/**
@ -2715,6 +2978,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_size_t off_start_offset, off_end_offset;
binder_size_t off_min;
binder_size_t sg_buf_offset, sg_buf_end_offset;
binder_size_t user_offset = 0;
struct binder_proc *target_proc = NULL;
struct binder_thread *target_thread = NULL;
struct binder_node *target_node = NULL;
@ -2729,6 +2993,12 @@ static void binder_transaction(struct binder_proc *proc,
int t_debug_id = atomic_inc_return(&binder_last_id);
char *secctx = NULL;
u32 secctx_sz = 0;
struct list_head sgc_head;
struct list_head pf_head;
const void __user *user_buffer = (const void __user *)
(uintptr_t)tr->data.ptr.buffer;
INIT_LIST_HEAD(&sgc_head);
INIT_LIST_HEAD(&pf_head);
e = binder_transaction_log_add(&binder_transaction_log);
e->debug_id = t_debug_id;
@ -3064,19 +3334,6 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF);
trace_binder_transaction_alloc_buf(t->buffer);
if (binder_alloc_copy_user_to_buffer(
&target_proc->alloc,
t->buffer, 0,
(const void __user *)
(uintptr_t)tr->data.ptr.buffer,
tr->data_size)) {
binder_user_error("%d:%d got transaction with invalid data ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
return_error_param = -EFAULT;
return_error_line = __LINE__;
goto err_copy_data_failed;
}
if (binder_alloc_copy_user_to_buffer(
&target_proc->alloc,
t->buffer,
@ -3121,6 +3378,7 @@ static void binder_transaction(struct binder_proc *proc,
size_t object_size;
struct binder_object object;
binder_size_t object_offset;
binder_size_t copy_size;
if (binder_alloc_copy_from_buffer(&target_proc->alloc,
&object_offset,
@ -3132,8 +3390,27 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
object_size = binder_get_object(target_proc, t->buffer,
object_offset, &object);
/*
* Copy the source user buffer up to the next object
* that will be processed.
*/
copy_size = object_offset - user_offset;
if (copy_size && (user_offset > object_offset ||
binder_alloc_copy_user_to_buffer(
&target_proc->alloc,
t->buffer, user_offset,
user_buffer + user_offset,
copy_size))) {
binder_user_error("%d:%d got transaction with invalid data ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
return_error_param = -EFAULT;
return_error_line = __LINE__;
goto err_copy_data_failed;
}
object_size = binder_get_object(target_proc, user_buffer,
t->buffer, object_offset, &object);
if (object_size == 0 || object_offset < off_min) {
binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
proc->pid, thread->pid,
@ -3145,6 +3422,11 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
/*
* Set offset to the next buffer fragment to be
* copied
*/
user_offset = object_offset + object_size;
hdr = &object.hdr;
off_min = object_offset + object_size;
@ -3207,6 +3489,8 @@ static void binder_transaction(struct binder_proc *proc,
case BINDER_TYPE_FDA: {
struct binder_object ptr_object;
binder_size_t parent_offset;
struct binder_object user_object;
size_t user_parent_size;
struct binder_fd_array_object *fda =
to_binder_fd_array_object(hdr);
size_t num_valid = (buffer_offset - off_start_offset) /
@ -3238,11 +3522,35 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_parent;
}
ret = binder_translate_fd_array(fda, parent, t, thread,
in_reply_to);
if (ret < 0) {
/*
* We need to read the user version of the parent
* object to get the original user offset
*/
user_parent_size =
binder_get_object(proc, user_buffer, t->buffer,
parent_offset, &user_object);
if (user_parent_size != sizeof(user_object.bbo)) {
binder_user_error("%d:%d invalid ptr object size: %zd vs %zd\n",
proc->pid, thread->pid,
user_parent_size,
sizeof(user_object.bbo));
return_error = BR_FAILED_REPLY;
return_error_param = ret;
return_error_param = -EINVAL;
return_error_line = __LINE__;
goto err_bad_parent;
}
ret = binder_translate_fd_array(&pf_head, fda,
user_buffer, parent,
&user_object.bbo, t,
thread, in_reply_to);
if (!ret)
ret = binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer,
object_offset,
fda, sizeof(*fda));
if (ret) {
return_error = BR_FAILED_REPLY;
return_error_param = ret > 0 ? -EINVAL : ret;
return_error_line = __LINE__;
goto err_translate_failed;
}
@ -3264,19 +3572,14 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
if (binder_alloc_copy_user_to_buffer(
&target_proc->alloc,
t->buffer,
sg_buf_offset,
(const void __user *)
(uintptr_t)bp->buffer,
bp->length)) {
binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
proc->pid, thread->pid);
return_error_param = -EFAULT;
ret = binder_defer_copy(&sgc_head, sg_buf_offset,
(const void __user *)(uintptr_t)bp->buffer,
bp->length);
if (ret) {
return_error = BR_FAILED_REPLY;
return_error_param = ret;
return_error_line = __LINE__;
goto err_copy_data_failed;
goto err_translate_failed;
}
/* Fixup buffer pointer to target proc address space */
bp->buffer = (uintptr_t)
@ -3285,7 +3588,8 @@ static void binder_transaction(struct binder_proc *proc,
num_valid = (buffer_offset - off_start_offset) /
sizeof(binder_size_t);
ret = binder_fixup_parent(t, thread, bp,
ret = binder_fixup_parent(&pf_head, t,
thread, bp,
off_start_offset,
num_valid,
last_fixup_obj_off,
@ -3312,6 +3616,30 @@ static void binder_transaction(struct binder_proc *proc,
goto err_bad_object_type;
}
}
/* Done processing objects, copy the rest of the buffer */
if (binder_alloc_copy_user_to_buffer(
&target_proc->alloc,
t->buffer, user_offset,
user_buffer + user_offset,
tr->data_size - user_offset)) {
binder_user_error("%d:%d got transaction with invalid data ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
return_error_param = -EFAULT;
return_error_line = __LINE__;
goto err_copy_data_failed;
}
ret = binder_do_deferred_txn_copies(&target_proc->alloc, t->buffer,
&sgc_head, &pf_head);
if (ret) {
binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
return_error_param = ret;
return_error_line = __LINE__;
goto err_copy_data_failed;
}
if (t->buffer->oneway_spam_suspect)
tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
else
@ -3387,6 +3715,7 @@ err_bad_object_type:
err_bad_offset:
err_bad_parent:
err_copy_data_failed:
binder_cleanup_deferred_txn_lists(&sgc_head, &pf_head);
binder_free_txn_fixups(t);
trace_binder_transaction_failed_buffer_release(t->buffer);
binder_transaction_buffer_release(target_proc, NULL, t->buffer,

View file

@ -7,6 +7,7 @@
*/
#ifndef __GENKSYMS__
#include <linux/dma-buf.h>
#include <linux/rmap.h>
#endif
@ -74,6 +75,7 @@
#include <trace/hooks/snd_compr.h>
#include <trace/hooks/ipv4.h>
#include <trace/hooks/pci.h>
#include <trace/hooks/dmabuf.h>
/*
* Export tracepoints that act as a bare tracehook (ie: have no trace event
@ -462,12 +464,15 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_alloc_si);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_si);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_pages);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_shmem_page_flag);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mmput);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sched_pelt_multiplier);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_pages_reclaim_bypass);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_pages_failure_bypass);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_check_page_look_around_ref);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_look_around);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_look_around_migrate_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_test_clear_look_around_ref);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_dma_buf_stats_teardown);
/*
* For type visibility
*/

View file

@ -219,6 +219,9 @@ static void genpd_debug_remove(struct generic_pm_domain *genpd)
{
struct dentry *d;
if (!genpd_debugfs_dir)
return;
d = debugfs_lookup(genpd->name, genpd_debugfs_dir);
debugfs_remove(d);
}
@ -1972,6 +1975,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
genpd->device_count = 0;
genpd->max_off_time_ns = -1;
genpd->max_off_time_changed = true;
genpd->next_wakeup = KTIME_MAX;
genpd->provider = NULL;
genpd->has_provider = false;
genpd->accounting_time = ktime_get();
@ -2052,9 +2056,9 @@ static int genpd_remove(struct generic_pm_domain *genpd)
kfree(link);
}
genpd_debug_remove(genpd);
list_del(&genpd->gpd_list_node);
genpd_unlock(genpd);
genpd_debug_remove(genpd);
cancel_work_sync(&genpd->power_off_work);
if (genpd_is_cpu_domain(genpd))
free_cpumask_var(genpd->cpus);

View file

@ -3827,8 +3827,9 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
struct clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id)
{
struct device *dev = hw->core->dev;
const char *name = dev ? dev_name(dev) : NULL;
return clk_hw_create_clk(dev, hw, dev_name(dev), con_id);
return clk_hw_create_clk(dev, hw, name, con_id);
}
EXPORT_SYMBOL(clk_hw_get_clk);

View file

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
menu "Clock driver for ARM Reference designs"
depends on HAS_IOMEM
config ICST
bool "Clock driver for ARM Reference designs ICST"

View file

@ -67,7 +67,7 @@ menuconfig DMABUF_HEAPS
menuconfig DMABUF_SYSFS_STATS
bool "DMA-BUF sysfs statistics"
select DMA_SHARED_BUFFER
depends on DMA_SHARED_BUFFER
help
Choose this option to enable DMA-BUF sysfs statistics
in location /sys/kernel/dmabuf/buffers.

View file

@ -13,6 +13,8 @@
#include <linux/sysfs.h>
#include <linux/workqueue.h>
#include <trace/hooks/dmabuf.h>
#include "dma-buf-sysfs-stats.h"
#define to_dma_buf_entry_from_kobj(x) container_of(x, struct dma_buf_sysfs_entry, kobj)
@ -88,13 +90,17 @@ static struct kobj_type dma_buf_ktype = {
void dma_buf_stats_teardown(struct dma_buf *dmabuf)
{
struct dma_buf_sysfs_entry *sysfs_entry;
bool skip_sysfs_release = false;
sysfs_entry = dmabuf->sysfs_entry;
if (!sysfs_entry)
return;
kobject_del(&sysfs_entry->kobj);
kobject_put(&sysfs_entry->kobj);
trace_android_rvh_dma_buf_stats_teardown(sysfs_entry, &skip_sysfs_release);
if (!skip_sysfs_release) {
kobject_del(&sysfs_entry->kobj);
kobject_put(&sysfs_entry->kobj);
}
}
/*
@ -136,15 +142,21 @@ void dma_buf_uninit_sysfs_statistics(void)
kset_unregister(dma_buf_stats_kset);
}
struct dma_buf_create_sysfs_entry {
struct dma_buf *dmabuf;
struct work_struct work;
};
union dma_buf_create_sysfs_work_entry {
struct dma_buf_create_sysfs_entry create_entry;
struct dma_buf_sysfs_entry sysfs_entry;
};
static void sysfs_add_workfn(struct work_struct *work)
{
/* The ABI would have to change for this to be false, but let's be paranoid. */
_Static_assert(sizeof(struct kobject) >= sizeof(struct work_struct),
"kobject is smaller than work_struct");
struct dma_buf_sysfs_entry *sysfs_entry =
container_of((struct kobject *)work, struct dma_buf_sysfs_entry, kobj);
struct dma_buf *dmabuf = sysfs_entry->dmabuf;
struct dma_buf_create_sysfs_entry *create_entry =
container_of(work, struct dma_buf_create_sysfs_entry, work);
struct dma_buf *dmabuf = create_entry->dmabuf;
/*
* A dmabuf is ref-counted via its file member. If this handler holds the only
@ -155,6 +167,7 @@ static void sysfs_add_workfn(struct work_struct *work)
* is released, and that can't happen until the end of this function.
*/
if (file_count(dmabuf->file) > 1) {
dmabuf->sysfs_entry->dmabuf = dmabuf;
/*
* kobject_init_and_add expects kobject to be zero-filled, but we have populated it
* to trigger this work function.
@ -179,8 +192,8 @@ static void sysfs_add_workfn(struct work_struct *work)
int dma_buf_stats_setup(struct dma_buf *dmabuf)
{
struct dma_buf_sysfs_entry *sysfs_entry;
struct work_struct *work;
struct dma_buf_create_sysfs_entry *create_entry;
union dma_buf_create_sysfs_work_entry *work_entry;
if (!dmabuf || !dmabuf->file)
return -EINVAL;
@ -190,21 +203,18 @@ int dma_buf_stats_setup(struct dma_buf *dmabuf)
return -EINVAL;
}
sysfs_entry = kmalloc(sizeof(struct dma_buf_sysfs_entry), GFP_KERNEL);
if (!sysfs_entry)
work_entry = kmalloc(sizeof(union dma_buf_create_sysfs_work_entry), GFP_KERNEL);
if (!work_entry)
return -ENOMEM;
sysfs_entry->dmabuf = dmabuf;
dmabuf->sysfs_entry = sysfs_entry;
dmabuf->sysfs_entry = &work_entry->sysfs_entry;
/*
* The use of kobj as a work_struct is an ugly hack
* to avoid an ABI break in this frozen kernel.
*/
work = (struct work_struct *)&dmabuf->sysfs_entry->kobj;
INIT_WORK(work, sysfs_add_workfn);
create_entry = &work_entry->create_entry;
create_entry->dmabuf = dmabuf;
INIT_WORK(&create_entry->work, sysfs_add_workfn);
get_dma_buf(dmabuf); /* This reference will be dropped in sysfs_add_workfn. */
schedule_work(work);
schedule_work(&create_entry->work);
return 0;
}

View file

@ -126,10 +126,11 @@ static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
struct cma_heap_buffer *buffer = dmabuf->priv;
struct dma_heap_attachment *a;
mutex_lock(&buffer->lock);
if (buffer->vmap_cnt)
invalidate_kernel_vmap_range(buffer->vaddr, buffer->len);
mutex_lock(&buffer->lock);
list_for_each_entry(a, &buffer->attachments, list) {
if (!a->mapped)
continue;
@ -146,10 +147,11 @@ static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
struct cma_heap_buffer *buffer = dmabuf->priv;
struct dma_heap_attachment *a;
mutex_lock(&buffer->lock);
if (buffer->vmap_cnt)
flush_kernel_vmap_range(buffer->vaddr, buffer->len);
mutex_lock(&buffer->lock);
list_for_each_entry(a, &buffer->attachments, list) {
if (!a->mapped)
continue;

View file

@ -11,10 +11,16 @@
#include <linux/freezer.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/swap.h>
#include <linux/sched/signal.h>
#include "page_pool.h"
struct dmabuf_page_pool_with_spinlock {
struct dmabuf_page_pool pool;
struct spinlock spinlock;
};
static LIST_HEAD(pool_list);
static DEFINE_MUTEX(pool_list_lock);
@ -35,34 +41,41 @@ static inline void dmabuf_page_pool_free_pages(struct dmabuf_page_pool *pool,
static void dmabuf_page_pool_add(struct dmabuf_page_pool *pool, struct page *page)
{
int index;
struct dmabuf_page_pool_with_spinlock *container_pool =
container_of(pool, struct dmabuf_page_pool_with_spinlock, pool);
if (PageHighMem(page))
index = POOL_HIGHPAGE;
else
index = POOL_LOWPAGE;
mutex_lock(&pool->mutex);
spin_lock(&container_pool->spinlock);
list_add_tail(&page->lru, &pool->items[index]);
pool->count[index]++;
spin_unlock(&container_pool->spinlock);
mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE,
1 << pool->order);
mutex_unlock(&pool->mutex);
}
static struct page *dmabuf_page_pool_remove(struct dmabuf_page_pool *pool, int index)
{
struct page *page;
struct dmabuf_page_pool_with_spinlock *container_pool =
container_of(pool, struct dmabuf_page_pool_with_spinlock, pool);
mutex_lock(&pool->mutex);
spin_lock(&container_pool->spinlock);
page = list_first_entry_or_null(&pool->items[index], struct page, lru);
if (page) {
pool->count[index]--;
list_del(&page->lru);
spin_unlock(&container_pool->spinlock);
mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE,
-(1 << pool->order));
goto out;
}
mutex_unlock(&pool->mutex);
spin_unlock(&container_pool->spinlock);
out:
return page;
}
@ -113,19 +126,25 @@ static int dmabuf_page_pool_total(struct dmabuf_page_pool *pool, bool high)
struct dmabuf_page_pool *dmabuf_page_pool_create(gfp_t gfp_mask, unsigned int order)
{
struct dmabuf_page_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL);
struct dmabuf_page_pool *pool;
struct dmabuf_page_pool_with_spinlock *container_pool =
kmalloc(sizeof(*container_pool), GFP_KERNEL);
int i;
if (!pool)
if (!container_pool)
return NULL;
spin_lock_init(&container_pool->spinlock);
pool = &container_pool->pool;
for (i = 0; i < POOL_TYPE_SIZE; i++) {
pool->count[i] = 0;
INIT_LIST_HEAD(&pool->items[i]);
}
pool->gfp_mask = gfp_mask | __GFP_COMP;
pool->order = order;
mutex_init(&pool->mutex);
mutex_init(&pool->mutex); /* No longer used! */
mutex_lock(&pool->mutex); /* Make sure anyone who attempts to acquire this hangs */
mutex_lock(&pool_list_lock);
list_add(&pool->list, &pool_list);
@ -138,6 +157,7 @@ EXPORT_SYMBOL_GPL(dmabuf_page_pool_create);
void dmabuf_page_pool_destroy(struct dmabuf_page_pool *pool)
{
struct page *page;
struct dmabuf_page_pool_with_spinlock *container_pool;
int i;
/* Remove us from the pool list */
@ -151,7 +171,8 @@ void dmabuf_page_pool_destroy(struct dmabuf_page_pool *pool)
dmabuf_page_pool_free_pages(pool, page);
}
kfree(pool);
container_pool = container_of(pool, struct dmabuf_page_pool_with_spinlock, pool);
kfree(container_pool);
}
EXPORT_SYMBOL_GPL(dmabuf_page_pool_destroy);

View file

@ -40,7 +40,7 @@ enum {
struct dmabuf_page_pool {
int count[POOL_TYPE_SIZE];
struct list_head items[POOL_TYPE_SIZE];
struct mutex mutex;
struct mutex mutex; /* No longer used! */
gfp_t gfp_mask;
unsigned int order;
struct list_head list;

View file

@ -1090,6 +1090,7 @@
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 0x09cc
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE 0x0ba0
#define USB_DEVICE_ID_SONY_PS5_CONTROLLER 0x0ce6
#define USB_DEVICE_ID_SONY_PS5_CONTROLLER_2 0x0df2
#define USB_DEVICE_ID_SONY_MOTION_CONTROLLER 0x03d5
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002

View file

@ -11,6 +11,8 @@
#include <linux/hid.h>
#include <linux/idr.h>
#include <linux/input/mt.h>
#include <linux/leds.h>
#include <linux/led-class-multicolor.h>
#include <linux/module.h>
#include <asm/unaligned.h>
@ -38,11 +40,13 @@ struct ps_device {
uint8_t battery_capacity;
int battery_status;
const char *input_dev_name; /* Name of primary input device. */
uint8_t mac_address[6]; /* Note: stored in little endian order. */
uint32_t hw_version;
uint32_t fw_version;
int (*parse_report)(struct ps_device *dev, struct hid_report *report, u8 *data, int size);
void (*remove)(struct ps_device *dev);
};
/* Calibration data for playstation motion sensors. */
@ -53,6 +57,13 @@ struct ps_calibration_data {
int sens_denom;
};
struct ps_led_info {
const char *name;
const char *color;
enum led_brightness (*brightness_get)(struct led_classdev *cdev);
int (*brightness_set)(struct led_classdev *cdev, enum led_brightness);
};
/* Seed values for DualShock4 / DualSense CRC32 for different report types. */
#define PS_INPUT_CRC32_SEED 0xA1
#define PS_OUTPUT_CRC32_SEED 0xA2
@ -97,6 +108,9 @@ struct ps_calibration_data {
#define DS_STATUS_CHARGING GENMASK(7, 4)
#define DS_STATUS_CHARGING_SHIFT 4
/* Feature version from DualSense Firmware Info report. */
#define DS_FEATURE_VERSION(major, minor) ((major & 0xff) << 8 | (minor & 0xff))
/*
* Status of a DualSense touch point contact.
* Contact IDs, with highest bit set are 'inactive'
@ -115,6 +129,7 @@ struct ps_calibration_data {
#define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3)
#define DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE BIT(4)
#define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1)
#define DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2 BIT(2)
#define DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE BIT(4)
#define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
@ -132,6 +147,9 @@ struct dualsense {
struct input_dev *sensors;
struct input_dev *touchpad;
/* Update version is used as a feature/capability version. */
uint16_t update_version;
/* Calibration data for accelerometer and gyroscope. */
struct ps_calibration_data accel_calib_data[3];
struct ps_calibration_data gyro_calib_data[3];
@ -142,11 +160,13 @@ struct dualsense {
uint32_t sensor_timestamp_us;
/* Compatible rumble state */
bool use_vibration_v2;
bool update_rumble;
uint8_t motor_left;
uint8_t motor_right;
/* RGB lightbar */
struct led_classdev_mc lightbar;
bool update_lightbar;
uint8_t lightbar_red;
uint8_t lightbar_green;
@ -163,6 +183,7 @@ struct dualsense {
struct led_classdev player_leds[5];
struct work_struct output_worker;
bool output_worker_initialized;
void *output_report_dmabuf;
uint8_t output_seq; /* Sequence number for output report. */
};
@ -288,6 +309,9 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
{0, 0},
};
static inline void dualsense_schedule_work(struct dualsense *ds);
static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t green, uint8_t blue);
/*
* Add a new ps_device to ps_devices if it doesn't exist.
* Return error on duplicate device, which can happen if the same
@ -525,6 +549,71 @@ static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *bu
return 0;
}
static int ps_led_register(struct ps_device *ps_dev, struct led_classdev *led,
const struct ps_led_info *led_info)
{
int ret;
led->name = devm_kasprintf(&ps_dev->hdev->dev, GFP_KERNEL,
"%s:%s:%s", ps_dev->input_dev_name, led_info->color, led_info->name);
if (!led->name)
return -ENOMEM;
led->brightness = 0;
led->max_brightness = 1;
led->flags = LED_CORE_SUSPENDRESUME;
led->brightness_get = led_info->brightness_get;
led->brightness_set_blocking = led_info->brightness_set;
ret = devm_led_classdev_register(&ps_dev->hdev->dev, led);
if (ret) {
hid_err(ps_dev->hdev, "Failed to register LED %s: %d\n", led_info->name, ret);
return ret;
}
return 0;
}
/* Register a DualSense/DualShock4 RGB lightbar represented by a multicolor LED. */
static int ps_lightbar_register(struct ps_device *ps_dev, struct led_classdev_mc *lightbar_mc_dev,
int (*brightness_set)(struct led_classdev *, enum led_brightness))
{
struct hid_device *hdev = ps_dev->hdev;
struct mc_subled *mc_led_info;
struct led_classdev *led_cdev;
int ret;
mc_led_info = devm_kmalloc_array(&hdev->dev, 3, sizeof(*mc_led_info),
GFP_KERNEL | __GFP_ZERO);
if (!mc_led_info)
return -ENOMEM;
mc_led_info[0].color_index = LED_COLOR_ID_RED;
mc_led_info[1].color_index = LED_COLOR_ID_GREEN;
mc_led_info[2].color_index = LED_COLOR_ID_BLUE;
lightbar_mc_dev->subled_info = mc_led_info;
lightbar_mc_dev->num_colors = 3;
led_cdev = &lightbar_mc_dev->led_cdev;
led_cdev->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s:rgb:indicator",
ps_dev->input_dev_name);
if (!led_cdev->name)
return -ENOMEM;
led_cdev->brightness = 255;
led_cdev->max_brightness = 255;
led_cdev->brightness_set_blocking = brightness_set;
ret = devm_led_classdev_multicolor_register(&hdev->dev, lightbar_mc_dev);
if (ret < 0) {
hid_err(hdev, "Cannot register multicolor LED device\n");
return ret;
}
return 0;
}
static struct input_dev *ps_sensors_create(struct hid_device *hdev, int accel_range, int accel_res,
int gyro_range, int gyro_res)
{
@ -614,15 +703,12 @@ static ssize_t hardware_version_show(struct device *dev,
static DEVICE_ATTR_RO(hardware_version);
static struct attribute *ps_device_attributes[] = {
static struct attribute *ps_device_attrs[] = {
&dev_attr_firmware_version.attr,
&dev_attr_hardware_version.attr,
NULL
};
static const struct attribute_group ps_device_attribute_group = {
.attrs = ps_device_attributes,
};
ATTRIBUTE_GROUPS(ps_device);
static int dualsense_get_calibration_data(struct dualsense *ds)
{
@ -714,6 +800,7 @@ err_free:
return ret;
}
static int dualsense_get_firmware_info(struct dualsense *ds)
{
uint8_t *buf;
@ -733,6 +820,15 @@ static int dualsense_get_firmware_info(struct dualsense *ds)
ds->base.hw_version = get_unaligned_le32(&buf[24]);
ds->base.fw_version = get_unaligned_le32(&buf[28]);
/* Update version is some kind of feature version. It is distinct from
* the firmware version as there can be many different variations of a
* controller over time with the same physical shell, but with different
* PCBs and other internal changes. The update version (internal name) is
* used as a means to detect what features are available and change behavior.
* Note: the version is different between DualSense and DualSense Edge.
*/
ds->update_version = get_unaligned_le16(&buf[44]);
err_free:
kfree(buf);
return ret;
@ -761,6 +857,53 @@ err_free:
return ret;
}
static int dualsense_lightbar_set_brightness(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev);
struct dualsense *ds = container_of(mc_cdev, struct dualsense, lightbar);
uint8_t red, green, blue;
led_mc_calc_color_components(mc_cdev, brightness);
red = mc_cdev->subled_info[0].brightness;
green = mc_cdev->subled_info[1].brightness;
blue = mc_cdev->subled_info[2].brightness;
dualsense_set_lightbar(ds, red, green, blue);
return 0;
}
static enum led_brightness dualsense_player_led_get_brightness(struct led_classdev *led)
{
struct hid_device *hdev = to_hid_device(led->dev->parent);
struct dualsense *ds = hid_get_drvdata(hdev);
return !!(ds->player_leds_state & BIT(led - ds->player_leds));
}
static int dualsense_player_led_set_brightness(struct led_classdev *led, enum led_brightness value)
{
struct hid_device *hdev = to_hid_device(led->dev->parent);
struct dualsense *ds = hid_get_drvdata(hdev);
unsigned long flags;
unsigned int led_index;
spin_lock_irqsave(&ds->base.lock, flags);
led_index = led - ds->player_leds;
if (value == LED_OFF)
ds->player_leds_state &= ~BIT(led_index);
else
ds->player_leds_state |= BIT(led_index);
ds->update_player_leds = true;
spin_unlock_irqrestore(&ds->base.lock, flags);
dualsense_schedule_work(ds);
return 0;
}
static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_output_report *rp,
void *buf)
{
@ -800,6 +943,16 @@ static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_
}
}
static inline void dualsense_schedule_work(struct dualsense *ds)
{
unsigned long flags;
spin_lock_irqsave(&ds->base.lock, flags);
if (ds->output_worker_initialized)
schedule_work(&ds->output_worker);
spin_unlock_irqrestore(&ds->base.lock, flags);
}
/*
* Helper function to send DualSense output reports. Applies a CRC at the end of a report
* for Bluetooth reports.
@ -838,7 +991,10 @@ static void dualsense_output_worker(struct work_struct *work)
if (ds->update_rumble) {
/* Select classic rumble style haptics and enable it. */
common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT;
common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION;
if (ds->use_vibration_v2)
common->valid_flag2 |= DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2;
else
common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION;
common->motor_left = ds->motor_left;
common->motor_right = ds->motor_right;
ds->update_rumble = false;
@ -960,7 +1116,7 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r
spin_unlock_irqrestore(&ps_dev->lock, flags);
/* Schedule updating of microphone state at hardware level. */
schedule_work(&ds->output_worker);
dualsense_schedule_work(ds);
}
ds->last_btn_mic_state = btn_mic_state;
@ -1075,10 +1231,22 @@ static int dualsense_play_effect(struct input_dev *dev, void *data, struct ff_ef
ds->motor_right = effect->u.rumble.weak_magnitude / 256;
spin_unlock_irqrestore(&ds->base.lock, flags);
schedule_work(&ds->output_worker);
dualsense_schedule_work(ds);
return 0;
}
static void dualsense_remove(struct ps_device *ps_dev)
{
struct dualsense *ds = container_of(ps_dev, struct dualsense, base);
unsigned long flags;
spin_lock_irqsave(&ds->base.lock, flags);
ds->output_worker_initialized = false;
spin_unlock_irqrestore(&ds->base.lock, flags);
cancel_work_sync(&ds->output_worker);
}
static int dualsense_reset_leds(struct dualsense *ds)
{
struct dualsense_output_report report;
@ -1106,12 +1274,16 @@ static int dualsense_reset_leds(struct dualsense *ds)
static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t green, uint8_t blue)
{
unsigned long flags;
spin_lock_irqsave(&ds->base.lock, flags);
ds->update_lightbar = true;
ds->lightbar_red = red;
ds->lightbar_green = green;
ds->lightbar_blue = blue;
spin_unlock_irqrestore(&ds->base.lock, flags);
schedule_work(&ds->output_worker);
dualsense_schedule_work(ds);
}
static void dualsense_set_player_leds(struct dualsense *ds)
@ -1134,7 +1306,7 @@ static void dualsense_set_player_leds(struct dualsense *ds)
ds->update_player_leds = true;
ds->player_leds_state = player_ids[player_id];
schedule_work(&ds->output_worker);
dualsense_schedule_work(ds);
}
static struct ps_device *dualsense_create(struct hid_device *hdev)
@ -1142,7 +1314,20 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
struct dualsense *ds;
struct ps_device *ps_dev;
uint8_t max_output_report_size;
int ret;
int i, ret;
static const struct ps_led_info player_leds_info[] = {
{ LED_FUNCTION_PLAYER1, "white", dualsense_player_led_get_brightness,
dualsense_player_led_set_brightness },
{ LED_FUNCTION_PLAYER2, "white", dualsense_player_led_get_brightness,
dualsense_player_led_set_brightness },
{ LED_FUNCTION_PLAYER3, "white", dualsense_player_led_get_brightness,
dualsense_player_led_set_brightness },
{ LED_FUNCTION_PLAYER4, "white", dualsense_player_led_get_brightness,
dualsense_player_led_set_brightness },
{ LED_FUNCTION_PLAYER5, "white", dualsense_player_led_get_brightness,
dualsense_player_led_set_brightness }
};
ds = devm_kzalloc(&hdev->dev, sizeof(*ds), GFP_KERNEL);
if (!ds)
@ -1160,7 +1345,9 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
ps_dev->battery_capacity = 100; /* initial value until parse_report. */
ps_dev->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
ps_dev->parse_report = dualsense_parse_report;
ps_dev->remove = dualsense_remove;
INIT_WORK(&ds->output_worker, dualsense_output_worker);
ds->output_worker_initialized = true;
hid_set_drvdata(hdev, ds);
max_output_report_size = sizeof(struct dualsense_output_report_bt);
@ -1181,6 +1368,21 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
return ERR_PTR(ret);
}
/* Original DualSense firmware simulated classic controller rumble through
* its new haptics hardware. It felt different from classic rumble users
* were used to. Since then new firmwares were introduced to change behavior
* and make this new 'v2' behavior default on PlayStation and other platforms.
* The original DualSense requires a new enough firmware as bundled with PS5
* software released in 2021. DualSense edge supports it out of the box.
* Both devices also support the old mode, but it is not really used.
*/
if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER) {
/* Feature version 2.21 introduced new vibration method. */
ds->use_vibration_v2 = ds->update_version >= DS_FEATURE_VERSION(2, 21);
} else if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) {
ds->use_vibration_v2 = true;
}
ret = ps_devices_list_add(ps_dev);
if (ret)
return ERR_PTR(ret);
@ -1196,6 +1398,8 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
ret = PTR_ERR(ds->gamepad);
goto err;
}
/* Use gamepad input device name as primary device name for e.g. LEDs */
ps_dev->input_dev_name = dev_name(&ds->gamepad->dev);
ds->sensors = ps_sensors_create(hdev, DS_ACC_RANGE, DS_ACC_RES_PER_G,
DS_GYRO_RANGE, DS_GYRO_RES_PER_DEG_S);
@ -1223,8 +1427,21 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
if (ret)
goto err;
ret = ps_lightbar_register(ps_dev, &ds->lightbar, dualsense_lightbar_set_brightness);
if (ret)
goto err;
/* Set default lightbar color. */
dualsense_set_lightbar(ds, 0, 0, 128); /* blue */
for (i = 0; i < ARRAY_SIZE(player_leds_info); i++) {
const struct ps_led_info *led_info = &player_leds_info[i];
ret = ps_led_register(ps_dev, &ds->player_leds[i], led_info);
if (ret < 0)
goto err;
}
ret = ps_device_set_player_id(ps_dev);
if (ret) {
hid_err(hdev, "Failed to assign player id for DualSense: %d\n", ret);
@ -1282,7 +1499,8 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err_stop;
}
if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER) {
if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER ||
hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) {
dev = dualsense_create(hdev);
if (IS_ERR(dev)) {
hid_err(hdev, "Failed to create dualsense.\n");
@ -1291,12 +1509,6 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
}
ret = devm_device_add_group(&hdev->dev, &ps_device_attribute_group);
if (ret) {
hid_err(hdev, "Failed to register sysfs nodes.\n");
goto err_close;
}
return ret;
err_close:
@ -1313,6 +1525,9 @@ static void ps_remove(struct hid_device *hdev)
ps_devices_list_remove(dev);
ps_device_release_player_id(dev);
if (dev->remove)
dev->remove(dev);
hid_hw_close(hdev);
hid_hw_stop(hdev);
}
@ -1320,6 +1535,8 @@ static void ps_remove(struct hid_device *hdev)
static const struct hid_device_id ps_devices[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
{ }
};
MODULE_DEVICE_TABLE(hid, ps_devices);
@ -1330,6 +1547,9 @@ static struct hid_driver ps_driver = {
.probe = ps_probe,
.remove = ps_remove,
.raw_event = ps_raw_event,
.driver = {
.dev_groups = ps_device_groups,
},
};
static int __init ps_init(void)

View file

@ -458,7 +458,7 @@ static void mtk_iommu_domain_free(struct iommu_domain *domain)
static int mtk_iommu_attach_device(struct iommu_domain *domain,
struct device *dev)
{
struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
struct mtk_iommu_data *data = dev_iommu_priv_get(dev), *frstdata;
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
struct device *m4udev = data->dev;
int ret, domid;
@ -468,20 +468,24 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
return domid;
if (!dom->data) {
if (mtk_iommu_domain_finalise(dom, data, domid))
/* Data is in the frstdata in sharing pgtable case. */
frstdata = mtk_iommu_get_m4u_data();
if (mtk_iommu_domain_finalise(dom, frstdata, domid))
return -ENODEV;
dom->data = data;
}
mutex_lock(&data->mutex);
if (!data->m4u_dom) { /* Initialize the M4U HW */
ret = pm_runtime_resume_and_get(m4udev);
if (ret < 0)
return ret;
goto err_unlock;
ret = mtk_iommu_hw_init(data);
if (ret) {
pm_runtime_put(m4udev);
return ret;
goto err_unlock;
}
data->m4u_dom = dom;
writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
@ -489,9 +493,14 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
pm_runtime_put(m4udev);
}
mutex_unlock(&data->mutex);
mtk_iommu_config(data, dev, true, domid);
return 0;
err_unlock:
mutex_unlock(&data->mutex);
return ret;
}
static void mtk_iommu_detach_device(struct iommu_domain *domain,
@ -603,6 +612,7 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev)
if (domid < 0)
return ERR_PTR(domid);
mutex_lock(&data->mutex);
group = data->m4u_group[domid];
if (!group) {
group = iommu_group_alloc();
@ -611,6 +621,7 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev)
} else {
iommu_group_ref_get(group);
}
mutex_unlock(&data->mutex);
return group;
}
@ -884,6 +895,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, data);
mutex_init(&data->mutex);
ret = iommu_device_sysfs_add(&data->iommu, dev, NULL,
"mtk-iommu.%pa", &ioaddr);
@ -934,7 +946,6 @@ static int mtk_iommu_remove(struct platform_device *pdev)
list_del(&data->list);
clk_disable_unprepare(data->bclk);
device_link_remove(data->smicomm_dev, &pdev->dev);
pm_runtime_disable(&pdev->dev);
devm_free_irq(&pdev->dev, data->irq, data);

View file

@ -80,6 +80,8 @@ struct mtk_iommu_data {
struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */
struct mutex mutex; /* Protect m4u_group/m4u_dom above */
struct list_head list;
struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX];
};

View file

@ -3002,18 +3002,12 @@ static int __init allocate_lpi_tables(void)
return 0;
}
static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
static u64 read_vpend_dirty_clear(void __iomem *vlpi_base)
{
u32 count = 1000000; /* 1s! */
bool clean;
u64 val;
val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
val &= ~GICR_VPENDBASER_Valid;
val &= ~clr;
val |= set;
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
do {
val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
clean = !(val & GICR_VPENDBASER_Dirty);
@ -3024,10 +3018,26 @@ static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
}
} while (!clean && count);
if (unlikely(val & GICR_VPENDBASER_Dirty)) {
if (unlikely(!clean))
pr_err_ratelimited("ITS virtual pending table not cleaning\n");
return val;
}
static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
{
u64 val;
/* Make sure we wait until the RD is done with the initial scan */
val = read_vpend_dirty_clear(vlpi_base);
val &= ~GICR_VPENDBASER_Valid;
val &= ~clr;
val |= set;
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
val = read_vpend_dirty_clear(vlpi_base);
if (unlikely(val & GICR_VPENDBASER_Dirty))
val |= GICR_VPENDBASER_PendingLast;
}
return val;
}

View file

@ -188,7 +188,6 @@ static void message_kill(struct message *m, mempool_t *pool)
{
m->bio->bi_status = BLK_STS_IOERR;
bio_endio(m->bio);
bio_put(m->bio);
mempool_free(m, pool);
}
@ -989,7 +988,6 @@ finish_bio:
*/
WARN_ON(bio_size(c->cur_from_user->bio) != 0);
bio_endio(c->cur_from_user->bio);
bio_put(c->cur_from_user->bio);
/*
* We don't actually need to take the target lock here, as all
@ -1227,7 +1225,6 @@ static int user_map(struct dm_target *ti, struct bio *bio)
return DM_MAPIO_REQUEUE;
}
bio_get(bio);
entry->msg.type = bio_type_to_user_type(bio);
entry->msg.flags = bio_flags_to_user_flags(bio);
entry->msg.sector = bio->bi_iter.bi_sector;

View file

@ -350,7 +350,7 @@ static int scmi_regulator_probe(struct scmi_device *sdev)
if (ret == -ENOMEM)
return ret;
}
of_node_put(np);
/*
* Register a regulator for each valid regulator-DT-entry that we
* can successfully reach via SCMI and has a valid associated voltage

View file

@ -501,7 +501,7 @@ static void ufs_mtk_init_va09_pwr_ctrl(struct ufs_hba *hba)
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
host->reg_va09 = regulator_get(hba->dev, "va09");
if (!host->reg_va09)
if (IS_ERR(host->reg_va09))
dev_info(hba->dev, "failed to get va09");
else
host->caps |= UFS_MTK_CAP_VA09_PWR_CTRL;

View file

@ -2093,12 +2093,13 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
lrbp->issue_time_stamp = ktime_get();
lrbp->compl_time_stamp = ktime_set(0, 0);
ufshcd_vops_setup_xfer_req(hba, task_tag, (lrbp->cmd ? true : false));
trace_android_vh_ufs_send_command(hba, lrbp);
ufshcd_add_command_trace(hba, task_tag, "send");
ufshcd_clk_scaling_start_busy(hba);
if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
ufshcd_start_monitor(hba, lrbp);
if (hba->vops && hba->vops->setup_xfer_req)
hba->vops->setup_xfer_req(hba, task_tag, !!lrbp->cmd);
if (ufshcd_has_utrlcnr(hba)) {
set_bit(task_tag, &hba->outstanding_reqs);
ufshcd_writel(hba, 1 << task_tag,

View file

@ -1304,18 +1304,6 @@ static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba,
return -ENOTSUPP;
}
static inline void ufshcd_vops_setup_xfer_req(struct ufs_hba *hba, int tag,
bool is_scsi_cmd)
{
if (hba->vops && hba->vops->setup_xfer_req) {
unsigned long flags;
spin_lock_irqsave(hba->host->host_lock, flags);
hba->vops->setup_xfer_req(hba, tag, is_scsi_cmd);
spin_unlock_irqrestore(hba->host->host_lock, flags);
}
}
static inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba,
int tag, u8 tm_function)
{

View file

@ -301,6 +301,7 @@ int dwc3_core_soft_reset(struct dwc3 *dwc)
udelay(1);
} while (--retries);
dev_warn(dwc->dev, "DWC3 controller soft reset failed.\n");
return -ETIMEDOUT;
done:

View file

@ -350,7 +350,7 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
}
}
static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup)
{
u32 val;
int i, ret;
@ -369,7 +369,7 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
if (ret)
dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret);
if (device_may_wakeup(qcom->dev))
if (wakeup)
dwc3_qcom_enable_interrupts(qcom);
qcom->is_suspended = true;
@ -377,7 +377,7 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
return 0;
}
static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
static int dwc3_qcom_resume(struct dwc3_qcom *qcom, bool wakeup)
{
int ret;
int i;
@ -385,7 +385,7 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
if (!qcom->is_suspended)
return 0;
if (device_may_wakeup(qcom->dev))
if (wakeup)
dwc3_qcom_disable_interrupts(qcom);
for (i = 0; i < qcom->num_clocks; i++) {
@ -885,9 +885,11 @@ static int dwc3_qcom_remove(struct platform_device *pdev)
static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev)
{
struct dwc3_qcom *qcom = dev_get_drvdata(dev);
bool wakeup = device_may_wakeup(dev);
int ret = 0;
ret = dwc3_qcom_suspend(qcom);
ret = dwc3_qcom_suspend(qcom, wakeup);
if (!ret)
qcom->pm_suspended = true;
@ -897,9 +899,10 @@ static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev)
static int __maybe_unused dwc3_qcom_pm_resume(struct device *dev)
{
struct dwc3_qcom *qcom = dev_get_drvdata(dev);
bool wakeup = device_may_wakeup(dev);
int ret;
ret = dwc3_qcom_resume(qcom);
ret = dwc3_qcom_resume(qcom, wakeup);
if (!ret)
qcom->pm_suspended = false;
@ -910,14 +913,14 @@ static int __maybe_unused dwc3_qcom_runtime_suspend(struct device *dev)
{
struct dwc3_qcom *qcom = dev_get_drvdata(dev);
return dwc3_qcom_suspend(qcom);
return dwc3_qcom_suspend(qcom, true);
}
static int __maybe_unused dwc3_qcom_runtime_resume(struct device *dev)
{
struct dwc3_qcom *qcom = dev_get_drvdata(dev);
return dwc3_qcom_resume(qcom);
return dwc3_qcom_resume(qcom, true);
}
static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = {

View file

@ -218,7 +218,7 @@ out:
return ret;
}
static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
{
struct dwc3_ep *dep;
@ -239,6 +239,8 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
dwc3_gadget_giveback(dep, req, -ECONNRESET);
}
dwc->eps[0]->trb_enqueue = 0;
dwc->eps[1]->trb_enqueue = 0;
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
}
@ -813,7 +815,7 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
int ret = -EINVAL;
u32 len;
if (!dwc->gadget_driver)
if (!dwc->gadget_driver || !dwc->connected)
goto out;
trace_dwc3_ctrl_req(ctrl);
@ -1087,13 +1089,18 @@ void dwc3_ep0_send_delayed_status(struct dwc3 *dwc)
__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
}
static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep)
void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep)
{
struct dwc3_gadget_ep_cmd_params params;
u32 cmd;
int ret;
if (!dep->resource_index)
/*
* For status/DATA OUT stage, TRB will be queued on ep0 out
* endpoint for which resource index is zero. Hence allow
* queuing ENDXFER command for ep0 out endpoint.
*/
if (!dep->resource_index && dep->number)
return;
cmd = DWC3_DEPCMD_ENDTRANSFER;
@ -1134,6 +1141,11 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS)
return;
if (dwc->setup_packet_pending) {
dwc3_ep0_stall_and_restart(dwc);
return;
}
dwc->ep0state = EP0_STATUS_PHASE;
if (dwc->delayed_status) {

View file

@ -332,9 +332,17 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
}
}
dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0);
dwc3_writel(dep->regs, DWC3_DEPCMDPAR1, params->param1);
dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2);
/*
* For some commands such as Update Transfer command, DEPCMDPARn
* registers are reserved. Since the driver often sends Update Transfer
* command, don't write to DEPCMDPARn to avoid register write delays and
* improve performance.
*/
if (DWC3_DEPCMD_CMD(cmd) != DWC3_DEPCMD_UPDATETRANSFER) {
dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0);
dwc3_writel(dep->regs, DWC3_DEPCMDPAR1, params->param1);
dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2);
}
/*
* Synopsys Databook 2.60a states in section 6.3.2.5.6 of that if we're
@ -358,6 +366,12 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
cmd |= DWC3_DEPCMD_CMDACT;
dwc3_writel(dep->regs, DWC3_DEPCMD, cmd);
if (!(cmd & DWC3_DEPCMD_CMDACT)) {
ret = 0;
goto skip_status;
}
do {
reg = dwc3_readl(dep->regs, DWC3_DEPCMD);
if (!(reg & DWC3_DEPCMD_CMDACT)) {
@ -399,6 +413,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
cmd_status = -ETIMEDOUT;
}
skip_status:
trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
@ -870,12 +885,13 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
reg |= DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
dep->trb_dequeue = 0;
dep->trb_enqueue = 0;
if (usb_endpoint_xfer_control(desc))
goto out;
/* Initialize the TRB ring */
dep->trb_dequeue = 0;
dep->trb_enqueue = 0;
memset(dep->trb_pool, 0,
sizeof(struct dwc3_trb) * DWC3_TRB_NUM);
@ -1638,6 +1654,40 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
return DWC3_DSTS_SOFFN(reg);
}
/**
* __dwc3_stop_active_transfer - stop the current active transfer
* @dep: isoc endpoint
* @force: set forcerm bit in the command
* @interrupt: command complete interrupt after End Transfer command
*
* When setting force, the ForceRM bit will be set. In that case
* the controller won't update the TRB progress on command
* completion. It also won't clear the HWO bit in the TRB.
* The command will also not complete immediately in that case.
*/
static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
{
struct dwc3_gadget_ep_cmd_params params;
u32 cmd;
int ret;
cmd = DWC3_DEPCMD_ENDTRANSFER;
cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0;
cmd |= interrupt ? DWC3_DEPCMD_CMDIOC : 0;
cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
memset(&params, 0, sizeof(params));
ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
WARN_ON_ONCE(ret);
dep->resource_index = 0;
if (!interrupt)
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
else if (!ret)
dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
return ret;
}
/**
* dwc3_gadget_start_isoc_quirk - workaround invalid frame number
* @dep: isoc endpoint
@ -1813,21 +1863,8 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
* status, issue END_TRANSFER command and retry on the next XferNotReady
* event.
*/
if (ret == -EAGAIN) {
struct dwc3_gadget_ep_cmd_params params;
u32 cmd;
cmd = DWC3_DEPCMD_ENDTRANSFER |
DWC3_DEPCMD_CMDIOC |
DWC3_DEPCMD_PARAM(dep->resource_index);
dep->resource_index = 0;
memset(&params, 0, sizeof(params));
ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
if (!ret)
dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
}
if (ret == -EAGAIN)
ret = __dwc3_stop_active_transfer(dep, false, true);
return ret;
}
@ -1885,13 +1922,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
* errors which will force us issue EndTransfer command.
*/
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
if (!(dep->flags & DWC3_EP_PENDING_REQUEST) &&
!(dep->flags & DWC3_EP_TRANSFER_STARTED))
return 0;
if ((dep->flags & DWC3_EP_PENDING_REQUEST)) {
if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) {
if ((dep->flags & DWC3_EP_PENDING_REQUEST))
return __dwc3_gadget_start_isoc(dep);
return 0;
}
}
@ -2011,16 +2046,6 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
if (r == req) {
struct dwc3_request *t;
/*
* If a Setup packet is received but yet to DMA out, the controller will
* not process the End Transfer command of any endpoint. Polling of its
* DEPCMD.CmdAct may block setting up TRB for Setup packet, causing a
* timeout. Delay issuing the End Transfer command until the Setup TRB is
* prepared.
*/
if (dwc->ep0state != EP0_SETUP_PHASE && !dwc->delayed_status)
dep->flags |= DWC3_EP_DELAY_STOP;
/* wait until it is processed */
dwc3_stop_active_transfer(dep, true, true);
@ -2459,6 +2484,23 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc)
spin_lock_irqsave(&dwc->lock, flags);
dwc->connected = false;
/*
* Per databook, when we want to stop the gadget, if a control transfer
* is still in process, complete it and get the core into setup phase.
*/
if (dwc->ep0state != EP0_SETUP_PHASE) {
int ret;
reinit_completion(&dwc->ep0_in_setup);
spin_unlock_irqrestore(&dwc->lock, flags);
ret = wait_for_completion_timeout(&dwc->ep0_in_setup,
msecs_to_jiffies(DWC3_PULL_UP_TIMEOUT));
spin_lock_irqsave(&dwc->lock, flags);
if (ret == 0)
dev_warn(dwc->dev, "timed out waiting for SETUP phase\n");
}
/*
* In the Synopsys DesignWare Cores USB3 Databook Rev. 3.30a
* Section 4.1.8 Table 4-7, it states that for a device-initiated
@ -2490,19 +2532,6 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
vdwc->softconnect = is_on;
/*
* Per databook, when we want to stop the gadget, if a control transfer
* is still in process, complete it and get the core into setup phase.
*/
if (!is_on && dwc->ep0state != EP0_SETUP_PHASE) {
reinit_completion(&dwc->ep0_in_setup);
ret = wait_for_completion_timeout(&dwc->ep0_in_setup,
msecs_to_jiffies(DWC3_PULL_UP_TIMEOUT));
if (ret == 0)
dev_warn(dwc->dev, "timed out waiting for SETUP phase\n");
}
/*
* Avoid issuing a runtime resume if the device is already in the
* suspended state during gadget disconnect. DWC3 gadget was already
@ -2688,6 +2717,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
/* begin to receive SETUP packets */
dwc->ep0state = EP0_SETUP_PHASE;
dwc->ep0_bounced = false;
dwc->link_state = DWC3_LINK_STATE_SS_DIS;
dwc->delayed_status = false;
dwc3_ep0_out_start(dwc);
@ -2936,6 +2966,7 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
struct dwc3 *dwc = dep->dwc;
u32 mdwidth;
int size;
int maxpacket;
mdwidth = dwc3_mdwidth(dwc);
@ -2948,21 +2979,24 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
else
size = DWC31_GTXFIFOSIZ_TXFDEP(size);
/* FIFO Depth is in MDWDITH bytes. Multiply */
size *= mdwidth;
/*
* To meet performance requirement, a minimum TxFIFO size of 3x
* MaxPacketSize is recommended for endpoints that support burst and a
* minimum TxFIFO size of 2x MaxPacketSize for endpoints that don't
* support burst. Use those numbers and we can calculate the max packet
* limit as below.
* maxpacket size is determined as part of the following, after assuming
* a mult value of one maxpacket:
* DWC3 revision 280A and prior:
* fifo_size = mult * (max_packet / mdwidth) + 1;
* maxpacket = mdwidth * (fifo_size - 1);
*
* DWC3 revision 290A and onwards:
* fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1
* maxpacket = mdwidth * ((fifo_size - 1) - 1) - mdwidth;
*/
if (dwc->maximum_speed >= USB_SPEED_SUPER)
size /= 3;
if (DWC3_VER_IS_PRIOR(DWC3, 290A))
maxpacket = mdwidth * (size - 1);
else
size /= 2;
maxpacket = mdwidth * ((size - 1) - 1) - mdwidth;
/* Functionally, space for one max packet is sufficient */
size = min_t(int, maxpacket, 1024);
usb_ep_set_maxpacket_limit(&dep->endpoint, size);
dep->endpoint.max_streams = 16;
@ -3638,15 +3672,34 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
bool interrupt)
{
struct dwc3_gadget_ep_cmd_params params;
u32 cmd;
int ret;
struct dwc3 *dwc = dep->dwc;
/*
* Only issue End Transfer command to the control endpoint of a started
* Data Phase. Typically we should only do so in error cases such as
* invalid/unexpected direction as described in the control transfer
* flow of the programming guide.
*/
if (dep->number <= 1 && dwc->ep0state != EP0_DATA_PHASE)
return;
if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) ||
(dep->flags & DWC3_EP_DELAY_STOP) ||
(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
return;
/*
* If a Setup packet is received but yet to DMA out, the controller will
* not process the End Transfer command of any endpoint. Polling of its
* DEPCMD.CmdAct may block setting up TRB for Setup packet, causing a
* timeout. Delay issuing the End Transfer command until the Setup TRB is
* prepared.
*/
if (dwc->ep0state != EP0_SETUP_PHASE && !dwc->delayed_status) {
dep->flags |= DWC3_EP_DELAY_STOP;
return;
}
/*
* NOTICE: We are violating what the Databook says about the
* EndTransfer command. Ideally we would _always_ wait for the
@ -3673,20 +3726,7 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
*
* This mode is NOT available on the DWC_usb31 IP.
*/
cmd = DWC3_DEPCMD_ENDTRANSFER;
cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0;
cmd |= interrupt ? DWC3_DEPCMD_CMDIOC : 0;
cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
memset(&params, 0, sizeof(params));
ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
WARN_ON_ONCE(ret);
dep->resource_index = 0;
if (!interrupt)
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
else
dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
__dwc3_stop_active_transfer(dep, force, interrupt);
}
EXPORT_SYMBOL_GPL(dwc3_stop_active_transfer);
@ -3723,13 +3763,24 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
reg &= ~DWC3_DCTL_INITU2ENA;
dwc3_gadget_dctl_write_safe(dwc, reg);
dwc->connected = false;
dwc3_disconnect_gadget(dwc);
dwc->gadget->speed = USB_SPEED_UNKNOWN;
dwc->setup_packet_pending = false;
usb_gadget_set_state(dwc->gadget, USB_STATE_NOTATTACHED);
dwc->connected = false;
if (dwc->ep0state != EP0_SETUP_PHASE) {
unsigned int dir;
dir = !!dwc->ep0_expect_in;
if (dwc->ep0state == EP0_DATA_PHASE)
dwc3_ep0_end_control_data(dwc, dwc->eps[dir]);
else
dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]);
dwc3_ep0_stall_and_restart(dwc);
}
}
static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
@ -3777,6 +3828,27 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
}
dwc3_reset_gadget(dwc);
/*
* From SNPS databook section 8.1.2, the EP0 should be in setup
* phase. So ensure that EP0 is in setup phase by issuing a stall
* and restart if EP0 is not in setup phase.
*/
if (dwc->ep0state != EP0_SETUP_PHASE) {
unsigned int dir;
dir = !!dwc->ep0_expect_in;
if (dwc->ep0state == EP0_DATA_PHASE)
dwc3_ep0_end_control_data(dwc, dwc->eps[dir]);
else
dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]);
dwc->eps[0]->trb_enqueue = 0;
dwc->eps[1]->trb_enqueue = 0;
dwc3_ep0_stall_and_restart(dwc);
}
/*
* In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
* Section 4.1.2 Table 4-2, it states that during a USB reset, the SW
@ -4157,7 +4229,6 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
struct dwc3 *dwc = evt->dwc;
irqreturn_t ret = IRQ_NONE;
int left;
u32 reg;
left = evt->count;
@ -4188,9 +4259,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
ret = IRQ_HANDLED;
/* Unmask interrupt */
reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0));
reg &= ~DWC3_GEVNTSIZ_INTMASK;
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg);
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
DWC3_GEVNTSIZ_SIZE(evt->length));
if (dwc->imod_interval) {
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB);
@ -4224,7 +4294,6 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
struct dwc3 *dwc = evt->dwc;
u32 amount;
u32 count;
u32 reg;
if (pm_runtime_suspended(dwc->dev)) {
pm_runtime_get(dwc->dev);
@ -4251,9 +4320,8 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
evt->flags |= DWC3_EVENT_PENDING;
/* Mask interrupt */
reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0));
reg |= DWC3_GEVNTSIZ_INTMASK;
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg);
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(evt->length));
amount = min(count, evt->length - evt->lpos);
memcpy(evt->cache + evt->lpos, evt->buf + evt->lpos, amount);

View file

@ -110,6 +110,8 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
void dwc3_ep0_interrupt(struct dwc3 *dwc,
const struct dwc3_event_depevt *event);
void dwc3_ep0_out_start(struct dwc3 *dwc);
void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep);
void dwc3_ep0_stall_and_restart(struct dwc3 *dwc);
int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,

View file

@ -16,7 +16,7 @@
#include <linux/usb/ch9.h>
#ifdef CONFIG_USB_CONFIGFS_F_ACC
extern int acc_ctrlrequest(struct usb_composite_dev *cdev,
extern int acc_ctrlrequest_composite(struct usb_composite_dev *cdev,
const struct usb_ctrlrequest *ctrl);
void acc_disconnect(void);
#endif
@ -1572,7 +1572,7 @@ static int android_setup(struct usb_gadget *gadget,
#ifdef CONFIG_USB_CONFIGFS_F_ACC
if (value < 0)
value = acc_ctrlrequest(cdev, c);
value = acc_ctrlrequest_composite(cdev, c);
#endif
if (value < 0)

View file

@ -1085,6 +1085,26 @@ err:
}
EXPORT_SYMBOL_GPL(acc_ctrlrequest);
int acc_ctrlrequest_composite(struct usb_composite_dev *cdev,
const struct usb_ctrlrequest *ctrl)
{
u16 w_length = le16_to_cpu(ctrl->wLength);
if (w_length > USB_COMP_EP0_BUFSIZ) {
if (ctrl->bRequestType & USB_DIR_IN) {
/* Cast away the const, we are going to overwrite on purpose. */
__le16 *temp = (__le16 *)&ctrl->wLength;
*temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ);
w_length = USB_COMP_EP0_BUFSIZ;
} else {
return -EINVAL;
}
}
return acc_ctrlrequest(cdev, ctrl);
}
EXPORT_SYMBOL_GPL(acc_ctrlrequest_composite);
static int
__acc_function_bind(struct usb_configuration *c,
struct usb_function *f, bool configfs)

View file

@ -279,6 +279,9 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
struct usb_request *req = ffs->ep0req;
int ret;
if (!req)
return -EINVAL;
req->zero = len < le16_to_cpu(ffs->ev.setup.wLength);
spin_unlock_irq(&ffs->ev.waitq.lock);
@ -1891,10 +1894,14 @@ static void functionfs_unbind(struct ffs_data *ffs)
ENTER();
if (!WARN_ON(!ffs->gadget)) {
/* dequeue before freeing ep0req */
usb_ep_dequeue(ffs->gadget->ep0, ffs->ep0req);
mutex_lock(&ffs->mutex);
usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req);
ffs->ep0req = NULL;
ffs->gadget = NULL;
clear_bit(FFS_FL_BOUND, &ffs->flags);
mutex_unlock(&ffs->mutex);
ffs_data_put(ffs);
}
}

View file

@ -1191,13 +1191,14 @@ static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
u8 format;
int i, len;
format = common->cmnd[2] & 0xf;
if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */
start_track > 1) {
(start_track > 1 && format != 0x1)) {
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL;
}
format = common->cmnd[2] & 0xf;
/*
* Check if CDB is old style SFF-8020i
* i.e. format is in 2 MSBs of byte 9
@ -1207,8 +1208,8 @@ static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
format = (common->cmnd[9] >> 6) & 0x3;
switch (format) {
case 0:
/* Formatted TOC */
case 0: /* Formatted TOC */
case 1: /* Multi-session info */
len = 4 + 2*8; /* 4 byte header + 2 descriptors */
memset(buf, 0, len);
buf[1] = len - 2; /* TOC Length excludes length field */
@ -1249,7 +1250,7 @@ static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
return len;
default:
/* Multi-session, PMA, ATIP, CD-TEXT not supported/required */
/* PMA, ATIP, CD-TEXT not supported/required */
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL;
}

View file

@ -281,6 +281,12 @@ static struct usb_endpoint_descriptor ss_ep_int_desc = {
.bInterval = 4,
};
static struct usb_ss_ep_comp_descriptor ss_ep_int_desc_comp = {
.bLength = sizeof(ss_ep_int_desc_comp),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
.wBytesPerInterval = cpu_to_le16(6),
};
/* Audio Streaming OUT Interface - Alt0 */
static struct usb_interface_descriptor std_as_out_if0_desc = {
.bLength = sizeof std_as_out_if0_desc,
@ -594,7 +600,8 @@ static struct usb_descriptor_header *ss_audio_desc[] = {
(struct usb_descriptor_header *)&in_feature_unit_desc,
(struct usb_descriptor_header *)&io_out_ot_desc,
(struct usb_descriptor_header *)&ss_ep_int_desc,
(struct usb_descriptor_header *)&ss_ep_int_desc,
(struct usb_descriptor_header *)&ss_ep_int_desc_comp,
(struct usb_descriptor_header *)&std_as_out_if0_desc,
(struct usb_descriptor_header *)&std_as_out_if1_desc,
@ -746,6 +753,7 @@ static void setup_headers(struct f_uac2_opts *opts,
struct usb_ss_ep_comp_descriptor *epout_desc_comp = NULL;
struct usb_ss_ep_comp_descriptor *epin_desc_comp = NULL;
struct usb_ss_ep_comp_descriptor *epin_fback_desc_comp = NULL;
struct usb_ss_ep_comp_descriptor *ep_int_desc_comp = NULL;
struct usb_endpoint_descriptor *epout_desc;
struct usb_endpoint_descriptor *epin_desc;
struct usb_endpoint_descriptor *epin_fback_desc;
@ -773,6 +781,7 @@ static void setup_headers(struct f_uac2_opts *opts,
epin_fback_desc = &ss_epin_fback_desc;
epin_fback_desc_comp = &ss_epin_fback_desc_comp;
ep_int_desc = &ss_ep_int_desc;
ep_int_desc_comp = &ss_ep_int_desc_comp;
}
i = 0;
@ -801,8 +810,11 @@ static void setup_headers(struct f_uac2_opts *opts,
if (EPOUT_EN(opts))
headers[i++] = USBDHDR(&io_out_ot_desc);
if (FUOUT_EN(opts) || FUIN_EN(opts))
headers[i++] = USBDHDR(ep_int_desc);
if (FUOUT_EN(opts) || FUIN_EN(opts)) {
headers[i++] = USBDHDR(ep_int_desc);
if (ep_int_desc_comp)
headers[i++] = USBDHDR(ep_int_desc_comp);
}
if (EPOUT_EN(opts)) {
headers[i++] = USBDHDR(&std_as_out_if0_desc);

View file

@ -2448,6 +2448,7 @@ static ssize_t f_uvc_opts_string_##cname##_store(struct config_item *item,\
const char *page, size_t len) \
{ \
struct f_uvc_opts *opts = to_f_uvc_opts(item); \
int size = min(sizeof(opts->aname), len + 1); \
int ret = 0; \
\
mutex_lock(&opts->lock); \
@ -2456,8 +2457,9 @@ static ssize_t f_uvc_opts_string_##cname##_store(struct config_item *item,\
goto end; \
} \
\
ret = snprintf(opts->aname, min(sizeof(opts->aname), len), \
"%s", page); \
ret = strscpy(opts->aname, page, size); \
if (ret == -E2BIG) \
ret = size - 1; \
\
end: \
mutex_unlock(&opts->lock); \

View file

@ -85,9 +85,25 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val)
static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
bool vconn_pres;
enum typec_cc_polarity polarity = TYPEC_POLARITY_CC1;
unsigned int reg;
int ret;
ret = regmap_read(tcpci->regmap, TCPC_POWER_STATUS, &reg);
if (ret < 0)
return ret;
vconn_pres = !!(reg & TCPC_POWER_STATUS_VCONN_PRES);
if (vconn_pres) {
ret = regmap_read(tcpci->regmap, TCPC_TCPC_CTRL, &reg);
if (ret < 0)
return ret;
if (reg & TCPC_TCPC_CTRL_ORIENTATION)
polarity = TYPEC_POLARITY_CC2;
}
switch (cc) {
case TYPEC_CC_RA:
reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) |
@ -122,6 +138,16 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
break;
}
if (vconn_pres) {
if (polarity == TYPEC_POLARITY_CC2) {
reg &= ~(TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT);
reg |= (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT);
} else {
reg &= ~(TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT);
reg |= (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT);
}
}
ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
if (ret < 0)
return ret;

View file

@ -98,6 +98,7 @@
#define TCPC_POWER_STATUS_SOURCING_VBUS BIT(4)
#define TCPC_POWER_STATUS_VBUS_DET BIT(3)
#define TCPC_POWER_STATUS_VBUS_PRES BIT(2)
#define TCPC_POWER_STATUS_VCONN_PRES BIT(1)
#define TCPC_POWER_STATUS_SINKING_VBUS BIT(0)
#define TCPC_FAULT_STATUS 0x1f

View file

@ -5354,6 +5354,10 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
case PR_SWAP_SNK_SRC_SOURCE_ON:
/* Do nothing, vsafe0v is expected during transition */
break;
case SNK_ATTACH_WAIT:
case SNK_DEBOUNCED:
/*Do nothing, still waiting for VSAFE5V for connect */
break;
default:
if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
tcpm_set_state(port, SNK_UNATTACHED, 0);

View file

@ -1061,6 +1061,15 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
con->num = index + 1;
con->ucsi = ucsi;
cap->fwnode = ucsi_find_fwnode(con);
con->usb_role_sw = fwnode_usb_role_switch_get(cap->fwnode);
if (IS_ERR(con->usb_role_sw)) {
dev_err(ucsi->dev, "con%d: failed to get usb role switch\n",
con->num);
return PTR_ERR(con->usb_role_sw);
}
/* Delay other interactions with the con until registration is complete */
mutex_lock(&con->lock);
@ -1096,7 +1105,6 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY)
*accessory = TYPEC_ACCESSORY_DEBUG;
cap->fwnode = ucsi_find_fwnode(con);
cap->driver_data = con;
cap->ops = &ucsi_ops;
@ -1154,13 +1162,6 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
ucsi_port_psy_changed(con);
}
con->usb_role_sw = fwnode_usb_role_switch_get(cap->fwnode);
if (IS_ERR(con->usb_role_sw)) {
dev_err(ucsi->dev, "con%d: failed to get usb role switch\n",
con->num);
con->usb_role_sw = NULL;
}
/* Only notify USB controller if partner supports USB data */
if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB))
u_role = USB_ROLE_NONE;
@ -1273,12 +1274,21 @@ err:
static void ucsi_init_work(struct work_struct *work)
{
struct ucsi *ucsi = container_of(work, struct ucsi, work);
struct ucsi_android *aucsi = container_of(work,
struct ucsi_android, work.work);
int ret;
ret = ucsi_init(ucsi);
ret = ucsi_init(&aucsi->ucsi);
if (ret)
dev_err(ucsi->dev, "PPM init failed (%d)\n", ret);
dev_err(aucsi->ucsi.dev, "PPM init failed (%d)\n", ret);
if (ret == -EPROBE_DEFER) {
if (aucsi->work_count++ > UCSI_ROLE_SWITCH_WAIT_COUNT)
return;
queue_delayed_work(system_long_wq, &aucsi->work,
UCSI_ROLE_SWITCH_INTERVAL);
}
}
/**
@ -1310,15 +1320,17 @@ EXPORT_SYMBOL_GPL(ucsi_set_drvdata);
struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops)
{
struct ucsi *ucsi;
struct ucsi_android *aucsi;
if (!ops || !ops->read || !ops->sync_write || !ops->async_write)
return ERR_PTR(-EINVAL);
ucsi = kzalloc(sizeof(*ucsi), GFP_KERNEL);
if (!ucsi)
aucsi = kzalloc(sizeof(*aucsi), GFP_KERNEL);
if (!aucsi)
return ERR_PTR(-ENOMEM);
INIT_WORK(&ucsi->work, ucsi_init_work);
ucsi = &aucsi->ucsi;
INIT_DELAYED_WORK(&aucsi->work, ucsi_init_work);
mutex_init(&ucsi->ppm_lock);
ucsi->dev = dev;
ucsi->ops = ops;
@ -1333,7 +1345,9 @@ EXPORT_SYMBOL_GPL(ucsi_create);
*/
void ucsi_destroy(struct ucsi *ucsi)
{
kfree(ucsi);
struct ucsi_android *aucsi = container_of(ucsi,
struct ucsi_android, ucsi);
kfree(aucsi);
}
EXPORT_SYMBOL_GPL(ucsi_destroy);
@ -1343,6 +1357,8 @@ EXPORT_SYMBOL_GPL(ucsi_destroy);
*/
int ucsi_register(struct ucsi *ucsi)
{
struct ucsi_android *aucsi = container_of(ucsi,
struct ucsi_android, ucsi);
int ret;
ret = ucsi->ops->read(ucsi, UCSI_VERSION, &ucsi->version,
@ -1353,7 +1369,7 @@ int ucsi_register(struct ucsi *ucsi)
if (!ucsi->version)
return -ENODEV;
queue_work(system_long_wq, &ucsi->work);
queue_delayed_work(system_long_wq, &aucsi->work, 0);
return 0;
}
@ -1367,11 +1383,13 @@ EXPORT_SYMBOL_GPL(ucsi_register);
*/
void ucsi_unregister(struct ucsi *ucsi)
{
struct ucsi_android *aucsi = container_of(ucsi,
struct ucsi_android, ucsi);
u64 cmd = UCSI_SET_NOTIFICATION_ENABLE;
int i;
/* Make sure that we are not in the middle of driver initialization */
cancel_work_sync(&ucsi->work);
cancel_delayed_work_sync(&aucsi->work);
/* Disable notifications */
ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));

View file

@ -289,6 +289,9 @@ struct ucsi {
struct ucsi_connector *connector;
struct work_struct work;
#define UCSI_ROLE_SWITCH_RETRY_PER_HZ 10
#define UCSI_ROLE_SWITCH_INTERVAL (HZ / UCSI_ROLE_SWITCH_RETRY_PER_HZ)
#define UCSI_ROLE_SWITCH_WAIT_COUNT (10 * UCSI_ROLE_SWITCH_RETRY_PER_HZ)
/* PPM Communication lock */
struct mutex ppm_lock;
@ -304,6 +307,25 @@ struct ucsi {
#define EVENT_PROCESSING 3
};
/**
* struct ucsi_android - contains parameters without modifying the format
* of ucsi struct.
* @ucsi: contains the ucsi reference.
* @work: work structure for queuing ucsi_init_work.
* @work_count: to track the wait count(MAX= UCSI_ROLE_SWITCH_WAIT_COUNT).
*
* Required to address Bug: 260537721
* If the role switch module probes late the
* fwnode_usb_role_switch_get() will fail with -EPROBE_DEFER.
* To recover from this, restart the ucsi_init_work
* to find the fwnode again using a delayed workqueue.
*/
struct ucsi_android {
struct ucsi ucsi;
struct delayed_work work;
int work_count;
};
#define UCSI_MAX_SVID 5
#define UCSI_MAX_ALTMODES (UCSI_MAX_SVID * 6)

View file

@ -3655,6 +3655,9 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle,
struct buffer_head *bh;
if (!ext4_has_inline_data(inode)) {
struct ext4_dir_entry_2 *de;
unsigned int offset;
/* The first directory block must not be a hole, so
* treat it as DIRENT_HTREE
*/
@ -3663,9 +3666,30 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle,
*retval = PTR_ERR(bh);
return NULL;
}
*parent_de = ext4_next_entry(
(struct ext4_dir_entry_2 *)bh->b_data,
inode->i_sb->s_blocksize);
de = (struct ext4_dir_entry_2 *) bh->b_data;
if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data,
bh->b_size, 0, 0) ||
le32_to_cpu(de->inode) != inode->i_ino ||
strcmp(".", de->name)) {
EXT4_ERROR_INODE(inode, "directory missing '.'");
brelse(bh);
*retval = -EFSCORRUPTED;
return NULL;
}
offset = ext4_rec_len_from_disk(de->rec_len,
inode->i_sb->s_blocksize);
de = ext4_next_entry(de, inode->i_sb->s_blocksize);
if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data,
bh->b_size, 0, offset) ||
le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) {
EXT4_ERROR_INODE(inode, "directory missing '..'");
brelse(bh);
*retval = -EFSCORRUPTED;
return NULL;
}
*parent_de = de;
return bh;
}

View file

@ -1469,6 +1469,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc,
if (cluster_may_compress(cc)) {
err = f2fs_compress_pages(cc);
if (err == -EAGAIN) {
add_compr_block_stat(cc->inode, cc->cluster_size);
goto write;
} else if (err) {
f2fs_put_rpages_wbc(cc, wbc, true, 1);
@ -1659,6 +1660,30 @@ void f2fs_put_page_dic(struct page *page)
f2fs_put_dic(dic);
}
/*
* check whether cluster blocks are contiguous, and add extent cache entry
* only if cluster blocks are logically and physically contiguous.
*/
unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn)
{
bool compressed = f2fs_data_blkaddr(dn) == COMPRESS_ADDR;
int i = compressed ? 1 : 0;
block_t first_blkaddr = data_blkaddr(dn->inode, dn->node_page,
dn->ofs_in_node + i);
for (i += 1; i < F2FS_I(dn->inode)->i_cluster_size; i++) {
block_t blkaddr = data_blkaddr(dn->inode, dn->node_page,
dn->ofs_in_node + i);
if (!__is_valid_data_blkaddr(blkaddr))
break;
if (first_blkaddr + i - (compressed ? 1 : 0) != blkaddr)
return 0;
}
return compressed ? i - 1 : i;
}
const struct address_space_operations f2fs_compress_aops = {
.releasepage = f2fs_release_page,
.invalidatepage = f2fs_invalidate_page,

View file

@ -1085,7 +1085,7 @@ void f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr)
{
dn->data_blkaddr = blkaddr;
f2fs_set_data_blkaddr(dn);
f2fs_update_extent_cache(dn);
f2fs_update_read_extent_cache(dn);
}
/* dn->ofs_in_node will be returned with up-to-date last block pointer */
@ -1151,10 +1151,10 @@ int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index)
int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index)
{
struct extent_info ei = {0, 0, 0};
struct extent_info ei = {0, };
struct inode *inode = dn->inode;
if (f2fs_lookup_extent_cache(inode, index, &ei)) {
if (f2fs_lookup_read_extent_cache(inode, index, &ei)) {
dn->data_blkaddr = ei.blk + index - ei.fofs;
return 0;
}
@ -1168,14 +1168,14 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
struct address_space *mapping = inode->i_mapping;
struct dnode_of_data dn;
struct page *page;
struct extent_info ei = {0,0,0};
struct extent_info ei = {0, };
int err;
page = f2fs_grab_cache_page(mapping, index, for_write);
if (!page)
return ERR_PTR(-ENOMEM);
if (f2fs_lookup_extent_cache(inode, index, &ei)) {
if (f2fs_lookup_read_extent_cache(inode, index, &ei)) {
dn.data_blkaddr = ei.blk + index - ei.fofs;
if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr,
DATA_GENERIC_ENHANCE_READ)) {
@ -1466,7 +1466,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
int err = 0, ofs = 1;
unsigned int ofs_in_node, last_ofs_in_node;
blkcnt_t prealloc;
struct extent_info ei = {0,0,0};
struct extent_info ei = {0, };
block_t blkaddr;
unsigned int start_pgofs;
@ -1480,7 +1480,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
pgofs = (pgoff_t)map->m_lblk;
end = pgofs + maxblocks;
if (!create && f2fs_lookup_extent_cache(inode, pgofs, &ei)) {
if (!create && f2fs_lookup_read_extent_cache(inode, pgofs, &ei)) {
if (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
map->m_may_create)
goto next_dnode;
@ -1654,7 +1654,7 @@ skip:
if (map->m_flags & F2FS_MAP_MAPPED) {
unsigned int ofs = start_pgofs - map->m_lblk;
f2fs_update_extent_cache_range(&dn,
f2fs_update_read_extent_cache_range(&dn,
start_pgofs, map->m_pblk + ofs,
map->m_len - ofs);
}
@ -1679,7 +1679,7 @@ sync_out:
if (map->m_flags & F2FS_MAP_MAPPED) {
unsigned int ofs = start_pgofs - map->m_lblk;
f2fs_update_extent_cache_range(&dn,
f2fs_update_read_extent_cache_range(&dn,
start_pgofs, map->m_pblk + ofs,
map->m_len - ofs);
}
@ -2156,6 +2156,8 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
sector_t last_block_in_file;
const unsigned blocksize = blks_to_bytes(inode, 1);
struct decompress_io_ctx *dic = NULL;
struct extent_info ei = {};
bool from_dnode = true;
int i;
int ret = 0;
@ -2188,6 +2190,12 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
if (f2fs_cluster_is_empty(cc))
goto out;
if (f2fs_lookup_read_extent_cache(inode, start_idx, &ei))
from_dnode = false;
if (!from_dnode)
goto skip_reading_dnode;
set_new_dnode(&dn, inode, NULL, NULL, 0);
ret = f2fs_get_dnode_of_data(&dn, start_idx, LOOKUP_NODE);
if (ret)
@ -2195,11 +2203,13 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
f2fs_bug_on(sbi, dn.data_blkaddr != COMPRESS_ADDR);
skip_reading_dnode:
for (i = 1; i < cc->cluster_size; i++) {
block_t blkaddr;
blkaddr = data_blkaddr(dn.inode, dn.node_page,
dn.ofs_in_node + i);
blkaddr = from_dnode ? data_blkaddr(dn.inode, dn.node_page,
dn.ofs_in_node + i) :
ei.blk + i - 1;
if (!__is_valid_data_blkaddr(blkaddr))
break;
@ -2209,6 +2219,9 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
goto out_put_dnode;
}
cc->nr_cpages++;
if (!from_dnode && i >= ei.c_len)
break;
}
/* nothing to decompress */
@ -2228,8 +2241,9 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
block_t blkaddr;
struct bio_post_read_ctx *ctx;
blkaddr = data_blkaddr(dn.inode, dn.node_page,
dn.ofs_in_node + i + 1);
blkaddr = from_dnode ? data_blkaddr(dn.inode, dn.node_page,
dn.ofs_in_node + i + 1) :
ei.blk + i;
f2fs_wait_on_block_writeback(inode, blkaddr);
@ -2274,13 +2288,15 @@ submit_and_realloc:
*last_block_in_bio = blkaddr;
}
f2fs_put_dnode(&dn);
if (from_dnode)
f2fs_put_dnode(&dn);
*bio_ret = bio;
return 0;
out_put_dnode:
f2fs_put_dnode(&dn);
if (from_dnode)
f2fs_put_dnode(&dn);
out:
for (i = 0; i < cc->cluster_size; i++) {
if (cc->rpages[i]) {
@ -2584,14 +2600,14 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
struct page *page = fio->page;
struct inode *inode = page->mapping->host;
struct dnode_of_data dn;
struct extent_info ei = {0,0,0};
struct extent_info ei = {0, };
struct node_info ni;
bool ipu_force = false;
int err = 0;
set_new_dnode(&dn, inode, NULL, NULL, 0);
if (need_inplace_update(fio) &&
f2fs_lookup_extent_cache(inode, page->index, &ei)) {
f2fs_lookup_read_extent_cache(inode, page->index, &ei)) {
fio->old_blkaddr = ei.blk + page->index - ei.fofs;
if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
@ -3265,7 +3281,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
struct dnode_of_data dn;
struct page *ipage;
bool locked = false;
struct extent_info ei = {0,0,0};
struct extent_info ei = {0, };
int err = 0;
int flag;
@ -3316,7 +3332,7 @@ restart:
} else if (locked) {
err = f2fs_get_block(&dn, index);
} else {
if (f2fs_lookup_extent_cache(inode, index, &ei)) {
if (f2fs_lookup_read_extent_cache(inode, index, &ei)) {
dn.data_blkaddr = ei.blk + index - ei.fofs;
} else {
/* hole case */

View file

@ -72,15 +72,26 @@ static void update_general_status(struct f2fs_sb_info *sbi)
si->main_area_zones = si->main_area_sections /
le32_to_cpu(raw_super->secs_per_zone);
/* validation check of the segment numbers */
/* general extent cache stats */
for (i = 0; i < NR_EXTENT_CACHES; i++) {
struct extent_tree_info *eti = &sbi->extent_tree[i];
si->hit_cached[i] = atomic64_read(&sbi->read_hit_cached[i]);
si->hit_rbtree[i] = atomic64_read(&sbi->read_hit_rbtree[i]);
si->total_ext[i] = atomic64_read(&sbi->total_hit_ext[i]);
si->hit_total[i] = si->hit_cached[i] + si->hit_rbtree[i];
si->ext_tree[i] = atomic_read(&eti->total_ext_tree);
si->zombie_tree[i] = atomic_read(&eti->total_zombie_tree);
si->ext_node[i] = atomic_read(&eti->total_ext_node);
}
/* read extent_cache only */
si->hit_largest = atomic64_read(&sbi->read_hit_largest);
si->hit_cached = atomic64_read(&sbi->read_hit_cached);
si->hit_rbtree = atomic64_read(&sbi->read_hit_rbtree);
si->hit_total = si->hit_largest + si->hit_cached + si->hit_rbtree;
si->total_ext = atomic64_read(&sbi->total_hit_ext);
si->ext_tree = atomic_read(&sbi->total_ext_tree);
si->zombie_tree = atomic_read(&sbi->total_zombie_tree);
si->ext_node = atomic_read(&sbi->total_ext_node);
si->hit_total[EX_READ] += si->hit_largest;
/* block age extent_cache only */
si->allocated_data_blocks = atomic64_read(&sbi->allocated_data_blocks);
/* validation check of the segment numbers */
si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
@ -299,10 +310,16 @@ get_cache:
si->cache_mem += si->inmem_pages * sizeof(struct inmem_pages);
for (i = 0; i < MAX_INO_ENTRY; i++)
si->cache_mem += sbi->im[i].ino_num * sizeof(struct ino_entry);
si->cache_mem += atomic_read(&sbi->total_ext_tree) *
for (i = 0; i < NR_EXTENT_CACHES; i++) {
struct extent_tree_info *eti = &sbi->extent_tree[i];
si->ext_mem[i] = atomic_read(&eti->total_ext_tree) *
sizeof(struct extent_tree);
si->cache_mem += atomic_read(&sbi->total_ext_node) *
si->ext_mem[i] += atomic_read(&eti->total_ext_node) *
sizeof(struct extent_node);
si->cache_mem += si->ext_mem[i];
}
si->page_mem = 0;
if (sbi->node_inode) {
@ -471,16 +488,34 @@ static int stat_show(struct seq_file *s, void *v)
si->skipped_atomic_files[BG_GC]);
seq_printf(s, "BG skip : IO: %u, Other: %u\n",
si->io_skip_bggc, si->other_skip_bggc);
seq_puts(s, "\nExtent Cache:\n");
seq_puts(s, "\nExtent Cache (Read):\n");
seq_printf(s, " - Hit Count: L1-1:%llu L1-2:%llu L2:%llu\n",
si->hit_largest, si->hit_cached,
si->hit_rbtree);
si->hit_largest, si->hit_cached[EX_READ],
si->hit_rbtree[EX_READ]);
seq_printf(s, " - Hit Ratio: %llu%% (%llu / %llu)\n",
!si->total_ext ? 0 :
div64_u64(si->hit_total * 100, si->total_ext),
si->hit_total, si->total_ext);
!si->total_ext[EX_READ] ? 0 :
div64_u64(si->hit_total[EX_READ] * 100,
si->total_ext[EX_READ]),
si->hit_total[EX_READ], si->total_ext[EX_READ]);
seq_printf(s, " - Inner Struct Count: tree: %d(%d), node: %d\n",
si->ext_tree, si->zombie_tree, si->ext_node);
si->ext_tree[EX_READ], si->zombie_tree[EX_READ],
si->ext_node[EX_READ]);
seq_puts(s, "\nExtent Cache (Block Age):\n");
seq_printf(s, " - Allocated Data Blocks: %llu\n",
si->allocated_data_blocks);
seq_printf(s, " - Hit Count: L1:%llu L2:%llu\n",
si->hit_cached[EX_BLOCK_AGE],
si->hit_rbtree[EX_BLOCK_AGE]);
seq_printf(s, " - Hit Ratio: %llu%% (%llu / %llu)\n",
!si->total_ext[EX_BLOCK_AGE] ? 0 :
div64_u64(si->hit_total[EX_BLOCK_AGE] * 100,
si->total_ext[EX_BLOCK_AGE]),
si->hit_total[EX_BLOCK_AGE],
si->total_ext[EX_BLOCK_AGE]);
seq_printf(s, " - Inner Struct Count: tree: %d(%d), node: %d\n",
si->ext_tree[EX_BLOCK_AGE],
si->zombie_tree[EX_BLOCK_AGE],
si->ext_node[EX_BLOCK_AGE]);
seq_puts(s, "\nBalancing F2FS Async:\n");
seq_printf(s, " - DIO (R: %4d, W: %4d)\n",
si->nr_dio_read, si->nr_dio_write);
@ -546,8 +581,12 @@ static int stat_show(struct seq_file *s, void *v)
(si->base_mem + si->cache_mem + si->page_mem) >> 10);
seq_printf(s, " - static: %llu KB\n",
si->base_mem >> 10);
seq_printf(s, " - cached: %llu KB\n",
seq_printf(s, " - cached all: %llu KB\n",
si->cache_mem >> 10);
seq_printf(s, " - read extent cache: %llu KB\n",
si->ext_mem[EX_READ] >> 10);
seq_printf(s, " - block age extent cache: %llu KB\n",
si->ext_mem[EX_BLOCK_AGE] >> 10);
seq_printf(s, " - paged : %llu KB\n",
si->page_mem >> 10);
}
@ -579,10 +618,15 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
si->sbi = sbi;
sbi->stat_info = si;
atomic64_set(&sbi->total_hit_ext, 0);
atomic64_set(&sbi->read_hit_rbtree, 0);
/* general extent cache stats */
for (i = 0; i < NR_EXTENT_CACHES; i++) {
atomic64_set(&sbi->total_hit_ext[i], 0);
atomic64_set(&sbi->read_hit_rbtree[i], 0);
atomic64_set(&sbi->read_hit_cached[i], 0);
}
/* read extent_cache only */
atomic64_set(&sbi->read_hit_largest, 0);
atomic64_set(&sbi->read_hit_cached, 0);
atomic_set(&sbi->inline_xattr, 0);
atomic_set(&sbi->inline_inode, 0);

View file

@ -82,7 +82,8 @@ int f2fs_init_casefolded_name(const struct inode *dir,
#ifdef CONFIG_UNICODE
struct super_block *sb = dir->i_sb;
if (IS_CASEFOLDED(dir)) {
if (IS_CASEFOLDED(dir) &&
!is_dot_dotdot(fname->usr_fname->name, fname->usr_fname->len)) {
fname->cf_name.name = kmem_cache_alloc(f2fs_cf_name_slab,
GFP_NOFS);
if (!fname->cf_name.name)

File diff suppressed because it is too large Load diff

View file

@ -84,7 +84,7 @@ extern const char *f2fs_fault_name[FAULT_MAX];
#define F2FS_MOUNT_FLUSH_MERGE 0x00000400
#define F2FS_MOUNT_NOBARRIER 0x00000800
#define F2FS_MOUNT_FASTBOOT 0x00001000
#define F2FS_MOUNT_EXTENT_CACHE 0x00002000
#define F2FS_MOUNT_READ_EXTENT_CACHE 0x00002000
#define F2FS_MOUNT_DATA_FLUSH 0x00008000
#define F2FS_MOUNT_FAULT_INJECTION 0x00010000
#define F2FS_MOUNT_USRQUOTA 0x00080000
@ -99,6 +99,7 @@ extern const char *f2fs_fault_name[FAULT_MAX];
#define F2FS_MOUNT_MERGE_CHECKPOINT 0x10000000
#define F2FS_MOUNT_GC_MERGE 0x20000000
#define F2FS_MOUNT_COMPRESS_CACHE 0x40000000
#define F2FS_MOUNT_AGE_EXTENT_CACHE 0x80000000
#define F2FS_OPTION(sbi) ((sbi)->mount_opt)
#define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= ~F2FS_MOUNT_##option)
@ -494,11 +495,11 @@ struct f2fs_filename {
#ifdef CONFIG_UNICODE
/*
* For casefolded directories: the casefolded name, but it's left NULL
* if the original name is not valid Unicode, if the directory is both
* casefolded and encrypted and its encryption key is unavailable, or if
* the filesystem is doing an internal operation where usr_fname is also
* NULL. In all these cases we fall back to treating the name as an
* opaque byte sequence.
* if the original name is not valid Unicode, if the original name is
* "." or "..", if the directory is both casefolded and encrypted and
* its encryption key is unavailable, or if the filesystem is doing an
* internal operation where usr_fname is also NULL. In all these cases
* we fall back to treating the name as an opaque byte sequence.
*/
struct fscrypt_str cf_name;
#endif
@ -572,7 +573,26 @@ enum {
#define F2FS_MIN_EXTENT_LEN 64 /* minimum extent length */
/* number of extent info in extent cache we try to shrink */
#define EXTENT_CACHE_SHRINK_NUMBER 128
#define READ_EXTENT_CACHE_SHRINK_NUMBER 128
/* number of age extent info in extent cache we try to shrink */
#define AGE_EXTENT_CACHE_SHRINK_NUMBER 128
#define LAST_AGE_WEIGHT 30
#define SAME_AGE_REGION 1024
/*
* Define data block with age less than 1GB as hot data
* define data block with age less than 10GB but more than 1GB as warm data
*/
#define DEF_HOT_DATA_AGE_THRESHOLD 262144
#define DEF_WARM_DATA_AGE_THRESHOLD 2621440
/* extent cache type */
enum extent_type {
EX_READ,
EX_BLOCK_AGE,
NR_EXTENT_CACHES,
};
struct rb_entry {
struct rb_node rb_node; /* rb node located in rb-tree */
@ -588,7 +608,24 @@ struct rb_entry {
struct extent_info {
unsigned int fofs; /* start offset in a file */
unsigned int len; /* length of the extent */
u32 blk; /* start block address of the extent */
union {
/* read extent_cache */
struct {
/* start block address of the extent */
block_t blk;
#ifdef CONFIG_F2FS_FS_COMPRESSION
/* physical extent length of compressed blocks */
unsigned int c_len;
#endif
};
/* block age extent_cache */
struct {
/* block age of the extent */
unsigned long long age;
/* last total blocks allocated */
unsigned long long last_blocks;
};
};
};
struct extent_node {
@ -600,13 +637,25 @@ struct extent_node {
struct extent_tree {
nid_t ino; /* inode number */
enum extent_type type; /* keep the extent tree type */
struct rb_root_cached root; /* root of extent info rb-tree */
struct extent_node *cached_en; /* recently accessed extent node */
struct extent_info largest; /* largested extent info */
struct list_head list; /* to be used by sbi->zombie_list */
rwlock_t lock; /* protect extent info rb-tree */
atomic_t node_cnt; /* # of extent node in rb-tree*/
bool largest_updated; /* largest extent updated */
struct extent_info largest; /* largest cached extent for EX_READ */
};
struct extent_tree_info {
struct radix_tree_root extent_tree_root;/* cache extent cache entries */
struct mutex extent_tree_lock; /* locking extent radix tree */
struct list_head extent_list; /* lru list for shrinker */
spinlock_t extent_lock; /* locking extent lru list */
atomic_t total_ext_tree; /* extent tree count */
struct list_head zombie_list; /* extent zombie tree list */
atomic_t total_zombie_tree; /* extent zombie tree count */
atomic_t total_ext_node; /* extent info count */
};
/*
@ -766,7 +815,8 @@ struct f2fs_inode_info {
struct list_head inmem_pages; /* inmemory pages managed by f2fs */
struct task_struct *inmem_task; /* store inmemory task */
struct mutex inmem_lock; /* lock for inmemory pages */
struct extent_tree *extent_tree; /* cached extent_tree entry */
struct extent_tree *extent_tree[NR_EXTENT_CACHES];
/* cached extent_tree entry */
/* avoid racing between foreground op and gc */
struct f2fs_rwsem i_gc_rwsem[2];
@ -788,7 +838,7 @@ struct f2fs_inode_info {
unsigned int i_cluster_size; /* cluster size */
};
static inline void get_extent_info(struct extent_info *ext,
static inline void get_read_extent_info(struct extent_info *ext,
struct f2fs_extent *i_ext)
{
ext->fofs = le32_to_cpu(i_ext->fofs);
@ -796,7 +846,7 @@ static inline void get_extent_info(struct extent_info *ext,
ext->len = le32_to_cpu(i_ext->len);
}
static inline void set_raw_extent(struct extent_info *ext,
static inline void set_raw_read_extent(struct extent_info *ext,
struct f2fs_extent *i_ext)
{
i_ext->fofs = cpu_to_le32(ext->fofs);
@ -804,14 +854,6 @@ static inline void set_raw_extent(struct extent_info *ext,
i_ext->len = cpu_to_le32(ext->len);
}
static inline void set_extent_info(struct extent_info *ei, unsigned int fofs,
u32 blk, unsigned int len)
{
ei->fofs = fofs;
ei->blk = blk;
ei->len = len;
}
static inline bool __is_discard_mergeable(struct discard_info *back,
struct discard_info *front, unsigned int max_len)
{
@ -831,35 +873,6 @@ static inline bool __is_discard_front_mergeable(struct discard_info *cur,
return __is_discard_mergeable(cur, front, max_len);
}
static inline bool __is_extent_mergeable(struct extent_info *back,
struct extent_info *front)
{
return (back->fofs + back->len == front->fofs &&
back->blk + back->len == front->blk);
}
static inline bool __is_back_mergeable(struct extent_info *cur,
struct extent_info *back)
{
return __is_extent_mergeable(back, cur);
}
static inline bool __is_front_mergeable(struct extent_info *cur,
struct extent_info *front)
{
return __is_extent_mergeable(cur, front);
}
extern void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync);
static inline void __try_update_largest_extent(struct extent_tree *et,
struct extent_node *en)
{
if (en->ei.len > et->largest.len) {
et->largest = en->ei;
et->largest_updated = true;
}
}
/*
* For free nid management
*/
@ -1601,14 +1614,12 @@ struct f2fs_sb_info {
struct mutex flush_lock; /* for flush exclusion */
/* for extent tree cache */
struct radix_tree_root extent_tree_root;/* cache extent cache entries */
struct mutex extent_tree_lock; /* locking extent radix tree */
struct list_head extent_list; /* lru list for shrinker */
spinlock_t extent_lock; /* locking extent lru list */
atomic_t total_ext_tree; /* extent tree count */
struct list_head zombie_list; /* extent zombie tree list */
atomic_t total_zombie_tree; /* extent zombie tree count */
atomic_t total_ext_node; /* extent info count */
struct extent_tree_info extent_tree[NR_EXTENT_CACHES];
atomic64_t allocated_data_blocks; /* for block age extent_cache */
/* The threshold used for hot and warm data seperation*/
unsigned int hot_data_age_threshold;
unsigned int warm_data_age_threshold;
/* basic filesystem units */
unsigned int log_sectors_per_block; /* log2 sectors per block */
@ -1689,10 +1700,14 @@ struct f2fs_sb_info {
unsigned int segment_count[2]; /* # of allocated segments */
unsigned int block_count[2]; /* # of allocated blocks */
atomic_t inplace_count; /* # of inplace update */
atomic64_t total_hit_ext; /* # of lookup extent cache */
atomic64_t read_hit_rbtree; /* # of hit rbtree extent node */
atomic64_t read_hit_largest; /* # of hit largest extent node */
atomic64_t read_hit_cached; /* # of hit cached extent node */
/* # of lookup extent cache */
atomic64_t total_hit_ext[NR_EXTENT_CACHES];
/* # of hit rbtree extent node */
atomic64_t read_hit_rbtree[NR_EXTENT_CACHES];
/* # of hit cached extent node */
atomic64_t read_hit_cached[NR_EXTENT_CACHES];
/* # of hit largest extent node in read extent cache */
atomic64_t read_hit_largest;
atomic_t inline_xattr; /* # of inline_xattr inodes */
atomic_t inline_inode; /* # of inline_data inodes */
atomic_t inline_dir; /* # of inline_dentry inodes */
@ -2485,6 +2500,7 @@ static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
}
extern void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync);
static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
struct inode *inode, bool is_inode)
{
@ -3775,9 +3791,19 @@ struct f2fs_stat_info {
struct f2fs_sb_info *sbi;
int all_area_segs, sit_area_segs, nat_area_segs, ssa_area_segs;
int main_area_segs, main_area_sections, main_area_zones;
unsigned long long hit_largest, hit_cached, hit_rbtree;
unsigned long long hit_total, total_ext;
int ext_tree, zombie_tree, ext_node;
unsigned long long hit_cached[NR_EXTENT_CACHES];
unsigned long long hit_rbtree[NR_EXTENT_CACHES];
unsigned long long total_ext[NR_EXTENT_CACHES];
unsigned long long hit_total[NR_EXTENT_CACHES];
int ext_tree[NR_EXTENT_CACHES];
int zombie_tree[NR_EXTENT_CACHES];
int ext_node[NR_EXTENT_CACHES];
/* to count memory footprint */
unsigned long long ext_mem[NR_EXTENT_CACHES];
/* for read extent cache */
unsigned long long hit_largest;
/* for block age extent cache */
unsigned long long allocated_data_blocks;
int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta;
int ndirty_data, ndirty_qdata;
int inmem_pages;
@ -3838,10 +3864,10 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
#define stat_other_skip_bggc_count(sbi) ((sbi)->other_skip_bggc++)
#define stat_inc_dirty_inode(sbi, type) ((sbi)->ndirty_inode[type]++)
#define stat_dec_dirty_inode(sbi, type) ((sbi)->ndirty_inode[type]--)
#define stat_inc_total_hit(sbi) (atomic64_inc(&(sbi)->total_hit_ext))
#define stat_inc_rbtree_node_hit(sbi) (atomic64_inc(&(sbi)->read_hit_rbtree))
#define stat_inc_total_hit(sbi, type) (atomic64_inc(&(sbi)->total_hit_ext[type]))
#define stat_inc_rbtree_node_hit(sbi, type) (atomic64_inc(&(sbi)->read_hit_rbtree[type]))
#define stat_inc_largest_node_hit(sbi) (atomic64_inc(&(sbi)->read_hit_largest))
#define stat_inc_cached_node_hit(sbi) (atomic64_inc(&(sbi)->read_hit_cached))
#define stat_inc_cached_node_hit(sbi, type) (atomic64_inc(&(sbi)->read_hit_cached[type]))
#define stat_inc_inline_xattr(inode) \
do { \
if (f2fs_has_inline_xattr(inode)) \
@ -3967,10 +3993,10 @@ void f2fs_update_sit_info(struct f2fs_sb_info *sbi);
#define stat_other_skip_bggc_count(sbi) do { } while (0)
#define stat_inc_dirty_inode(sbi, type) do { } while (0)
#define stat_dec_dirty_inode(sbi, type) do { } while (0)
#define stat_inc_total_hit(sbi) do { } while (0)
#define stat_inc_rbtree_node_hit(sbi) do { } while (0)
#define stat_inc_total_hit(sbi, type) do { } while (0)
#define stat_inc_rbtree_node_hit(sbi, type) do { } while (0)
#define stat_inc_largest_node_hit(sbi) do { } while (0)
#define stat_inc_cached_node_hit(sbi) do { } while (0)
#define stat_inc_cached_node_hit(sbi, type) do { } while (0)
#define stat_inc_inline_xattr(inode) do { } while (0)
#define stat_dec_inline_xattr(inode) do { } while (0)
#define stat_inc_inline_inode(inode) do { } while (0)
@ -4075,20 +4101,34 @@ struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root,
bool force, bool *leftmost);
bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi,
struct rb_root_cached *root, bool check_key);
unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink);
void f2fs_init_extent_tree(struct inode *inode, struct page *ipage);
void f2fs_init_extent_tree(struct inode *inode);
void f2fs_drop_extent_tree(struct inode *inode);
unsigned int f2fs_destroy_extent_node(struct inode *inode);
void f2fs_destroy_extent_node(struct inode *inode);
void f2fs_destroy_extent_tree(struct inode *inode);
bool f2fs_lookup_extent_cache(struct inode *inode, pgoff_t pgofs,
struct extent_info *ei);
void f2fs_update_extent_cache(struct dnode_of_data *dn);
void f2fs_update_extent_cache_range(struct dnode_of_data *dn,
pgoff_t fofs, block_t blkaddr, unsigned int len);
void f2fs_init_extent_cache_info(struct f2fs_sb_info *sbi);
int __init f2fs_create_extent_cache(void);
void f2fs_destroy_extent_cache(void);
/* read extent cache ops */
void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage);
bool f2fs_lookup_read_extent_cache(struct inode *inode, pgoff_t pgofs,
struct extent_info *ei);
void f2fs_update_read_extent_cache(struct dnode_of_data *dn);
void f2fs_update_read_extent_cache_range(struct dnode_of_data *dn,
pgoff_t fofs, block_t blkaddr, unsigned int len);
unsigned int f2fs_shrink_read_extent_tree(struct f2fs_sb_info *sbi,
int nr_shrink);
/* block age extent cache ops */
void f2fs_init_age_extent_tree(struct inode *inode);
bool f2fs_lookup_age_extent_cache(struct inode *inode, pgoff_t pgofs,
struct extent_info *ei);
void f2fs_update_age_extent_cache(struct dnode_of_data *dn);
void f2fs_update_age_extent_cache_range(struct dnode_of_data *dn,
pgoff_t fofs, unsigned int len);
unsigned int f2fs_shrink_age_extent_tree(struct f2fs_sb_info *sbi,
int nr_shrink);
/*
* sysfs.c
*/
@ -4152,12 +4192,16 @@ int f2fs_write_multi_pages(struct compress_ctx *cc,
struct writeback_control *wbc,
enum iostat_type io_type);
int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index);
void f2fs_update_read_extent_tree_range_compressed(struct inode *inode,
pgoff_t fofs, block_t blkaddr,
unsigned int llen, unsigned int c_len);
int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
unsigned nr_pages, sector_t *last_block_in_bio,
bool is_readahead, bool for_write);
struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc);
void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed);
void f2fs_put_page_dic(struct page *page);
unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn);
int f2fs_init_compress_ctx(struct compress_ctx *cc);
void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse);
void f2fs_init_compress_info(struct f2fs_sb_info *sbi);
@ -4212,6 +4256,7 @@ static inline void f2fs_put_page_dic(struct page *page)
{
WARN_ON_ONCE(1);
}
static inline unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn) { return 0; }
static inline int f2fs_init_compress_inode(struct f2fs_sb_info *sbi) { return 0; }
static inline void f2fs_destroy_compress_inode(struct f2fs_sb_info *sbi) { }
static inline int f2fs_init_page_array_cache(struct f2fs_sb_info *sbi) { return 0; }
@ -4227,6 +4272,10 @@ static inline bool f2fs_load_compressed_page(struct f2fs_sb_info *sbi,
static inline void f2fs_invalidate_compress_pages(struct f2fs_sb_info *sbi,
nid_t ino) { }
#define inc_compr_inode_stat(inode) do { } while (0)
static inline void f2fs_update_read_extent_tree_range_compressed(
struct inode *inode,
pgoff_t fofs, block_t blkaddr,
unsigned int llen, unsigned int c_len) { }
#endif
static inline int set_compress_context(struct inode *inode)
@ -4296,26 +4345,6 @@ F2FS_FEATURE_FUNCS(casefold, CASEFOLD);
F2FS_FEATURE_FUNCS(compression, COMPRESSION);
F2FS_FEATURE_FUNCS(readonly, RO);
static inline bool f2fs_may_extent_tree(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
if (!test_opt(sbi, EXTENT_CACHE) ||
is_inode_flag_set(inode, FI_NO_EXTENT) ||
(is_inode_flag_set(inode, FI_COMPRESSED_FILE) &&
!f2fs_sb_has_readonly(sbi)))
return false;
/*
* for recovered files during mount do not create extents
* if shrinker is not registered.
*/
if (list_empty(&sbi->s_list))
return false;
return S_ISREG(inode->i_mode);
}
#ifdef CONFIG_BLK_DEV_ZONED
static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
block_t blkaddr)

View file

@ -607,7 +607,8 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count)
*/
fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page),
dn->inode) + ofs;
f2fs_update_extent_cache_range(dn, fofs, 0, len);
f2fs_update_read_extent_cache_range(dn, fofs, 0, len);
f2fs_update_age_extent_cache_range(dn, fofs, nr_free);
dec_valid_block_count(sbi, dn->inode, nr_free);
}
dn->ofs_in_node = ofs;
@ -1430,7 +1431,7 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,
f2fs_set_data_blkaddr(dn);
}
f2fs_update_extent_cache_range(dn, start, 0, index - start);
f2fs_update_read_extent_cache_range(dn, start, 0, index - start);
return ret;
}
@ -2590,7 +2591,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
struct f2fs_map_blocks map = { .m_next_extent = NULL,
.m_seg_type = NO_CHECK_TYPE,
.m_may_create = false };
struct extent_info ei = {0, 0, 0};
struct extent_info ei = {};
pgoff_t pg_start, pg_end, next_pgofs;
unsigned int blk_per_seg = sbi->blocks_per_seg;
unsigned int total = 0, sec_num;
@ -2622,7 +2623,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
* lookup mapping info in extent cache, skip defragmenting if physical
* block addresses are continuous.
*/
if (f2fs_lookup_extent_cache(inode, pg_start, &ei)) {
if (f2fs_lookup_read_extent_cache(inode, pg_start, &ei)) {
if (ei.fofs + ei.len >= pg_end)
goto out;
}

View file

@ -1062,7 +1062,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
struct address_space *mapping = inode->i_mapping;
struct dnode_of_data dn;
struct page *page;
struct extent_info ei = {0, 0, 0};
struct extent_info ei = {0, };
struct f2fs_io_info fio = {
.sbi = sbi,
.ino = inode->i_ino,
@ -1080,7 +1080,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
if (!page)
return -ENOMEM;
if (f2fs_lookup_extent_cache(inode, index, &ei)) {
if (f2fs_lookup_read_extent_cache(inode, index, &ei)) {
dn.data_blkaddr = ei.blk + index - ei.fofs;
if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
DATA_GENERIC_ENHANCE_READ))) {

View file

@ -91,7 +91,7 @@ static u32 TEA_hash_name(const u8 *p, size_t len)
/*
* Compute @fname->hash. For all directories, @fname->disk_name must be set.
* For casefolded directories, @fname->usr_fname must be set, and also
* @fname->cf_name if the filename is valid Unicode.
* @fname->cf_name if the filename is valid Unicode and is not "." or "..".
*/
void f2fs_hash_filename(const struct inode *dir, struct f2fs_filename *fname)
{
@ -110,10 +110,11 @@ void f2fs_hash_filename(const struct inode *dir, struct f2fs_filename *fname)
/*
* If the casefolded name is provided, hash it instead of the
* on-disk name. If the casefolded name is *not* provided, that
* should only be because the name wasn't valid Unicode, so fall
* back to treating the name as an opaque byte sequence. Note
* that to handle encrypted directories, the fallback must use
* usr_fname (plaintext) rather than disk_name (ciphertext).
* should only be because the name wasn't valid Unicode or was
* "." or "..", so fall back to treating the name as an opaque
* byte sequence. Note that to handle encrypted directories,
* the fallback must use usr_fname (plaintext) rather than
* disk_name (ciphertext).
*/
WARN_ON_ONCE(!fname->usr_fname->name);
if (fname->cf_name.name) {

View file

@ -260,8 +260,8 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page)
return false;
}
if (F2FS_I(inode)->extent_tree) {
struct extent_info *ei = &F2FS_I(inode)->extent_tree->largest;
if (fi->extent_tree[EX_READ]) {
struct extent_info *ei = &fi->extent_tree[EX_READ]->largest;
if (ei->len &&
(!f2fs_is_valid_blkaddr(sbi, ei->blk,
@ -380,8 +380,6 @@ static int do_read_inode(struct inode *inode)
fi->i_pino = le32_to_cpu(ri->i_pino);
fi->i_dir_level = ri->i_dir_level;
f2fs_init_extent_tree(inode, node_page);
get_inline_info(inode, ri);
fi->i_extra_isize = f2fs_has_extra_attr(inode) ?
@ -469,6 +467,11 @@ static int do_read_inode(struct inode *inode)
F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
/* Need all the flag bits */
f2fs_init_read_extent_tree(inode, node_page);
f2fs_init_age_extent_tree(inode);
f2fs_put_page(node_page, 1);
stat_inc_inline_xattr(inode);
@ -571,7 +574,7 @@ retry:
void f2fs_update_inode(struct inode *inode, struct page *node_page)
{
struct f2fs_inode *ri;
struct extent_tree *et = F2FS_I(inode)->extent_tree;
struct extent_tree *et = F2FS_I(inode)->extent_tree[EX_READ];
f2fs_wait_on_page_writeback(node_page, NODE, true, true);
set_page_dirty(node_page);
@ -590,7 +593,7 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page)
if (et) {
read_lock(&et->lock);
set_raw_extent(&et->largest, &ri->i_ext);
set_raw_read_extent(&et->largest, &ri->i_ext);
read_unlock(&et->lock);
} else {
memset(&ri->i_ext, 0, sizeof(ri->i_ext));

View file

@ -105,8 +105,6 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
}
F2FS_I(inode)->i_inline_xattr_size = xattr_size;
f2fs_init_extent_tree(inode, NULL);
F2FS_I(inode)->i_flags =
f2fs_mask_flags(mode, F2FS_I(dir)->i_flags & F2FS_FL_INHERITED);
@ -133,6 +131,8 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
f2fs_set_inode_flags(inode);
f2fs_init_extent_tree(inode);
trace_f2fs_new_inode(inode, 0);
return inode;
@ -618,6 +618,8 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
goto fail;
}
f2fs_delete_entry(de, page, dir, inode);
f2fs_unlock_op(sbi);
#ifdef CONFIG_UNICODE
/* VFS negative dentries are incompatible with Encoding and
* Case-insensitiveness. Eventually we'll want avoid
@ -628,8 +630,6 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
if (IS_CASEFOLDED(dir))
d_invalidate(dentry);
#endif
f2fs_unlock_op(sbi);
if (IS_DIRSYNC(dir))
f2fs_sync_fs(sbi->sb, 1);
fail:

View file

@ -58,7 +58,7 @@ bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type)
avail_ram = val.totalram - val.totalhigh;
/*
* give 25%, 25%, 50%, 50%, 50% memory for each components respectively
* give 25%, 25%, 50%, 50%, 25%, 25% memory for each components respectively
*/
if (type == FREE_NIDS) {
mem_size = (nm_i->nid_cnt[FREE_NID] *
@ -83,12 +83,16 @@ bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type)
sizeof(struct ino_entry);
mem_size >>= PAGE_SHIFT;
res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1);
} else if (type == EXTENT_CACHE) {
mem_size = (atomic_read(&sbi->total_ext_tree) *
} else if (type == READ_EXTENT_CACHE || type == AGE_EXTENT_CACHE) {
enum extent_type etype = type == READ_EXTENT_CACHE ?
EX_READ : EX_BLOCK_AGE;
struct extent_tree_info *eti = &sbi->extent_tree[etype];
mem_size = (atomic_read(&eti->total_ext_tree) *
sizeof(struct extent_tree) +
atomic_read(&sbi->total_ext_node) *
atomic_read(&eti->total_ext_node) *
sizeof(struct extent_node)) >> PAGE_SHIFT;
res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1);
res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2);
} else if (type == INMEM_PAGES) {
/* it allows 20% / total_ram for inmemory pages */
mem_size = get_pages(sbi, F2FS_INMEM_PAGES);
@ -846,6 +850,26 @@ int f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
dn->ofs_in_node = offset[level];
dn->node_page = npage[level];
dn->data_blkaddr = f2fs_data_blkaddr(dn);
if (is_inode_flag_set(dn->inode, FI_COMPRESSED_FILE) &&
f2fs_sb_has_readonly(sbi)) {
unsigned int c_len = f2fs_cluster_blocks_are_contiguous(dn);
block_t blkaddr;
if (!c_len)
goto out;
blkaddr = f2fs_data_blkaddr(dn);
if (blkaddr == COMPRESS_ADDR)
blkaddr = data_blkaddr(dn->inode, dn->node_page,
dn->ofs_in_node + 1);
f2fs_update_read_extent_tree_range_compressed(dn->inode,
index, blkaddr,
F2FS_I(dn->inode)->i_cluster_size,
c_len);
}
out:
return 0;
release_pages:
@ -1339,8 +1363,8 @@ static int read_node_page(struct page *page, int op_flags)
if (err)
return err;
if (unlikely(ni.blk_addr == NULL_ADDR) ||
is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)) {
/* NEW_ADDR can be seen, after cp_error drops some dirty node pages */
if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR)) {
ClearPageUptodate(page);
return -ENOENT;
}

View file

@ -148,7 +148,8 @@ enum mem_type {
NAT_ENTRIES, /* indicates the cached nat entry */
DIRTY_DENTS, /* indicates dirty dentry pages */
INO_ENTRIES, /* indicates inode entries */
EXTENT_CACHE, /* indicates extent cache */
READ_EXTENT_CACHE, /* indicates read extent cache */
AGE_EXTENT_CACHE, /* indicates age extent cache */
INMEM_PAGES, /* indicates inmemory pages */
DISCARD_CACHE, /* indicates memory of cached discard cmds */
COMPRESS_PAGE, /* indicates memory of cached compressed pages */

View file

@ -536,8 +536,14 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg)
return;
/* try to shrink extent cache when there is no enough memory */
if (!f2fs_available_free_memory(sbi, EXTENT_CACHE))
f2fs_shrink_extent_tree(sbi, EXTENT_CACHE_SHRINK_NUMBER);
if (!f2fs_available_free_memory(sbi, READ_EXTENT_CACHE))
f2fs_shrink_read_extent_tree(sbi,
READ_EXTENT_CACHE_SHRINK_NUMBER);
/* try to shrink age extent cache when there is no enough memory */
if (!f2fs_available_free_memory(sbi, AGE_EXTENT_CACHE))
f2fs_shrink_age_extent_tree(sbi,
AGE_EXTENT_CACHE_SHRINK_NUMBER);
/* check the # of cached NAT entries */
if (!f2fs_available_free_memory(sbi, NAT_ENTRIES))
@ -3292,10 +3298,28 @@ static int __get_segment_type_4(struct f2fs_io_info *fio)
}
}
static int __get_age_segment_type(struct inode *inode, pgoff_t pgofs)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct extent_info ei = {};
if (f2fs_lookup_age_extent_cache(inode, pgofs, &ei)) {
if (!ei.age)
return NO_CHECK_TYPE;
if (ei.age <= sbi->hot_data_age_threshold)
return CURSEG_HOT_DATA;
if (ei.age <= sbi->warm_data_age_threshold)
return CURSEG_WARM_DATA;
return CURSEG_COLD_DATA;
}
return NO_CHECK_TYPE;
}
static int __get_segment_type_6(struct f2fs_io_info *fio)
{
if (fio->type == DATA) {
struct inode *inode = fio->page->mapping->host;
int type;
if (is_inode_flag_set(inode, FI_ALIGNED_WRITE))
return CURSEG_COLD_DATA_PINNED;
@ -3310,6 +3334,11 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
}
if (file_is_cold(inode) || f2fs_need_compress_data(inode))
return CURSEG_COLD_DATA;
type = __get_age_segment_type(inode, fio->page->index);
if (type != NO_CHECK_TYPE)
return type;
if (file_is_hot(inode) ||
is_inode_flag_set(inode, FI_HOT_DATA) ||
f2fs_is_atomic_file(inode) ||
@ -3421,6 +3450,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
locate_dirty_segment(sbi, GET_SEGNO(sbi, *new_blkaddr));
if (IS_DATASEG(type))
atomic64_inc(&sbi->allocated_data_blocks);
up_write(&sit_i->sentry_lock);
if (page && IS_NODESEG(type)) {
@ -3542,6 +3574,8 @@ void f2fs_outplace_write_data(struct dnode_of_data *dn,
struct f2fs_summary sum;
f2fs_bug_on(sbi, dn->data_blkaddr == NULL_ADDR);
if (fio->io_type == FS_DATA_IO || fio->io_type == FS_CP_DATA_IO)
f2fs_update_age_extent_cache(dn);
set_summary(&sum, dn->nid, dn->ofs_in_node, fio->version);
do_write_page(&sum, fio);
f2fs_update_data_blkaddr(dn, fio->new_blkaddr);

View file

@ -28,10 +28,13 @@ static unsigned long __count_free_nids(struct f2fs_sb_info *sbi)
return count > 0 ? count : 0;
}
static unsigned long __count_extent_cache(struct f2fs_sb_info *sbi)
static unsigned long __count_extent_cache(struct f2fs_sb_info *sbi,
enum extent_type type)
{
return atomic_read(&sbi->total_zombie_tree) +
atomic_read(&sbi->total_ext_node);
struct extent_tree_info *eti = &sbi->extent_tree[type];
return atomic_read(&eti->total_zombie_tree) +
atomic_read(&eti->total_ext_node);
}
unsigned long f2fs_shrink_count(struct shrinker *shrink,
@ -53,8 +56,11 @@ unsigned long f2fs_shrink_count(struct shrinker *shrink,
}
spin_unlock(&f2fs_list_lock);
/* count extent cache entries */
count += __count_extent_cache(sbi);
/* count read extent cache entries */
count += __count_extent_cache(sbi, EX_READ);
/* count block age extent cache entries */
count += __count_extent_cache(sbi, EX_BLOCK_AGE);
/* count clean nat cache entries */
count += __count_nat_entries(sbi);
@ -100,7 +106,10 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink,
sbi->shrinker_run_no = run_no;
/* shrink extent cache entries */
freed += f2fs_shrink_extent_tree(sbi, nr >> 1);
freed += f2fs_shrink_age_extent_tree(sbi, nr >> 2);
/* shrink read extent cache entries */
freed += f2fs_shrink_read_extent_tree(sbi, nr >> 2);
/* shrink clean nat cache entries */
if (freed < nr)
@ -130,7 +139,9 @@ void f2fs_join_shrinker(struct f2fs_sb_info *sbi)
void f2fs_leave_shrinker(struct f2fs_sb_info *sbi)
{
f2fs_shrink_extent_tree(sbi, __count_extent_cache(sbi));
f2fs_shrink_read_extent_tree(sbi, __count_extent_cache(sbi, EX_READ));
f2fs_shrink_age_extent_tree(sbi,
__count_extent_cache(sbi, EX_BLOCK_AGE));
spin_lock(&f2fs_list_lock);
list_del_init(&sbi->s_list);

View file

@ -154,6 +154,7 @@ enum {
Opt_atgc,
Opt_gc_merge,
Opt_nogc_merge,
Opt_age_extent_cache,
Opt_err,
};
@ -229,6 +230,7 @@ static match_table_t f2fs_tokens = {
{Opt_atgc, "atgc"},
{Opt_gc_merge, "gc_merge"},
{Opt_nogc_merge, "nogc_merge"},
{Opt_age_extent_cache, "age_extent_cache"},
{Opt_err, NULL},
};
@ -753,10 +755,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
set_opt(sbi, FASTBOOT);
break;
case Opt_extent_cache:
set_opt(sbi, EXTENT_CACHE);
set_opt(sbi, READ_EXTENT_CACHE);
break;
case Opt_noextent_cache:
clear_opt(sbi, EXTENT_CACHE);
clear_opt(sbi, READ_EXTENT_CACHE);
break;
case Opt_noinline_data:
clear_opt(sbi, INLINE_DATA);
@ -1148,6 +1150,9 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
case Opt_nogc_merge:
clear_opt(sbi, GC_MERGE);
break;
case Opt_age_extent_cache:
set_opt(sbi, AGE_EXTENT_CACHE);
break;
default:
f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value",
p);
@ -1817,10 +1822,12 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
seq_puts(seq, ",nobarrier");
if (test_opt(sbi, FASTBOOT))
seq_puts(seq, ",fastboot");
if (test_opt(sbi, EXTENT_CACHE))
if (test_opt(sbi, READ_EXTENT_CACHE))
seq_puts(seq, ",extent_cache");
else
seq_puts(seq, ",noextent_cache");
if (test_opt(sbi, AGE_EXTENT_CACHE))
seq_puts(seq, ",age_extent_cache");
if (test_opt(sbi, DATA_FLUSH))
seq_puts(seq, ",data_flush");
@ -1922,7 +1929,7 @@ static void default_options(struct f2fs_sb_info *sbi)
set_opt(sbi, INLINE_XATTR);
set_opt(sbi, INLINE_DATA);
set_opt(sbi, INLINE_DENTRY);
set_opt(sbi, EXTENT_CACHE);
set_opt(sbi, READ_EXTENT_CACHE);
set_opt(sbi, NOHEAP);
clear_opt(sbi, DISABLE_CHECKPOINT);
set_opt(sbi, MERGE_CHECKPOINT);
@ -2042,7 +2049,8 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
bool need_restart_gc = false, need_stop_gc = false;
bool need_restart_ckpt = false, need_stop_ckpt = false;
bool need_restart_flush = false, need_stop_flush = false;
bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE);
bool no_read_extent_cache = !test_opt(sbi, READ_EXTENT_CACHE);
bool no_age_extent_cache = !test_opt(sbi, AGE_EXTENT_CACHE);
bool disable_checkpoint = test_opt(sbi, DISABLE_CHECKPOINT);
bool no_io_align = !F2FS_IO_ALIGNED(sbi);
bool no_atgc = !test_opt(sbi, ATGC);
@ -2132,11 +2140,17 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
}
/* disallow enable/disable extent_cache dynamically */
if (no_extent_cache == !!test_opt(sbi, EXTENT_CACHE)) {
if (no_read_extent_cache == !!test_opt(sbi, READ_EXTENT_CACHE)) {
err = -EINVAL;
f2fs_warn(sbi, "switch extent_cache option is not allowed");
goto restore_opts;
}
/* disallow enable/disable age extent_cache dynamically */
if (no_age_extent_cache == !!test_opt(sbi, AGE_EXTENT_CACHE)) {
err = -EINVAL;
f2fs_warn(sbi, "switch age_extent_cache option is not allowed");
goto restore_opts;
}
if (no_io_align == !!F2FS_IO_ALIGNED(sbi)) {
err = -EINVAL;

View file

@ -549,6 +549,24 @@ out:
return count;
}
if (!strcmp(a->attr.name, "hot_data_age_threshold")) {
if (t == 0 || t >= sbi->warm_data_age_threshold)
return -EINVAL;
if (t == *ui)
return count;
*ui = (unsigned int)t;
return count;
}
if (!strcmp(a->attr.name, "warm_data_age_threshold")) {
if (t == 0 || t <= sbi->hot_data_age_threshold)
return -EINVAL;
if (t == *ui)
return count;
*ui = (unsigned int)t;
return count;
}
*ui = (unsigned int)t;
return count;
@ -778,6 +796,10 @@ F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_age_threshold, age_threshold);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_segment_mode, gc_segment_mode);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_reclaimed_segments, gc_reclaimed_segs);
/* For block age extent cache */
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, hot_data_age_threshold, hot_data_age_threshold);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, warm_data_age_threshold, warm_data_age_threshold);
#define ATTR_LIST(name) (&f2fs_attr_##name.attr)
static struct attribute *f2fs_attrs[] = {
ATTR_LIST(gc_urgent_sleep_time),
@ -853,6 +875,8 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(atgc_age_threshold),
ATTR_LIST(gc_segment_mode),
ATTR_LIST(gc_reclaimed_segments),
ATTR_LIST(hot_data_age_threshold),
ATTR_LIST(warm_data_age_threshold),
NULL,
};
ATTRIBUTE_GROUPS(f2fs);

View file

@ -208,10 +208,13 @@ static unsigned int fuse_req_hash(u64 unique)
/**
* A new request is available, wake fiq->waitq
*/
static void fuse_dev_wake_and_unlock(struct fuse_iqueue *fiq)
static void fuse_dev_wake_and_unlock(struct fuse_iqueue *fiq, bool sync)
__releases(fiq->lock)
{
wake_up(&fiq->waitq);
if (sync)
wake_up_sync(&fiq->waitq);
else
wake_up(&fiq->waitq);
kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
spin_unlock(&fiq->lock);
}
@ -224,14 +227,14 @@ const struct fuse_iqueue_ops fuse_dev_fiq_ops = {
EXPORT_SYMBOL_GPL(fuse_dev_fiq_ops);
static void queue_request_and_unlock(struct fuse_iqueue *fiq,
struct fuse_req *req)
struct fuse_req *req, bool sync)
__releases(fiq->lock)
{
req->in.h.len = sizeof(struct fuse_in_header) +
fuse_len_args(req->args->in_numargs,
(struct fuse_arg *) req->args->in_args);
list_add_tail(&req->list, &fiq->pending);
fiq->ops->wake_pending_and_unlock(fiq);
fiq->ops->wake_pending_and_unlock(fiq, sync);
}
void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
@ -246,7 +249,7 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
if (fiq->connected) {
fiq->forget_list_tail->next = forget;
fiq->forget_list_tail = forget;
fiq->ops->wake_forget_and_unlock(fiq);
fiq->ops->wake_forget_and_unlock(fiq, false);
} else {
kfree(forget);
spin_unlock(&fiq->lock);
@ -266,7 +269,7 @@ static void flush_bg_queue(struct fuse_conn *fc)
fc->active_background++;
spin_lock(&fiq->lock);
req->in.h.unique = fuse_get_unique(fiq);
queue_request_and_unlock(fiq, req);
queue_request_and_unlock(fiq, req, false);
}
}
@ -359,7 +362,7 @@ static int queue_interrupt(struct fuse_req *req)
spin_unlock(&fiq->lock);
return 0;
}
fiq->ops->wake_interrupt_and_unlock(fiq);
fiq->ops->wake_interrupt_and_unlock(fiq, false);
} else {
spin_unlock(&fiq->lock);
}
@ -426,7 +429,7 @@ static void __fuse_request_send(struct fuse_req *req)
/* acquire extra reference, since request is still needed
after fuse_request_end() */
__fuse_get_request(req);
queue_request_and_unlock(fiq, req);
queue_request_and_unlock(fiq, req, true);
request_wait_answer(req);
/* Pairs with smp_wmb() in fuse_request_end() */
@ -601,7 +604,7 @@ static int fuse_simple_notify_reply(struct fuse_mount *fm,
spin_lock(&fiq->lock);
if (fiq->connected) {
queue_request_and_unlock(fiq, req);
queue_request_and_unlock(fiq, req, false);
} else {
err = -ENODEV;
spin_unlock(&fiq->lock);

View file

@ -412,19 +412,19 @@ struct fuse_iqueue_ops {
/**
* Signal that a forget has been queued
*/
void (*wake_forget_and_unlock)(struct fuse_iqueue *fiq)
void (*wake_forget_and_unlock)(struct fuse_iqueue *fiq, bool sync)
__releases(fiq->lock);
/**
* Signal that an INTERRUPT request has been queued
*/
void (*wake_interrupt_and_unlock)(struct fuse_iqueue *fiq)
void (*wake_interrupt_and_unlock)(struct fuse_iqueue *fiq, bool sync)
__releases(fiq->lock);
/**
* Signal that a request has been queued
*/
void (*wake_pending_and_unlock)(struct fuse_iqueue *fiq)
void (*wake_pending_and_unlock)(struct fuse_iqueue *fiq, bool sync)
__releases(fiq->lock);
/**

View file

@ -971,7 +971,7 @@ static struct virtio_driver virtio_fs_driver = {
#endif
};
static void virtio_fs_wake_forget_and_unlock(struct fuse_iqueue *fiq)
static void virtio_fs_wake_forget_and_unlock(struct fuse_iqueue *fiq, bool sync)
__releases(fiq->lock)
{
struct fuse_forget_link *link;
@ -1006,7 +1006,8 @@ __releases(fiq->lock)
kfree(link);
}
static void virtio_fs_wake_interrupt_and_unlock(struct fuse_iqueue *fiq)
static void virtio_fs_wake_interrupt_and_unlock(struct fuse_iqueue *fiq,
bool sync)
__releases(fiq->lock)
{
/*
@ -1221,7 +1222,8 @@ out:
return ret;
}
static void virtio_fs_wake_pending_and_unlock(struct fuse_iqueue *fiq)
static void virtio_fs_wake_pending_and_unlock(struct fuse_iqueue *fiq,
bool sync)
__releases(fiq->lock)
{
unsigned int queue_id = VQ_REQUEST; /* TODO multiqueue */

View file

@ -679,7 +679,7 @@ static int ramoops_parse_dt(struct platform_device *pdev,
field = value; \
}
parse_u32("mem-type", pdata->record_size, pdata->mem_type);
parse_u32("mem-type", pdata->mem_type, pdata->mem_type);
parse_u32("record-size", pdata->record_size, 0);
parse_u32("console-size", pdata->console_size, 0);
parse_u32("ftrace-size", pdata->ftrace_size, 0);

View file

@ -149,7 +149,7 @@ struct ahash_alg {
struct shash_desc {
struct crypto_shash *tfm;
void *__ctx[] __aligned(ARCH_SLAB_MINALIGN);
void *__ctx[] __aligned(UL(16));
};
#define HASH_MAX_DIGESTSIZE 64

View file

@ -60,6 +60,13 @@
#define LED_FUNCTION_MICMUTE "micmute"
#define LED_FUNCTION_MUTE "mute"
/* Used for player LEDs as found on game controllers from e.g. Nintendo, Sony. */
#define LED_FUNCTION_PLAYER1 "player-1"
#define LED_FUNCTION_PLAYER2 "player-2"
#define LED_FUNCTION_PLAYER3 "player-3"
#define LED_FUNCTION_PLAYER4 "player-4"
#define LED_FUNCTION_PLAYER5 "player-5"
/* Miscelleaus functions. Use functions above if you can. */
#define LED_FUNCTION_ACTIVITY "activity"
#define LED_FUNCTION_ALARM "alarm"

View file

@ -5,6 +5,7 @@
#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/printk.h>
#include <linux/cache.h>
struct task_struct;

Some files were not shown because too many files have changed in this diff Show more