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
143 changed files with 5421 additions and 2427 deletions

View File

@@ -514,3 +514,17 @@ Date: July 2021
Contact: "Daeho Jeong" <daehojeong@google.com> Contact: "Daeho Jeong" <daehojeong@google.com>
Description: You can control for which gc mode the "gc_reclaimed_segments" node shows. 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". 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 difficult since unequal pointers can no longer be
compared. However, if this command-line option is compared. However, if this command-line option is
specified, then all normal pointers will have their true specified, then all normal pointers will have their true
value printed. Pointers printed via %pK may still be value printed. This option should only be specified when
hashed. This option should only be specified when
debugging the kernel. Please do not use on production debugging the kernel. Please do not use on production
kernels. kernels.

View File

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

View File

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

View File

@@ -300,6 +300,10 @@ inlinecrypt When possible, encrypt/decrypt the contents of encrypted
Documentation/block/inline-encryption.rst. Documentation/block/inline-encryption.rst.
atgc Enable age-threshold garbage collection, it provides high atgc Enable age-threshold garbage collection, it provides high
effectiveness and efficiency on background GC. 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 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 += $(stackp-flags-y)
KBUILD_CFLAGS-$(CONFIG_WERROR) += -Werror
KBUILD_CFLAGS += $(KBUILD_CFLAGS-y)
ifdef CONFIG_CC_IS_CLANG ifdef CONFIG_CC_IS_CLANG
KBUILD_CPPFLAGS += -Qunused-arguments KBUILD_CPPFLAGS += -Qunused-arguments
KBUILD_CFLAGS += -Wno-format-invalid-specifier 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_kasprintf
devm_kfree devm_kfree
devm_kmalloc devm_kmalloc
devm_led_classdev_flash_register_ext
devm_led_classdev_register_ext devm_led_classdev_register_ext
devm_led_classdev_unregister devm_led_classdev_unregister
devm_mbox_controller_register devm_mbox_controller_register
@@ -1149,7 +1150,9 @@
kvmalloc_node kvmalloc_node
led_classdev_flash_register_ext led_classdev_flash_register_ext
led_classdev_flash_unregister led_classdev_flash_unregister
led_colors
led_get_flash_fault led_get_flash_fault
led_set_brightness
led_set_brightness_sync led_set_brightness_sync
led_set_flash_brightness led_set_flash_brightness
led_set_flash_timeout led_set_flash_timeout
@@ -1159,6 +1162,7 @@
led_update_brightness led_update_brightness
led_update_flash_brightness led_update_flash_brightness
linear_range_get_max_value linear_range_get_max_value
linear_range_get_selector_high
linear_range_get_value linear_range_get_value
__list_add_valid __list_add_valid
__list_del_entry_valid __list_del_entry_valid
@@ -1704,6 +1708,7 @@
regulator_enable regulator_enable
regulator_enable_regmap regulator_enable_regmap
regulator_get regulator_get
regulator_get_bypass_regmap
regulator_get_current_limit_regmap regulator_get_current_limit_regmap
regulator_get_mode regulator_get_mode
regulator_get_optional regulator_get_optional
@@ -1721,6 +1726,7 @@
regulator_notifier_call_chain regulator_notifier_call_chain
regulator_put regulator_put
regulator_set_active_discharge_regmap regulator_set_active_discharge_regmap
regulator_set_bypass_regmap
regulator_set_current_limit regulator_set_current_limit
regulator_set_current_limit_regmap regulator_set_current_limit_regmap
regulator_set_load regulator_set_load
@@ -2973,6 +2979,7 @@
platform_find_device_by_driver platform_find_device_by_driver
pm_wq pm_wq
power_supply_is_system_supplied power_supply_is_system_supplied
power_supply_register_no_ws
power_supply_unreg_notifier power_supply_unreg_notifier
prepare_to_wait prepare_to_wait
printk_deferred printk_deferred

View File

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

View File

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

View File

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

View File

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

View File

@@ -200,3 +200,11 @@
wakeup_sources_read_unlock wakeup_sources_read_unlock
wakeup_sources_walk_start wakeup_sources_walk_start
wakeup_sources_walk_next 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 config ARM64_ERRATUM_2051678
bool "Cortex-A510: 2051678: disable Hardware Update of the page table's dirty bit" bool "Cortex-A510: 2051678: disable Hardware Update of the page table's dirty bit"
default y
help help
This options adds the workaround for ARM Cortex-A510 erratum ARM64_ERRATUM_2051678. This options adds the workaround for ARM Cortex-A510 erratum ARM64_ERRATUM_2051678.
Affected Coretex-A510 might not respect the ordering rules for Affected Coretex-A510 might not respect the ordering rules for

View File

@@ -152,6 +152,7 @@ config ARCH_MEDIATEK
config ARCH_MESON config ARCH_MESON
bool "Amlogic Platforms" bool "Amlogic Platforms"
select COMMON_CLK
help help
This enables support for the arm64 based Amlogic SoCs This enables support for the arm64 based Amlogic SoCs
such as the s905, S905X/D, S912, A113X/D or S905X/D2 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=y
CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_LEDS_CLASS_FLASH=y CONFIG_LEDS_CLASS_FLASH=y
CONFIG_LEDS_CLASS_MULTICOLOR=y
CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_EDAC=y CONFIG_EDAC=y

View File

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

View File

@@ -6,6 +6,7 @@
#define __ASM_CACHE_H #define __ASM_CACHE_H
#include <asm/cputype.h> #include <asm/cputype.h>
#include <asm/mte-def.h>
#define CTR_L1IP_SHIFT 14 #define CTR_L1IP_SHIFT 14
#define CTR_L1IP_MASK 3 #define CTR_L1IP_MASK 3
@@ -49,15 +50,21 @@
*/ */
#define ARCH_DMA_MINALIGN (128) #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__ #ifndef __ASSEMBLY__
#include <linux/bitops.h> #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_ALIASING 0
#define ICACHEF_VPIPT 1 #define ICACHEF_VPIPT 1

View File

@@ -107,7 +107,7 @@
msr_s SYS_ICC_SRE_EL2, x0 msr_s SYS_ICC_SRE_EL2, x0
isb // Make sure SRE is now set isb // Make sure SRE is now set
mrs_s x0, SYS_ICC_SRE_EL2 // Read SRE back, 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 msr_s SYS_ICH_HCR_EL2, xzr // Reset ICC_HCR_EL2 to defaults
.Lskip_gicv3_\@: .Lskip_gicv3_\@:
.endm .endm

View File

@@ -780,6 +780,10 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu);
#define kvm_vcpu_has_pmu(vcpu) \ #define kvm_vcpu_has_pmu(vcpu) \
(test_bit(KVM_ARM_VCPU_PMU_V3, (vcpu)->arch.features)) (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); int kvm_trng_call(struct kvm_vcpu *vcpu);
#ifdef CONFIG_KVM #ifdef CONFIG_KVM
extern phys_addr_t hyp_mem_base; extern phys_addr_t hyp_mem_base;

View File

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

View File

@@ -10,6 +10,7 @@
#include <asm/alternative.h> #include <asm/alternative.h>
#include <asm/cmpxchg.h> #include <asm/cmpxchg.h>
#include <asm/stack_pointer.h> #include <asm/stack_pointer.h>
#include <asm/sysreg.h>
static inline void set_my_cpu_offset(unsigned long off) 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); 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; 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); __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); 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); 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; 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))) if (likely(!vcpu_mode_is_32bit(vcpu)))
return false; return false;
return !system_supports_32bit_el0() || return !kvm_supports_32bit_el0();
static_branch_unlikely(&arm64_mismatched_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; u64 mode = (*(u64 *)valp) & PSR_AA32_MODE_MASK;
switch (mode) { switch (mode) {
case PSR_AA32_MODE_USR: case PSR_AA32_MODE_USR:
if (!system_supports_32bit_el0()) if (!kvm_supports_32bit_el0())
return -EINVAL; return -EINVAL;
break; break;
case PSR_AA32_MODE_FIQ: 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; 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); exception_index = ARM_EXCEPTION_CODE(exception_index);
switch (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) 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) 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) if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); 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); 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) val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
| (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E); | (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E);
if (!system_supports_32bit_el0()) if (!kvm_supports_32bit_el0())
val |= ARMV8_PMU_PMCR_LC; val |= ARMV8_PMU_PMCR_LC;
__vcpu_sys_reg(vcpu, r->reg) = val; __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 = __vcpu_sys_reg(vcpu, PMCR_EL0);
val &= ~ARMV8_PMU_PMCR_MASK; val &= ~ARMV8_PMU_PMCR_MASK;
val |= p->regval & 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; val |= ARMV8_PMU_PMCR_LC;
__vcpu_sys_reg(vcpu, PMCR_EL0) = val; __vcpu_sys_reg(vcpu, PMCR_EL0) = val;
kvm_pmu_handle_pmcr(vcpu, val); kvm_pmu_handle_pmcr(vcpu, val);

View File

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

View File

@@ -6,9 +6,9 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <linux/cache.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/current.h> #include <asm/current.h>
#include <asm/cache.h>
#include <abi/reg_ops.h> #include <abi/reg_ops.h>
#include <abi/regdef.h> #include <abi/regdef.h>
#include <abi/switch_context.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) # define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
# else /* CONFIG_MMU */ # else /* CONFIG_MMU */
# define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT) # 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 /* CONFIG_MMU */
# endif /* __ASSEMBLY__ */ # endif /* __ASSEMBLY__ */

View File

@@ -464,6 +464,7 @@ CONFIG_MMC_CRYPTO=y
CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_LEDS_CLASS_FLASH=y CONFIG_LEDS_CLASS_FLASH=y
CONFIG_LEDS_CLASS_MULTICOLOR=y
CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_EDAC=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) 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 * If the IO scheduler does not respect hardware queues when
* dispatching, we just don't bother with multiple HW queues and * 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 * just causes lock contention inside the scheduler and pointless cache
* bouncing. * bouncing.
*/ */
hctx = blk_mq_map_queue_type(q, HCTX_TYPE_DEFAULT, struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, 0, ctx);
raw_smp_processor_id());
if (!blk_mq_hctx_stopped(hctx)) if (!blk_mq_hctx_stopped(hctx))
return hctx; return hctx;
return NULL; 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]; per_prio = &dd->per_prio[prio];
if (at_head) { if (at_head) {
list_add(&rq->queuelist, &per_prio->dispatch); list_add(&rq->queuelist, &per_prio->dispatch);
rq->fifo_time = jiffies;
} else { } else {
deadline_add_rq_rb(per_prio, rq); 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_JIFFIES(deadline_aging_expire_show, dd->aging_expire);
SHOW_INT(deadline_writes_starved_show, dd->writes_starved); SHOW_INT(deadline_writes_starved_show, dd->writes_starved);
SHOW_INT(deadline_front_merges_show, dd->front_merges); 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); SHOW_INT(deadline_fifo_batch_show, dd->fifo_batch);
#undef SHOW_INT #undef SHOW_INT
#undef SHOW_JIFFIES #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_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_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX);
STORE_INT(deadline_front_merges_store, &dd->front_merges, 0, 1); 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); STORE_INT(deadline_fifo_batch_store, &dd->fifo_batch, 0, INT_MAX);
#undef STORE_FUNCTION #undef STORE_FUNCTION
#undef STORE_INT #undef STORE_INT

View File

