Merge branch 'android14-6.1' into android14-6.1-lts

This catches the -lts branch up with a lot of abi updates and resolves a
merge conflict in f2fs.  Changes in here include:

* 976b055754 UPSTREAM: HID: Use kvzalloc instead of kzalloc in hid_register_field()
* fadb08b366 FROMGIT: xhci: Fix Link TRB DMA in command ring stopped completion event
* 19b68814b1 Merge tag 'android14-6.1.112_r00' into android14-6.1
* 29d66b3902 UPSTREAM: exit: Sleep at TASK_IDLE when waiting for application core dump
* 179ccc9377 UPSTREAM: spi: spi-geni-qcom: Rename the label unmap_if_dma
* 9a072aa707 UPSTREAM: spi: spi-geni-qcom: Add SPI Device mode support for GENI based QuPv3
* 759bab9407 ANDROID: GKI: update symbol list for honor
* f949397a1b ANDROID: GKI: net: add vendor hooks for link data path
* 3165cd1163 ANDROID: ABI: Update symbol list for spi-geni-qcom updates
* 3b727b0154 UPSTREAM: spi: spi-geni-qcom: Do not do DMA map/unmap inside driver, use framework instead
* a874ed06eb UPSTREAM: Revert "tty: serial: simplify qcom_geni_serial_send_chunk_fifo()"
* e9c03c47d6 UPSTREAM: serial: qcom-geni: Don't cancel/abort if we can't get the port lock
* 2c16ff3847 UPSTREAM: serial: qcom_geni: Convert to platform remove callback returning void
* 7161dbc311 UPSTREAM: serial: qcom-geni: Use port lock wrappers
* cd5bd514c0 UPSTREAM: tty: serial: qcom-geni-serial: Poll primary sequencer irq status after cancel_tx
* 5722a4dd8b UPSTREAM: serial: qcom-geni: clean up clock-rate debug printk
* d5e0fbcd4a UPSTREAM: serial: qcom-geni: use icc tag defines
* 5bdef2817a ANDROID: ABI: update gki symbol list
* a03d1670d2 ANDROID: Add vendor hook for cma adjusting
* e02772c76d BACKPORT: firmware: arm_scmi: Queue in scmi layer for mailbox implementation
* 4dc2498506 UPSTREAM: tty: serial: simplify qcom_geni_serial_send_chunk_fifo()
* 719b876f95 UPSTREAM: tty: serial: qcom-geni-serial: Add a poll_init() function
* d15f99d2b5 UPSTREAM: serial: qcom-geni: drop bogus uart_write_wakeup()
* 3991e7fcc9 UPSTREAM: serial: qcom-geni: fix mapping of empty DMA buffer
* 64bccf317e UPSTREAM: serial: qcom-geni: fix DMA mapping leak on shutdown
* 4c3917c600 UPSTREAM: serial: qcom-geni: fix console shutdown hang
* 8bbc5694db UPSTREAM: serial: qcom_geni: Fix variable naming
* 53be6ca12d BACKPORT: tty: serial: qcom-geni-serial: add support for serial engine DMA
* 3321cd20f3 BACKPORT: soc: qcom-geni-se: add more symbol definitions
* 61df751af7 BACKPORT: tty: serial: qcom-geni-serial: use of_device_id data
* 3ebd383e35 BACKPORT: tty: serial: qcom-geni-serial: drop the return value from handle_rx
* a88673be7e UPSTREAM: tty: serial: qcom-geni-serial: refactor qcom_geni_serial_send_chunk_fifo()
* 94076b81a1 UPSTREAM: soc: qcom: geni-se: add GP_LENGTH/IRQ_EN_SET/IRQ_EN_CLEAR registers
* a137aa79a6 UPSTREAM: soc: qcom: geni-se: Add M_TX_FIFO_NOT_EMPTY bit definition
* 1790581f0a FROMLIST: ufs: core: requeue aborted request
* 51903b71f0 FROMLIST: ufs: core: fix the issue of ICU failure
* 00f19bd9ed ANDROID: GKI: Add symbol for rockchip pci remove
* 5e1f4bb11f ANDROID: abi_gki_aarch64_qcom: Add pci_ecam_map_bus and pci_host_common_probe
* 72f51dd698 ANDROID: abi_gki_aarch64_honor: whitelist symbols added for skip memcg reclaim by priority
* f2b3f5888f ANDROID: mm: add vendor hook to skip memcg reclaim by priority
* add3d68602 ANDROID: KVM: arm64: Don't run a protected VCPU if it isn't runnable
* 1fe91f863a ANDROID: usb: Optimization the transfer rate of accessory mode in USB3.2 mode
* 299cc91948 UPSTREAM: spi: spi-geni-qcom: Select FIFO mode for chip select
* b490c66749 ANDROID: KVM: arm64: Don't skip accounting when memcache top-up fails
* 1181501872 ANDROID: KVM: arm64: Fix accounting when VM creation fails
* 8baadbac00 UPSTREAM: spi: geni-qcom: Convert to platform remove callback returning void
* 5ab05b86ef UPSTREAM: spi: spi-geni-qcom: Add support for SE DMA mode
* 271bd223dd UPSTREAM: soc: qcom: geni-se: Add SPI Device mode support for GENI based QuPv3
* 27021bed80 UPSTREAM: tty: serial: qcom-geni-serial: split out the FIFO tx code
* ad717604be UPSTREAM: tty: serial: qcom-geni-serial: remove unneeded tabs
* ad37632534 UPSTREAM: tty: serial: qcom-geni-serial: refactor qcom_geni_serial_isr()
* 1f0775355f UPSTREAM: tty: serial: qcom-geni-serial: remove stray newlines
* 59cbbd0b09 UPSTREAM: tty: serial: qcom-geni-serial: improve the to_dev_port() macro
* f4eec633c0 UPSTREAM: tty: serial: qcom-geni-serial: align #define values
* b92a6c8545 UPSTREAM: tty: serial: qcom-geni-serial: remove unused symbols
* 6e6cda8f06 UPSTREAM: tty: serial: qcom-geni-serial: drop unneeded forward definitions
* d75a50763e UPSTREAM: tty: serial: qcom-geni-serial: stop operations in progress at shutdown
* 481220c5b9 ANDROID: abi_gki_aarch64_qcom: whitelist mm symbols
* e697302b05 ANDROID: mm: export lru_gen_caps
* 1a3bbc1910 ANDROID: mm: export unpack_shadow
* a6266110c1 UPSTREAM: i2c: qcom-geni: Use IRQF_NO_AUTOEN flag in request_irq()
* c24feb930a UPSTREAM: i2c: qcom-geni: Use goto for clearer exit path
* 80c036f7f2 UPSTREAM: i2c: qcom-geni: Add missing geni_icc_disable in geni_i2c_runtime_resume
* 688cbb4cee UPSTREAM: i2c: qcom-geni: Add missing geni_icc_disable in geni_i2c_runtime_resume
* aff2261bb1 UPSTREAM: i2c: qcom-geni: Add missing clk_disable_unprepare in geni_i2c_runtime_resume
* 371a327f3d UPSTREAM: i2c: qcom-geni: use 'time_left' variable with wait_for_completion_timeout()
* c756c6b094 UPSTREAM: i2c: qcom-geni: remove printout on handled timeouts
* fa329140c1 UPSTREAM: i2c: qcom-geni: fix missing clk_disable_unprepare() and geni_se_resources_off()
* 8fd3f0784d UPSTREAM: i2c: qcom-geni: Convert to devm_platform_ioremap_resource()
* 02b20eb4bc UPSTREAM: i2c: Convert to platform remove callback returning void
* a650b9fb29 UPSTREAM: i2c: qcom-geni: change i2c_master_hub to static
* aa4151b832 UPSTREAM: i2c: qcom-geni: add support for I2C Master Hub variant
* 47d1f8edd6 UPSTREAM: i2c: qcom-geni: add desc struct to prepare support for I2C Master Hub variant
* 752034bc87 UPSTREAM: wifi: cfg80211: fix reporting failed MLO links status with cfg80211_connect_done
* 40c204b003 UPSTREAM: scsi: ufs: core: Do not set link to OFF state while waking up from hibernation
* 2589c7fa08 UPSTREAM: mm/mglru: fix overshooting shrinker memory
* 4d8187d2c8 UPSTREAM: gso: fix udp gso fraglist segmentation after pull from frag_list
* b11f74b6c1 UPSTREAM: soc: qcom: geni-se: Do not bother about enable/disable of interrupts in secondary sequencer
* f9d2a8a3bf UPSTREAM: soc: qcom: geni-se: Add interfaces geni_se_tx_init_dma() and geni_se_rx_init_dma()
* 8097478ae8 UPSTREAM: unicode: Don't special case ignorable code points
* d41d398db6 BACKPORT: f2fs: fix to handle segment allocation failure correctly
* 751a02f798 UPSTREAM: f2fs: stop checkpoint when get a out-of-bounds segment
* acc7335e1f BACKPORT: f2fs: kill heap-based allocation
* 19e119d2d0 Reapply "io_uring: drop any code related to SCM_RIGHTS"
* 80e851bf0d FROMGIT: scsi: ufs: core: Support Updating UIC Command Timeout
* 0d60f50b9d ANDROID: GKI: Update symbol list for mtk
* 0ff444ed0b UPSTREAM: Revert "usb: typec: tcpm: clear pd_event queue in PORT_RESET"
* 311457e823 ANDROID: GKI: update symbol list for transsion
* 8d29837471 UPSTREAM: firmware_loader: Abort all upcoming firmware load request once reboot triggered
* a9d791a2b2 UPSTREAM: firmware_loader: Refactor kill_pending_fw_fallback_reqs()
* 0e8b65e41f ANDROID: sched: Make uclamp changes depend on CAP_SYS_NICE
* d4dab27b9d UPSTREAM: f2fs: fix to update i_ctime in __f2fs_setxattr()
* d645f73da1 UPSTREAM: f2fs: atomic: fix to truncate pagecache before on-disk metadata truncation
* 693980c220 BACKPORT: f2fs: Create COW inode from parent dentry for atomic write
* e35539a5ac BACKPORT: f2fs: atomic: fix to avoid racing w/ GC
* 9de4353ca0 UPSTREAM: f2fs: use meta inode for GC of COW file
* 9b5ee2f2b1 BACKPORT: f2fs: use meta inode for GC of atomic file
* 30f8a76da5 ANDROID: abi_gki_aarch64_qcom: Add missing symbol to QCOM list
* 6f2e0215d7 ANDROID: GKI: Add KMI symbols for virtio-audio
* ba06e1f121 ANDROID: fix up ABI with change to private struct geni_wrapper
* e0de5c9e33 UPSTREAM: soc: qcom: geni-se: add desc struct to specify clocks from device match data
* 1cdc168f1e ANDROID: GKI: Update symbol list for mtk
* 7c49c3acea UPSTREAM: arm64: cputype: Add Neoverse-V3 definitions
* 53769a60e3 UPSTREAM: arm64: cputype: Add Cortex-X4 definitions
* ecc82c7e71 UPSTREAM: arm64: barrier: Restore spec_bar() macro
* bd3cc5c733 UPSTREAM: KVM: arm64: Add memory length checks and remove inline in do_ffa_mem_xfer
* a43e7c2c12 ANDROID: GKI: Update symbol list for BCMSTB
* 5162f9a67b UPSTREAM: arm64: Add Neoverse-V2 part
* 1105954181 UPSTREAM: usb: dwc3: core: update LC timer as per USB Spec V3.2
* cc274231f6 ANDROID: GKI: Add symbol for pci power limit

Change-Id: Ie47fa8a9c5b1da4140b099de4d9d6647089c6e18
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2024-11-07 15:35:17 +00:00
61 changed files with 6033 additions and 4231 deletions

View File