@@ -9,6 +9,7 @@ function update_config() {
-d CPU_BIG_ENDIAN \ -d CPU_BIG_ENDIAN \
-d DYNAMIC_FTRACE \ -d DYNAMIC_FTRACE \
-e UNWINDER_FRAME_POINTER \ -e UNWINDER_FRAME_POINTER \
-d WERROR \
(cd ${OUT_DIR} && \ (cd ${OUT_DIR} && \
make O=${OUT_DIR} $archsubarch CROSS_COMPILE=${CROSS_COMPILE} "${TOOL_ARGS[@]}" ${MAKE_ARGS} olddefconfig) 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 \ gf128mul.o aes_generic.o lib-crypto-aes.o \
jitterentropy.o jitterentropy-kcapi.o \ jitterentropy.o jitterentropy-kcapi.o \
sha1_generic.o sha256_generic.o sha512_generic.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)) crypto-fips-objs := $(foreach o,$(crypto-fips-objs),$(o:.o=-fips.o))
# get the arch to add its objects to $(crypto-fips-objs) # 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 * binder_get_object() - gets object and checks for valid metadata
* @proc: binder_proc owning the buffer * @proc: binder_proc owning the buffer
* @u: sender's user pointer to base of buffer
* @buffer: binder_buffer that we're parsing. * @buffer: binder_buffer that we're parsing.
* @offset: offset in the @buffer at which to validate an object. * @offset: offset in the @buffer at which to validate an object.
* @object: struct binder_object to read into * @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 * size of that object. Otherwise, it returns zero. The object
* is read into the struct binder_object pointed to by @object. * is read into the struct binder_object pointed to by @object.
*/ */
static size_t binder_get_object(struct binder_proc *proc, static size_t binder_get_object(struct binder_proc *proc,
const void __user *u,
struct binder_buffer *buffer, struct binder_buffer *buffer,
unsigned long offset, unsigned long offset,
struct binder_object *object) struct binder_object *object)
@@ -1792,10 +1798,16 @@ static size_t binder_get_object(struct binder_proc *proc,
size_t object_size = 0; size_t object_size = 0;
read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset); read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
if (offset > buffer->data_size || read_size < sizeof(*hdr) || if (offset > buffer->data_size || read_size < sizeof(*hdr))
binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
offset, read_size))
return 0; 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. */ /* Ok, now see if we read a complete object. */
hdr = &object->hdr; hdr = &object->hdr;
@@ -1868,7 +1880,7 @@ static struct binder_buffer_object *binder_validate_ptr(
b, buffer_offset, b, buffer_offset,
sizeof(object_offset))) sizeof(object_offset)))
return NULL; 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) if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
return NULL; return NULL;
if (object_offsetp) if (object_offsetp)
@@ -1933,7 +1945,8 @@ static bool binder_validate_fixup(struct binder_proc *proc,
unsigned long buffer_offset; unsigned long buffer_offset;
struct binder_object last_object; struct binder_object last_object;
struct binder_buffer_object *last_bbo; 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); &last_object);
if (object_size != sizeof(*last_bbo)) if (object_size != sizeof(*last_bbo))
return false; 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, if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
buffer, buffer_offset, buffer, buffer_offset,
sizeof(object_offset))) sizeof(object_offset)))
object_size = binder_get_object(proc, buffer, object_size = binder_get_object(proc, NULL, buffer,
object_offset, &object); object_offset, &object);
if (object_size == 0) { if (object_size == 0) {
pr_err("transaction release %d bad object at offset %lld, size %zd\n", pr_err("transaction release %d bad object at offset %lld, size %zd\n",
@@ -2389,16 +2402,266 @@ err_fd_not_accepted:
return ret; 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 *parent,
struct binder_buffer_object *sender_uparent,
struct binder_transaction *t, struct binder_transaction *t,
struct binder_thread *thread, struct binder_thread *thread,
struct binder_transaction *in_reply_to) struct binder_transaction *in_reply_to)
{ {
binder_size_t fdi, fd_buf_size; binder_size_t fdi, fd_buf_size;
binder_size_t fda_offset; binder_size_t fda_offset;
const void __user *sender_ufda_base;
struct binder_proc *proc = thread->proc; 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; fd_buf_size = sizeof(u32) * fda->num_fds;
if (fda->num_fds >= SIZE_MAX / sizeof(u32)) { 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_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) +
fda->parent_offset; 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", binder_user_error("%d:%d parent offset not aligned correctly.\n",
proc->pid, thread->pid); proc->pid, thread->pid);
return -EINVAL; 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++) { for (fdi = 0; fdi < fda->num_fds; fdi++) {
u32 fd; u32 fd;
int ret;
binder_size_t offset = fda_offset + fdi * sizeof(fd); 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, ret = copy_from_user(&fd, sender_ufda_base + sender_uoffset, sizeof(fd));
&fd, t->buffer,
offset, sizeof(fd));
if (!ret) if (!ret)
ret = binder_translate_fd(fd, offset, t, thread, ret = binder_translate_fd(fd, offset, t, thread,
in_reply_to); in_reply_to);
@@ -2444,7 +2713,8 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
return 0; 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_thread *thread,
struct binder_buffer_object *bp, struct binder_buffer_object *bp,
binder_size_t off_start_offset, binder_size_t off_start_offset,
@@ -2490,14 +2760,7 @@ static int binder_fixup_parent(struct binder_transaction *t,
} }
buffer_offset = bp->parent_offset + buffer_offset = bp->parent_offset +
(uintptr_t)parent->buffer - (uintptr_t)b->user_data; (uintptr_t)parent->buffer - (uintptr_t)b->user_data;
if (binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset, return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0);
&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;
} }
/** /**
@@ -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_start_offset, off_end_offset;
binder_size_t off_min; binder_size_t off_min;
binder_size_t sg_buf_offset, sg_buf_end_offset; binder_size_t sg_buf_offset, sg_buf_end_offset;
binder_size_t user_offset = 0;
struct binder_proc *target_proc = NULL; struct binder_proc *target_proc = NULL;
struct binder_thread *target_thread = NULL; struct binder_thread *target_thread = NULL;
struct binder_node *target_node = 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); int t_debug_id = atomic_inc_return(&binder_last_id);
char *secctx = NULL; char *secctx = NULL;
u32 secctx_sz = 0; 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 = binder_transaction_log_add(&binder_transaction_log);
e->debug_id = t_debug_id; 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); t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF);
trace_binder_transaction_alloc_buf(t->buffer); 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( if (binder_alloc_copy_user_to_buffer(
&target_proc->alloc, &target_proc->alloc,
t->buffer, t->buffer,
@@ -3121,6 +3378,7 @@ static void binder_transaction(struct binder_proc *proc,
size_t object_size; size_t object_size;
struct binder_object object; struct binder_object object;
binder_size_t object_offset; binder_size_t object_offset;
binder_size_t copy_size;
if (binder_alloc_copy_from_buffer(&target_proc->alloc, if (binder_alloc_copy_from_buffer(&target_proc->alloc,
&object_offset, &object_offset,
@@ -3132,8 +3390,27 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__; return_error_line = __LINE__;
goto err_bad_offset; 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) { 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", binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
proc->pid, thread->pid, proc->pid, thread->pid,
@@ -3145,6 +3422,11 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__; return_error_line = __LINE__;
goto err_bad_offset; goto err_bad_offset;
} }
/*
* Set offset to the next buffer fragment to be
* copied
*/
user_offset = object_offset + object_size;
hdr = &object.hdr; hdr = &object.hdr;
off_min = object_offset + object_size; off_min = object_offset + object_size;
@@ -3207,6 +3489,8 @@ static void binder_transaction(struct binder_proc *proc,
case BINDER_TYPE_FDA: { case BINDER_TYPE_FDA: {
struct binder_object ptr_object; struct binder_object ptr_object;
binder_size_t parent_offset; binder_size_t parent_offset;
struct binder_object user_object;
size_t user_parent_size;
struct binder_fd_array_object *fda = struct binder_fd_array_object *fda =
to_binder_fd_array_object(hdr); to_binder_fd_array_object(hdr);
size_t num_valid = (buffer_offset - off_start_offset) / 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__; return_error_line = __LINE__;
goto err_bad_parent; goto err_bad_parent;
} }
ret = binder_translate_fd_array(fda, parent, t, thread, /*
in_reply_to); * We need to read the user version of the parent
if (ret < 0) { * 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 = 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__; return_error_line = __LINE__;
goto err_translate_failed; goto err_translate_failed;
} }
@@ -3264,19 +3572,14 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__; return_error_line = __LINE__;
goto err_bad_offset; goto err_bad_offset;
} }
if (binder_alloc_copy_user_to_buffer( ret = binder_defer_copy(&sgc_head, sg_buf_offset,
&target_proc->alloc, (const void __user *)(uintptr_t)bp->buffer,
t->buffer, bp->length);
sg_buf_offset, if (ret) {
(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;
return_error = BR_FAILED_REPLY; return_error = BR_FAILED_REPLY;
return_error_param = ret;
return_error_line = __LINE__; return_error_line = __LINE__;
goto err_copy_data_failed; goto err_translate_failed;
} }
/* Fixup buffer pointer to target proc address space */ /* Fixup buffer pointer to target proc address space */
bp->buffer = (uintptr_t) bp->buffer = (uintptr_t)
@@ -3285,7 +3588,8 @@ static void binder_transaction(struct binder_proc *proc,
num_valid = (buffer_offset - off_start_offset) / num_valid = (buffer_offset - off_start_offset) /
sizeof(binder_size_t); sizeof(binder_size_t);
ret = binder_fixup_parent(t, thread, bp, ret = binder_fixup_parent(&pf_head, t,
thread, bp,
off_start_offset, off_start_offset,
num_valid, num_valid,
last_fixup_obj_off, last_fixup_obj_off,
@@ -3312,6 +3616,30 @@ static void binder_transaction(struct binder_proc *proc,
goto err_bad_object_type; 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) if (t->buffer->oneway_spam_suspect)
tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT; tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
else else
@@ -3387,6 +3715,7 @@ err_bad_object_type:
err_bad_offset: err_bad_offset:
err_bad_parent: err_bad_parent:
err_copy_data_failed: err_copy_data_failed:
binder_cleanup_deferred_txn_lists(&sgc_head, &pf_head);
binder_free_txn_fixups(t); binder_free_txn_fixups(t);
trace_binder_transaction_failed_buffer_release(t->buffer); trace_binder_transaction_failed_buffer_release(t->buffer);
binder_transaction_buffer_release(target_proc, NULL, t->buffer, binder_transaction_buffer_release(target_proc, NULL, t->buffer,

View File

@@ -7,6 +7,7 @@
*/ */
#ifndef __GENKSYMS__ #ifndef __GENKSYMS__
#include <linux/dma-buf.h>
#include <linux/rmap.h> #include <linux/rmap.h>
#endif #endif
@@ -74,6 +75,7 @@
#include <trace/hooks/snd_compr.h> #include <trace/hooks/snd_compr.h>
#include <trace/hooks/ipv4.h> #include <trace/hooks/ipv4.h>
#include <trace/hooks/pci.h> #include <trace/hooks/pci.h>
#include <trace/hooks/dmabuf.h>
/* /*
* Export tracepoints that act as a bare tracehook (ie: have no trace event * 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_alloc_si);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_pages); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_pages);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_shmem_page_flag); 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_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_check_page_look_around_ref);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_look_around); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_look_around);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_look_around_migrate_page); 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_vh_test_clear_look_around_ref);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_dma_buf_stats_teardown);
/* /*
* For type visibility * For type visibility
*/ */

View File

@@ -219,6 +219,9 @@ static void genpd_debug_remove(struct generic_pm_domain *genpd)
{ {
struct dentry *d; struct dentry *d;
if (!genpd_debugfs_dir)
return;
d = debugfs_lookup(genpd->name, genpd_debugfs_dir); d = debugfs_lookup(genpd->name, genpd_debugfs_dir);
debugfs_remove(d); debugfs_remove(d);
} }
@@ -1972,6 +1975,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
genpd->device_count = 0; genpd->device_count = 0;
genpd->max_off_time_ns = -1; genpd->max_off_time_ns = -1;
genpd->max_off_time_changed = true; genpd->max_off_time_changed = true;
genpd->next_wakeup = KTIME_MAX;
genpd->provider = NULL; genpd->provider = NULL;
genpd->has_provider = false; genpd->has_provider = false;
genpd->accounting_time = ktime_get(); genpd->accounting_time = ktime_get();
@@ -2052,9 +2056,9 @@ static int genpd_remove(struct generic_pm_domain *genpd)
kfree(link); kfree(link);
} }
genpd_debug_remove(genpd);
list_del(&genpd->gpd_list_node); list_del(&genpd->gpd_list_node);
genpd_unlock(genpd); genpd_unlock(genpd);
genpd_debug_remove(genpd);
cancel_work_sync(&genpd->power_off_work); cancel_work_sync(&genpd->power_off_work);
if (genpd_is_cpu_domain(genpd)) if (genpd_is_cpu_domain(genpd))
free_cpumask_var(genpd->cpus); 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 clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id)
{ {
struct device *dev = hw->core->dev; 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); EXPORT_SYMBOL(clk_hw_get_clk);

View File

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

View File

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

View File

@@ -13,6 +13,8 @@
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <trace/hooks/dmabuf.h>
#include "dma-buf-sysfs-stats.h" #include "dma-buf-sysfs-stats.h"
#define to_dma_buf_entry_from_kobj(x) container_of(x, struct dma_buf_sysfs_entry, kobj) #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) void dma_buf_stats_teardown(struct dma_buf *dmabuf)
{ {
struct dma_buf_sysfs_entry *sysfs_entry; struct dma_buf_sysfs_entry *sysfs_entry;
bool skip_sysfs_release = false;
sysfs_entry = dmabuf->sysfs_entry; sysfs_entry = dmabuf->sysfs_entry;
if (!sysfs_entry) if (!sysfs_entry)
return; return;
kobject_del(&sysfs_entry->kobj); trace_android_rvh_dma_buf_stats_teardown(sysfs_entry, &skip_sysfs_release);
kobject_put(&sysfs_entry->kobj); 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); 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) 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. */ struct dma_buf_create_sysfs_entry *create_entry =
_Static_assert(sizeof(struct kobject) >= sizeof(struct work_struct), container_of(work, struct dma_buf_create_sysfs_entry, work);
"kobject is smaller than work_struct"); struct dma_buf *dmabuf = create_entry->dmabuf;
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;
/* /*
* A dmabuf is ref-counted via its file member. If this handler holds the only * 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. * is released, and that can't happen until the end of this function.
*/ */
if (file_count(dmabuf->file) > 1) { 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 * kobject_init_and_add expects kobject to be zero-filled, but we have populated it
* to trigger this work function. * 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) int dma_buf_stats_setup(struct dma_buf *dmabuf)
{ {
struct dma_buf_sysfs_entry *sysfs_entry; struct dma_buf_create_sysfs_entry *create_entry;
struct work_struct *work; union dma_buf_create_sysfs_work_entry *work_entry;
if (!dmabuf || !dmabuf->file) if (!dmabuf || !dmabuf->file)
return -EINVAL; return -EINVAL;
@@ -190,21 +203,18 @@ int dma_buf_stats_setup(struct dma_buf *dmabuf)
return -EINVAL; return -EINVAL;
} }
sysfs_entry = kmalloc(sizeof(struct dma_buf_sysfs_entry), GFP_KERNEL); work_entry = kmalloc(sizeof(union dma_buf_create_sysfs_work_entry), GFP_KERNEL);
if (!sysfs_entry) if (!work_entry)
return -ENOMEM; return -ENOMEM;
sysfs_entry->dmabuf = dmabuf; dmabuf->sysfs_entry = &work_entry->sysfs_entry;
dmabuf->sysfs_entry = sysfs_entry;
/* create_entry = &work_entry->create_entry;
* The use of kobj as a work_struct is an ugly hack create_entry->dmabuf = dmabuf;
* to avoid an ABI break in this frozen kernel.
*/ INIT_WORK(&create_entry->work, sysfs_add_workfn);
work = (struct work_struct *)&dmabuf->sysfs_entry->kobj;
INIT_WORK(work, sysfs_add_workfn);
get_dma_buf(dmabuf); /* This reference will be dropped in 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; 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 cma_heap_buffer *buffer = dmabuf->priv;
struct dma_heap_attachment *a; struct dma_heap_attachment *a;
mutex_lock(&buffer->lock);
if (buffer->vmap_cnt) if (buffer->vmap_cnt)
invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); invalidate_kernel_vmap_range(buffer->vaddr, buffer->len);
mutex_lock(&buffer->lock);
list_for_each_entry(a, &buffer->attachments, list) { list_for_each_entry(a, &buffer->attachments, list) {
if (!a->mapped) if (!a->mapped)
continue; 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 cma_heap_buffer *buffer = dmabuf->priv;
struct dma_heap_attachment *a; struct dma_heap_attachment *a;
mutex_lock(&buffer->lock);
if (buffer->vmap_cnt) if (buffer->vmap_cnt)
flush_kernel_vmap_range(buffer->vaddr, buffer->len); flush_kernel_vmap_range(buffer->vaddr, buffer->len);
mutex_lock(&buffer->lock);
list_for_each_entry(a, &buffer->attachments, list) { list_for_each_entry(a, &buffer->attachments, list) {
if (!a->mapped) if (!a->mapped)
continue; continue;

View File

@@ -11,10 +11,16 @@
#include <linux/freezer.h> #include <linux/freezer.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#include "page_pool.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 LIST_HEAD(pool_list);
static DEFINE_MUTEX(pool_list_lock); 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) static void dmabuf_page_pool_add(struct dmabuf_page_pool *pool, struct page *page)
{ {
int index; int index;
struct dmabuf_page_pool_with_spinlock *container_pool =
container_of(pool, struct dmabuf_page_pool_with_spinlock, pool);
if (PageHighMem(page)) if (PageHighMem(page))
index = POOL_HIGHPAGE; index = POOL_HIGHPAGE;
else else
index = POOL_LOWPAGE; index = POOL_LOWPAGE;
mutex_lock(&pool->mutex); spin_lock(&container_pool->spinlock);
list_add_tail(&page->lru, &pool->items[index]); list_add_tail(&page->lru, &pool->items[index]);
pool->count[index]++; pool->count[index]++;
spin_unlock(&container_pool->spinlock);
mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE, mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE,
1 << pool->order); 1 << pool->order);
mutex_unlock(&pool->mutex);
} }
static struct page *dmabuf_page_pool_remove(struct dmabuf_page_pool *pool, int index) static struct page *dmabuf_page_pool_remove(struct dmabuf_page_pool *pool, int index)
{ {
struct page *page; 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); page = list_first_entry_or_null(&pool->items[index], struct page, lru);
if (page) { if (page) {
pool->count[index]--; pool->count[index]--;
list_del(&page->lru); list_del(&page->lru);
spin_unlock(&container_pool->spinlock);
mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE, mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE,
-(1 << pool->order)); -(1 << pool->order));
goto out;
} }
mutex_unlock(&pool->mutex); spin_unlock(&container_pool->spinlock);
out:
return page; 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 *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; int i;
if (!pool) if (!container_pool)
return NULL; return NULL;
spin_lock_init(&container_pool->spinlock);
pool = &container_pool->pool;
for (i = 0; i < POOL_TYPE_SIZE; i++) { for (i = 0; i < POOL_TYPE_SIZE; i++) {
pool->count[i] = 0; pool->count[i] = 0;
INIT_LIST_HEAD(&pool->items[i]); INIT_LIST_HEAD(&pool->items[i]);
} }
pool->gfp_mask = gfp_mask | __GFP_COMP; pool->gfp_mask = gfp_mask | __GFP_COMP;
pool->order = order; 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); mutex_lock(&pool_list_lock);
list_add(&pool->list, &pool_list); 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) void dmabuf_page_pool_destroy(struct dmabuf_page_pool *pool)
{ {
struct page *page; struct page *page;
struct dmabuf_page_pool_with_spinlock *container_pool;
int i; int i;
/* Remove us from the pool list */ /* 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); 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); EXPORT_SYMBOL_GPL(dmabuf_page_pool_destroy);

View File

@@ -40,7 +40,7 @@ enum {
struct dmabuf_page_pool { struct dmabuf_page_pool {
int count[POOL_TYPE_SIZE]; int count[POOL_TYPE_SIZE];
struct list_head items[POOL_TYPE_SIZE]; struct list_head items[POOL_TYPE_SIZE];
struct mutex mutex; struct mutex mutex; /* No longer used! */
gfp_t gfp_mask; gfp_t gfp_mask;
unsigned int order; unsigned int order;
struct list_head list; 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_2 0x09cc
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE 0x0ba0 #define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE 0x0ba0
#define USB_DEVICE_ID_SONY_PS5_CONTROLLER 0x0ce6 #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_MOTION_CONTROLLER 0x03d5
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002

View File

@@ -11,6 +11,8 @@
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/leds.h>
#include <linux/led-class-multicolor.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
@@ -38,11 +40,13 @@ struct ps_device {
uint8_t battery_capacity; uint8_t battery_capacity;
int battery_status; int battery_status;
const char *input_dev_name; /* Name of primary input device. */
uint8_t mac_address[6]; /* Note: stored in little endian order. */ uint8_t mac_address[6]; /* Note: stored in little endian order. */
uint32_t hw_version; uint32_t hw_version;
uint32_t fw_version; uint32_t fw_version;
int (*parse_report)(struct ps_device *dev, struct hid_report *report, u8 *data, int size); 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. */ /* Calibration data for playstation motion sensors. */
@@ -53,6 +57,13 @@ struct ps_calibration_data {
int sens_denom; 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. */ /* Seed values for DualShock4 / DualSense CRC32 for different report types. */
#define PS_INPUT_CRC32_SEED 0xA1 #define PS_INPUT_CRC32_SEED 0xA1
#define PS_OUTPUT_CRC32_SEED 0xA2 #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 GENMASK(7, 4)
#define DS_STATUS_CHARGING_SHIFT 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. * Status of a DualSense touch point contact.
* Contact IDs, with highest bit set are 'inactive' * 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_RELEASE_LEDS BIT(3)
#define DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE BIT(4) #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_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_POWER_SAVE_CONTROL_MIC_MUTE BIT(4)
#define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1) #define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
@@ -132,6 +147,9 @@ struct dualsense {
struct input_dev *sensors; struct input_dev *sensors;
struct input_dev *touchpad; struct input_dev *touchpad;
/* Update version is used as a feature/capability version. */
uint16_t update_version;
/* Calibration data for accelerometer and gyroscope. */ /* Calibration data for accelerometer and gyroscope. */
struct ps_calibration_data accel_calib_data[3]; struct ps_calibration_data accel_calib_data[3];
struct ps_calibration_data gyro_calib_data[3]; struct ps_calibration_data gyro_calib_data[3];
@@ -142,11 +160,13 @@ struct dualsense {
uint32_t sensor_timestamp_us; uint32_t sensor_timestamp_us;
/* Compatible rumble state */ /* Compatible rumble state */
bool use_vibration_v2;
bool update_rumble; bool update_rumble;
uint8_t motor_left; uint8_t motor_left;
uint8_t motor_right; uint8_t motor_right;
/* RGB lightbar */ /* RGB lightbar */
struct led_classdev_mc lightbar;
bool update_lightbar; bool update_lightbar;
uint8_t lightbar_red; uint8_t lightbar_red;
uint8_t lightbar_green; uint8_t lightbar_green;
@@ -163,6 +183,7 @@ struct dualsense {
struct led_classdev player_leds[5]; struct led_classdev player_leds[5];
struct work_struct output_worker; struct work_struct output_worker;
bool output_worker_initialized;
void *output_report_dmabuf; void *output_report_dmabuf;
uint8_t output_seq; /* Sequence number for output report. */ 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}, {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. * Add a new ps_device to ps_devices if it doesn't exist.
* Return error on duplicate device, which can happen if the same * 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; 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, static struct input_dev *ps_sensors_create(struct hid_device *hdev, int accel_range, int accel_res,
int gyro_range, int gyro_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 DEVICE_ATTR_RO(hardware_version);
static struct attribute *ps_device_attributes[] = { static struct attribute *ps_device_attrs[] = {
&dev_attr_firmware_version.attr, &dev_attr_firmware_version.attr,
&dev_attr_hardware_version.attr, &dev_attr_hardware_version.attr,
NULL NULL
}; };
ATTRIBUTE_GROUPS(ps_device);
static const struct attribute_group ps_device_attribute_group = {
.attrs = ps_device_attributes,
};
static int dualsense_get_calibration_data(struct dualsense *ds) static int dualsense_get_calibration_data(struct dualsense *ds)
{ {
@@ -714,6 +800,7 @@ err_free:
return ret; return ret;
} }
static int dualsense_get_firmware_info(struct dualsense *ds) static int dualsense_get_firmware_info(struct dualsense *ds)
{ {
uint8_t *buf; 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.hw_version = get_unaligned_le32(&buf[24]);
ds->base.fw_version = get_unaligned_le32(&buf[28]); 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: err_free:
kfree(buf); kfree(buf);
return ret; return ret;
@@ -761,6 +857,53 @@ err_free:
return ret; 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, static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_output_report *rp,
void *buf) 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 * Helper function to send DualSense output reports. Applies a CRC at the end of a report
* for Bluetooth reports. * for Bluetooth reports.
@@ -838,7 +991,10 @@ static void dualsense_output_worker(struct work_struct *work)
if (ds->update_rumble) { if (ds->update_rumble) {
/* Select classic rumble style haptics and enable it. */ /* Select classic rumble style haptics and enable it. */
common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT; 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_left = ds->motor_left;
common->motor_right = ds->motor_right; common->motor_right = ds->motor_right;
ds->update_rumble = false; 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); spin_unlock_irqrestore(&ps_dev->lock, flags);
/* Schedule updating of microphone state at hardware level. */ /* 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; 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; ds->motor_right = effect->u.rumble.weak_magnitude / 256;
spin_unlock_irqrestore(&ds->base.lock, flags); spin_unlock_irqrestore(&ds->base.lock, flags);
schedule_work(&ds->output_worker); dualsense_schedule_work(ds);
return 0; 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) static int dualsense_reset_leds(struct dualsense *ds)
{ {
struct dualsense_output_report report; 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) 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->update_lightbar = true;
ds->lightbar_red = red; ds->lightbar_red = red;
ds->lightbar_green = green; ds->lightbar_green = green;
ds->lightbar_blue = blue; 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) 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->update_player_leds = true;
ds->player_leds_state = player_ids[player_id]; 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) 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 dualsense *ds;
struct ps_device *ps_dev; struct ps_device *ps_dev;
uint8_t max_output_report_size; 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); ds = devm_kzalloc(&hdev->dev, sizeof(*ds), GFP_KERNEL);
if (!ds) 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_capacity = 100; /* initial value until parse_report. */
ps_dev->battery_status = POWER_SUPPLY_STATUS_UNKNOWN; ps_dev->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
ps_dev->parse_report = dualsense_parse_report; ps_dev->parse_report = dualsense_parse_report;
ps_dev->remove = dualsense_remove;
INIT_WORK(&ds->output_worker, dualsense_output_worker); INIT_WORK(&ds->output_worker, dualsense_output_worker);
ds->output_worker_initialized = true;
hid_set_drvdata(hdev, ds); hid_set_drvdata(hdev, ds);
max_output_report_size = sizeof(struct dualsense_output_report_bt); 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); 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); ret = ps_devices_list_add(ps_dev);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
@@ -1196,6 +1398,8 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
ret = PTR_ERR(ds->gamepad); ret = PTR_ERR(ds->gamepad);
goto err; 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->sensors = ps_sensors_create(hdev, DS_ACC_RANGE, DS_ACC_RES_PER_G,
DS_GYRO_RANGE, DS_GYRO_RES_PER_DEG_S); 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) if (ret)
goto err; 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 */ 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); ret = ps_device_set_player_id(ps_dev);
if (ret) { if (ret) {
hid_err(hdev, "Failed to assign player id for DualSense: %d\n", 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; 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); dev = dualsense_create(hdev);
if (IS_ERR(dev)) { if (IS_ERR(dev)) {
hid_err(hdev, "Failed to create dualsense.\n"); 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; return ret;
err_close: err_close:
@@ -1313,6 +1525,9 @@ static void ps_remove(struct hid_device *hdev)
ps_devices_list_remove(dev); ps_devices_list_remove(dev);
ps_device_release_player_id(dev); ps_device_release_player_id(dev);
if (dev->remove)
dev->remove(dev);
hid_hw_close(hdev); hid_hw_close(hdev);
hid_hw_stop(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[] = { static const struct hid_device_id ps_devices[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) }, { 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_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); MODULE_DEVICE_TABLE(hid, ps_devices);
@@ -1330,6 +1547,9 @@ static struct hid_driver ps_driver = {
.probe = ps_probe, .probe = ps_probe,
.remove = ps_remove, .remove = ps_remove,
.raw_event = ps_raw_event, .raw_event = ps_raw_event,
.driver = {
.dev_groups = ps_device_groups,
},
}; };
static int __init ps_init(void) 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, static int mtk_iommu_attach_device(struct iommu_domain *domain,
struct device *dev) 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 mtk_iommu_domain *dom = to_mtk_domain(domain);
struct device *m4udev = data->dev; struct device *m4udev = data->dev;
int ret, domid; int ret, domid;
@@ -468,20 +468,24 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
return domid; return domid;
if (!dom->data) { 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; return -ENODEV;
dom->data = data; dom->data = data;
} }
mutex_lock(&data->mutex);
if (!data->m4u_dom) { /* Initialize the M4U HW */ if (!data->m4u_dom) { /* Initialize the M4U HW */
ret = pm_runtime_resume_and_get(m4udev); ret = pm_runtime_resume_and_get(m4udev);
if (ret < 0) if (ret < 0)
return ret; goto err_unlock;
ret = mtk_iommu_hw_init(data); ret = mtk_iommu_hw_init(data);
if (ret) { if (ret) {
pm_runtime_put(m4udev); pm_runtime_put(m4udev);
return ret; goto err_unlock;
} }
data->m4u_dom = dom; data->m4u_dom = dom;
writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, 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); pm_runtime_put(m4udev);
} }
mutex_unlock(&data->mutex);
mtk_iommu_config(data, dev, true, domid); mtk_iommu_config(data, dev, true, domid);
return 0; return 0;
err_unlock:
mutex_unlock(&data->mutex);
return ret;
} }
static void mtk_iommu_detach_device(struct iommu_domain *domain, 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) if (domid < 0)
return ERR_PTR(domid); return ERR_PTR(domid);
mutex_lock(&data->mutex);
group = data->m4u_group[domid]; group = data->m4u_group[domid];
if (!group) { if (!group) {
group = iommu_group_alloc(); group = iommu_group_alloc();
@@ -611,6 +621,7 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev)
} else { } else {
iommu_group_ref_get(group); iommu_group_ref_get(group);
} }
mutex_unlock(&data->mutex);
return group; return group;
} }
@@ -884,6 +895,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
} }
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
mutex_init(&data->mutex);
ret = iommu_device_sysfs_add(&data->iommu, dev, NULL, ret = iommu_device_sysfs_add(&data->iommu, dev, NULL,
"mtk-iommu.%pa", &ioaddr); "mtk-iommu.%pa", &ioaddr);
@@ -934,7 +946,6 @@ static int mtk_iommu_remove(struct platform_device *pdev)
list_del(&data->list); list_del(&data->list);
clk_disable_unprepare(data->bclk);
device_link_remove(data->smicomm_dev, &pdev->dev); device_link_remove(data->smicomm_dev, &pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
devm_free_irq(&pdev->dev, data->irq, data); 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 dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */
struct mutex mutex; /* Protect m4u_group/m4u_dom above */
struct list_head list; struct list_head list;
struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; 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; 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! */ u32 count = 1000000; /* 1s! */
bool clean; bool clean;
u64 val; 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 { do {
val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER); val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
clean = !(val & GICR_VPENDBASER_Dirty); 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); } while (!clean && count);
if (unlikely(val & GICR_VPENDBASER_Dirty)) { if (unlikely(!clean))
pr_err_ratelimited("ITS virtual pending table not cleaning\n"); 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; val |= GICR_VPENDBASER_PendingLast;
}
return val; 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; m->bio->bi_status = BLK_STS_IOERR;
bio_endio(m->bio); bio_endio(m->bio);
bio_put(m->bio);
mempool_free(m, pool); mempool_free(m, pool);
} }
@@ -989,7 +988,6 @@ finish_bio:
*/ */
WARN_ON(bio_size(c->cur_from_user->bio) != 0); WARN_ON(bio_size(c->cur_from_user->bio) != 0);
bio_endio(c->cur_from_user->bio); 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 * 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; return DM_MAPIO_REQUEUE;
} }
bio_get(bio);
entry->msg.type = bio_type_to_user_type(bio); entry->msg.type = bio_type_to_user_type(bio);
entry->msg.flags = bio_flags_to_user_flags(bio); entry->msg.flags = bio_flags_to_user_flags(bio);
entry->msg.sector = bio->bi_iter.bi_sector; 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) if (ret == -ENOMEM)
return ret; return ret;
} }
of_node_put(np);
/* /*
* Register a regulator for each valid regulator-DT-entry that we * Register a regulator for each valid regulator-DT-entry that we
* can successfully reach via SCMI and has a valid associated voltage * 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); struct ufs_mtk_host *host = ufshcd_get_variant(hba);
host->reg_va09 = regulator_get(hba->dev, "va09"); 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"); dev_info(hba->dev, "failed to get va09");
else else
host->caps |= UFS_MTK_CAP_VA09_PWR_CTRL; 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->issue_time_stamp = ktime_get();
lrbp->compl_time_stamp = ktime_set(0, 0); 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); trace_android_vh_ufs_send_command(hba, lrbp);
ufshcd_add_command_trace(hba, task_tag, "send"); ufshcd_add_command_trace(hba, task_tag, "send");
ufshcd_clk_scaling_start_busy(hba); ufshcd_clk_scaling_start_busy(hba);
if (unlikely(ufshcd_should_inform_monitor(hba, lrbp))) if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
ufshcd_start_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)) { if (ufshcd_has_utrlcnr(hba)) {
set_bit(task_tag, &hba->outstanding_reqs); set_bit(task_tag, &hba->outstanding_reqs);
ufshcd_writel(hba, 1 << task_tag, 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; 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, static inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba,
int tag, u8 tm_function) int tag, u8 tm_function)
{ {

View File

@@ -301,6 +301,7 @@ int dwc3_core_soft_reset(struct dwc3 *dwc)
udelay(1); udelay(1);
} while (--retries); } while (--retries);
dev_warn(dwc->dev, "DWC3 controller soft reset failed.\n");
return -ETIMEDOUT; return -ETIMEDOUT;
done: 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; u32 val;
int i, ret; int i, ret;
@@ -369,7 +369,7 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
if (ret) if (ret)
dev_warn(qcom->dev, "failed to disable interconnect: %d\n", 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); dwc3_qcom_enable_interrupts(qcom);
qcom->is_suspended = true; qcom->is_suspended = true;
@@ -377,7 +377,7 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
return 0; 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 ret;
int i; int i;
@@ -385,7 +385,7 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
if (!qcom->is_suspended) if (!qcom->is_suspended)
return 0; return 0;
if (device_may_wakeup(qcom->dev)) if (wakeup)
dwc3_qcom_disable_interrupts(qcom); dwc3_qcom_disable_interrupts(qcom);
for (i = 0; i < qcom->num_clocks; i++) { 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) static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev)
{ {
struct dwc3_qcom *qcom = dev_get_drvdata(dev); struct dwc3_qcom *qcom = dev_get_drvdata(dev);
bool wakeup = device_may_wakeup(dev);
int ret = 0; int ret = 0;
ret = dwc3_qcom_suspend(qcom);
ret = dwc3_qcom_suspend(qcom, wakeup);
if (!ret) if (!ret)
qcom->pm_suspended = true; 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) static int __maybe_unused dwc3_qcom_pm_resume(struct device *dev)
{ {
struct dwc3_qcom *qcom = dev_get_drvdata(dev); struct dwc3_qcom *qcom = dev_get_drvdata(dev);
bool wakeup = device_may_wakeup(dev);
int ret; int ret;
ret = dwc3_qcom_resume(qcom); ret = dwc3_qcom_resume(qcom, wakeup);
if (!ret) if (!ret)
qcom->pm_suspended = false; 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); 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) static int __maybe_unused dwc3_qcom_runtime_resume(struct device *dev)
{ {
struct dwc3_qcom *qcom = dev_get_drvdata(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 = { static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = {

View File

@@ -218,7 +218,7 @@ out:
return ret; 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; struct dwc3_ep *dep;
@@ -239,6 +239,8 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
dwc3_gadget_giveback(dep, req, -ECONNRESET); dwc3_gadget_giveback(dep, req, -ECONNRESET);
} }
dwc->eps[0]->trb_enqueue = 0;
dwc->eps[1]->trb_enqueue = 0;
dwc->ep0state = EP0_SETUP_PHASE; dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc); dwc3_ep0_out_start(dwc);
} }
@@ -813,7 +815,7 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
int ret = -EINVAL; int ret = -EINVAL;
u32 len; u32 len;
if (!dwc->gadget_driver) if (!dwc->gadget_driver || !dwc->connected)
goto out; goto out;
trace_dwc3_ctrl_req(ctrl); 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]); __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; struct dwc3_gadget_ep_cmd_params params;
u32 cmd; u32 cmd;
int ret; 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; return;
cmd = DWC3_DEPCMD_ENDTRANSFER; 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) if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS)
return; return;
if (dwc->setup_packet_pending) {
dwc3_ep0_stall_and_restart(dwc);
return;
}
dwc->ep0state = EP0_STATUS_PHASE; dwc->ep0state = EP0_STATUS_PHASE;
if (dwc->delayed_status) { 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); * For some commands such as Update Transfer command, DEPCMDPARn
dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2); * 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 * 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; cmd |= DWC3_DEPCMD_CMDACT;
dwc3_writel(dep->regs, DWC3_DEPCMD, cmd); dwc3_writel(dep->regs, DWC3_DEPCMD, cmd);
if (!(cmd & DWC3_DEPCMD_CMDACT)) {
ret = 0;
goto skip_status;
}
do { do {
reg = dwc3_readl(dep->regs, DWC3_DEPCMD); reg = dwc3_readl(dep->regs, DWC3_DEPCMD);
if (!(reg & DWC3_DEPCMD_CMDACT)) { 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; cmd_status = -ETIMEDOUT;
} }
skip_status:
trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status); trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) { 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); reg |= DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
dep->trb_dequeue = 0;
dep->trb_enqueue = 0;
if (usb_endpoint_xfer_control(desc)) if (usb_endpoint_xfer_control(desc))
goto out; goto out;
/* Initialize the TRB ring */ /* Initialize the TRB ring */
dep->trb_dequeue = 0;
dep->trb_enqueue = 0;
memset(dep->trb_pool, 0, memset(dep->trb_pool, 0,
sizeof(struct dwc3_trb) * DWC3_TRB_NUM); 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); 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 * dwc3_gadget_start_isoc_quirk - workaround invalid frame number
* @dep: isoc endpoint * @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 * status, issue END_TRANSFER command and retry on the next XferNotReady
* event. * event.
*/ */
if (ret == -EAGAIN) { if (ret == -EAGAIN)
struct dwc3_gadget_ep_cmd_params params; ret = __dwc3_stop_active_transfer(dep, false, true);
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;
}
return ret; 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. * errors which will force us issue EndTransfer command.
*/ */
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
if (!(dep->flags & DWC3_EP_PENDING_REQUEST) && if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) {
!(dep->flags & DWC3_EP_TRANSFER_STARTED)) if ((dep->flags & DWC3_EP_PENDING_REQUEST))
return 0;
if ((dep->flags & DWC3_EP_PENDING_REQUEST)) {
if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
return __dwc3_gadget_start_isoc(dep); 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) { if (r == req) {
struct dwc3_request *t; 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 */ /* wait until it is processed */
dwc3_stop_active_transfer(dep, true, true); 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); spin_lock_irqsave(&dwc->lock, flags);
dwc->connected = false; 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 * In the Synopsys DesignWare Cores USB3 Databook Rev. 3.30a
* Section 4.1.8 Table 4-7, it states that for a device-initiated * 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; 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 * Avoid issuing a runtime resume if the device is already in the
* suspended state during gadget disconnect. DWC3 gadget was already * 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 */ /* begin to receive SETUP packets */
dwc->ep0state = EP0_SETUP_PHASE; dwc->ep0state = EP0_SETUP_PHASE;
dwc->ep0_bounced = false;
dwc->link_state = DWC3_LINK_STATE_SS_DIS; dwc->link_state = DWC3_LINK_STATE_SS_DIS;
dwc->delayed_status = false; dwc->delayed_status = false;
dwc3_ep0_out_start(dwc); 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; struct dwc3 *dwc = dep->dwc;
u32 mdwidth; u32 mdwidth;
int size; int size;
int maxpacket;
mdwidth = dwc3_mdwidth(dwc); mdwidth = dwc3_mdwidth(dwc);
@@ -2948,21 +2979,24 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
else else
size = DWC31_GTXFIFOSIZ_TXFDEP(size); size = DWC31_GTXFIFOSIZ_TXFDEP(size);
/* FIFO Depth is in MDWDITH bytes. Multiply */
size *= mdwidth;
/* /*
* To meet performance requirement, a minimum TxFIFO size of 3x * maxpacket size is determined as part of the following, after assuming
* MaxPacketSize is recommended for endpoints that support burst and a * a mult value of one maxpacket:
* minimum TxFIFO size of 2x MaxPacketSize for endpoints that don't * DWC3 revision 280A and prior:
* support burst. Use those numbers and we can calculate the max packet * fifo_size = mult * (max_packet / mdwidth) + 1;
* limit as below. * 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) if (DWC3_VER_IS_PRIOR(DWC3, 290A))
size /= 3; maxpacket = mdwidth * (size - 1);
else 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); usb_ep_set_maxpacket_limit(&dep->endpoint, size);
dep->endpoint.max_streams = 16; 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, void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
bool interrupt) bool interrupt)
{ {
struct dwc3_gadget_ep_cmd_params params; struct dwc3 *dwc = dep->dwc;
u32 cmd;
int ret; /*
* 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) || if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) ||
(dep->flags & DWC3_EP_DELAY_STOP) || (dep->flags & DWC3_EP_DELAY_STOP) ||
(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) (dep->flags & DWC3_EP_END_TRANSFER_PENDING))
return; 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 * NOTICE: We are violating what the Databook says about the
* EndTransfer command. Ideally we would _always_ wait for 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. * This mode is NOT available on the DWC_usb31 IP.
*/ */
__dwc3_stop_active_transfer(dep, force, interrupt);
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;
} }
EXPORT_SYMBOL_GPL(dwc3_stop_active_transfer); EXPORT_SYMBOL_GPL(dwc3_stop_active_transfer);
@@ -3723,13 +3763,24 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
reg &= ~DWC3_DCTL_INITU2ENA; reg &= ~DWC3_DCTL_INITU2ENA;
dwc3_gadget_dctl_write_safe(dwc, reg); dwc3_gadget_dctl_write_safe(dwc, reg);
dwc->connected = false;
dwc3_disconnect_gadget(dwc); dwc3_disconnect_gadget(dwc);
dwc->gadget->speed = USB_SPEED_UNKNOWN; dwc->gadget->speed = USB_SPEED_UNKNOWN;
dwc->setup_packet_pending = false; dwc->setup_packet_pending = false;
usb_gadget_set_state(dwc->gadget, USB_STATE_NOTATTACHED); 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) 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); 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 * 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 * 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; struct dwc3 *dwc = evt->dwc;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
int left; int left;
u32 reg;
left = evt->count; left = evt->count;
@@ -4188,9 +4259,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
/* Unmask interrupt */ /* Unmask interrupt */
reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0)); dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
reg &= ~DWC3_GEVNTSIZ_INTMASK; DWC3_GEVNTSIZ_SIZE(evt->length));
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg);
if (dwc->imod_interval) { if (dwc->imod_interval) {
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB); 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; struct dwc3 *dwc = evt->dwc;
u32 amount; u32 amount;
u32 count; u32 count;
u32 reg;
if (pm_runtime_suspended(dwc->dev)) { if (pm_runtime_suspended(dwc->dev)) {
pm_runtime_get(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; evt->flags |= DWC3_EVENT_PENDING;
/* Mask interrupt */ /* Mask interrupt */
reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0)); dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
reg |= DWC3_GEVNTSIZ_INTMASK; DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(evt->length));
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg);
amount = min(count, evt->length - evt->lpos); amount = min(count, evt->length - evt->lpos);
memcpy(evt->cache + evt->lpos, evt->buf + evt->lpos, amount); 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, void dwc3_ep0_interrupt(struct dwc3 *dwc,
const struct dwc3_event_depevt *event); const struct dwc3_event_depevt *event);
void dwc3_ep0_out_start(struct dwc3 *dwc); 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_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, int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,

View File

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

View File

@@ -1085,6 +1085,26 @@ err:
} }
EXPORT_SYMBOL_GPL(acc_ctrlrequest); 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 static int
__acc_function_bind(struct usb_configuration *c, __acc_function_bind(struct usb_configuration *c,
struct usb_function *f, bool configfs) 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; struct usb_request *req = ffs->ep0req;
int ret; int ret;
if (!req)
return -EINVAL;
req->zero = len < le16_to_cpu(ffs->ev.setup.wLength); req->zero = len < le16_to_cpu(ffs->ev.setup.wLength);
spin_unlock_irq(&ffs->ev.waitq.lock); spin_unlock_irq(&ffs->ev.waitq.lock);
@@ -1891,10 +1894,14 @@ static void functionfs_unbind(struct ffs_data *ffs)
ENTER(); ENTER();
if (!WARN_ON(!ffs->gadget)) { 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); usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req);
ffs->ep0req = NULL; ffs->ep0req = NULL;
ffs->gadget = NULL; ffs->gadget = NULL;
clear_bit(FFS_FL_BOUND, &ffs->flags); clear_bit(FFS_FL_BOUND, &ffs->flags);
mutex_unlock(&ffs->mutex);
ffs_data_put(ffs); 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; u8 format;
int i, len; int i, len;
format = common->cmnd[2] & 0xf;
if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ 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; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL; return -EINVAL;
} }
format = common->cmnd[2] & 0xf;
/* /*
* Check if CDB is old style SFF-8020i * Check if CDB is old style SFF-8020i
* i.e. format is in 2 MSBs of byte 9 * 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; format = (common->cmnd[9] >> 6) & 0x3;
switch (format) { switch (format) {
case 0: case 0: /* Formatted TOC */
/* Formatted TOC */ case 1: /* Multi-session info */
len = 4 + 2*8; /* 4 byte header + 2 descriptors */ len = 4 + 2*8; /* 4 byte header + 2 descriptors */
memset(buf, 0, len); memset(buf, 0, len);
buf[1] = len - 2; /* TOC Length excludes length field */ 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; return len;
default: 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; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL; return -EINVAL;
} }