@@ -122,6 +122,7 @@ filegroup(
"android/abi_gki_aarch64_sony",
"android/abi_gki_aarch64_sunxi",
"android/abi_gki_aarch64_telechips",
"android/abi_gki_aarch64_transsion",
"android/abi_gki_aarch64_tuxera",
"android/abi_gki_aarch64_type_visibility",
"android/abi_gki_aarch64_unisoc",

View File

@@ -126,9 +126,7 @@ norecovery Disable the roll-forward recovery routine, mounted read-
discard/nodiscard Enable/disable real-time discard in f2fs, if discard is
enabled, f2fs will issue discard/TRIM commands when a
segment is cleaned.
no_heap Disable heap-style segment allocation which finds free
segments for data from the beginning of main area, while
for node from the end of main area.
heap/no_heap Deprecated.
nouser_xattr Disable Extended User Attributes. Note: xattr is enabled
by default if CONFIG_F2FS_FS_XATTR is selected.
noacl Disable POSIX Access Control List. Note: acl is enabled

File diff suppressed because it is too large Load Diff

View File

@@ -147,6 +147,7 @@
dma_map_sg_attrs
dma_set_coherent_mask
dma_set_mask
dma_sync_single_for_device
dma_unmap_page_attrs
dma_unmap_sg_attrs
do_trace_netlink_extack
@@ -188,6 +189,7 @@
get_net_ns_by_fd
get_net_ns_by_pid
get_random_bytes
get_zeroed_page
gic_nonsecure_priorities
gpiochip_add_data_with_key
gpiochip_find
@@ -415,6 +417,7 @@
phy_start
phy_stop
phy_trigger_machine
platform_device_put
platform_device_register_full
platform_device_unregister
__platform_driver_probe
@@ -783,7 +786,6 @@
dma_sync_single_for_cpu
of_get_ethdev_address
of_platform_populate
platform_get_irq_byname
__skb_pad
synchronize_irq
@@ -863,6 +865,23 @@
of_find_net_device_by_node
of_find_node_by_phandle
# required by brcmstb-iommu.ko
devm_get_free_pages
generic_device_group
iommu_device_register
iommu_device_sysfs_add
iommu_device_sysfs_remove
iommu_device_unlink
iommu_device_unregister
iommu_fwspec_init
iommu_group_alloc
iommu_group_put
iommu_group_ref_get
iommu_group_set_name
pci_device_group
pci_find_host_bridge
platform_get_irq_byname
# required by brcmstb-proc-info.ko
find_get_pid
generic_file_open
@@ -1075,7 +1094,6 @@
platform_device_add_data
platform_device_add_resources
platform_device_alloc
platform_device_put
softnet_data
# required by gpio-brcmstb.ko
@@ -1594,7 +1612,6 @@
dma_get_slave_caps
dma_release_channel
dma_request_chan
dma_sync_single_for_device
empty_zero_page
gpiochip_request_own_desc
__of_get_address
@@ -1689,7 +1706,6 @@
device_find_child_by_name
device_for_each_child
_find_first_zero_bit
get_zeroed_page
rtnl_configure_link
rtnl_create_link
@@ -1751,3 +1767,11 @@
# required by bstm.ko
phys_mem_access_prot
generic_access_phys
# required by bcm_astra.ko
strnlen_user
tty_buffer_set_limit
tty_buffer_request_room
# required by bcm_athena.ko
__read_overflow2_field

View File

@@ -1145,6 +1145,8 @@
geni_se_rx_dma_unprep
geni_se_tx_dma_prep
geni_se_tx_dma_unprep
geni_se_rx_init_dma
geni_se_tx_init_dma
i2c_get_dma_safe_msg_buf
i2c_put_dma_safe_msg_buf

View File

@@ -10,6 +10,7 @@
__tracepoint_android_vh_modify_scan_control
__tracepoint_android_vh_should_continue_reclaim
__tracepoint_android_vh_tune_fault_around_bytes
__tracepoint_android_vh_should_memcg_bypass
__traceiter_android_vh_get_page_wmark
__traceiter_android_vh_page_add_new_anon_rmap
__traceiter_android_vh_do_shrink_slab
@@ -25,6 +26,7 @@
__traceiter_android_vh_modify_scan_control
__traceiter_android_vh_should_continue_reclaim
__traceiter_android_vh_tune_fault_around_bytes
__traceiter_android_vh_should_memcg_bypass
binder_alloc_copy_from_buffer
kfree
__kmalloc
@@ -46,3 +48,7 @@
udp4_lib_lookup
udp6_lib_lookup
next_arg
__tracepoint_android_vh_dc_send_copy
__traceiter_android_vh_dc_send_copy
__tracepoint_android_vh_dc_receive
__traceiter_android_vh_dc_receive

View File

@@ -17,6 +17,7 @@
alarm_start_relative
alarm_try_to_cancel
alloc_chrdev_region
alloc_contig_range
alloc_etherdev_mqs
alloc_io_pgtable_ops
alloc_netdev_mqs
@@ -31,6 +32,8 @@
android_rvh_probe_register
anon_inode_getfd
anon_inode_getfile
arc4_crypt
arc4_setkey
__arch_clear_user
__arch_copy_from_user
__arch_copy_to_user
@@ -593,6 +596,7 @@
dev_pm_opp_put_opp_table
dev_pm_opp_register_notifier
dev_pm_opp_remove_all_dynamic
dev_pm_opp_remove_table
dev_pm_opp_set_config
dev_pm_opp_unregister_notifier
dev_pm_qos_add_notifier
@@ -964,6 +968,7 @@
frame_vector_destroy
frame_vector_to_pages
frame_vector_to_pfns
free_contig_range
free_io_pgtable_ops
free_irq
free_netdev

View File

@@ -1879,6 +1879,7 @@
lowpan_register_netdevice
lowpan_unregister_netdev
lowpan_unregister_netdevice
lru_gen_caps
mac_pton
mas_find
match_string
@@ -2292,12 +2293,14 @@
pcie_capability_clear_and_set_word
pcie_capability_read_dword
pcie_capability_read_word
pci_ecam_map_bus
pci_enable_device
pci_enable_pcie_error_reporting
pci_find_ext_capability
pci_free_irq_vectors
pci_get_device
pci_get_domain_bus_and_slot
pci_host_common_probe
pci_host_probe
pci_iomap
pci_iounmap
@@ -2488,6 +2491,7 @@
power_supply_get_property
power_supply_put
power_supply_register
power_supply_register_no_ws
power_supply_reg_notifier
power_supply_set_property
power_supply_unregister
@@ -3766,6 +3770,7 @@
__uio_register_device
uio_unregister_device
unlock_page
unpack_shadow
unregister_blkdev
unregister_candev
__unregister_chrdev

View File

@@ -2105,6 +2105,7 @@
# required by pcie-dw-rockchip.ko
device_release_driver
dw_pcie_find_ext_capability
dw_pcie_host_deinit
dw_pcie_host_init
dw_pcie_link_up
dw_pcie_read
@@ -2121,6 +2122,7 @@
devm_pci_remap_cfg_resource
jiffies_to_usecs
of_pci_get_max_link_speed
of_pci_get_slot_power_limit
pci_host_probe
pci_remove_root_bus
pci_stop_root_bus

View File

@@ -18,6 +18,7 @@
__traceiter_android_vh_delayacct_compact_end
__traceiter_android_vh_delayacct_wpcopy_start
__traceiter_android_vh_delayacct_wpcopy_end
__traceiter_android_vh_exit_mm
__tracepoint_android_rvh_delayacct_init
__tracepoint_android_rvh_delayacct_tsk_init
__tracepoint_android_rvh_delayacct_tsk_free
@@ -35,3 +36,37 @@
__tracepoint_android_vh_delayacct_compact_end
__tracepoint_android_vh_delayacct_wpcopy_start
__tracepoint_android_vh_delayacct_wpcopy_end
__tracepoint_android_vh_exit_mm
# required by tran_io.ko
__percpu_counter_init
_atomic_dec_and_lock_irqsave
add_disk_randomness
bio_uninit
blk_mq_alloc_disk_for_queue
block_read_full_folio
bsg_register_queue
bsg_unregister_queue
buffer_check_dirty_writeback
call_rcu_hurry
clock_t_to_jiffies
devcgroup_check_permission
filemap_fdatawait_keep_errors
folio_mark_dirty
folio_unlock
invalidate_bh_lrus
io_cgrp_subsys
mempool_exit
mempool_init
percpu_counter_destroy
percpu_ref_exit
percpu_ref_init
percpu_ref_is_zero
percpu_ref_kill_and_confirm
percpu_ref_resurrect
percpu_ref_switch_to_atomic_sync
percpu_ref_switch_to_percpu
read_cache_folio
register_tracepoint_module_notifier
scsi_register_driver
trace_seq_puts

View File

@@ -1367,6 +1367,12 @@
snd_pcm_set_ops
wait_for_completion_interruptible_timeout
# required by virtio-audio
snd_device_new
snd_pcm_hw_limit_rates
_snd_pcm_stream_lock_irqsave
snd_pcm_stream_unlock_irqrestore
# required by vkms.ko
__devm_drm_dev_alloc
devres_open_group

View File

@@ -116,6 +116,10 @@
__tracepoint_android_rvh_check_preempt_tick
__tracepoint_android_rvh_dequeue_entity
__tracepoint_android_rvh_enqueue_entity
__traceiter_android_vh_alloc_flags_cma_adjust
__traceiter_android_vh_rmqueue_cma_fallback
__tracepoint_android_vh_alloc_flags_cma_adjust
__tracepoint_android_vh_rmqueue_cma_fallback
console_printk
__traceiter_android_vh_binder_transaction_init
__tracepoint_android_vh_binder_transaction_init

View File

@@ -411,9 +411,9 @@ out:
return;
}
static __always_inline void do_ffa_mem_xfer(const u64 func_id,
struct arm_smccc_res *res,
struct kvm_cpu_context *ctxt)
static void __do_ffa_mem_xfer(const u64 func_id,
struct arm_smccc_res *res,
struct kvm_cpu_context *ctxt)
{
DECLARE_REG(u32, len, ctxt, 1);
DECLARE_REG(u32, fraglen, ctxt, 2);
@@ -424,9 +424,6 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id,
u32 offset, nr_ranges;
int ret = 0;
BUILD_BUG_ON(func_id != FFA_FN64_MEM_SHARE &&
func_id != FFA_FN64_MEM_LEND);
if (addr_mbz || npages_mbz || fraglen > len ||
fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
ret = FFA_RET_INVALID_PARAMETERS;
@@ -445,6 +442,11 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id,
goto out_unlock;
}
if (len > ffa_desc_buf.len) {
ret = FFA_RET_NO_MEMORY;
goto out_unlock;
}
buf = hyp_buffers.tx;
memcpy(buf, host_buffers.tx, fraglen);
@@ -494,6 +496,13 @@ err_unshare:
goto out_unlock;
}
#define do_ffa_mem_xfer(fid, res, ctxt) \
do { \
BUILD_BUG_ON((fid) != FFA_FN64_MEM_SHARE && \
(fid) != FFA_FN64_MEM_LEND); \
__do_ffa_mem_xfer((fid), (res), (ctxt)); \
} while (0);
static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
struct kvm_cpu_context *ctxt)
{

View File

@@ -576,9 +576,6 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
hyp_entry_exit_handler_fn ec_handler;
u8 esr_ec;
if (READ_ONCE(hyp_vcpu->power_state) == PSCI_0_2_AFFINITY_LEVEL_ON_PENDING)
pkvm_reset_vcpu(hyp_vcpu);
/*
* If we deal with a non-protected guest and the state is potentially
* dirty (from a host perspective), copy the state back into the hyp
@@ -823,19 +820,29 @@ static struct kvm_vcpu *__get_host_hyp_vcpus(struct kvm_vcpu *arg,
__get_host_hyp_vcpus(__vcpu, hyp_vcpup); \
})
static bool is_vcpu_runnable(struct pkvm_hyp_vcpu *hyp_vcpu)
{
return (!pkvm_hyp_vcpu_is_protected(hyp_vcpu) ||
hyp_vcpu->power_state == PSCI_0_2_AFFINITY_LEVEL_ON);
}
static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)
{
struct pkvm_hyp_vcpu *hyp_vcpu;
struct kvm_vcpu *host_vcpu;
int ret;
int ret = ARM_EXCEPTION_IL;
host_vcpu = get_host_hyp_vcpus(host_ctxt, 1, &hyp_vcpu);
if (!host_vcpu) {
ret = -EINVAL;
if (!host_vcpu)
goto out;
}
if (unlikely(hyp_vcpu)) {
if (hyp_vcpu->power_state == PSCI_0_2_AFFINITY_LEVEL_ON_PENDING)
pkvm_reset_vcpu(hyp_vcpu);
if (unlikely(!is_vcpu_runnable(hyp_vcpu)))
goto out;
flush_hyp_vcpu(hyp_vcpu);
ret = __kvm_vcpu_run(&hyp_vcpu->vcpu);

View File

@@ -981,9 +981,7 @@ int topup_hyp_memcache(struct kvm_vcpu *vcpu)
err = __topup_hyp_memcache(mc, kvm_mmu_cache_min_pages(vcpu->kvm),
hyp_mc_alloc_fn,
kvm_host_pa, NULL);
if (!err)
account_hyp_memcache(mc, prev_nr_pages, vcpu->kvm);
account_hyp_memcache(mc, prev_nr_pages, vcpu->kvm);
return err;
}

View File

@@ -262,6 +262,8 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
host_kvm->arch.pkvm.handle = handle;
total_sz = hyp_vm_sz + last_ran_sz + pgd_sz;
atomic64_set(&host_kvm->stat.protected_hyp_mem, total_sz);
kvm_account_pgtable_pages(pgd, pgd_sz >> PAGE_SHIFT);
/* Donate memory for the vcpus at hyp and initialize it. */
hyp_vcpu_sz = PAGE_ALIGN(PKVM_HYP_VCPU_SIZE);
@@ -280,18 +282,15 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
goto destroy_vm;
}
total_sz += hyp_vcpu_sz;
ret = kvm_call_hyp_nvhe(__pkvm_init_vcpu, handle, host_vcpu,
hyp_vcpu);
if (ret) {
free_pages_exact(hyp_vcpu, hyp_vcpu_sz);
goto destroy_vm;
}
}
atomic64_set(&host_kvm->stat.protected_hyp_mem, total_sz);
kvm_account_pgtable_pages(pgd, pgd_sz >> PAGE_SHIFT);
atomic64_add(hyp_vcpu_sz, &host_kvm->stat.protected_hyp_mem);
}
return 0;

View File

@@ -214,6 +214,8 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_shmem_get_folio);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_record_pcpu_rwsem_time_early);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_check_mmap_file);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_check_file_open);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_dc_send_copy);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_dc_receive);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_check_bpf_syscall);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ignore_dmabuf_vmap_bounds);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rproc_recovery);
@@ -344,6 +346,8 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_ctl_dirty_rate);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_check_hibernation_swap);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_save_cpu_resume);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_save_hib_resume_bdev);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_flags_cma_adjust);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rmqueue_cma_fallback);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_encrypt_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_init_aes_encrypt);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_skip_swap_map_write);
@@ -425,6 +429,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_do_read_fault);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_queue_request_and_unlock);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_fuse_request_end);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_read_trylock_failed);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_should_memcg_bypass);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shmem_swapin_folio);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_do_wp_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_do_swap_page);

View File