View File

@@ -281,6 +281,12 @@ static struct usb_endpoint_descriptor ss_ep_int_desc = {
.bInterval = 4, .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 */ /* Audio Streaming OUT Interface - Alt0 */
static struct usb_interface_descriptor std_as_out_if0_desc = { static struct usb_interface_descriptor std_as_out_if0_desc = {
.bLength = sizeof 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 *)&in_feature_unit_desc,
(struct usb_descriptor_header *)&io_out_ot_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_if0_desc,
(struct usb_descriptor_header *)&std_as_out_if1_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 *epout_desc_comp = NULL;
struct usb_ss_ep_comp_descriptor *epin_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 *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 *epout_desc;
struct usb_endpoint_descriptor *epin_desc; struct usb_endpoint_descriptor *epin_desc;
struct usb_endpoint_descriptor *epin_fback_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 = &ss_epin_fback_desc;
epin_fback_desc_comp = &ss_epin_fback_desc_comp; epin_fback_desc_comp = &ss_epin_fback_desc_comp;
ep_int_desc = &ss_ep_int_desc; ep_int_desc = &ss_ep_int_desc;
ep_int_desc_comp = &ss_ep_int_desc_comp;
} }
i = 0; i = 0;
@@ -801,8 +810,11 @@ static void setup_headers(struct f_uac2_opts *opts,
if (EPOUT_EN(opts)) if (EPOUT_EN(opts))
headers[i++] = USBDHDR(&io_out_ot_desc); headers[i++] = USBDHDR(&io_out_ot_desc);
if (FUOUT_EN(opts) || FUIN_EN(opts)) if (FUOUT_EN(opts) || FUIN_EN(opts)) {
headers[i++] = USBDHDR(ep_int_desc); headers[i++] = USBDHDR(ep_int_desc);
if (ep_int_desc_comp)
headers[i++] = USBDHDR(ep_int_desc_comp);
}
if (EPOUT_EN(opts)) { if (EPOUT_EN(opts)) {
headers[i++] = USBDHDR(&std_as_out_if0_desc); 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) \ const char *page, size_t len) \
{ \ { \
struct f_uvc_opts *opts = to_f_uvc_opts(item); \ struct f_uvc_opts *opts = to_f_uvc_opts(item); \
int size = min(sizeof(opts->aname), len + 1); \
int ret = 0; \ int ret = 0; \
\ \
mutex_lock(&opts->lock); \ mutex_lock(&opts->lock); \
@@ -2456,8 +2457,9 @@ static ssize_t f_uvc_opts_string_##cname##_store(struct config_item *item,\
goto end; \ goto end; \
} \ } \
\ \
ret = snprintf(opts->aname, min(sizeof(opts->aname), len), \ ret = strscpy(opts->aname, page, size); \
"%s", page); \ if (ret == -E2BIG) \
ret = size - 1; \
\ \
end: \ end: \
mutex_unlock(&opts->lock); \ 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) static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
{ {
struct tcpci *tcpci = tcpc_to_tcpci(tcpc); struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
bool vconn_pres;
enum typec_cc_polarity polarity = TYPEC_POLARITY_CC1;
unsigned int reg; unsigned int reg;
int ret; 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) { switch (cc) {
case TYPEC_CC_RA: case TYPEC_CC_RA:
reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) | 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; 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); ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;

View File

@@ -98,6 +98,7 @@
#define TCPC_POWER_STATUS_SOURCING_VBUS BIT(4) #define TCPC_POWER_STATUS_SOURCING_VBUS BIT(4)
#define TCPC_POWER_STATUS_VBUS_DET BIT(3) #define TCPC_POWER_STATUS_VBUS_DET BIT(3)
#define TCPC_POWER_STATUS_VBUS_PRES BIT(2) #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_POWER_STATUS_SINKING_VBUS BIT(0)
#define TCPC_FAULT_STATUS 0x1f #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: case PR_SWAP_SNK_SRC_SOURCE_ON:
/* Do nothing, vsafe0v is expected during transition */ /* Do nothing, vsafe0v is expected during transition */
break; break;
case SNK_ATTACH_WAIT:
case SNK_DEBOUNCED:
/*Do nothing, still waiting for VSAFE5V for connect */
break;
default: default:
if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled) if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
tcpm_set_state(port, SNK_UNATTACHED, 0); 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->num = index + 1;
con->ucsi = ucsi; 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 */ /* Delay other interactions with the con until registration is complete */
mutex_lock(&con->lock); 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) if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY)
*accessory = TYPEC_ACCESSORY_DEBUG; *accessory = TYPEC_ACCESSORY_DEBUG;
cap->fwnode = ucsi_find_fwnode(con);
cap->driver_data = con; cap->driver_data = con;
cap->ops = &ucsi_ops; cap->ops = &ucsi_ops;
@@ -1154,13 +1162,6 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
ucsi_port_psy_changed(con); 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 */ /* Only notify USB controller if partner supports USB data */
if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB)) if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB))
u_role = USB_ROLE_NONE; u_role = USB_ROLE_NONE;
@@ -1273,12 +1274,21 @@ err:
static void ucsi_init_work(struct work_struct *work) 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; int ret;
ret = ucsi_init(ucsi); ret = ucsi_init(&aucsi->ucsi);
if (ret) 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_create(struct device *dev, const struct ucsi_operations *ops)
{ {
struct ucsi *ucsi; struct ucsi *ucsi;
struct ucsi_android *aucsi;
if (!ops || !ops->read || !ops->sync_write || !ops->async_write) if (!ops || !ops->read || !ops->sync_write || !ops->async_write)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
ucsi = kzalloc(sizeof(*ucsi), GFP_KERNEL); aucsi = kzalloc(sizeof(*aucsi), GFP_KERNEL);
if (!ucsi) if (!aucsi)
return ERR_PTR(-ENOMEM); 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); mutex_init(&ucsi->ppm_lock);
ucsi->dev = dev; ucsi->dev = dev;
ucsi->ops = ops; ucsi->ops = ops;
@@ -1333,7 +1345,9 @@ EXPORT_SYMBOL_GPL(ucsi_create);
*/ */
void ucsi_destroy(struct ucsi *ucsi) 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); EXPORT_SYMBOL_GPL(ucsi_destroy);
@@ -1343,6 +1357,8 @@ EXPORT_SYMBOL_GPL(ucsi_destroy);
*/ */
int ucsi_register(struct ucsi *ucsi) int ucsi_register(struct ucsi *ucsi)
{ {
struct ucsi_android *aucsi = container_of(ucsi,
struct ucsi_android, ucsi);
int ret; int ret;
ret = ucsi->ops->read(ucsi, UCSI_VERSION, &ucsi->version, ret = ucsi->ops->read(ucsi, UCSI_VERSION, &ucsi->version,
@@ -1353,7 +1369,7 @@ int ucsi_register(struct ucsi *ucsi)
if (!ucsi->version) if (!ucsi->version)
return -ENODEV; return -ENODEV;
queue_work(system_long_wq, &ucsi->work); queue_delayed_work(system_long_wq, &aucsi->work, 0);
return 0; return 0;
} }
@@ -1367,11 +1383,13 @@ EXPORT_SYMBOL_GPL(ucsi_register);
*/ */
void ucsi_unregister(struct ucsi *ucsi) void ucsi_unregister(struct ucsi *ucsi)
{ {
struct ucsi_android *aucsi = container_of(ucsi,
struct ucsi_android, ucsi);
u64 cmd = UCSI_SET_NOTIFICATION_ENABLE; u64 cmd = UCSI_SET_NOTIFICATION_ENABLE;
int i; int i;
/* Make sure that we are not in the middle of driver initialization */ /* 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 */ /* Disable notifications */
ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));

View File

@@ -289,6 +289,9 @@ struct ucsi {
struct ucsi_connector *connector; struct ucsi_connector *connector;
struct work_struct work; 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 */ /* PPM Communication lock */
struct mutex ppm_lock; struct mutex ppm_lock;
@@ -304,6 +307,25 @@ struct ucsi {
#define EVENT_PROCESSING 3 #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_SVID 5
#define UCSI_MAX_ALTMODES (UCSI_MAX_SVID * 6) #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; struct buffer_head *bh;
if (!ext4_has_inline_data(inode)) { 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 /* The first directory block must not be a hole, so
* treat it as DIRENT_HTREE * 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); *retval = PTR_ERR(bh);
return NULL; return NULL;
} }
*parent_de = ext4_next_entry(
(struct ext4_dir_entry_2 *)bh->b_data, de = (struct ext4_dir_entry_2 *) bh->b_data;
inode->i_sb->s_blocksize); 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; return bh;
} }

View File

@@ -1469,6 +1469,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc,
if (cluster_may_compress(cc)) { if (cluster_may_compress(cc)) {
err = f2fs_compress_pages(cc); err = f2fs_compress_pages(cc);
if (err == -EAGAIN) { if (err == -EAGAIN) {
add_compr_block_stat(cc->inode, cc->cluster_size);
goto write; goto write;
} else if (err) { } else if (err) {
f2fs_put_rpages_wbc(cc, wbc, true, 1); f2fs_put_rpages_wbc(cc, wbc, true, 1);
@@ -1659,6 +1660,30 @@ void f2fs_put_page_dic(struct page *page)
f2fs_put_dic(dic); 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 = { const struct address_space_operations f2fs_compress_aops = {
.releasepage = f2fs_release_page, .releasepage = f2fs_release_page,
.invalidatepage = f2fs_invalidate_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; dn->data_blkaddr = blkaddr;
f2fs_set_data_blkaddr(dn); 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 */ /* 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) 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; 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; dn->data_blkaddr = ei.blk + index - ei.fofs;
return 0; 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 address_space *mapping = inode->i_mapping;
struct dnode_of_data dn; struct dnode_of_data dn;
struct page *page; struct page *page;
struct extent_info ei = {0,0,0}; struct extent_info ei = {0, };
int err; int err;
page = f2fs_grab_cache_page(mapping, index, for_write); page = f2fs_grab_cache_page(mapping, index, for_write);
if (!page) if (!page)
return ERR_PTR(-ENOMEM); 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; dn.data_blkaddr = ei.blk + index - ei.fofs;
if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr, if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr,
DATA_GENERIC_ENHANCE_READ)) { 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; int err = 0, ofs = 1;
unsigned int ofs_in_node, last_ofs_in_node; unsigned int ofs_in_node, last_ofs_in_node;
blkcnt_t prealloc; blkcnt_t prealloc;
struct extent_info ei = {0,0,0}; struct extent_info ei = {0, };
block_t blkaddr; block_t blkaddr;
unsigned int start_pgofs; 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; pgofs = (pgoff_t)map->m_lblk;
end = pgofs + maxblocks; 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 && if (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
map->m_may_create) map->m_may_create)
goto next_dnode; goto next_dnode;
@@ -1654,7 +1654,7 @@ skip:
if (map->m_flags & F2FS_MAP_MAPPED) { if (map->m_flags & F2FS_MAP_MAPPED) {
unsigned int ofs = start_pgofs - map->m_lblk; 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, start_pgofs, map->m_pblk + ofs,
map->m_len - ofs); map->m_len - ofs);
} }
@@ -1679,7 +1679,7 @@ sync_out:
if (map->m_flags & F2FS_MAP_MAPPED) { if (map->m_flags & F2FS_MAP_MAPPED) {
unsigned int ofs = start_pgofs - map->m_lblk; 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, start_pgofs, map->m_pblk + ofs,
map->m_len - 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; sector_t last_block_in_file;
const unsigned blocksize = blks_to_bytes(inode, 1); const unsigned blocksize = blks_to_bytes(inode, 1);
struct decompress_io_ctx *dic = NULL; struct decompress_io_ctx *dic = NULL;
struct extent_info ei = {};
bool from_dnode = true;
int i; int i;
int ret = 0; 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)) if (f2fs_cluster_is_empty(cc))
goto out; 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); set_new_dnode(&dn, inode, NULL, NULL, 0);
ret = f2fs_get_dnode_of_data(&dn, start_idx, LOOKUP_NODE); ret = f2fs_get_dnode_of_data(&dn, start_idx, LOOKUP_NODE);
if (ret) 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); f2fs_bug_on(sbi, dn.data_blkaddr != COMPRESS_ADDR);
skip_reading_dnode:
for (i = 1; i < cc->cluster_size; i++) { for (i = 1; i < cc->cluster_size; i++) {
block_t blkaddr; block_t blkaddr;
blkaddr = data_blkaddr(dn.inode, dn.node_page, blkaddr = from_dnode ? data_blkaddr(dn.inode, dn.node_page,
dn.ofs_in_node + i); dn.ofs_in_node + i) :
ei.blk + i - 1;
if (!__is_valid_data_blkaddr(blkaddr)) if (!__is_valid_data_blkaddr(blkaddr))
break; break;
@@ -2209,6 +2219,9 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
goto out_put_dnode; goto out_put_dnode;
} }
cc->nr_cpages++; cc->nr_cpages++;
if (!from_dnode && i >= ei.c_len)
break;
} }
/* nothing to decompress */ /* nothing to decompress */
@@ -2228,8 +2241,9 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
block_t blkaddr; block_t blkaddr;
struct bio_post_read_ctx *ctx; struct bio_post_read_ctx *ctx;
blkaddr = data_blkaddr(dn.inode, dn.node_page, blkaddr = from_dnode ? data_blkaddr(dn.inode, dn.node_page,
dn.ofs_in_node + i + 1); dn.ofs_in_node + i + 1) :
ei.blk + i;
f2fs_wait_on_block_writeback(inode, blkaddr); f2fs_wait_on_block_writeback(inode, blkaddr);
@@ -2274,13 +2288,15 @@ submit_and_realloc:
*last_block_in_bio = blkaddr; *last_block_in_bio = blkaddr;
} }
f2fs_put_dnode(&dn); if (from_dnode)
f2fs_put_dnode(&dn);
*bio_ret = bio; *bio_ret = bio;
return 0; return 0;
out_put_dnode: out_put_dnode:
f2fs_put_dnode(&dn); if (from_dnode)
f2fs_put_dnode(&dn);
out: out:
for (i = 0; i < cc->cluster_size; i++) { for (i = 0; i < cc->cluster_size; i++) {
if (cc->rpages[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 page *page = fio->page;
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
struct dnode_of_data dn; struct dnode_of_data dn;
struct extent_info ei = {0,0,0}; struct extent_info ei = {0, };
struct node_info ni; struct node_info ni;
bool ipu_force = false; bool ipu_force = false;
int err = 0; int err = 0;
set_new_dnode(&dn, inode, NULL, NULL, 0); set_new_dnode(&dn, inode, NULL, NULL, 0);
if (need_inplace_update(fio) && 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; fio->old_blkaddr = ei.blk + page->index - ei.fofs;
if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, 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 dnode_of_data dn;
struct page *ipage; struct page *ipage;
bool locked = false; bool locked = false;
struct extent_info ei = {0,0,0}; struct extent_info ei = {0, };
int err = 0; int err = 0;
int flag; int flag;
@@ -3316,7 +3332,7 @@ restart:
} else if (locked) { } else if (locked) {
err = f2fs_get_block(&dn, index); err = f2fs_get_block(&dn, index);
} else { } 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; dn.data_blkaddr = ei.blk + index - ei.fofs;
} else { } else {
/* hole case */ /* 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 / si->main_area_zones = si->main_area_sections /
le32_to_cpu(raw_super->secs_per_zone); 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_largest = atomic64_read(&sbi->read_hit_largest);
si->hit_cached = atomic64_read(&sbi->read_hit_cached); si->hit_total[EX_READ] += si->hit_largest;
si->hit_rbtree = atomic64_read(&sbi->read_hit_rbtree);
si->hit_total = si->hit_largest + si->hit_cached + si->hit_rbtree; /* block age extent_cache only */
si->total_ext = atomic64_read(&sbi->total_hit_ext); si->allocated_data_blocks = atomic64_read(&sbi->allocated_data_blocks);
si->ext_tree = atomic_read(&sbi->total_ext_tree);
si->zombie_tree = atomic_read(&sbi->total_zombie_tree); /* validation check of the segment numbers */
si->ext_node = atomic_read(&sbi->total_ext_node);
si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES); si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS); si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META); 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); si->cache_mem += si->inmem_pages * sizeof(struct inmem_pages);
for (i = 0; i < MAX_INO_ENTRY; i++) for (i = 0; i < MAX_INO_ENTRY; i++)
si->cache_mem += sbi->im[i].ino_num * sizeof(struct ino_entry); 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); 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); sizeof(struct extent_node);
si->cache_mem += si->ext_mem[i];
}
si->page_mem = 0; si->page_mem = 0;
if (sbi->node_inode) { if (sbi->node_inode) {
@@ -471,16 +488,34 @@ static int stat_show(struct seq_file *s, void *v)
si->skipped_atomic_files[BG_GC]); si->skipped_atomic_files[BG_GC]);
seq_printf(s, "BG skip : IO: %u, Other: %u\n", seq_printf(s, "BG skip : IO: %u, Other: %u\n",
si->io_skip_bggc, si->other_skip_bggc); 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", seq_printf(s, " - Hit Count: L1-1:%llu L1-2:%llu L2:%llu\n",
si->hit_largest, si->hit_cached, si->hit_largest, si->hit_cached[EX_READ],
si->hit_rbtree); si->hit_rbtree[EX_READ]);
seq_printf(s, " - Hit Ratio: %llu%% (%llu / %llu)\n", seq_printf(s, " - Hit Ratio: %llu%% (%llu / %llu)\n",
!si->total_ext ? 0 : !si->total_ext[EX_READ] ? 0 :
div64_u64(si->hit_total * 100, si->total_ext), div64_u64(si->hit_total[EX_READ] * 100,
si->hit_total, si->total_ext); 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", 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_puts(s, "\nBalancing F2FS Async:\n");
seq_printf(s, " - DIO (R: %4d, W: %4d)\n", seq_printf(s, " - DIO (R: %4d, W: %4d)\n",
si->nr_dio_read, si->nr_dio_write); 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); (si->base_mem + si->cache_mem + si->page_mem) >> 10);
seq_printf(s, " - static: %llu KB\n", seq_printf(s, " - static: %llu KB\n",
si->base_mem >> 10); si->base_mem >> 10);
seq_printf(s, " - cached: %llu KB\n", seq_printf(s, " - cached all: %llu KB\n",
si->cache_mem >> 10); 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", seq_printf(s, " - paged : %llu KB\n",
si->page_mem >> 10); si->page_mem >> 10);
} }
@@ -579,10 +618,15 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
si->sbi = sbi; si->sbi = sbi;
sbi->stat_info = si; sbi->stat_info = si;
atomic64_set(&sbi->total_hit_ext, 0); /* general extent cache stats */
atomic64_set(&sbi->read_hit_rbtree, 0); 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_largest, 0);
atomic64_set(&sbi->read_hit_cached, 0);
atomic_set(&sbi->inline_xattr, 0); atomic_set(&sbi->inline_xattr, 0);
atomic_set(&sbi->inline_inode, 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 #ifdef CONFIG_UNICODE
struct super_block *sb = dir->i_sb; 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, fname->cf_name.name = kmem_cache_alloc(f2fs_cf_name_slab,
GFP_NOFS); GFP_NOFS);
if (!fname->cf_name.name) 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_FLUSH_MERGE 0x00000400
#define F2FS_MOUNT_NOBARRIER 0x00000800 #define F2FS_MOUNT_NOBARRIER 0x00000800
#define F2FS_MOUNT_FASTBOOT 0x00001000 #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_DATA_FLUSH 0x00008000
#define F2FS_MOUNT_FAULT_INJECTION 0x00010000 #define F2FS_MOUNT_FAULT_INJECTION 0x00010000
#define F2FS_MOUNT_USRQUOTA 0x00080000 #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_MERGE_CHECKPOINT 0x10000000
#define F2FS_MOUNT_GC_MERGE 0x20000000 #define F2FS_MOUNT_GC_MERGE 0x20000000
#define F2FS_MOUNT_COMPRESS_CACHE 0x40000000 #define F2FS_MOUNT_COMPRESS_CACHE 0x40000000
#define F2FS_MOUNT_AGE_EXTENT_CACHE 0x80000000
#define F2FS_OPTION(sbi) ((sbi)->mount_opt) #define F2FS_OPTION(sbi) ((sbi)->mount_opt)
#define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= ~F2FS_MOUNT_##option) #define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= ~F2FS_MOUNT_##option)
@@ -494,11 +495,11 @@ struct f2fs_filename {
#ifdef CONFIG_UNICODE #ifdef CONFIG_UNICODE
/* /*
* For casefolded directories: the casefolded name, but it's left NULL * For casefolded directories: the casefolded name, but it's left NULL
* if the original name is not valid Unicode, if the directory is both * if the original name is not valid Unicode, if the original name is
* casefolded and encrypted and its encryption key is unavailable, or if * "." or "..", if the directory is both casefolded and encrypted and
* the filesystem is doing an internal operation where usr_fname is also * its encryption key is unavailable, or if the filesystem is doing an
* NULL. In all these cases we fall back to treating the name as an * internal operation where usr_fname is also NULL. In all these cases
* opaque byte sequence. * we fall back to treating the name as an opaque byte sequence.
*/ */
struct fscrypt_str cf_name; struct fscrypt_str cf_name;
#endif #endif
@@ -572,7 +573,26 @@ enum {
#define F2FS_MIN_EXTENT_LEN 64 /* minimum extent length */ #define F2FS_MIN_EXTENT_LEN 64 /* minimum extent length */
/* number of extent info in extent cache we try to shrink */ /* 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_entry {
struct rb_node rb_node; /* rb node located in rb-tree */ struct rb_node rb_node; /* rb node located in rb-tree */
@@ -588,7 +608,24 @@ struct rb_entry {
struct extent_info { struct extent_info {
unsigned int fofs; /* start offset in a file */ unsigned int fofs; /* start offset in a file */
unsigned int len; /* length of the extent */ 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 { struct extent_node {
@@ -600,13 +637,25 @@ struct extent_node {
struct extent_tree { struct extent_tree {
nid_t ino; /* inode number */ 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 rb_root_cached root; /* root of extent info rb-tree */
struct extent_node *cached_en; /* recently accessed extent node */ 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 */ struct list_head list; /* to be used by sbi->zombie_list */
rwlock_t lock; /* protect extent info rb-tree */ rwlock_t lock; /* protect extent info rb-tree */
atomic_t node_cnt; /* # of extent node in rb-tree*/ atomic_t node_cnt; /* # of extent node in rb-tree*/
bool largest_updated; /* largest extent updated */ 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 list_head inmem_pages; /* inmemory pages managed by f2fs */
struct task_struct *inmem_task; /* store inmemory task */ struct task_struct *inmem_task; /* store inmemory task */
struct mutex inmem_lock; /* lock for inmemory pages */ 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 */ /* avoid racing between foreground op and gc */
struct f2fs_rwsem i_gc_rwsem[2]; struct f2fs_rwsem i_gc_rwsem[2];
@@ -788,7 +838,7 @@ struct f2fs_inode_info {
unsigned int i_cluster_size; /* cluster size */ 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) struct f2fs_extent *i_ext)
{ {
ext->fofs = le32_to_cpu(i_ext->fofs); 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); 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) struct f2fs_extent *i_ext)
{ {
i_ext->fofs = cpu_to_le32(ext->fofs); 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); 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, static inline bool __is_discard_mergeable(struct discard_info *back,
struct discard_info *front, unsigned int max_len) 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); 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 * For free nid management
*/ */
@@ -1601,14 +1614,12 @@ struct f2fs_sb_info {
struct mutex flush_lock; /* for flush exclusion */ struct mutex flush_lock; /* for flush exclusion */
/* for extent tree cache */ /* for extent tree cache */
struct radix_tree_root extent_tree_root;/* cache extent cache entries */ struct extent_tree_info extent_tree[NR_EXTENT_CACHES];
struct mutex extent_tree_lock; /* locking extent radix tree */ atomic64_t allocated_data_blocks; /* for block age extent_cache */
struct list_head extent_list; /* lru list for shrinker */
spinlock_t extent_lock; /* locking extent lru list */ /* The threshold used for hot and warm data seperation*/
atomic_t total_ext_tree; /* extent tree count */ unsigned int hot_data_age_threshold;
struct list_head zombie_list; /* extent zombie tree list */ unsigned int warm_data_age_threshold;
atomic_t total_zombie_tree; /* extent zombie tree count */
atomic_t total_ext_node; /* extent info count */
/* basic filesystem units */ /* basic filesystem units */
unsigned int log_sectors_per_block; /* log2 sectors per block */ 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 segment_count[2]; /* # of allocated segments */
unsigned int block_count[2]; /* # of allocated blocks */ unsigned int block_count[2]; /* # of allocated blocks */
atomic_t inplace_count; /* # of inplace update */ atomic_t inplace_count; /* # of inplace update */
atomic64_t total_hit_ext; /* # of lookup extent cache */ /* # of lookup extent cache */
atomic64_t read_hit_rbtree; /* # of hit rbtree extent node */ atomic64_t total_hit_ext[NR_EXTENT_CACHES];
atomic64_t read_hit_largest; /* # of hit largest extent node */ /* # of hit rbtree extent node */
atomic64_t read_hit_cached; /* # of hit cached 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_xattr; /* # of inline_xattr inodes */
atomic_t inline_inode; /* # of inline_data inodes */ atomic_t inline_inode; /* # of inline_data inodes */
atomic_t inline_dir; /* # of inline_dentry 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); 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, static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
struct inode *inode, bool is_inode) struct inode *inode, bool is_inode)
{ {
@@ -3775,9 +3791,19 @@ struct f2fs_stat_info {
struct f2fs_sb_info *sbi; struct f2fs_sb_info *sbi;
int all_area_segs, sit_area_segs, nat_area_segs, ssa_area_segs; int all_area_segs, sit_area_segs, nat_area_segs, ssa_area_segs;
int main_area_segs, main_area_sections, main_area_zones; int main_area_segs, main_area_sections, main_area_zones;
unsigned long long hit_largest, hit_cached, hit_rbtree; unsigned long long hit_cached[NR_EXTENT_CACHES];
unsigned long long hit_total, total_ext; unsigned long long hit_rbtree[NR_EXTENT_CACHES];
int ext_tree, zombie_tree, ext_node; 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_node, ndirty_dent, ndirty_meta, ndirty_imeta;
int ndirty_data, ndirty_qdata; int ndirty_data, ndirty_qdata;
int inmem_pages; 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_other_skip_bggc_count(sbi) ((sbi)->other_skip_bggc++)
#define stat_inc_dirty_inode(sbi, type) ((sbi)->ndirty_inode[type]++) #define stat_inc_dirty_inode(sbi, type) ((sbi)->ndirty_inode[type]++)
#define stat_dec_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_total_hit(sbi, type) (atomic64_inc(&(sbi)->total_hit_ext[type]))
#define stat_inc_rbtree_node_hit(sbi) (atomic64_inc(&(sbi)->read_hit_rbtree)) #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_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) \ #define stat_inc_inline_xattr(inode) \
do { \ do { \
if (f2fs_has_inline_xattr(inode)) \ 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_other_skip_bggc_count(sbi) do { } while (0)
#define stat_inc_dirty_inode(sbi, type) 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_dec_dirty_inode(sbi, type) do { } while (0)
#define stat_inc_total_hit(sbi) do { } while (0) #define stat_inc_total_hit(sbi, type) do { } while (0)
#define stat_inc_rbtree_node_hit(sbi) 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_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_inc_inline_xattr(inode) do { } while (0)
#define stat_dec_inline_xattr(inode) do { } while (0) #define stat_dec_inline_xattr(inode) do { } while (0)
#define stat_inc_inline_inode(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 force, bool *leftmost);
bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi, bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi,
struct rb_root_cached *root, bool check_key); 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);
void f2fs_init_extent_tree(struct inode *inode, struct page *ipage);
void f2fs_drop_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); 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); void f2fs_init_extent_cache_info(struct f2fs_sb_info *sbi);
int __init f2fs_create_extent_cache(void); int __init f2fs_create_extent_cache(void);
void f2fs_destroy_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 * sysfs.c
*/ */
@@ -4152,12 +4192,16 @@ int f2fs_write_multi_pages(struct compress_ctx *cc,
struct writeback_control *wbc, struct writeback_control *wbc,
enum iostat_type io_type); enum iostat_type io_type);
int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index); 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, int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
unsigned nr_pages, sector_t *last_block_in_bio, unsigned nr_pages, sector_t *last_block_in_bio,
bool is_readahead, bool for_write); bool is_readahead, bool for_write);
struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc); 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_decompress_end_io(struct decompress_io_ctx *dic, bool failed);
void f2fs_put_page_dic(struct page *page); 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); int f2fs_init_compress_ctx(struct compress_ctx *cc);
void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse); void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse);
void f2fs_init_compress_info(struct f2fs_sb_info *sbi); 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); 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 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 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; } 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, static inline void f2fs_invalidate_compress_pages(struct f2fs_sb_info *sbi,
nid_t ino) { } nid_t ino) { }
#define inc_compr_inode_stat(inode) do { } while (0) #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 #endif
static inline int set_compress_context(struct inode *inode) 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(compression, COMPRESSION);
F2FS_FEATURE_FUNCS(readonly, RO); 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 #ifdef CONFIG_BLK_DEV_ZONED
static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi, static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
block_t blkaddr) 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), fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page),
dn->inode) + ofs; 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); dec_valid_block_count(sbi, dn->inode, nr_free);
} }
dn->ofs_in_node = ofs; 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_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; 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, struct f2fs_map_blocks map = { .m_next_extent = NULL,
.m_seg_type = NO_CHECK_TYPE, .m_seg_type = NO_CHECK_TYPE,
.m_may_create = false }; .m_may_create = false };
struct extent_info ei = {0, 0, 0}; struct extent_info ei = {};
pgoff_t pg_start, pg_end, next_pgofs; pgoff_t pg_start, pg_end, next_pgofs;
unsigned int blk_per_seg = sbi->blocks_per_seg; unsigned int blk_per_seg = sbi->blocks_per_seg;
unsigned int total = 0, sec_num; 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 * lookup mapping info in extent cache, skip defragmenting if physical
* block addresses are continuous. * 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) if (ei.fofs + ei.len >= pg_end)
goto out; 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 address_space *mapping = inode->i_mapping;
struct dnode_of_data dn; struct dnode_of_data dn;
struct page *page; struct page *page;
struct extent_info ei = {0, 0, 0}; struct extent_info ei = {0, };
struct f2fs_io_info fio = { struct f2fs_io_info fio = {
.sbi = sbi, .sbi = sbi,
.ino = inode->i_ino, .ino = inode->i_ino,
@@ -1080,7 +1080,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
if (!page) if (!page)
return -ENOMEM; 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; dn.data_blkaddr = ei.blk + index - ei.fofs;
if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr, if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
DATA_GENERIC_ENHANCE_READ))) { 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. * Compute @fname->hash. For all directories, @fname->disk_name must be set.
* For casefolded directories, @fname->usr_fname must be set, and also * 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) 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 * If the casefolded name is provided, hash it instead of the
* on-disk name. If the casefolded name is *not* provided, that * on-disk name. If the casefolded name is *not* provided, that
* should only be because the name wasn't valid Unicode, so fall * should only be because the name wasn't valid Unicode or was
* back to treating the name as an opaque byte sequence. Note * "." or "..", so fall back to treating the name as an opaque
* that to handle encrypted directories, the fallback must use * byte sequence. Note that to handle encrypted directories,
* usr_fname (plaintext) rather than disk_name (ciphertext). * the fallback must use usr_fname (plaintext) rather than
* disk_name (ciphertext).
*/ */
WARN_ON_ONCE(!fname->usr_fname->name); WARN_ON_ONCE(!fname->usr_fname->name);
if (fname->cf_name.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; return false;
} }
if (F2FS_I(inode)->extent_tree) { if (fi->extent_tree[EX_READ]) {
struct extent_info *ei = &F2FS_I(inode)->extent_tree->largest; struct extent_info *ei = &fi->extent_tree[EX_READ]->largest;
if (ei->len && if (ei->len &&
(!f2fs_is_valid_blkaddr(sbi, ei->blk, (!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_pino = le32_to_cpu(ri->i_pino);
fi->i_dir_level = ri->i_dir_level; fi->i_dir_level = ri->i_dir_level;
f2fs_init_extent_tree(inode, node_page);
get_inline_info(inode, ri); get_inline_info(inode, ri);
fi->i_extra_isize = f2fs_has_extra_attr(inode) ? 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[1] = inode->i_ctime;
F2FS_I(inode)->i_disk_time[2] = inode->i_mtime; F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime; 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); f2fs_put_page(node_page, 1);
stat_inc_inline_xattr(inode); stat_inc_inline_xattr(inode);
@@ -571,7 +574,7 @@ retry:
void f2fs_update_inode(struct inode *inode, struct page *node_page) void f2fs_update_inode(struct inode *inode, struct page *node_page)
{ {
struct f2fs_inode *ri; 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); f2fs_wait_on_page_writeback(node_page, NODE, true, true);
set_page_dirty(node_page); set_page_dirty(node_page);
@@ -590,7 +593,7 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page)
if (et) { if (et) {
read_lock(&et->lock); 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); read_unlock(&et->lock);
} else { } else {
memset(&ri->i_ext, 0, sizeof(ri->i_ext)); 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_I(inode)->i_inline_xattr_size = xattr_size;
f2fs_init_extent_tree(inode, NULL);
F2FS_I(inode)->i_flags = F2FS_I(inode)->i_flags =
f2fs_mask_flags(mode, F2FS_I(dir)->i_flags & F2FS_FL_INHERITED); 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_set_inode_flags(inode);
f2fs_init_extent_tree(inode);
trace_f2fs_new_inode(inode, 0); trace_f2fs_new_inode(inode, 0);
return inode; return inode;
@@ -618,6 +618,8 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
goto fail; goto fail;
} }
f2fs_delete_entry(de, page, dir, inode); f2fs_delete_entry(de, page, dir, inode);
f2fs_unlock_op(sbi);
#ifdef CONFIG_UNICODE #ifdef CONFIG_UNICODE
/* VFS negative dentries are incompatible with Encoding and /* VFS negative dentries are incompatible with Encoding and
* Case-insensitiveness. Eventually we'll want avoid * 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)) if (IS_CASEFOLDED(dir))
d_invalidate(dentry); d_invalidate(dentry);
#endif #endif
f2fs_unlock_op(sbi);
if (IS_DIRSYNC(dir)) if (IS_DIRSYNC(dir))
f2fs_sync_fs(sbi->sb, 1); f2fs_sync_fs(sbi->sb, 1);
fail: 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; 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) { if (type == FREE_NIDS) {
mem_size = (nm_i->nid_cnt[FREE_NID] * 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); sizeof(struct ino_entry);
mem_size >>= PAGE_SHIFT; mem_size >>= PAGE_SHIFT;
res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1);
} else if (type == EXTENT_CACHE) { } else if (type == READ_EXTENT_CACHE || type == AGE_EXTENT_CACHE) {
mem_size = (atomic_read(&sbi->total_ext_tree) * 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) + sizeof(struct extent_tree) +
atomic_read(&sbi->total_ext_node) * atomic_read(&eti->total_ext_node) *
sizeof(struct extent_node)) >> PAGE_SHIFT; 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) { } else if (type == INMEM_PAGES) {
/* it allows 20% / total_ram for inmemory pages */ /* it allows 20% / total_ram for inmemory pages */
mem_size = get_pages(sbi, F2FS_INMEM_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->ofs_in_node = offset[level];
dn->node_page = npage[level]; dn->node_page = npage[level];
dn->data_blkaddr = f2fs_data_blkaddr(dn); 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; return 0;
release_pages: release_pages:
@@ -1339,8 +1363,8 @@ static int read_node_page(struct page *page, int op_flags)
if (err) if (err)
return err; return err;
if (unlikely(ni.blk_addr == NULL_ADDR) || /* NEW_ADDR can be seen, after cp_error drops some dirty node pages */
is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)) { if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR)) {
ClearPageUptodate(page); ClearPageUptodate(page);
return -ENOENT; return -ENOENT;
} }

View File

@@ -148,7 +148,8 @@ enum mem_type {
NAT_ENTRIES, /* indicates the cached nat entry */ NAT_ENTRIES, /* indicates the cached nat entry */
DIRTY_DENTS, /* indicates dirty dentry pages */ DIRTY_DENTS, /* indicates dirty dentry pages */
INO_ENTRIES, /* indicates inode entries */ 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 */ INMEM_PAGES, /* indicates inmemory pages */
DISCARD_CACHE, /* indicates memory of cached discard cmds */ DISCARD_CACHE, /* indicates memory of cached discard cmds */
COMPRESS_PAGE, /* indicates memory of cached compressed pages */ 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; return;
/* try to shrink extent cache when there is no enough memory */ /* try to shrink extent cache when there is no enough memory */
if (!f2fs_available_free_memory(sbi, EXTENT_CACHE)) if (!f2fs_available_free_memory(sbi, READ_EXTENT_CACHE))
f2fs_shrink_extent_tree(sbi, EXTENT_CACHE_SHRINK_NUMBER); 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 */ /* check the # of cached NAT entries */
if (!f2fs_available_free_memory(sbi, 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) static int __get_segment_type_6(struct f2fs_io_info *fio)
{ {
if (fio->type == DATA) { if (fio->type == DATA) {
struct inode *inode = fio->page->mapping->host; struct inode *inode = fio->page->mapping->host;
int type;
if (is_inode_flag_set(inode, FI_ALIGNED_WRITE)) if (is_inode_flag_set(inode, FI_ALIGNED_WRITE))
return CURSEG_COLD_DATA_PINNED; 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)) if (file_is_cold(inode) || f2fs_need_compress_data(inode))
return CURSEG_COLD_DATA; 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) || if (file_is_hot(inode) ||
is_inode_flag_set(inode, FI_HOT_DATA) || is_inode_flag_set(inode, FI_HOT_DATA) ||
f2fs_is_atomic_file(inode) || 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, old_blkaddr));
locate_dirty_segment(sbi, GET_SEGNO(sbi, *new_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); up_write(&sit_i->sentry_lock);
if (page && IS_NODESEG(type)) { if (page && IS_NODESEG(type)) {
@@ -3542,6 +3574,8 @@ void f2fs_outplace_write_data(struct dnode_of_data *dn,
struct f2fs_summary sum; struct f2fs_summary sum;
f2fs_bug_on(sbi, dn->data_blkaddr == NULL_ADDR); 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); set_summary(&sum, dn->nid, dn->ofs_in_node, fio->version);
do_write_page(&sum, fio); do_write_page(&sum, fio);
f2fs_update_data_blkaddr(dn, fio->new_blkaddr); 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; 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) + struct extent_tree_info *eti = &sbi->extent_tree[type];
atomic_read(&sbi->total_ext_node);
return atomic_read(&eti->total_zombie_tree) +
atomic_read(&eti->total_ext_node);
} }
unsigned long f2fs_shrink_count(struct shrinker *shrink, 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); spin_unlock(&f2fs_list_lock);
/* count extent cache entries */ /* count read extent cache entries */
count += __count_extent_cache(sbi); 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 clean nat cache entries */
count += __count_nat_entries(sbi); count += __count_nat_entries(sbi);
@@ -100,7 +106,10 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink,
sbi->shrinker_run_no = run_no; sbi->shrinker_run_no = run_no;
/* shrink extent cache entries */ /* 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 */ /* shrink clean nat cache entries */
if (freed < nr) 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) 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); spin_lock(&f2fs_list_lock);
list_del_init(&sbi->s_list); list_del_init(&sbi->s_list);

View File

@@ -154,6 +154,7 @@ enum {
Opt_atgc, Opt_atgc,
Opt_gc_merge, Opt_gc_merge,
Opt_nogc_merge, Opt_nogc_merge,
Opt_age_extent_cache,
Opt_err, Opt_err,
}; };
@@ -229,6 +230,7 @@ static match_table_t f2fs_tokens = {
{Opt_atgc, "atgc"}, {Opt_atgc, "atgc"},
{Opt_gc_merge, "gc_merge"}, {Opt_gc_merge, "gc_merge"},
{Opt_nogc_merge, "nogc_merge"}, {Opt_nogc_merge, "nogc_merge"},
{Opt_age_extent_cache, "age_extent_cache"},
{Opt_err, NULL}, {Opt_err, NULL},
}; };
@@ -753,10 +755,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
set_opt(sbi, FASTBOOT); set_opt(sbi, FASTBOOT);
break; break;
case Opt_extent_cache: case Opt_extent_cache:
set_opt(sbi, EXTENT_CACHE); set_opt(sbi, READ_EXTENT_CACHE);
break; break;
case Opt_noextent_cache: case Opt_noextent_cache:
clear_opt(sbi, EXTENT_CACHE); clear_opt(sbi, READ_EXTENT_CACHE);
break; break;
case Opt_noinline_data: case Opt_noinline_data:
clear_opt(sbi, INLINE_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: case Opt_nogc_merge:
clear_opt(sbi, GC_MERGE); clear_opt(sbi, GC_MERGE);
break; break;
case Opt_age_extent_cache:
set_opt(sbi, AGE_EXTENT_CACHE);
break;
default: default:
f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value", f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value",
p); p);
@@ -1817,10 +1822,12 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
seq_puts(seq, ",nobarrier"); seq_puts(seq, ",nobarrier");
if (test_opt(sbi, FASTBOOT)) if (test_opt(sbi, FASTBOOT))
seq_puts(seq, ",fastboot"); seq_puts(seq, ",fastboot");
if (test_opt(sbi, EXTENT_CACHE)) if (test_opt(sbi, READ_EXTENT_CACHE))
seq_puts(seq, ",extent_cache"); seq_puts(seq, ",extent_cache");
else else
seq_puts(seq, ",noextent_cache"); seq_puts(seq, ",noextent_cache");
if (test_opt(sbi, AGE_EXTENT_CACHE))
seq_puts(seq, ",age_extent_cache");
if (test_opt(sbi, DATA_FLUSH)) if (test_opt(sbi, DATA_FLUSH))
seq_puts(seq, ",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_XATTR);
set_opt(sbi, INLINE_DATA); set_opt(sbi, INLINE_DATA);
set_opt(sbi, INLINE_DENTRY); set_opt(sbi, INLINE_DENTRY);
set_opt(sbi, EXTENT_CACHE); set_opt(sbi, READ_EXTENT_CACHE);
set_opt(sbi, NOHEAP); set_opt(sbi, NOHEAP);
clear_opt(sbi, DISABLE_CHECKPOINT); clear_opt(sbi, DISABLE_CHECKPOINT);
set_opt(sbi, MERGE_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_gc = false, need_stop_gc = false;
bool need_restart_ckpt = false, need_stop_ckpt = false; bool need_restart_ckpt = false, need_stop_ckpt = false;
bool need_restart_flush = false, need_stop_flush = 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 disable_checkpoint = test_opt(sbi, DISABLE_CHECKPOINT);
bool no_io_align = !F2FS_IO_ALIGNED(sbi); bool no_io_align = !F2FS_IO_ALIGNED(sbi);
bool no_atgc = !test_opt(sbi, ATGC); 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 */ /* 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; err = -EINVAL;
f2fs_warn(sbi, "switch extent_cache option is not allowed"); f2fs_warn(sbi, "switch extent_cache option is not allowed");
goto restore_opts; 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)) { if (no_io_align == !!F2FS_IO_ALIGNED(sbi)) {
err = -EINVAL; err = -EINVAL;

View File

@@ -549,6 +549,24 @@ out:
return count; 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; *ui = (unsigned int)t;
return count; 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_segment_mode, gc_segment_mode);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_reclaimed_segments, gc_reclaimed_segs); 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) #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
static struct attribute *f2fs_attrs[] = { static struct attribute *f2fs_attrs[] = {
ATTR_LIST(gc_urgent_sleep_time), ATTR_LIST(gc_urgent_sleep_time),
@@ -853,6 +875,8 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(atgc_age_threshold), ATTR_LIST(atgc_age_threshold),
ATTR_LIST(gc_segment_mode), ATTR_LIST(gc_segment_mode),
ATTR_LIST(gc_reclaimed_segments), ATTR_LIST(gc_reclaimed_segments),
ATTR_LIST(hot_data_age_threshold),
ATTR_LIST(warm_data_age_threshold),
NULL, NULL,
}; };
ATTRIBUTE_GROUPS(f2fs); 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 * 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) __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); kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
spin_unlock(&fiq->lock); spin_unlock(&fiq->lock);
} }
@@ -224,14 +227,14 @@ const struct fuse_iqueue_ops fuse_dev_fiq_ops = {
EXPORT_SYMBOL_GPL(fuse_dev_fiq_ops); EXPORT_SYMBOL_GPL(fuse_dev_fiq_ops);
static void queue_request_and_unlock(struct fuse_iqueue *fiq, static void queue_request_and_unlock(struct fuse_iqueue *fiq,
struct fuse_req *req) struct fuse_req *req, bool sync)
__releases(fiq->lock) __releases(fiq->lock)
{ {
req->in.h.len = sizeof(struct fuse_in_header) + req->in.h.len = sizeof(struct fuse_in_header) +
fuse_len_args(req->args->in_numargs, fuse_len_args(req->args->in_numargs,
(struct fuse_arg *) req->args->in_args); (struct fuse_arg *) req->args->in_args);
list_add_tail(&req->list, &fiq->pending); 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, 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) { if (fiq->connected) {
fiq->forget_list_tail->next = forget; fiq->forget_list_tail->next = forget;
fiq->forget_list_tail = forget; fiq->forget_list_tail = forget;
fiq->ops->wake_forget_and_unlock(fiq); fiq->ops->wake_forget_and_unlock(fiq, false);
} else { } else {
kfree(forget); kfree(forget);
spin_unlock(&fiq->lock); spin_unlock(&fiq->lock);
@@ -266,7 +269,7 @@ static void flush_bg_queue(struct fuse_conn *fc)
fc->active_background++; fc->active_background++;
spin_lock(&fiq->lock); spin_lock(&fiq->lock);
req->in.h.unique = fuse_get_unique(fiq); 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); spin_unlock(&fiq->lock);
return 0; return 0;
} }
fiq->ops->wake_interrupt_and_unlock(fiq); fiq->ops->wake_interrupt_and_unlock(fiq, false);
} else { } else {
spin_unlock(&fiq->lock); 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 /* acquire extra reference, since request is still needed
after fuse_request_end() */ after fuse_request_end() */
__fuse_get_request(req); __fuse_get_request(req);
queue_request_and_unlock(fiq, req); queue_request_and_unlock(fiq, req, true);
request_wait_answer(req); request_wait_answer(req);
/* Pairs with smp_wmb() in fuse_request_end() */ /* 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); spin_lock(&fiq->lock);
if (fiq->connected) { if (fiq->connected) {
queue_request_and_unlock(fiq, req); queue_request_and_unlock(fiq, req, false);
} else { } else {
err = -ENODEV; err = -ENODEV;
spin_unlock(&fiq->lock); spin_unlock(&fiq->lock);

View File

@@ -412,19 +412,19 @@ struct fuse_iqueue_ops {
/** /**
* Signal that a forget has been queued * 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); __releases(fiq->lock);
/** /**
* Signal that an INTERRUPT request has been queued * 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); __releases(fiq->lock);
/** /**
* Signal that a request has been queued * 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); __releases(fiq->lock);
/** /**

View File

@@ -971,7 +971,7 @@ static struct virtio_driver virtio_fs_driver = {
#endif #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) __releases(fiq->lock)
{ {
struct fuse_forget_link *link; struct fuse_forget_link *link;
@@ -1006,7 +1006,8 @@ __releases(fiq->lock)
kfree(link); 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) __releases(fiq->lock)
{ {
/* /*
@@ -1221,7 +1222,8 @@ out:
return ret; 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) __releases(fiq->lock)
{ {
unsigned int queue_id = VQ_REQUEST; /* TODO multiqueue */ 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; \ 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("record-size", pdata->record_size, 0);
parse_u32("console-size", pdata->console_size, 0); parse_u32("console-size", pdata->console_size, 0);
parse_u32("ftrace-size", pdata->ftrace_size, 0); parse_u32("ftrace-size", pdata->ftrace_size, 0);

View File

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

View File

@@ -60,6 +60,13 @@
#define LED_FUNCTION_MICMUTE "micmute" #define LED_FUNCTION_MICMUTE "micmute"
#define LED_FUNCTION_MUTE "mute" #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. */ /* Miscelleaus functions. Use functions above if you can. */
#define LED_FUNCTION_ACTIVITY "activity" #define LED_FUNCTION_ACTIVITY "activity"
#define LED_FUNCTION_ALARM "alarm" #define LED_FUNCTION_ALARM "alarm"

View File

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

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