@@ -46,7 +46,7 @@ static inline int fw_sysfs_wait_timeout(struct fw_priv *fw_priv, long timeout)
static LIST_HEAD(pending_fw_head);
void kill_pending_fw_fallback_reqs(bool only_kill_custom)
void kill_pending_fw_fallback_reqs(bool kill_all)
{
struct fw_priv *fw_priv;
struct fw_priv *next;
@@ -54,9 +54,13 @@ void kill_pending_fw_fallback_reqs(bool only_kill_custom)
mutex_lock(&fw_lock);
list_for_each_entry_safe(fw_priv, next, &pending_fw_head,
pending_list) {
if (!fw_priv->need_uevent || !only_kill_custom)
if (kill_all || !fw_priv->need_uevent)
__fw_load_abort(fw_priv);
}
if (kill_all)
fw_load_abort_all = true;
mutex_unlock(&fw_lock);
}
@@ -86,7 +90,7 @@ static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, long timeout)
}
mutex_lock(&fw_lock);
if (fw_state_is_aborted(fw_priv)) {
if (fw_load_abort_all || fw_state_is_aborted(fw_priv)) {
mutex_unlock(&fw_lock);
retval = -EINTR;
goto out;

View File

@@ -13,7 +13,7 @@ int firmware_fallback_sysfs(struct firmware *fw, const char *name,
struct device *device,
u32 opt_flags,
int ret);
void kill_pending_fw_fallback_reqs(bool only_kill_custom);
void kill_pending_fw_fallback_reqs(bool kill_all);
void fw_fallback_set_cache_timeout(void);
void fw_fallback_set_default_timeout(void);
@@ -28,7 +28,7 @@ static inline int firmware_fallback_sysfs(struct firmware *fw, const char *name,
return ret;
}
static inline void kill_pending_fw_fallback_reqs(bool only_kill_custom) { }
static inline void kill_pending_fw_fallback_reqs(bool kill_all) { }
static inline void fw_fallback_set_cache_timeout(void) { }
static inline void fw_fallback_set_default_timeout(void) { }
#endif /* CONFIG_FW_LOADER_USER_HELPER */

View File

@@ -88,6 +88,7 @@ struct fw_priv {
extern struct mutex fw_lock;
extern struct firmware_cache fw_cache;
extern bool fw_load_abort_all;
static inline bool __fw_state_check(struct fw_priv *fw_priv,
enum fw_status status)

View File

@@ -93,6 +93,7 @@ static inline struct fw_priv *to_fw_priv(struct kref *ref)
DEFINE_MUTEX(fw_lock);
struct firmware_cache fw_cache;
bool fw_load_abort_all;
void fw_state_init(struct fw_priv *fw_priv)
{
@@ -1560,10 +1561,10 @@ static int fw_pm_notify(struct notifier_block *notify_block,
case PM_SUSPEND_PREPARE:
case PM_RESTORE_PREPARE:
/*
* kill pending fallback requests with a custom fallback
* to avoid stalling suspend.
* Here, kill pending fallback requests will only kill
* non-uevent firmware request to avoid stalling suspend.
*/
kill_pending_fw_fallback_reqs(true);
kill_pending_fw_fallback_reqs(false);
device_cache_fw_images();
break;
@@ -1648,7 +1649,7 @@ static int fw_shutdown_notify(struct notifier_block *unused1,
* Kill all pending fallback requests to avoid both stalling shutdown,
* and avoid a deadlock with the usermode_lock.
*/
kill_pending_fw_fallback_reqs(false);
kill_pending_fw_fallback_reqs(true);
return NOTIFY_DONE;
}

View File

@@ -22,12 +22,14 @@
* @chan: Transmit/Receive mailbox channel
* @cinfo: SCMI channel info
* @shmem: Transmit/Receive shared memory area
* @chan_lock: Lock that prevents multiple xfers from being queued
*/
struct scmi_mailbox {
struct mbox_client cl;
struct mbox_chan *chan;
struct scmi_chan_info *cinfo;
struct scmi_shared_mem __iomem *shmem;
struct mutex chan_lock;
};
#define client_to_scmi_mailbox(c) container_of(c, struct scmi_mailbox, cl)
@@ -157,6 +159,7 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
cinfo->transport_info = smbox;
smbox->cinfo = cinfo;
mutex_init(&smbox->chan_lock);
return 0;
}
@@ -184,13 +187,23 @@ static int mailbox_send_message(struct scmi_chan_info *cinfo,
struct scmi_mailbox *smbox = cinfo->transport_info;
int ret;
/*
* The mailbox layer has its own queue. However the mailbox queue confuses
* the per message SCMI timeouts since the clock starts when the message is
* submitted into the mailbox queue. So when multiple messages are queued up
* the clock starts on all messages instead of only the one inflight.
*/
mutex_lock(&smbox->chan_lock);
ret = mbox_send_message(smbox->chan, xfer);
/* mbox_send_message returns non-negative value on success, so reset */
if (ret > 0)
ret = 0;
if (ret < 0) {
mutex_unlock(&smbox->chan_lock);
return ret;
}
return ret;
return 0;
}
static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret,
@@ -198,13 +211,10 @@ static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret,
{
struct scmi_mailbox *smbox = cinfo->transport_info;
/*
* NOTE: we might prefer not to need the mailbox ticker to manage the
* transfer queueing since the protocol layer queues things by itself.
* Unfortunately, we have to kick the mailbox framework after we have
* received our message.
*/
mbox_client_txdone(smbox->chan, ret);
/* Release channel */
mutex_unlock(&smbox->chan_lock);
}
static void mailbox_fetch_response(struct scmi_chan_info *cinfo,

View File

@@ -101,9 +101,9 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
return NULL;
}
field = kzalloc((sizeof(struct hid_field) +
usages * sizeof(struct hid_usage) +
3 * usages * sizeof(unsigned int)), GFP_KERNEL);
field = kvzalloc((sizeof(struct hid_field) +
usages * sizeof(struct hid_usage) +
3 * usages * sizeof(unsigned int)), GFP_KERNEL);
if (!field)
return NULL;
@@ -667,7 +667,7 @@ static void hid_free_report(struct hid_report *report)
kfree(report->field_entries);
for (n = 0; n < report->maxfield; n++)
kfree(report->field[n]);
kvfree(report->field[n]);
kfree(report);
}

View File

@@ -586,7 +586,8 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i
{
struct dma_slave_config config = {};
struct gpi_i2c_config peripheral = {};
int i, ret = 0, timeout;
int i, ret = 0;
unsigned long time_left;
dma_addr_t tx_addr, rx_addr;
void *tx_buf = NULL, *rx_buf = NULL;
const struct geni_i2c_clk_fld *itr = gi2c->clk_fld;
@@ -629,12 +630,9 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i
dma_async_issue_pending(gi2c->tx_c);
timeout = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
if (!timeout) {
dev_err(gi2c->se.dev, "I2C timeout gpi flags:%d addr:0x%x\n",
gi2c->cur->flags, gi2c->cur->addr);
time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
if (!time_left)
gi2c->err = -ETIMEDOUT;
}
if (gi2c->err) {
ret = gi2c->err;
@@ -767,7 +765,6 @@ err_tx:
static int geni_i2c_probe(struct platform_device *pdev)
{
struct geni_i2c_dev *gi2c;
struct resource *res;
u32 proto, tx_depth, fifo_disable;
int ret;
struct device *dev = &pdev->dev;
@@ -779,8 +776,7 @@ static int geni_i2c_probe(struct platform_device *pdev)
gi2c->se.dev = dev;
gi2c->se.wrapper = dev_get_drvdata(dev->parent);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
gi2c->se.base = devm_ioremap_resource(dev, res);
gi2c->se.base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(gi2c->se.base))
return PTR_ERR(gi2c->se.base);
@@ -821,15 +817,13 @@ static int geni_i2c_probe(struct platform_device *pdev)
init_completion(&gi2c->done);
spin_lock_init(&gi2c->lock);
platform_set_drvdata(pdev, gi2c);
ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, 0,
ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN,
dev_name(dev), gi2c);
if (ret) {
dev_err(dev, "Request_irq failed:%d: err:%d\n",
gi2c->irq, ret);
return ret;
}
/* Disable the interrupt so that the system can enter low-power mode */
disable_irq(gi2c->irq);
i2c_set_adapdata(&gi2c->adap, gi2c);
gi2c->adap.dev.parent = dev;
gi2c->adap.dev.of_node = dev->of_node;
@@ -942,14 +936,13 @@ err_dma:
return ret;
}
static int geni_i2c_remove(struct platform_device *pdev)
static void geni_i2c_remove(struct platform_device *pdev)
{
struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
i2c_del_adapter(&gi2c->adap);
release_gpi_dma(gi2c);
pm_runtime_disable(gi2c->se.dev);
return 0;
}
static void geni_i2c_shutdown(struct platform_device *pdev)
@@ -990,21 +983,24 @@ static int __maybe_unused geni_i2c_runtime_resume(struct device *dev)
return ret;
ret = clk_prepare_enable(gi2c->core_clk);
if (ret) {
geni_icc_disable(&gi2c->se);
return ret;
}
if (ret)
goto out_icc_disable;
ret = geni_se_resources_on(&gi2c->se);
if (ret) {
clk_disable_unprepare(gi2c->core_clk);
geni_icc_disable(&gi2c->se);
return ret;
}
if (ret)
goto out_clk_disable;
enable_irq(gi2c->irq);
gi2c->suspended = 0;
return 0;
out_clk_disable:
clk_disable_unprepare(gi2c->core_clk);
out_icc_disable:
geni_icc_disable(&gi2c->se);
return ret;
}
static int __maybe_unused geni_i2c_suspend_noirq(struct device *dev)
@@ -1036,15 +1032,23 @@ static const struct dev_pm_ops geni_i2c_pm_ops = {
NULL)
};
static const struct geni_i2c_desc i2c_master_hub = {
.has_core_clk = true,
.icc_ddr = NULL,
.no_dma_support = true,
.tx_fifo_depth = 16,
};
static const struct of_device_id geni_i2c_dt_match[] = {
{ .compatible = "qcom,geni-i2c" },
{ .compatible = "qcom,geni-i2c-master-hub", .data = &i2c_master_hub },
{}
};
MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
static struct platform_driver geni_i2c_driver = {
.probe = geni_i2c_probe,
.remove = geni_i2c_remove,
.remove_new = geni_i2c_remove,
.shutdown = geni_i2c_shutdown,
.driver = {
.name = "geni_i2c",

View File

@@ -81,19 +81,31 @@
*/
#define MAX_CLK_PERF_LEVEL 32
#define NUM_AHB_CLKS 2
#define MAX_CLKS 2
/**
* struct geni_wrapper - Data structure to represent the QUP Wrapper Core
* @dev: Device pointer of the QUP wrapper core
* @base: Base address of this instance of QUP wrapper core
* @ahb_clks: Handle to the primary & secondary AHB clocks
* @clks: Handle to the primary & optional secondary AHB clocks
* @num_clks: Count of clocks
* @to_core: Core ICC path
*/
struct geni_wrapper {
struct device *dev;
void __iomem *base;
struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
struct clk_bulk_data clks[MAX_CLKS];
unsigned int num_clks;
};
/**
* struct geni_se_desc - Data structure to represent the QUP Wrapper resources
* @clks: Name of the primary & optional secondary AHB clocks
* @num_clks: Count of clock names
*/
struct geni_se_desc {
unsigned int num_clks;
const char * const *clks;
};
static const char * const icc_path_names[] = {"qup-core", "qup-config",
@@ -269,27 +281,14 @@ static void geni_se_select_fifo_mode(struct geni_se *se)
geni_se_irq_clear(se);
/*
* The RX path for the UART is asynchronous and so needs more
* complex logic for enabling / disabling its interrupts.
*
* Specific notes:
* - The done and TX-related interrupts are managed manually.
* - We don't RX from the main sequencer (we use the secondary) so
* we don't need the RX-related interrupts enabled in the main
* sequencer for UART.
*/
/* UART driver manages enabling / disabling interrupts internally */
if (proto != GENI_SE_UART) {
/* Non-UART use only primary sequencer so dont bother about S_IRQ */
val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN;
val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
val |= S_CMD_DONE_EN;
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
}
val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
@@ -305,17 +304,14 @@ static void geni_se_select_dma_mode(struct geni_se *se)
geni_se_irq_clear(se);
/* UART driver manages enabling / disabling interrupts internally */
if (proto != GENI_SE_UART) {
/* Non-UART use only primary sequencer so dont bother about S_IRQ */
val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN);
val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
val &= ~S_CMD_DONE_EN;
if (val != val_old)
writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
}
val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
@@ -332,10 +328,6 @@ static void geni_se_select_gpi_mode(struct geni_se *se)
writel(0, se->base + SE_IRQ_EN);
val = readl(se->base + SE_GENI_S_IRQ_EN);
val &= ~S_CMD_DONE_EN;
writel(val, se->base + SE_GENI_S_IRQ_EN);
val = readl(se->base + SE_GENI_M_IRQ_EN);
val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN |
M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
@@ -496,8 +488,7 @@ static void geni_se_clks_off(struct geni_se *se)
struct geni_wrapper *wrapper = se->wrapper;
clk_disable_unprepare(se->clk);
clk_bulk_disable_unprepare(ARRAY_SIZE(wrapper->ahb_clks),
wrapper->ahb_clks);
clk_bulk_disable_unprepare(wrapper->num_clks, wrapper->clks);
}
/**
@@ -528,15 +519,13 @@ static int geni_se_clks_on(struct geni_se *se)
int ret;
struct geni_wrapper *wrapper = se->wrapper;
ret = clk_bulk_prepare_enable(ARRAY_SIZE(wrapper->ahb_clks),
wrapper->ahb_clks);
ret = clk_bulk_prepare_enable(wrapper->num_clks, wrapper->clks);
if (ret)
return ret;
ret = clk_prepare_enable(se->clk);
if (ret)
clk_bulk_disable_unprepare(ARRAY_SIZE(wrapper->ahb_clks),
wrapper->ahb_clks);
clk_bulk_disable_unprepare(wrapper->num_clks, wrapper->clks);
return ret;
}
@@ -673,6 +662,30 @@ EXPORT_SYMBOL(geni_se_clk_freq_match);
#define GENI_SE_DMA_EOT_EN BIT(1)
#define GENI_SE_DMA_AHB_ERR_EN BIT(2)
#define GENI_SE_DMA_EOT_BUF BIT(0)
/**
* geni_se_tx_init_dma() - Initiate TX DMA transfer on the serial engine
* @se: Pointer to the concerned serial engine.
* @iova: Mapped DMA address.
* @len: Length of the TX buffer.
*
* This function is used to initiate DMA TX transfer.
*/
void geni_se_tx_init_dma(struct geni_se *se, dma_addr_t iova, size_t len)
{
u32 val;
val = GENI_SE_DMA_DONE_EN;
val |= GENI_SE_DMA_EOT_EN;
val |= GENI_SE_DMA_AHB_ERR_EN;
writel_relaxed(val, se->base + SE_DMA_TX_IRQ_EN_SET);
writel_relaxed(lower_32_bits(iova), se->base + SE_DMA_TX_PTR_L);
writel_relaxed(upper_32_bits(iova), se->base + SE_DMA_TX_PTR_H);
writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR);
writel(len, se->base + SE_DMA_TX_LEN);
}
EXPORT_SYMBOL(geni_se_tx_init_dma);
/**
* geni_se_tx_dma_prep() - Prepare the serial engine for TX DMA transfer
* @se: Pointer to the concerned serial engine.
@@ -688,7 +701,6 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
dma_addr_t *iova)
{
struct geni_wrapper *wrapper = se->wrapper;
u32 val;
if (!wrapper)
return -EINVAL;
@@ -697,18 +709,35 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
if (dma_mapping_error(wrapper->dev, *iova))
return -EIO;
val = GENI_SE_DMA_DONE_EN;
val |= GENI_SE_DMA_EOT_EN;
val |= GENI_SE_DMA_AHB_ERR_EN;
writel_relaxed(val, se->base + SE_DMA_TX_IRQ_EN_SET);
writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L);
writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H);
writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR);
writel(len, se->base + SE_DMA_TX_LEN);
geni_se_tx_init_dma(se, *iova, len);
return 0;
}
EXPORT_SYMBOL(geni_se_tx_dma_prep);
/**
* geni_se_rx_init_dma() - Initiate RX DMA transfer on the serial engine
* @se: Pointer to the concerned serial engine.
* @iova: Mapped DMA address.
* @len: Length of the RX buffer.
*
* This function is used to initiate DMA RX transfer.
*/
void geni_se_rx_init_dma(struct geni_se *se, dma_addr_t iova, size_t len)
{
u32 val;
val = GENI_SE_DMA_DONE_EN;
val |= GENI_SE_DMA_EOT_EN;
val |= GENI_SE_DMA_AHB_ERR_EN;
writel_relaxed(val, se->base + SE_DMA_RX_IRQ_EN_SET);
writel_relaxed(lower_32_bits(iova), se->base + SE_DMA_RX_PTR_L);
writel_relaxed(upper_32_bits(iova), se->base + SE_DMA_RX_PTR_H);
/* RX does not have EOT buffer type bit. So just reset RX_ATTR */
writel_relaxed(0, se->base + SE_DMA_RX_ATTR);
writel(len, se->base + SE_DMA_RX_LEN);
}
EXPORT_SYMBOL(geni_se_rx_init_dma);
/**
* geni_se_rx_dma_prep() - Prepare the serial engine for RX DMA transfer
* @se: Pointer to the concerned serial engine.
@@ -724,7 +753,6 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
dma_addr_t *iova)
{
struct geni_wrapper *wrapper = se->wrapper;
u32 val;
if (!wrapper)
return -EINVAL;
@@ -733,15 +761,7 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
if (dma_mapping_error(wrapper->dev, *iova))
return -EIO;
val = GENI_SE_DMA_DONE_EN;
val |= GENI_SE_DMA_EOT_EN;
val |= GENI_SE_DMA_AHB_ERR_EN;
writel_relaxed(val, se->base + SE_DMA_RX_IRQ_EN_SET);
writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_RX_PTR_L);
writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H);
/* RX does not have EOT buffer type bit. So just reset RX_ATTR */
writel_relaxed(0, se->base + SE_DMA_RX_ATTR);
writel(len, se->base + SE_DMA_RX_LEN);
geni_se_rx_init_dma(se, *iova, len);
return 0;
}
EXPORT_SYMBOL(geni_se_rx_dma_prep);
@@ -887,11 +907,33 @@ static int geni_se_probe(struct platform_device *pdev)
return PTR_ERR(wrapper->base);
if (!has_acpi_companion(&pdev->dev)) {
wrapper->ahb_clks[0].id = "m-ahb";
wrapper->ahb_clks[1].id = "s-ahb";
ret = devm_clk_bulk_get(dev, NUM_AHB_CLKS, wrapper->ahb_clks);
const struct geni_se_desc *desc;
int i;
desc = device_get_match_data(&pdev->dev);
if (!desc)
return -EINVAL;
wrapper->num_clks = min_t(unsigned int, desc->num_clks, MAX_CLKS);
for (i = 0; i < wrapper->num_clks; ++i)
wrapper->clks[i].id = desc->clks[i];
ret = of_count_phandle_with_args(dev->of_node, "clocks", "#clock-cells");
if (ret < 0) {
dev_err(dev, "invalid clocks property at %pOF\n", dev->of_node);
return ret;
}
if (ret < wrapper->num_clks) {
dev_err(dev, "invalid clocks count at %pOF, expected %d entries\n",
dev->of_node, wrapper->num_clks);
return -EINVAL;
}
ret = devm_clk_bulk_get(dev, wrapper->num_clks, wrapper->clks);
if (ret) {
dev_err(dev, "Err getting AHB clks %d\n", ret);
dev_err(dev, "Err getting clks %d\n", ret);
return ret;
}
}
@@ -901,8 +943,18 @@ static int geni_se_probe(struct platform_device *pdev)
return devm_of_platform_populate(dev);
}
static const char * const qup_clks[] = {
"m-ahb",
"s-ahb",
};
static const struct geni_se_desc qup_desc = {
.clks = qup_clks,
.num_clks = ARRAY_SIZE(qup_clks),
};
static const struct of_device_id geni_se_dt_match[] = {
{ .compatible = "qcom,geni-se-qup", },
{ .compatible = "qcom,geni-se-qup", .data = &qup_desc },
{}
};
MODULE_DEVICE_TABLE(of, geni_se_dt_match);

View File

@@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/soc/qcom/geni-se.h>
#include <linux/spi/spi.h>
#include <linux/spinlock.h>
@@ -52,6 +53,9 @@
#define SPI_CS_CLK_DELAY_MSK GENMASK(19, 10)
#define SPI_CS_CLK_DELAY_SHFT 10
#define SE_SPI_SLAVE_EN (0x2BC)
#define SPI_SLAVE_EN BIT(0)
/* M_CMD OP codes for SPI */
#define SPI_TX_ONLY 1
#define SPI_RX_ONLY 2
@@ -87,6 +91,8 @@ struct spi_geni_master {
struct completion cs_done;
struct completion cancel_done;
struct completion abort_done;
struct completion tx_reset_done;
struct completion rx_reset_done;
unsigned int oversampling;
spinlock_t lock;
int irq;
@@ -97,6 +103,16 @@ struct spi_geni_master {
int cur_xfer_mode;
};
static void spi_slv_setup(struct spi_geni_master *mas)
{
struct geni_se *se = &mas->se;
writel(SPI_SLAVE_EN, se->base + SE_SPI_SLAVE_EN);
writel(GENI_IO_MUX_0_EN, se->base + GENI_OUTPUT_CTRL);
writel(START_TRIGGER, se->base + SE_GENI_CFG_SEQ_START);
dev_dbg(mas->dev, "spi slave setup done\n");
}
static int get_spi_clk_cfg(unsigned int speed_hz,
struct spi_geni_master *mas,
unsigned int *clk_idx,
@@ -129,23 +145,37 @@ static int get_spi_clk_cfg(unsigned int speed_hz,
return ret;
}
static void handle_fifo_timeout(struct spi_master *spi,
static void handle_se_timeout(struct spi_master *spi,
struct spi_message *msg)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
unsigned long time_left;
struct geni_se *se = &mas->se;
const struct spi_transfer *xfer;
spin_lock_irq(&mas->lock);
reinit_completion(&mas->cancel_done);
writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
if (mas->cur_xfer_mode == GENI_SE_FIFO)
writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
xfer = mas->cur_xfer;
mas->cur_xfer = NULL;
if (spi->slave) {
/*
* skip CMD Cancel sequnece since spi slave
* doesn`t support CMD Cancel sequnece
*/
spin_unlock_irq(&mas->lock);
goto reset_if_dma;
}
reinit_completion(&mas->cancel_done);
geni_se_cancel_m_cmd(se);
spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->cancel_done, HZ);
if (time_left)
return;
goto reset_if_dma;
spin_lock_irq(&mas->lock);
reinit_completion(&mas->abort_done);
@@ -162,6 +192,37 @@ static void handle_fifo_timeout(struct spi_master *spi,
*/
mas->abort_failed = true;
}
reset_if_dma:
if (mas->cur_xfer_mode == GENI_SE_DMA) {
if (xfer) {
if (xfer->tx_buf) {
spin_lock_irq(&mas->lock);
reinit_completion(&mas->tx_reset_done);
writel(1, se->base + SE_DMA_TX_FSM_RST);
spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->tx_reset_done, HZ);
if (!time_left)
dev_err(mas->dev, "DMA TX RESET failed\n");
}
if (xfer->rx_buf) {
spin_lock_irq(&mas->lock);
reinit_completion(&mas->rx_reset_done);
writel(1, se->base + SE_DMA_RX_FSM_RST);
spin_unlock_irq(&mas->lock);
time_left = wait_for_completion_timeout(&mas->rx_reset_done, HZ);
if (!time_left)
dev_err(mas->dev, "DMA RX RESET failed\n");
}
} else {
/*
* This can happen if a timeout happened and we had to wait
* for lock in this function because isr was holding the lock
* and handling transfer completion at that time.
*/
dev_warn(mas->dev, "Cancel/Abort on completed SPI transfer\n");
}
}
}
static void handle_gpi_timeout(struct spi_master *spi, struct spi_message *msg)
@@ -178,7 +239,8 @@ static void spi_geni_handle_err(struct spi_master *spi, struct spi_message *msg)
switch (mas->cur_xfer_mode) {
case GENI_SE_FIFO:
handle_fifo_timeout(spi, msg);
case GENI_SE_DMA:
handle_se_timeout(spi, msg);
break;
case GENI_GPI_DMA:
handle_gpi_timeout(spi, msg);
@@ -250,6 +312,10 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
}
mas->cs_flag = set_flag;
/* set xfer_mode to FIFO to complete cs_done in isr */
mas->cur_xfer_mode = GENI_SE_FIFO;
geni_se_select_mode(se, mas->cur_xfer_mode);
reinit_completion(&mas->cs_done);
if (set_flag)
geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0);
@@ -260,7 +326,7 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
time_left = wait_for_completion_timeout(&mas->cs_done, HZ);
if (!time_left) {
dev_warn(mas->dev, "Timeout setting chip select\n");
handle_fifo_timeout(spi, NULL);
handle_se_timeout(spi, NULL);
}
exit:
@@ -477,13 +543,40 @@ static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas
return 1;
}
static u32 get_xfer_len_in_words(struct spi_transfer *xfer,
struct spi_geni_master *mas)
{
u32 len;
if (!(mas->cur_bits_per_word % MIN_WORD_LEN))
len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word;
else
len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1);
len &= TRANS_LEN_MSK;
return len;
}
static bool geni_can_dma(struct spi_controller *ctlr,
struct spi_device *slv, struct spi_transfer *xfer)
{
struct spi_geni_master *mas = spi_master_get_devdata(slv->master);
u32 len, fifo_size;
/* check if dma is supported */
return mas->cur_xfer_mode != GENI_SE_FIFO;
if (mas->cur_xfer_mode == GENI_GPI_DMA)
return true;
/* Set SE DMA mode for SPI slave. */
if (ctlr->slave)
return true;
len = get_xfer_len_in_words(xfer, mas);
fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word;
if (len > fifo_size)
return true;
else
return false;
}
static int spi_geni_prepare_message(struct spi_master *spi,
@@ -494,6 +587,7 @@ static int spi_geni_prepare_message(struct spi_master *spi,
switch (mas->cur_xfer_mode) {
case GENI_SE_FIFO:
case GENI_SE_DMA:
if (spi_geni_is_abort_still_pending(mas))
return -EBUSY;
ret = setup_fifo_params(spi_msg->spi, spi);
@@ -553,6 +647,7 @@ static void spi_geni_release_dma_chan(struct spi_geni_master *mas)
static int spi_geni_init(struct spi_geni_master *mas)
{
struct spi_master *spi = dev_get_drvdata(mas->dev);
struct geni_se *se = &mas->se;
unsigned int proto, major, minor, ver;
u32 spi_tx_cfg, fifo_disable;
@@ -561,7 +656,14 @@ static int spi_geni_init(struct spi_geni_master *mas)
pm_runtime_get_sync(mas->dev);
proto = geni_se_read_proto(se);
if (proto != GENI_SE_SPI) {
if (spi->slave) {
if (proto != GENI_SE_SPI_SLAVE) {
dev_err(mas->dev, "Invalid proto %d\n", proto);
goto out_pm;
}
spi_slv_setup(mas);
} else if (proto != GENI_SE_SPI) {
dev_err(mas->dev, "Invalid proto %d\n", proto);
goto out_pm;
}
@@ -599,7 +701,7 @@ static int spi_geni_init(struct spi_geni_master *mas)
goto out_pm;
}
/*
* in case of failure to get dma channel, we can still do the
* in case of failure to get gpi dma channel, we can still do the
* FIFO mode, so fallthrough
*/
dev_warn(mas->dev, "FIFO mode disabled, but couldn't get DMA, fall back to FIFO mode\n");
@@ -613,9 +715,11 @@ static int spi_geni_init(struct spi_geni_master *mas)
}
/* We always control CS manually */
spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG);
spi_tx_cfg &= ~CS_TOGGLE;
writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG);
if (!spi->slave) {
spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG);
spi_tx_cfg &= ~CS_TOGGLE;
writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG);
}
out_pm:
pm_runtime_put(mas->dev);
@@ -718,7 +822,7 @@ static void geni_spi_handle_rx(struct spi_geni_master *mas)
mas->rx_rem_bytes -= rx_bytes;
}
static void setup_fifo_xfer(struct spi_transfer *xfer,
static int setup_se_xfer(struct spi_transfer *xfer,
struct spi_geni_master *mas,
u16 mode, struct spi_master *spi)
{
@@ -750,16 +854,12 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
/* Speed and bits per word can be overridden per transfer */
ret = geni_spi_set_clock_and_bw(mas, xfer->speed_hz);
if (ret)
return;
return ret;
mas->tx_rem_bytes = 0;
mas->rx_rem_bytes = 0;
if (!(mas->cur_bits_per_word % MIN_WORD_LEN))
len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word;
else
len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1);
len &= TRANS_LEN_MSK;
len = get_xfer_len_in_words(xfer, mas);
mas->cur_xfer = xfer;
if (xfer->tx_buf) {
@@ -774,17 +874,43 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
mas->rx_rem_bytes = xfer->len;
}
/*
* Select DMA mode if sgt are present; and with only 1 entry
* This is not a serious limitation because the xfer buffers are
* expected to fit into in 1 entry almost always, and if any
* doesn't for any reason we fall back to FIFO mode anyway
*/
if (!xfer->tx_sg.nents && !xfer->rx_sg.nents)
mas->cur_xfer_mode = GENI_SE_FIFO;
else if (xfer->tx_sg.nents > 1 || xfer->rx_sg.nents > 1) {
dev_warn_once(mas->dev, "Doing FIFO, cannot handle tx_nents-%d, rx_nents-%d\n",
xfer->tx_sg.nents, xfer->rx_sg.nents);
mas->cur_xfer_mode = GENI_SE_FIFO;
} else
mas->cur_xfer_mode = GENI_SE_DMA;
geni_se_select_mode(se, mas->cur_xfer_mode);
/*
* Lock around right before we start the transfer since our
* interrupt could come in at any time now.
*/
spin_lock_irq(&mas->lock);
geni_se_setup_m_cmd(se, m_cmd, FRAGMENTATION);
if (m_cmd & SPI_TX_ONLY) {
if (mas->cur_xfer_mode == GENI_SE_DMA) {
if (m_cmd & SPI_RX_ONLY)
geni_se_rx_init_dma(se, sg_dma_address(xfer->rx_sg.sgl),
sg_dma_len(xfer->rx_sg.sgl));
if (m_cmd & SPI_TX_ONLY)
geni_se_tx_init_dma(se, sg_dma_address(xfer->tx_sg.sgl),
sg_dma_len(xfer->tx_sg.sgl));
} else if (m_cmd & SPI_TX_ONLY) {
if (geni_spi_handle_tx(mas))
writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG);
}
spin_unlock_irq(&mas->lock);
return ret;
}
static int spi_geni_transfer_one(struct spi_master *spi,
@@ -792,6 +918,7 @@ static int spi_geni_transfer_one(struct spi_master *spi,
struct spi_transfer *xfer)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
int ret;
if (spi_geni_is_abort_still_pending(mas))
return -EBUSY;
@@ -800,9 +927,12 @@ static int spi_geni_transfer_one(struct spi_master *spi,
if (!xfer->len)
return 0;
if (mas->cur_xfer_mode == GENI_SE_FIFO) {
setup_fifo_xfer(xfer, mas, slv->mode, spi);
return 1;
if (mas->cur_xfer_mode == GENI_SE_FIFO || mas->cur_xfer_mode == GENI_SE_DMA) {
ret = setup_se_xfer(xfer, mas, slv->mode, spi);
/* SPI framework expects +ve ret code to wait for transfer complete */
if (!ret)
ret = 1;
return ret;
}
return setup_gsi_xfer(xfer, mas, slv, spi);
}
@@ -825,39 +955,62 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
spin_lock(&mas->lock);
if ((m_irq & M_RX_FIFO_WATERMARK_EN) || (m_irq & M_RX_FIFO_LAST_EN))
geni_spi_handle_rx(mas);
if (mas->cur_xfer_mode == GENI_SE_FIFO) {
if ((m_irq & M_RX_FIFO_WATERMARK_EN) || (m_irq & M_RX_FIFO_LAST_EN))
geni_spi_handle_rx(mas);
if (m_irq & M_TX_FIFO_WATERMARK_EN)
geni_spi_handle_tx(mas);
if (m_irq & M_TX_FIFO_WATERMARK_EN)
geni_spi_handle_tx(mas);
if (m_irq & M_CMD_DONE_EN) {
if (mas->cur_xfer) {
if (m_irq & M_CMD_DONE_EN) {
if (mas->cur_xfer) {
spi_finalize_current_transfer(spi);
mas->cur_xfer = NULL;
/*
* If this happens, then a CMD_DONE came before all the
* Tx buffer bytes were sent out. This is unusual, log
* this condition and disable the WM interrupt to
* prevent the system from stalling due an interrupt
* storm.
*
* If this happens when all Rx bytes haven't been
* received, log the condition. The only known time
* this can happen is if bits_per_word != 8 and some
* registers that expect xfer lengths in num spi_words
* weren't written correctly.
*/
if (mas->tx_rem_bytes) {
writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
dev_err(mas->dev, "Premature done. tx_rem = %d bpw%d\n",
mas->tx_rem_bytes, mas->cur_bits_per_word);
}
if (mas->rx_rem_bytes)
dev_err(mas->dev, "Premature done. rx_rem = %d bpw%d\n",
mas->rx_rem_bytes, mas->cur_bits_per_word);
} else {
complete(&mas->cs_done);
}
}
} else if (mas->cur_xfer_mode == GENI_SE_DMA) {
const struct spi_transfer *xfer = mas->cur_xfer;
u32 dma_tx_status = readl_relaxed(se->base + SE_DMA_TX_IRQ_STAT);
u32 dma_rx_status = readl_relaxed(se->base + SE_DMA_RX_IRQ_STAT);
if (dma_tx_status)
writel(dma_tx_status, se->base + SE_DMA_TX_IRQ_CLR);
if (dma_rx_status)
writel(dma_rx_status, se->base + SE_DMA_RX_IRQ_CLR);
if (dma_tx_status & TX_DMA_DONE)
mas->tx_rem_bytes = 0;
if (dma_rx_status & RX_DMA_DONE)
mas->rx_rem_bytes = 0;
if (dma_tx_status & TX_RESET_DONE)
complete(&mas->tx_reset_done);
if (dma_rx_status & RX_RESET_DONE)
complete(&mas->rx_reset_done);
if (!mas->tx_rem_bytes && !mas->rx_rem_bytes && xfer) {
spi_finalize_current_transfer(spi);
mas->cur_xfer = NULL;
/*
* If this happens, then a CMD_DONE came before all the
* Tx buffer bytes were sent out. This is unusual, log
* this condition and disable the WM interrupt to
* prevent the system from stalling due an interrupt
* storm.
*
* If this happens when all Rx bytes haven't been
* received, log the condition. The only known time
* this can happen is if bits_per_word != 8 and some
* registers that expect xfer lengths in num spi_words
* weren't written correctly.
*/
if (mas->tx_rem_bytes) {
writel(0, se->base + SE_GENI_TX_WATERMARK_REG);
dev_err(mas->dev, "Premature done. tx_rem = %d bpw%d\n",
mas->tx_rem_bytes, mas->cur_bits_per_word);
}
if (mas->rx_rem_bytes)
dev_err(mas->dev, "Premature done. rx_rem = %d bpw%d\n",
mas->rx_rem_bytes, mas->cur_bits_per_word);
} else {
complete(&mas->cs_done);
}
}
@@ -940,6 +1093,7 @@ static int spi_geni_probe(struct platform_device *pdev)
spi->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
spi->num_chipselect = 4;
spi->max_speed_hz = 50000000;
spi->max_dma_len = 0xffff0; /* 24 bits for tx/rx dma length */
spi->prepare_message = spi_geni_prepare_message;
spi->transfer_one = spi_geni_transfer_one;
spi->can_dma = geni_can_dma;
@@ -951,6 +1105,8 @@ static int spi_geni_probe(struct platform_device *pdev)
init_completion(&mas->cs_done);
init_completion(&mas->cancel_done);
init_completion(&mas->abort_done);
init_completion(&mas->tx_reset_done);
init_completion(&mas->rx_reset_done);
spin_lock_init(&mas->lock);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 250);
@@ -958,6 +1114,9 @@ static int spi_geni_probe(struct platform_device *pdev)
if (ret)
return ret;
if (device_property_read_bool(&pdev->dev, "spi-slave"))
spi->slave = true;
ret = geni_icc_get(&mas->se, NULL);
if (ret)
return ret;
@@ -978,7 +1137,7 @@ static int spi_geni_probe(struct platform_device *pdev)
* for dma (gsi) mode, the gsi will set cs based on params passed in
* TRE
*/
if (mas->cur_xfer_mode == GENI_SE_FIFO)
if (!spi->slave && mas->cur_xfer_mode == GENI_SE_FIFO)
spi->set_cs = spi_geni_set_cs;
/*

File diff suppressed because it is too large Load Diff

View File

@@ -510,7 +510,7 @@ int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag)
struct scsi_cmnd *cmd = lrbp->cmd;
struct ufs_hw_queue *hwq;
void __iomem *reg, *opr_sqd_base;
u32 nexus, id, val;
u32 nexus, id, val, rtc;
int err;
if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC)
@@ -540,17 +540,18 @@ int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag)
opr_sqd_base = mcq_opr_base(hba, OPR_SQD, id);
writel(nexus, opr_sqd_base + REG_SQCTI);
/* SQRTCy.ICU = 1 */
writel(SQ_ICU, opr_sqd_base + REG_SQRTC);
/* Initiate Cleanup */
writel(readl(opr_sqd_base + REG_SQRTC) | SQ_ICU,
opr_sqd_base + REG_SQRTC);
/* Poll SQRTSy.CUS = 1. Return result from SQRTSy.RTC */
reg = opr_sqd_base + REG_SQRTS;
err = read_poll_timeout(readl, val, val & SQ_CUS, 20,
MCQ_POLL_US, false, reg);
if (err)
dev_err(hba->dev, "%s: failed. hwq=%d, tag=%d err=%ld\n",
__func__, id, task_tag,
FIELD_GET(SQ_ICU_ERR_CODE_MASK, readl(reg)));
rtc = FIELD_GET(SQ_ICU_ERR_CODE_MASK, readl(reg));
if (err || rtc)
dev_err(hba->dev, "%s: failed. hwq=%d, tag=%d err=%d RTC=%d\n",
__func__, id, task_tag, err, rtc);
if (ufshcd_mcq_sq_start(hba, hwq))
err = -ETIMEDOUT;

View File

@@ -54,8 +54,10 @@
/* UIC command timeout, unit: ms */
#define UIC_CMD_TIMEOUT 500
enum {
UIC_CMD_TIMEOUT_DEFAULT = 500,
UIC_CMD_TIMEOUT_MAX = 2000,
};
/* NOP OUT retries waiting for NOP IN response */
#define NOP_OUT_RETRIES 10
/* Timeout after 50 msecs if NOP OUT hangs without response */
@@ -129,6 +131,23 @@ static const struct kernel_param_ops mcq_mode_ops = {
module_param_cb(use_mcq_mode, &mcq_mode_ops, &use_mcq_mode, 0644);
MODULE_PARM_DESC(use_mcq_mode, "Control MCQ mode for controllers starting from UFSHCI 4.0. 1 - enable MCQ, 0 - disable MCQ. MCQ is enabled by default");
static unsigned int uic_cmd_timeout = UIC_CMD_TIMEOUT_DEFAULT;
static int uic_cmd_timeout_set(const char *val, const struct kernel_param *kp)
{
return param_set_uint_minmax(val, kp, UIC_CMD_TIMEOUT_DEFAULT,
UIC_CMD_TIMEOUT_MAX);
}
static const struct kernel_param_ops uic_cmd_timeout_ops = {
.set = uic_cmd_timeout_set,
.get = param_get_uint,
};
module_param_cb(uic_cmd_timeout, &uic_cmd_timeout_ops, &uic_cmd_timeout, 0644);
MODULE_PARM_DESC(uic_cmd_timeout,
"UFS UIC command timeout in milliseconds. Defaults to 500ms. Supported values range from 500ms to 2 seconds inclusively");
#define ufshcd_toggle_vreg(_dev, _vreg, _on) \
({ \
int _ret; \
@@ -2380,7 +2399,7 @@ static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
{
u32 val;
int ret = read_poll_timeout(ufshcd_readl, val, val & UIC_COMMAND_READY,
500, UIC_CMD_TIMEOUT * 1000, false, hba,
500, uic_cmd_timeout * 1000, false, hba,
REG_CONTROLLER_STATUS);
return ret == 0 ? true : false;
}
@@ -2439,7 +2458,7 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
lockdep_assert_held(&hba->uic_cmd_mutex);
if (wait_for_completion_timeout(&uic_cmd->done,
msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
msecs_to_jiffies(uic_cmd_timeout))) {
ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
} else {
ret = -ETIMEDOUT;
@@ -4257,7 +4276,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
}
if (!wait_for_completion_timeout(hba->uic_async_done,
msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
msecs_to_jiffies(uic_cmd_timeout))) {
dev_err(hba->dev,
"pwr ctrl cmd 0x%x with mode 0x%x completion timeout\n",
cmd->command, cmd->argument3);
@@ -5401,10 +5420,12 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
}
break;
case OCS_ABORTED:
result |= DID_ABORT << 16;
break;
case OCS_INVALID_COMMAND_STATUS:
result |= DID_REQUEUE << 16;
dev_warn(hba->dev,
"OCS %s from controller for tag %d\n",
(ocs == OCS_ABORTED? "aborted" : "invalid"),
lrbp->task_tag);
break;
case OCS_INVALID_CMD_TABLE_ATTR:
case OCS_INVALID_PRDT_ATTR:
@@ -6477,9 +6498,6 @@ static bool ufshcd_abort_all(struct ufs_hba *hba)
if (is_mcq_enabled(hba)) {
struct ufshcd_lrb *lrbp;
int tag;
struct ufs_hw_queue *hwq;
unsigned long flags;
for (tag = 0; tag < hba->nutrs; tag++) {
lrbp = &hba->lrb[tag];
@@ -6493,13 +6511,6 @@ static bool ufshcd_abort_all(struct ufs_hba *hba)
needs_reset = true;
goto out;
}
hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd));
if (!hwq)
return 0;
spin_lock_irqsave(&hwq->cq_lock, flags);
if (ufshcd_cmd_inflight(lrbp->cmd))
ufshcd_release_scsi_cmd(hba, lrbp);
spin_unlock_irqrestore(&hwq->cq_lock, flags);
}
} else {
/* Clear pending transfer requests */
@@ -10269,9 +10280,6 @@ int ufshcd_system_restore(struct device *dev)
*/
ufshcd_readl(hba, REG_UTP_TASK_REQ_LIST_BASE_H);
/* Resuming from hibernate, assume that link was OFF */
ufshcd_set_link_off(hba);
return 0;
}

View File

@@ -172,7 +172,7 @@ static struct usb_ss_ep_comp_descriptor acc_superspeedplus_comp_desc = {
/* the following 2 values can be tweaked if necessary */
.bMaxBurst = 6,
/* .bmAttributes = 0, */
.bmAttributes = 16,
};
static struct usb_endpoint_descriptor acc_superspeed_in_desc = {
@@ -197,7 +197,7 @@ static struct usb_ss_ep_comp_descriptor acc_superspeed_comp_desc = {
/* the following 2 values can be tweaked if necessary */
.bMaxBurst = 6,
/* .bmAttributes = 0, */
.bmAttributes = 16,
};
static struct usb_endpoint_descriptor acc_highspeed_in_desc = {

View File

@@ -1691,6 +1691,14 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic);
cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
/* If CMD ring stopped we own the trbs between enqueue and dequeue */
if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) {
complete_all(&xhci->cmd_ring_stop_completion);
return;
}
cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
cmd_trb);
/*
@@ -1707,14 +1715,6 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
cancel_delayed_work(&xhci->cmd_timer);
cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
/* If CMD ring stopped we own the trbs between enqueue and dequeue */
if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) {
complete_all(&xhci->cmd_ring_stop_completion);
return;
}
if (cmd->command_trb != xhci->cmd_ring->dequeue) {
xhci_err(xhci,
"Command completion event does not match command\n");

View File

@@ -4935,7 +4935,6 @@ static void run_state_machine(struct tcpm_port *port)
break;
case PORT_RESET:
tcpm_reset_port(port);
port->pd_events = 0;
tcpm_set_cc(port, TYPEC_CC_OPEN);
tcpm_set_state(port, PORT_RESET_WAIT_OFF,
PD_T_ERROR_RECOVERY);

View File

@@ -1485,13 +1485,17 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
old_blkaddr = dn->data_blkaddr;
f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr,
&sum, seg_type, NULL);
err = f2fs_allocate_data_block(sbi, NULL, old_blkaddr,
&dn->data_blkaddr, &sum, seg_type, NULL);
if (err)
return err;
if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) {
invalidate_mapping_pages(META_MAPPING(sbi),
old_blkaddr, old_blkaddr);
f2fs_invalidate_compress_page(sbi, old_blkaddr);
}
f2fs_update_data_blkaddr(dn, dn->data_blkaddr);
return 0;
}
@@ -2668,7 +2672,7 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio)
return true;
if (IS_NOQUOTA(inode))
return true;
if (f2fs_is_atomic_file(inode))
if (f2fs_used_in_atomic_write(inode))
return true;
/* swap file is migrating in aligned write mode */
@@ -2707,10 +2711,13 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
struct dnode_of_data dn;
struct node_info ni;
bool ipu_force = false;
bool atomic_commit;
int err = 0;
/* Use COW inode to make dnode_of_data for atomic write */
if (f2fs_is_atomic_file(inode))
atomic_commit = f2fs_is_atomic_file(inode) &&
page_private_atomic(fio->page);
if (atomic_commit)
set_new_dnode(&dn, F2FS_I(inode)->cow_inode, NULL, NULL, 0);
else
set_new_dnode(&dn, inode, NULL, NULL, 0);
@@ -2756,7 +2763,7 @@ got_it:
}
/* wait for GCed page writeback via META_MAPPING */
if (fio->post_read)
if (fio->meta_gc)
f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);
/*
@@ -2814,6 +2821,8 @@ got_it:
f2fs_outplace_write_data(&dn, fio);
trace_f2fs_do_write_data_page(page, OPU);
set_inode_flag(inode, FI_APPEND_WRITE);
if (atomic_commit)
clear_page_private_atomic(page);
out_writepage:
f2fs_put_dnode(&dn);
out:
@@ -2852,7 +2861,7 @@ int f2fs_write_single_data_page(struct page *page, int *submitted,
.submitted = 0,
.compr_blocks = compr_blocks,
.need_lock = compr_blocks ? LOCK_DONE : LOCK_RETRY,
.post_read = f2fs_post_read_required(inode) ? 1 : 0,
.meta_gc = f2fs_meta_inode_gc_required(inode) ? 1 : 0,
.io_type = io_type,
.io_wbc = wbc,
.bio = bio,
@@ -3734,6 +3743,9 @@ static int f2fs_write_end(struct file *file,
set_page_dirty(page);
if (f2fs_is_atomic_file(inode))
set_page_private_atomic(page);
if (pos + copied > i_size_read(inode) &&
!f2fs_verity_in_progress(inode)) {
f2fs_i_size_write(inode, pos + copied);

View File

@@ -839,7 +839,11 @@ struct f2fs_inode_info {
struct task_struct *atomic_write_task; /* store atomic write task */
struct extent_tree *extent_tree[NR_EXTENT_CACHES];
/* cached extent_tree entry */
struct inode *cow_inode; /* copy-on-write inode for atomic write */
union {
struct inode *cow_inode; /* copy-on-write inode for atomic write */
struct inode *atomic_inode;
/* point to atomic_inode, available only for cow_inode */
};
/* avoid racing between foreground op and gc */
struct f2fs_rwsem i_gc_rwsem[2];
@@ -1207,7 +1211,7 @@ struct f2fs_io_info {
unsigned int is_por:1; /* indicate IO is from recovery or not */
unsigned int retry:1; /* need to reallocate block address */
unsigned int encrypted:1; /* indicate file is encrypted */
unsigned int post_read:1; /* require post read */
unsigned int meta_gc:1; /* require meta inode GC */
enum iostat_type io_type; /* io type */
struct writeback_control *io_wbc; /* writeback control */
struct bio **bio; /* bio for ipu */
@@ -1397,7 +1401,8 @@ static inline void f2fs_clear_bit(unsigned int nr, char *addr);
* bit 2 PAGE_PRIVATE_ONGOING_MIGRATION
* bit 3 PAGE_PRIVATE_INLINE_INODE
* bit 4 PAGE_PRIVATE_REF_RESOURCE
* bit 5- f2fs private data
* bit 5 PAGE_PRIVATE_ATOMIC_WRITE
* bit 6- f2fs private data
*
* Layout B: lowest bit should be 0
* page.private is a wrapped pointer.
@@ -1408,6 +1413,7 @@ enum {
PAGE_PRIVATE_ONGOING_MIGRATION, /* data page which is on-going migrating */
PAGE_PRIVATE_INLINE_INODE, /* inode page contains inline data */
PAGE_PRIVATE_REF_RESOURCE, /* dirty page has referenced resources */
PAGE_PRIVATE_ATOMIC_WRITE, /* data page from atomic write path */
PAGE_PRIVATE_MAX
};
@@ -2346,16 +2352,19 @@ PAGE_PRIVATE_GET_FUNC(nonpointer, NOT_POINTER);
PAGE_PRIVATE_GET_FUNC(inline, INLINE_INODE);
PAGE_PRIVATE_GET_FUNC(gcing, ONGOING_MIGRATION);
PAGE_PRIVATE_GET_FUNC(dummy, DUMMY_WRITE);
PAGE_PRIVATE_GET_FUNC(atomic, ATOMIC_WRITE);
PAGE_PRIVATE_SET_FUNC(reference, REF_RESOURCE);
PAGE_PRIVATE_SET_FUNC(inline, INLINE_INODE);
PAGE_PRIVATE_SET_FUNC(gcing, ONGOING_MIGRATION);
PAGE_PRIVATE_SET_FUNC(dummy, DUMMY_WRITE);
PAGE_PRIVATE_SET_FUNC(atomic, ATOMIC_WRITE);
PAGE_PRIVATE_CLEAR_FUNC(reference, REF_RESOURCE);
PAGE_PRIVATE_CLEAR_FUNC(inline, INLINE_INODE);
PAGE_PRIVATE_CLEAR_FUNC(gcing, ONGOING_MIGRATION);
PAGE_PRIVATE_CLEAR_FUNC(dummy, DUMMY_WRITE);
PAGE_PRIVATE_CLEAR_FUNC(atomic, ATOMIC_WRITE);
static inline unsigned long get_page_private_data(struct page *page)
{
@@ -2387,6 +2396,7 @@ static inline void clear_page_private_all(struct page *page)
clear_page_private_reference(page);
clear_page_private_gcing(page);
clear_page_private_inline(page);
clear_page_private_atomic(page);
f2fs_bug_on(F2FS_P_SB(page), page_private(page));
}
@@ -3667,7 +3677,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
block_t old_addr, block_t new_addr,
unsigned char version, bool recover_curseg,
bool recover_newaddr);
void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
block_t old_blkaddr, block_t *new_blkaddr,
struct f2fs_summary *sum, int type,
struct f2fs_io_info *fio);
@@ -4208,6 +4218,16 @@ static inline bool f2fs_post_read_required(struct inode *inode)
f2fs_compressed_file(inode);
}
static inline bool f2fs_used_in_atomic_write(struct inode *inode)
{
return f2fs_is_atomic_file(inode) || f2fs_is_cow_file(inode);
}
static inline bool f2fs_meta_inode_gc_required(struct inode *inode)
{
return f2fs_post_read_required(inode) || f2fs_used_in_atomic_write(inode);
}
/*
* compress.c
*/

View File

@@ -2095,7 +2095,6 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate)
struct user_namespace *mnt_userns = file_mnt_user_ns(filp);
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct inode *pinode;
loff_t isize;
int ret;
@@ -2144,15 +2143,10 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate)
/* Check if the inode already has a COW inode */
if (fi->cow_inode == NULL) {
/* Create a COW inode for atomic write */
pinode = f2fs_iget(inode->i_sb, fi->i_pino);
if (IS_ERR(pinode)) {
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
ret = PTR_ERR(pinode);
goto out;
}
struct dentry *dentry = file_dentry(filp);
struct inode *dir = d_inode(dentry->d_parent);
ret = f2fs_get_tmpfile(mnt_userns, pinode, &fi->cow_inode);
iput(pinode);
ret = f2fs_get_tmpfile(mnt_userns, dir, &fi->cow_inode);
if (ret) {
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
goto out;
@@ -2160,6 +2154,9 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate)
set_inode_flag(fi->cow_inode, FI_COW_FILE);
clear_inode_flag(fi->cow_inode, FI_INLINE_DATA);
/* Set the COW inode's atomic_inode to the atomic inode */
F2FS_I(fi->cow_inode)->atomic_inode = inode;
} else {
/* Reuse the already created COW inode */
f2fs_bug_on(sbi, get_dirty_pages(fi->cow_inode));
@@ -2297,8 +2294,11 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
case F2FS_GOING_DOWN_METASYNC:
/* do checkpoint only */
ret = f2fs_sync_fs(sb, 1);
if (ret)
if (ret) {
if (ret == -EIO)
ret = 0;
goto out;
}
f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
break;
@@ -2317,6 +2317,8 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
set_sbi_flag(sbi, SBI_IS_DIRTY);
/* do checkpoint only */
ret = f2fs_sync_fs(sb, 1);
if (ret == -EIO)
ret = 0;
goto out;
default:
ret = -EINVAL;

View File

@@ -280,11 +280,10 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
p->max_search > sbi->max_victim_search)
p->max_search = sbi->max_victim_search;
/* let's select beginning hot/small space first in no_heap mode*/
/* let's select beginning hot/small space first. */
if (f2fs_need_rand_seg(sbi))
p->offset = prandom_u32_max(MAIN_SECS(sbi) * sbi->segs_per_sec);
else if (test_opt(sbi, NOHEAP) &&
(type == CURSEG_HOT_DATA || IS_NODESEG(type)))
else if (type == CURSEG_HOT_DATA || IS_NODESEG(type))
p->offset = 0;
else
p->offset = SIT_I(sbi)->last_victim[p->gc_mode];
@@ -1172,7 +1171,8 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
static int ra_data_block(struct inode *inode, pgoff_t index)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct address_space *mapping = inode->i_mapping;
struct address_space *mapping = f2fs_is_cow_file(inode) ?
F2FS_I(inode)->atomic_inode->i_mapping : inode->i_mapping;
struct dnode_of_data dn;
struct page *page;
struct f2fs_io_info fio = {
@@ -1264,6 +1264,8 @@ put_page:
static int move_data_block(struct inode *inode, block_t bidx,
int gc_type, unsigned int segno, int off)
{
struct address_space *mapping = f2fs_is_cow_file(inode) ?
F2FS_I(inode)->atomic_inode->i_mapping : inode->i_mapping;
struct f2fs_io_info fio = {
.sbi = F2FS_I_SB(inode),
.ino = inode->i_ino,
@@ -1287,7 +1289,7 @@ static int move_data_block(struct inode *inode, block_t bidx,
CURSEG_ALL_DATA_ATGC : CURSEG_COLD_DATA;
/* do not read out */
page = f2fs_grab_cache_page(inode->i_mapping, bidx, false);
page = f2fs_grab_cache_page(mapping, bidx, false);
if (!page)
return -ENOMEM;
@@ -1364,8 +1366,13 @@ static int move_data_block(struct inode *inode, block_t bidx,
set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
/* allocate block address */
f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
err = f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
&sum, type, NULL);
if (err) {
f2fs_put_page(mpage, 1);
/* filesystem should shutdown, no need to recovery block */
goto up_out;
}
fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS);
@@ -1586,7 +1593,7 @@ next_step:
start_bidx = f2fs_start_bidx_of_node(nofs, inode) +
ofs_in_node;
if (f2fs_post_read_required(inode)) {
if (f2fs_meta_inode_gc_required(inode)) {
int err = ra_data_block(inode, start_bidx);
f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
@@ -1637,7 +1644,7 @@ next_step:
start_bidx = f2fs_start_bidx_of_node(nofs, inode)
+ ofs_in_node;
if (f2fs_post_read_required(inode))
if (f2fs_meta_inode_gc_required(inode))
err = move_data_block(inode, start_bidx,
gc_type, segno, off);
else
@@ -1645,7 +1652,7 @@ next_step:
segno, off);
if (!err && (gc_type == FG_GC ||
f2fs_post_read_required(inode)))
f2fs_meta_inode_gc_required(inode)))
submitted++;
if (locked) {

View File

@@ -16,7 +16,7 @@
static bool support_inline_data(struct inode *inode)
{
if (f2fs_is_atomic_file(inode))
if (f2fs_used_in_atomic_write(inode))
return false;
if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode))
return false;

View File

@@ -749,8 +749,9 @@ void f2fs_evict_inode(struct inode *inode)
f2fs_abort_atomic_write(inode, true);
if (fi->cow_inode) {
if (fi->cow_inode && f2fs_is_cow_file(fi->cow_inode)) {
clear_inode_flag(fi->cow_inode, FI_COW_FILE);
F2FS_I(fi->cow_inode)->atomic_inode = NULL;
iput(fi->cow_inode);
fi->cow_inode = NULL;
}

View File

@@ -410,6 +410,9 @@ int f2fs_commit_atomic_write(struct inode *inode)
*/
void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
{
if (f2fs_cp_error(sbi))
return;
if (time_to_inject(sbi, FAULT_CHECKPOINT))
f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT);
@@ -2553,18 +2556,17 @@ static int is_next_segment_free(struct f2fs_sb_info *sbi,
* Find a new segment from the free segments bitmap to right order
* This function should be returned with success, otherwise BUG
*/
static void get_new_segment(struct f2fs_sb_info *sbi,
unsigned int *newseg, bool new_sec, int dir)
static int get_new_segment(struct f2fs_sb_info *sbi,
unsigned int *newseg, bool new_sec)
{
struct free_segmap_info *free_i = FREE_I(sbi);
unsigned int segno, secno, zoneno;
unsigned int total_zones = MAIN_SECS(sbi) / sbi->secs_per_zone;
unsigned int hint = GET_SEC_FROM_SEG(sbi, *newseg);
unsigned int old_zoneno = GET_ZONE_FROM_SEG(sbi, *newseg);
unsigned int left_start = hint;
bool init = true;
int go_left = 0;
int i;
int ret = 0;
spin_lock(&free_i->segmap_lock);
@@ -2577,30 +2579,13 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
find_other_zone:
secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint);
if (secno >= MAIN_SECS(sbi)) {
if (dir == ALLOC_RIGHT) {
secno = find_first_zero_bit(free_i->free_secmap,
secno = find_first_zero_bit(free_i->free_secmap,
MAIN_SECS(sbi));
f2fs_bug_on(sbi, secno >= MAIN_SECS(sbi));
} else {
go_left = 1;
left_start = hint - 1;
if (secno >= MAIN_SECS(sbi)) {
ret = -ENOSPC;
goto out_unlock;
}
}
if (go_left == 0)
goto skip_left;
while (test_bit(left_start, free_i->free_secmap)) {
if (left_start > 0) {
left_start--;
continue;
}
left_start = find_first_zero_bit(free_i->free_secmap,
MAIN_SECS(sbi));
f2fs_bug_on(sbi, left_start >= MAIN_SECS(sbi));
break;
}
secno = left_start;
skip_left:
segno = GET_SEG_FROM_SEC(sbi, secno);
zoneno = GET_ZONE_FROM_SEC(sbi, secno);
@@ -2611,21 +2596,13 @@ skip_left:
goto got_it;
if (zoneno == old_zoneno)
goto got_it;
if (dir == ALLOC_LEFT) {
if (!go_left && zoneno + 1 >= total_zones)
goto got_it;
if (go_left && zoneno == 0)
goto got_it;
}
for (i = 0; i < NR_CURSEG_TYPE; i++)
if (CURSEG_I(sbi, i)->zone == zoneno)
break;
if (i < NR_CURSEG_TYPE) {
/* zone is in user, try another */
if (go_left)
hint = zoneno * sbi->secs_per_zone - 1;
else if (zoneno + 1 >= total_zones)
if (zoneno + 1 >= total_zones)
hint = 0;
else
hint = (zoneno + 1) * sbi->secs_per_zone;
@@ -2637,7 +2614,14 @@ got_it:
f2fs_bug_on(sbi, test_bit(segno, free_i->free_segmap));
__set_inuse(sbi, segno);
*newseg = segno;
out_unlock:
spin_unlock(&free_i->segmap_lock);
if (ret) {
f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT);
f2fs_bug_on(sbi, 1);
}
return ret;
}
static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
@@ -2646,6 +2630,10 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
struct summary_footer *sum_footer;
unsigned short seg_type = curseg->seg_type;
/* only happen when get_new_segment() fails */
if (curseg->next_segno == NULL_SEGNO)
return;
curseg->inited = true;
curseg->segno = curseg->next_segno;
curseg->zone = GET_ZONE_FROM_SEG(sbi, curseg->segno);
@@ -2684,8 +2672,7 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
return 0;
if (test_opt(sbi, NOHEAP) &&
(seg_type == CURSEG_HOT_DATA || IS_NODESEG(seg_type)))
if (seg_type == CURSEG_HOT_DATA || IS_NODESEG(seg_type))
return 0;
if (SIT_I(sbi)->last_victim[ALLOC_NEXT])
@@ -2705,21 +2692,16 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
{
struct curseg_info *curseg = CURSEG_I(sbi, type);
unsigned short seg_type = curseg->seg_type;
unsigned int segno = curseg->segno;
int dir = ALLOC_LEFT;
if (curseg->inited)
write_sum_page(sbi, curseg->sum_blk,
GET_SUM_BLOCK(sbi, segno));
if (seg_type == CURSEG_WARM_DATA || seg_type == CURSEG_COLD_DATA)
dir = ALLOC_RIGHT;
if (test_opt(sbi, NOHEAP))
dir = ALLOC_RIGHT;
write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, segno));
segno = __get_next_segno(sbi, type);
get_new_segment(sbi, &segno, new_sec, dir);
if (get_new_segment(sbi, &segno, new_sec)) {
curseg->segno = NULL_SEGNO;
return;
}
curseg->next_segno = segno;
reset_curseg(sbi, type, 1);
curseg->alloc_type = LFS;
@@ -3327,7 +3309,7 @@ static void f2fs_randomize_chunk(struct f2fs_sb_info *sbi,
prandom_u32_max(sbi->max_fragment_hole) + 1;
}
void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
block_t old_blkaddr, block_t *new_blkaddr,
struct f2fs_summary *sum, int type,
struct f2fs_io_info *fio)
@@ -3344,6 +3326,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
mutex_lock(&curseg->curseg_mutex);
down_write(&sit_i->sentry_lock);
if (curseg->segno == NULL_SEGNO)
goto out_err;
if (from_gc) {
f2fs_bug_on(sbi, GET_SEGNO(sbi, old_blkaddr) == NULL_SEGNO);
se = get_seg_entry(sbi, GET_SEGNO(sbi, old_blkaddr));
@@ -3398,6 +3383,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
change_curseg(sbi, type);
stat_inc_seg_type(sbi, curseg);
}
if (curseg->segno == NULL_SEGNO)
goto out_err;
}
/*
* segment dirty status should be updated after segment allocation,
@@ -3433,8 +3421,15 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
}
mutex_unlock(&curseg->curseg_mutex);
f2fs_up_read(&SM_I(sbi)->curseg_lock);
return 0;
out_err:
*new_blkaddr = NULL_ADDR;
up_write(&sit_i->sentry_lock);
mutex_unlock(&curseg->curseg_mutex);
f2fs_up_read(&SM_I(sbi)->curseg_lock);
return -ENOSPC;
}
void f2fs_update_device_state(struct f2fs_sb_info *sbi, nid_t ino,
@@ -3472,8 +3467,17 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
if (keep_order)
f2fs_down_read(&fio->sbi->io_order_lock);
reallocate:
f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
&fio->new_blkaddr, sum, type, fio);
if (f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
&fio->new_blkaddr, sum, type, fio)) {
if (fscrypt_inode_uses_fs_layer_crypto(fio->page->mapping->host))
fscrypt_finalize_bounce_page(&fio->encrypted_page);
if (PageWriteback(fio->page))
end_page_writeback(fio->page);
if (f2fs_in_warm_node_list(fio->sbi, fio->page))
f2fs_del_fsync_node_entry(fio->sbi, fio->page);
goto out;
}
if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO) {
invalidate_mapping_pages(META_MAPPING(fio->sbi),
fio->old_blkaddr, fio->old_blkaddr);
@@ -3488,7 +3492,7 @@ reallocate:
}
f2fs_update_device_state(fio->sbi, fio->ino, fio->new_blkaddr, 1);
out:
if (keep_order)
f2fs_up_read(&fio->sbi->io_order_lock);
}
@@ -3571,7 +3575,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
goto drop_bio;
}
if (fio->post_read)
if (fio->meta_gc)
invalidate_mapping_pages(META_MAPPING(sbi),
fio->new_blkaddr, fio->new_blkaddr);
@@ -3740,7 +3744,7 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr)
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct page *cpage;
if (!f2fs_post_read_required(inode))
if (!f2fs_meta_inode_gc_required(inode))
return;
if (!__is_valid_data_blkaddr(blkaddr))
@@ -3759,7 +3763,7 @@ void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
block_t i;
if (!f2fs_post_read_required(inode))
if (!f2fs_meta_inode_gc_required(inode))
return;
for (i = 0; i < len; i++)

View File

@@ -138,16 +138,6 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
#define SECTOR_TO_BLOCK(sectors) \
((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK)
/*
* indicate a block allocation direction: RIGHT and LEFT.
* RIGHT means allocating new sections towards the end of volume.
* LEFT means the opposite direction.
*/
enum {
ALLOC_RIGHT = 0,
ALLOC_LEFT
};
/*
* In the victim_sel_policy->alloc_mode, there are three block allocation modes.
* LFS writes data sequentially with cleaning operations.

View File

@@ -764,10 +764,8 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
clear_opt(sbi, DISCARD);
break;
case Opt_noheap:
set_opt(sbi, NOHEAP);
break;
case Opt_heap:
clear_opt(sbi, NOHEAP);
f2fs_warn(sbi, "heap/no_heap options were deprecated");
break;
#ifdef CONFIG_F2FS_FS_XATTR
case Opt_user_xattr:
@@ -1980,10 +1978,6 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
} else {
seq_puts(seq, ",nodiscard");
}
if (test_opt(sbi, NOHEAP))
seq_puts(seq, ",no_heap");
else
seq_puts(seq, ",heap");
#ifdef CONFIG_F2FS_FS_XATTR
if (test_opt(sbi, XATTR_USER))
seq_puts(seq, ",user_xattr");
@@ -2141,7 +2135,6 @@ static void default_options(struct f2fs_sb_info *sbi)
set_opt(sbi, INLINE_DATA);
set_opt(sbi, INLINE_DENTRY);
set_opt(sbi, READ_EXTENT_CACHE);
set_opt(sbi, NOHEAP);
clear_opt(sbi, DISABLE_CHECKPOINT);
set_opt(sbi, MERGE_CHECKPOINT);
F2FS_OPTION(sbi).unusable_cap = 0;

View File

@@ -2230,75 +2230,6 @@ static void nfdicf_init(void)
file_fail(fold_name);
}
static void ignore_init(void)
{
FILE *file;
unsigned int unichar;
unsigned int first;
unsigned int last;
unsigned int *um;
int count;
int ret;
if (verbose > 0)
printf("Parsing %s\n", prop_name);
file = fopen(prop_name, "r");
if (!file)
open_fail(prop_name, errno);
assert(file);
count = 0;
while (fgets(line, LINESIZE, file)) {
ret = sscanf(line, "%X..%X ; %s # ", &first, &last, buf0);
if (ret == 3) {
if (strcmp(buf0, "Default_Ignorable_Code_Point"))
continue;
if (!utf32valid(first) || !utf32valid(last))
line_fail(prop_name, line);
for (unichar = first; unichar <= last; unichar++) {
free(unicode_data[unichar].utf32nfdi);
um = malloc(sizeof(unsigned int));
*um = 0;
unicode_data[unichar].utf32nfdi = um;
free(unicode_data[unichar].utf32nfdicf);
um = malloc(sizeof(unsigned int));
*um = 0;
unicode_data[unichar].utf32nfdicf = um;
count++;
}
if (verbose > 1)
printf(" %X..%X Default_Ignorable_Code_Point\n",
first, last);
continue;
}
ret = sscanf(line, "%X ; %s # ", &unichar, buf0);
if (ret == 2) {
if (strcmp(buf0, "Default_Ignorable_Code_Point"))
continue;
if (!utf32valid(unichar))
line_fail(prop_name, line);
free(unicode_data[unichar].utf32nfdi);
um = malloc(sizeof(unsigned int));
*um = 0;
unicode_data[unichar].utf32nfdi = um;
free(unicode_data[unichar].utf32nfdicf);
um = malloc(sizeof(unsigned int));
*um = 0;
unicode_data[unichar].utf32nfdicf = um;
if (verbose > 1)
printf(" %X Default_Ignorable_Code_Point\n",
unichar);
count++;
continue;
}
}
fclose(file);
if (verbose > 0)
printf("Found %d entries\n", count);
if (count == 0)
file_fail(prop_name);
}
static void corrections_init(void)
{
FILE *file;
@@ -3410,7 +3341,6 @@ int main(int argc, char *argv[])
ccc_init();
nfdi_init();
nfdicf_init();
ignore_init();
corrections_init();
hangul_decompose();
nfdi_decompose();

File diff suppressed because it is too large Load Diff

View File

@@ -81,6 +81,7 @@ enum stop_cp_reason {
STOP_CP_REASON_CORRUPTED_SUMMARY,
STOP_CP_REASON_UPDATE_INODE,
STOP_CP_REASON_FLUSH_FAIL,
STOP_CP_REASON_NO_SEGMENT,
STOP_CP_REASON_MAX,
};

View File

@@ -330,6 +330,11 @@ struct io_ring_ctx {
struct list_head io_buffers_pages;
/*
* ANDROID: commit 6e5e6d274956 ("io_uring: drop any code related to
* SCM_RIGHTS") removed this variable, but we add it back to preserve
* the ABI. The field is not used anywhere.
*/
#if defined(CONFIG_UNIX)
struct socket *ring_sock;
#endif

View File

@@ -35,6 +35,7 @@ enum geni_se_protocol_type {
GENI_SE_UART,
GENI_SE_I2C,
GENI_SE_I3C,
GENI_SE_SPI_SLAVE,
};
struct geni_wrapper;
@@ -73,23 +74,29 @@ struct geni_se {
/* Common SE registers */
#define GENI_FORCE_DEFAULT_REG 0x20
#define GENI_OUTPUT_CTRL 0x24
#define SE_GENI_STATUS 0x40
#define GENI_SER_M_CLK_CFG 0x48
#define GENI_SER_S_CLK_CFG 0x4c
#define GENI_IF_DISABLE_RO 0x64
#define GENI_FW_REVISION_RO 0x68
#define SE_GENI_CLK_SEL 0x7c
#define SE_GENI_CFG_SEQ_START 0x84
#define SE_GENI_DMA_MODE_EN 0x258
#define SE_GENI_M_CMD0 0x600
#define SE_GENI_M_CMD_CTRL_REG 0x604
#define SE_GENI_M_IRQ_STATUS 0x610
#define SE_GENI_M_IRQ_EN 0x614
#define SE_GENI_M_IRQ_CLEAR 0x618
#define SE_GENI_M_IRQ_EN_SET 0x61c
#define SE_GENI_M_IRQ_EN_CLEAR 0x620
#define SE_GENI_S_CMD0 0x630
#define SE_GENI_S_CMD_CTRL_REG 0x634
#define SE_GENI_S_IRQ_STATUS 0x640
#define SE_GENI_S_IRQ_EN 0x644
#define SE_GENI_S_IRQ_CLEAR 0x648
#define SE_GENI_S_IRQ_EN_SET 0x64c
#define SE_GENI_S_IRQ_EN_CLEAR 0x650
#define SE_GENI_TX_FIFOn 0x700
#define SE_GENI_RX_FIFOn 0x780
#define SE_GENI_TX_FIFO_STATUS 0x800
@@ -98,11 +105,14 @@ struct geni_se {
#define SE_GENI_RX_WATERMARK_REG 0x810
#define SE_GENI_RX_RFR_WATERMARK_REG 0x814
#define SE_GENI_IOS 0x908
#define SE_GENI_M_GP_LENGTH 0x910
#define SE_GENI_S_GP_LENGTH 0x914
#define SE_DMA_TX_IRQ_STAT 0xc40
#define SE_DMA_TX_IRQ_CLR 0xc44
#define SE_DMA_TX_FSM_RST 0xc58
#define SE_DMA_RX_IRQ_STAT 0xd40
#define SE_DMA_RX_IRQ_CLR 0xd44
#define SE_DMA_RX_LEN_IN 0xd54
#define SE_DMA_RX_FSM_RST 0xd58
#define SE_HW_PARAM_0 0xe24
#define SE_HW_PARAM_1 0xe28
@@ -110,6 +120,9 @@ struct geni_se {
/* GENI_FORCE_DEFAULT_REG fields */
#define FORCE_DEFAULT BIT(0)
/* GENI_OUTPUT_CTRL fields */
#define GENI_IO_MUX_0_EN BIT(0)
/* GENI_STATUS fields */
#define M_GENI_CMD_ACTIVE BIT(0)
#define S_GENI_CMD_ACTIVE BIT(12)
@@ -129,6 +142,9 @@ struct geni_se {
/* GENI_CLK_SEL fields */
#define CLK_SEL_MSK GENMASK(2, 0)
/* SE_GENI_CFG_SEQ_START fields */
#define START_TRIGGER BIT(0)
/* SE_GENI_DMA_MODE_EN */
#define GENI_DMA_MODE_EN BIT(0)
@@ -168,6 +184,7 @@ struct geni_se {
#define M_GP_IRQ_3_EN BIT(12)
#define M_GP_IRQ_4_EN BIT(13)
#define M_GP_IRQ_5_EN BIT(14)
#define M_TX_FIFO_NOT_EMPTY_EN BIT(21)
#define M_IO_DATA_DEASSERT_EN BIT(22)
#define M_IO_DATA_ASSERT_EN BIT(23)
#define M_RX_FIFO_RD_ERR_EN BIT(24)
@@ -223,6 +240,9 @@ struct geni_se {
#define IO2_DATA_IN BIT(1)
#define RX_DATA_IN BIT(0)
/* SE_GENI_M_GP_LENGTH and SE_GENI_S_GP_LENGTH fields */
#define GP_LENGTH GENMASK(31, 0)
/* SE_DMA_TX_IRQ_STAT Register fields */
#define TX_DMA_DONE BIT(0)
#define TX_EOT BIT(1)
@@ -235,6 +255,8 @@ struct geni_se {
#define RX_SBE BIT(2)
#define RX_RESET_DONE BIT(3)
#define RX_FLUSH_DONE BIT(4)
#define RX_DMA_PARITY_ERR BIT(5)
#define RX_DMA_BREAK GENMASK(8, 7)
#define RX_GENI_GP_IRQ GENMASK(10, 5)
#define RX_GENI_CANCEL_IRQ BIT(11)
#define RX_GENI_GP_IRQ_EXT GENMASK(13, 12)
@@ -487,9 +509,13 @@ int geni_se_clk_freq_match(struct geni_se *se, unsigned long req_freq,
unsigned int *index, unsigned long *res_freq,
bool exact);
void geni_se_tx_init_dma(struct geni_se *se, dma_addr_t iova, size_t len);
int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
dma_addr_t *iova);
void geni_se_rx_init_dma(struct geni_se *se, dma_addr_t iova, size_t len);
int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
dma_addr_t *iova);

View File

@@ -282,6 +282,12 @@ DECLARE_HOOK(android_vh_filemap_map_pages,
TP_PROTO(struct file *file, pgoff_t first_pgoff,
pgoff_t last_pgoff, vm_fault_t ret),
TP_ARGS(file, first_pgoff, last_pgoff, ret));
DECLARE_HOOK(android_vh_alloc_flags_cma_adjust,
TP_PROTO(gfp_t gfp_mask, unsigned int *alloc_flags),
TP_ARGS(gfp_mask, alloc_flags));
DECLARE_HOOK(android_vh_rmqueue_cma_fallback,
TP_PROTO(struct zone *zone, unsigned int order, struct page **page),
TP_ARGS(zone, order, page));
#endif /* _TRACE_HOOK_MM_H */
/* This part must be outside protection */

View File

@@ -16,6 +16,7 @@ DECLARE_HOOK(android_vh_ptype_head,
struct nf_conn;
struct sock;
struct net_device;
DECLARE_RESTRICTED_HOOK(android_rvh_nf_conn_alloc,
TP_PROTO(struct nf_conn *nf_conn), TP_ARGS(nf_conn), 1);
DECLARE_RESTRICTED_HOOK(android_rvh_nf_conn_free,
@@ -31,7 +32,10 @@ DECLARE_HOOK(android_vh_netlink_poll,
TP_PROTO(struct file *file, struct socket *sock, poll_table *wait,
__poll_t *mask),
TP_ARGS(file, sock, wait, mask));
DECLARE_HOOK(android_vh_dc_send_copy,
TP_PROTO(struct sk_buff *skb, struct net_device *dev), TP_ARGS(skb, dev));
DECLARE_HOOK(android_vh_dc_receive,
TP_PROTO(struct sk_buff *skb, int *flag), TP_ARGS(skb, flag));
/* macro versions of hooks are no longer required */
#endif /* _TRACE_HOOK_NET_VH_H */

View File

@@ -72,6 +72,9 @@ DECLARE_HOOK(android_vh_do_folio_trylock,
DECLARE_HOOK(android_vh_page_referenced_check_bypass,
TP_PROTO(struct folio *folio, unsigned long nr_to_scan, int lru, bool *bypass),
TP_ARGS(folio, nr_to_scan, lru, bypass));
DECLARE_HOOK(android_vh_should_memcg_bypass,
TP_PROTO(struct mem_cgroup *memcg, int priority, bool *bypass),
TP_ARGS(memcg, priority, bypass));
#endif /* _TRACE_HOOK_VMSCAN_H */
/* This part must be outside protection */
#include <trace/define_trace.h>

View File

@@ -95,12 +95,10 @@ static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file,
needs_switch = true;
}
ret = io_scm_file_account(ctx, file);
if (!ret) {
*io_get_tag_slot(ctx->file_data, slot_index) = 0;
io_fixed_file_set(file_slot, file);
io_file_bitmap_set(&ctx->file_table, slot_index);
}
*io_get_tag_slot(ctx->file_data, slot_index) = 0;
io_fixed_file_set(file_slot, file);
io_file_bitmap_set(&ctx->file_table, slot_index);
return 0;
err:
if (needs_switch)
io_rsrc_node_switch(ctx, ctx->file_data);

View File

@@ -60,7 +60,6 @@
#include <linux/net.h>
#include <net/sock.h>
#include <net/af_unix.h>
#include <net/scm.h>
#include <linux/anon_inodes.h>
#include <linux/sched/mm.h>
#include <linux/uaccess.h>
@@ -2635,12 +2634,6 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
WARN_ON_ONCE(!list_empty(&ctx->rsrc_ref_list));
WARN_ON_ONCE(!llist_empty(&ctx->rsrc_put_llist));
#if defined(CONFIG_UNIX)
if (ctx->ring_sock) {
ctx->ring_sock->file = NULL; /* so that iput() is called */
sock_release(ctx->ring_sock);
}
#endif
WARN_ON_ONCE(!list_empty(&ctx->ltimeout_list));
if (ctx->mm_account) {
@@ -3448,32 +3441,12 @@ static int io_uring_install_fd(struct io_ring_ctx *ctx, struct file *file)
/*
* Allocate an anonymous fd, this is what constitutes the application
* visible backing of an io_uring instance. The application mmaps this
* fd to gain access to the SQ/CQ ring details. If UNIX sockets are enabled,
* we have to tie this fd to a socket for file garbage collection purposes.
* fd to gain access to the SQ/CQ ring details.
*/
static struct file *io_uring_get_file(struct io_ring_ctx *ctx)
{
struct file *file;
#if defined(CONFIG_UNIX)
int ret;
ret = sock_create_kern(&init_net, PF_UNIX, SOCK_RAW, IPPROTO_IP,
&ctx->ring_sock);
if (ret)
return ERR_PTR(ret);
#endif
file = anon_inode_getfile_secure("[io_uring]", &io_uring_fops, ctx,
return anon_inode_getfile_secure("[io_uring]", &io_uring_fops, ctx,
O_RDWR | O_CLOEXEC, NULL);
#if defined(CONFIG_UNIX)
if (IS_ERR(file)) {
sock_release(ctx->ring_sock);
ctx->ring_sock = NULL;
} else {
ctx->ring_sock->file = file;
}
#endif
return file;
}
static __cold int io_uring_create(unsigned entries, struct io_uring_params *p,

View File

@@ -494,11 +494,6 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
err = -EBADF;
break;
}
err = io_scm_file_account(ctx, file);
if (err) {
fput(file);
break;
}
*io_get_tag_slot(data, i) = tag;
io_fixed_file_set(file_slot, file);
io_file_bitmap_set(&ctx->file_table, i);
@@ -762,22 +757,12 @@ void __io_sqe_files_unregister(struct io_ring_ctx *ctx)
for (i = 0; i < ctx->nr_user_files; i++) {
struct file *file = io_file_from_index(&ctx->file_table, i);
/* skip scm accounted files, they'll be freed by ->ring_sock */
if (!file || io_file_need_scm(file))
if (!file)
continue;
io_file_bitmap_clear(&ctx->file_table, i);
fput(file);
}
#if defined(CONFIG_UNIX)
if (ctx->ring_sock) {
struct sock *sock = ctx->ring_sock->sk;
struct sk_buff *skb;
while ((skb = skb_dequeue(&sock->sk_receive_queue)) != NULL)
kfree_skb(skb);
}
#endif
io_free_file_tables(&ctx->file_table);
io_file_table_set_alloc_range(ctx, 0, 0);
io_rsrc_data_free(ctx->file_data);
@@ -805,134 +790,11 @@ int io_sqe_files_unregister(struct io_ring_ctx *ctx)
return ret;
}
/*
* Ensure the UNIX gc is aware of our file set, so we are certain that
* the io_uring can be safely unregistered on process exit, even if we have
* loops in the file referencing. We account only files that can hold other
* files because otherwise they can't form a loop and so are not interesting
* for GC.
*/
int __io_scm_file_account(struct io_ring_ctx *ctx, struct file *file)
{
#if defined(CONFIG_UNIX)
struct sock *sk = ctx->ring_sock->sk;
struct sk_buff_head *head = &sk->sk_receive_queue;
struct scm_fp_list *fpl;
struct sk_buff *skb;
if (likely(!io_file_need_scm(file)))
return 0;
/*
* See if we can merge this file into an existing skb SCM_RIGHTS
* file set. If there's no room, fall back to allocating a new skb
* and filling it in.
*/
spin_lock_irq(&head->lock);
skb = skb_peek(head);
if (skb && UNIXCB(skb).fp->count < SCM_MAX_FD)
__skb_unlink(skb, head);
else
skb = NULL;
spin_unlock_irq(&head->lock);
if (!skb) {
fpl = kzalloc(sizeof(*fpl), GFP_KERNEL);
if (!fpl)
return -ENOMEM;
skb = alloc_skb(0, GFP_KERNEL);
if (!skb) {
kfree(fpl);
return -ENOMEM;
}
fpl->user = get_uid(current_user());
fpl->max = SCM_MAX_FD;
fpl->count = 0;
UNIXCB(skb).fp = fpl;
skb->sk = sk;
skb->scm_io_uring = 1;
skb->destructor = unix_destruct_scm;
refcount_add(skb->truesize, &sk->sk_wmem_alloc);
}
fpl = UNIXCB(skb).fp;
fpl->fp[fpl->count++] = get_file(file);
unix_inflight(fpl->user, file);
skb_queue_head(head, skb);
fput(file);
#endif
return 0;
}
static void io_rsrc_file_put(struct io_ring_ctx *ctx, struct io_rsrc_put *prsrc)
{
struct file *file = prsrc->file;
#if defined(CONFIG_UNIX)
struct sock *sock = ctx->ring_sock->sk;
struct sk_buff_head list, *head = &sock->sk_receive_queue;
struct sk_buff *skb;
int i;
if (!io_file_need_scm(file)) {
fput(file);
return;
}
__skb_queue_head_init(&list);
/*
* Find the skb that holds this file in its SCM_RIGHTS. When found,
* remove this entry and rearrange the file array.
*/
skb = skb_dequeue(head);
while (skb) {
struct scm_fp_list *fp;
fp = UNIXCB(skb).fp;
for (i = 0; i < fp->count; i++) {
int left;
if (fp->fp[i] != file)
continue;
unix_notinflight(fp->user, fp->fp[i]);
left = fp->count - 1 - i;
if (left) {
memmove(&fp->fp[i], &fp->fp[i + 1],
left * sizeof(struct file *));
}
fp->count--;
if (!fp->count) {
kfree_skb(skb);
skb = NULL;
} else {
__skb_queue_tail(&list, skb);
}
fput(file);
file = NULL;
break;
}
if (!file)
break;
__skb_queue_tail(&list, skb);
skb = skb_dequeue(head);
}
if (skb_peek(&list)) {
spin_lock_irq(&head->lock);
while ((skb = __skb_dequeue(&list)) != NULL)
__skb_queue_tail(head, skb);
spin_unlock_irq(&head->lock);
}
#else
fput(file);
#endif
}
int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
@@ -986,21 +848,12 @@ int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
goto fail;
/*
* Don't allow io_uring instances to be registered. If UNIX
* isn't enabled, then this causes a reference cycle and this
* instance can never get freed. If UNIX is enabled we'll
* handle it just fine, but there's still no point in allowing
* a ring fd as it doesn't support regular read/write anyway.
* Don't allow io_uring instances to be registered.
*/
if (io_is_uring_fops(file)) {
fput(file);
goto fail;
}
ret = io_scm_file_account(ctx, file);
if (ret) {
fput(file);
goto fail;
}
file_slot = io_fixed_file_slot(&ctx->file_table, i);
io_fixed_file_set(file_slot, file);
io_file_bitmap_set(&ctx->file_table, i);

View File

@@ -77,21 +77,6 @@ int io_sqe_files_unregister(struct io_ring_ctx *ctx);
int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
unsigned nr_args, u64 __user *tags);
int __io_scm_file_account(struct io_ring_ctx *ctx, struct file *file);
static inline bool io_file_need_scm(struct file *filp)
{
return false;
}
static inline int io_scm_file_account(struct io_ring_ctx *ctx,
struct file *file)
{
if (likely(!io_file_need_scm(file)))
return 0;
return __io_scm_file_account(ctx, file);
}
int io_register_files_update(struct io_ring_ctx *ctx, void __user *arg,
unsigned nr_args);
int io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg,

View File

@@ -428,7 +428,7 @@ static void coredump_task_exit(struct task_struct *tsk)
complete(&core_state->startup);
for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE|TASK_FREEZABLE);
set_current_state(TASK_IDLE|TASK_FREEZABLE);
if (!self.task) /* see coredump_finish() */
break;
schedule();

View File

@@ -7663,6 +7663,12 @@ static int user_check_sched_setscheduler(struct task_struct *p,
if (p->sched_reset_on_fork && !reset_on_fork)
goto req_priv;
if (!capable(CAP_SYS_NICE)) {
/* Can't change util-clamps */
if (attr->sched_flags & SCHED_FLAG_UTIL_CLAMP)
return -EPERM;
}
return 0;
req_priv:

View File

@@ -3165,6 +3165,12 @@ __rmqueue(struct zone *zone, unsigned int order, int migratetype,
retry:
page = __rmqueue_smallest(zone, order, migratetype);
/*
* let normal GFP_MOVABLE has chance to try MIGRATE_CMA
*/
if (unlikely(!page) && (migratetype == MIGRATE_MOVABLE))
trace_android_vh_rmqueue_cma_fallback(zone, order, &page);
if (unlikely(!page) && __rmqueue_fallback(zone, order, migratetype,
alloc_flags))
goto retry;
@@ -4302,6 +4308,7 @@ static inline unsigned int gfp_to_alloc_flags_cma(gfp_t gfp_mask,
#ifdef CONFIG_CMA
if (gfp_migratetype(gfp_mask) == MIGRATE_MOVABLE && gfp_mask & __GFP_CMA)
alloc_flags |= ALLOC_CMA;
trace_android_vh_alloc_flags_cma_adjust(gfp_mask, &alloc_flags);
#endif
return alloc_flags;
}

View File

@@ -3237,6 +3237,7 @@ DEFINE_STATIC_KEY_ARRAY_TRUE(lru_gen_caps, NR_LRU_GEN_CAPS);
DEFINE_STATIC_KEY_ARRAY_FALSE(lru_gen_caps, NR_LRU_GEN_CAPS);
#define get_cap(cap) static_branch_unlikely(&lru_gen_caps[cap])
#endif
EXPORT_SYMBOL_GPL(lru_gen_caps);
/******************************************************************************
* shorthand helpers
@@ -5480,6 +5481,7 @@ static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc)
struct lru_gen_folio *lrugen = NULL;
struct mem_cgroup *memcg;
const struct hlist_nulls_node *pos;
bool bypass = false;
bin = first_bin = get_random_u32_below(MEMCG_NR_BINS);
restart:
@@ -5506,6 +5508,10 @@ restart:
continue;
}
trace_android_vh_should_memcg_bypass(memcg, sc->priority, &bypass);
if (bypass)
continue;
rcu_read_unlock();
op = shrink_one(lruvec, sc);
@@ -5593,7 +5599,11 @@ static void set_initial_priority(struct pglist_data *pgdat, struct scan_control
/* round down reclaimable and round up sc->nr_to_reclaim */
priority = fls_long(reclaimable) - 1 - fls_long(sc->nr_to_reclaim - 1);
sc->priority = clamp(priority, 0, DEF_PRIORITY);
/*
* The estimation is based on LRU pages only, so cap it to prevent
* overshoots of shrinker objects by large margins.
*/
sc->priority = clamp(priority, DEF_PRIORITY / 2, DEF_PRIORITY);
}
static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *sc)
@@ -7397,6 +7407,7 @@ static bool kswapd_shrink_node(pg_data_t *pgdat,
{
struct zone *zone;
int z;
unsigned long nr_reclaimed = sc->nr_reclaimed;
/* Reclaim a number of pages proportional to the number of zones */
sc->nr_to_reclaim = 0;
@@ -7424,7 +7435,8 @@ static bool kswapd_shrink_node(pg_data_t *pgdat,
if (sc->order && sc->nr_reclaimed >= compact_gap(sc->order))
sc->order = 0;
return sc->nr_scanned >= sc->nr_to_reclaim;
/* account for progress from mm_account_reclaimed_pages() */
return max(sc->nr_scanned, sc->nr_reclaimed - nr_reclaimed) >= sc->nr_to_reclaim;
}
/* Page allocator PCP high watermark is lowered if reclaim is active. */

View File

@@ -195,7 +195,7 @@ static void *pack_shadow(int memcgid, pg_data_t *pgdat, unsigned long eviction,
return xa_mk_value(eviction);
}
static void unpack_shadow(void *shadow, int *memcgidp, pg_data_t **pgdat,
void unpack_shadow(void *shadow, int *memcgidp, pg_data_t **pgdat,
unsigned long *evictionp, bool *workingsetp)
{
unsigned long entry = xa_to_value(shadow);
@@ -214,6 +214,7 @@ static void unpack_shadow(void *shadow, int *memcgidp, pg_data_t **pgdat,
*evictionp = entry;
*workingsetp = workingset;
}
EXPORT_SYMBOL_GPL(unpack_shadow);
#ifdef CONFIG_LRU_GEN

View File

@@ -3632,6 +3632,9 @@ static int xmit_one(struct sk_buff *skb, struct net_device *dev,
len = skb->len;
trace_net_dev_start_xmit(skb, dev);
trace_android_vh_dc_send_copy(skb, dev);
rc = netdev_start_xmit(skb, dev, txq, more);
trace_net_dev_xmit(skb, rc, dev, len);
@@ -5331,6 +5334,7 @@ static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc,
bool deliver_exact = false;
int ret = NET_RX_DROP;
__be16 type;
int flag = 0;
net_timestamp_check(!READ_ONCE(netdev_tstamp_prequeue), skb);
@@ -5350,6 +5354,10 @@ another_round:
__this_cpu_inc(softnet_data.processed);
trace_android_vh_dc_receive(skb, &flag);
if (flag != 0)
return NET_RX_DROP;
if (static_branch_unlikely(&generic_xdp_needed_key)) {
int ret2;

View File

@@ -289,8 +289,26 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
return NULL;
}
if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST)
return __udp_gso_segment_list(gso_skb, features, is_ipv6);
if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST) {
/* Detect modified geometry and pass those to skb_segment. */
if (skb_pagelen(gso_skb) - sizeof(*uh) == skb_shinfo(gso_skb)->gso_size)
return __udp_gso_segment_list(gso_skb, features, is_ipv6);
/* Setup csum, as fraglist skips this in udp4_gro_receive. */
gso_skb->csum_start = skb_transport_header(gso_skb) - gso_skb->head;
gso_skb->csum_offset = offsetof(struct udphdr, check);
gso_skb->ip_summed = CHECKSUM_PARTIAL;
uh = udp_hdr(gso_skb);
if (is_ipv6)
uh->check = ~udp_v6_check(gso_skb->len,
&ipv6_hdr(gso_skb)->saddr,
&ipv6_hdr(gso_skb)->daddr, 0);
else
uh->check = ~udp_v4_check(gso_skb->len,
ip_hdr(gso_skb)->saddr,
ip_hdr(gso_skb)->daddr, 0);
}
skb_pull(gso_skb, sizeof(*uh));

View File

@@ -1044,6 +1044,7 @@ void cfg80211_connect_done(struct net_device *dev,
cfg80211_hold_bss(
bss_from_pub(params->links[link].bss));
ev->cr.links[link].bss = params->links[link].bss;
ev->cr.links[link].status = params->links[link].status;
if (params->links[link].addr) {
ev->cr.links[link].addr = next;