mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 21:59:12 -04:00
Merge 019027da9d on remote branch
Change-Id: I78e4d6c452afdbbfbf2fa8e6b1327bb480304140
This commit is contained in:
commit
ceee9c69b1
34 changed files with 1194 additions and 452 deletions
|
|
@ -1 +1 @@
|
|||
LTS_5.4.226_d72fdcc7094f
|
||||
LTS_5.4.226_2af3bdf29330
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -10,6 +10,7 @@
|
|||
arm64_const_caps_ready
|
||||
bcmp
|
||||
cancel_delayed_work_sync
|
||||
cancel_work_sync
|
||||
capable
|
||||
cfg80211_inform_bss_data
|
||||
cfg80211_put_bss
|
||||
|
|
@ -28,6 +29,7 @@
|
|||
delayed_work_timer_fn
|
||||
destroy_workqueue
|
||||
_dev_err
|
||||
device_create
|
||||
device_register
|
||||
device_unregister
|
||||
_dev_info
|
||||
|
|
@ -39,6 +41,7 @@
|
|||
dma_set_coherent_mask
|
||||
dma_set_mask
|
||||
down_write
|
||||
ether_setup
|
||||
ethtool_op_get_link
|
||||
eth_validate_addr
|
||||
event_triggers_call
|
||||
|
|
@ -60,6 +63,7 @@
|
|||
init_wait_entry
|
||||
__init_waitqueue_head
|
||||
jiffies
|
||||
jiffies_to_msecs
|
||||
kfree
|
||||
kfree_skb
|
||||
__kmalloc
|
||||
|
|
@ -72,6 +76,8 @@
|
|||
kmemdup
|
||||
kstrdup
|
||||
ktime_get
|
||||
ktime_get_with_offset
|
||||
kvfree
|
||||
__list_add_valid
|
||||
__list_del_entry_valid
|
||||
__local_bh_enable_ip
|
||||
|
|
@ -83,6 +89,7 @@
|
|||
__module_get
|
||||
module_layout
|
||||
module_put
|
||||
__msecs_to_jiffies
|
||||
msleep
|
||||
__mutex_init
|
||||
mutex_lock
|
||||
|
|
@ -98,6 +105,7 @@
|
|||
netif_device_detach
|
||||
netif_tx_stop_all_queues
|
||||
netif_tx_wake_queue
|
||||
nf_conntrack_destroy
|
||||
no_llseek
|
||||
nonseekable_open
|
||||
noop_llseek
|
||||
|
|
@ -141,9 +149,8 @@
|
|||
_raw_spin_unlock_irqrestore
|
||||
__rcu_read_lock
|
||||
__rcu_read_unlock
|
||||
refcount_dec_and_test_checked
|
||||
refcount_inc_checked
|
||||
register_netdev
|
||||
refcount_warn_saturate
|
||||
register_netdevice
|
||||
register_netdevice_notifier
|
||||
register_virtio_device
|
||||
register_virtio_driver
|
||||
|
|
@ -158,9 +165,12 @@
|
|||
seq_printf
|
||||
sg_init_one
|
||||
sg_init_table
|
||||
skb_add_rx_frag
|
||||
skb_clone
|
||||
skb_dequeue
|
||||
skb_push
|
||||
skb_put
|
||||
skb_queue_tail
|
||||
sk_free
|
||||
snd_device_new
|
||||
snd_pcm_alt_chmaps
|
||||
|
|
@ -195,8 +205,11 @@
|
|||
unregister_virtio_device
|
||||
unregister_virtio_driver
|
||||
up_write
|
||||
virtio_break_device
|
||||
virtio_check_driver_offered_feature
|
||||
virtio_config_changed
|
||||
virtio_device_freeze
|
||||
virtio_device_restore
|
||||
virtio_max_dma_size
|
||||
virtqueue_add_inbuf
|
||||
virtqueue_add_outbuf
|
||||
|
|
@ -270,10 +283,8 @@
|
|||
hci_register_dev
|
||||
hci_unregister_dev
|
||||
skb_pull
|
||||
skb_push
|
||||
skb_queue_head
|
||||
skb_queue_purge
|
||||
skb_queue_tail
|
||||
|
||||
# required by incrementalfs.ko
|
||||
bin2hex
|
||||
|
|
@ -303,7 +314,6 @@
|
|||
generic_file_read_iter
|
||||
generic_file_splice_read
|
||||
generic_read_dir
|
||||
generic_shutdown_super
|
||||
__get_free_pages
|
||||
get_zeroed_page
|
||||
iget5_locked
|
||||
|
|
@ -315,6 +325,7 @@
|
|||
kernel_read
|
||||
kernel_write
|
||||
kern_path
|
||||
kill_anon_super
|
||||
kobject_create_and_add
|
||||
kobject_put
|
||||
lockref_get
|
||||
|
|
@ -323,7 +334,6 @@
|
|||
LZ4_decompress_safe
|
||||
match_int
|
||||
match_token
|
||||
__msecs_to_jiffies
|
||||
mutex_is_locked
|
||||
notify_change
|
||||
override_creds
|
||||
|
|
@ -357,6 +367,76 @@
|
|||
vfs_setxattr
|
||||
vfs_unlink
|
||||
|
||||
# required by mac80211_hwsim.ko
|
||||
alloc_netdev_mqs
|
||||
__cfg80211_alloc_event_skb
|
||||
__cfg80211_alloc_reply_skb
|
||||
__cfg80211_send_event_skb
|
||||
cfg80211_vendor_cmd_reply
|
||||
dev_alloc_name
|
||||
device_bind_driver
|
||||
device_release_driver
|
||||
dst_release
|
||||
eth_mac_addr
|
||||
genlmsg_put
|
||||
genl_notify
|
||||
genl_register_family
|
||||
genl_unregister_family
|
||||
hrtimer_cancel
|
||||
hrtimer_forward
|
||||
hrtimer_init
|
||||
hrtimer_start_range_ns
|
||||
ieee80211_alloc_hw_nm
|
||||
ieee80211_beacon_get_tim
|
||||
ieee80211_csa_finish
|
||||
ieee80211_csa_is_complete
|
||||
ieee80211_free_hw
|
||||
ieee80211_free_txskb
|
||||
ieee80211_get_tx_rates
|
||||
ieee80211_iterate_active_interfaces_atomic
|
||||
ieee80211_probereq_get
|
||||
ieee80211_queue_delayed_work
|
||||
ieee80211_ready_on_channel
|
||||
ieee80211_register_hw
|
||||
ieee80211_remain_on_channel_expired
|
||||
ieee80211_rx_irqsafe
|
||||
ieee80211_scan_completed
|
||||
ieee80211_start_tx_ba_cb_irqsafe
|
||||
ieee80211_stop_tx_ba_cb_irqsafe
|
||||
ieee80211_tx_prepare_skb
|
||||
ieee80211_tx_status_irqsafe
|
||||
ieee80211_unregister_hw
|
||||
init_net
|
||||
kstrndup
|
||||
__netdev_alloc_skb
|
||||
netif_rx
|
||||
netlink_broadcast
|
||||
netlink_register_notifier
|
||||
netlink_unicast
|
||||
netlink_unregister_notifier
|
||||
net_namespace_list
|
||||
nla_memcpy
|
||||
__nla_parse
|
||||
nla_put_64bit
|
||||
nla_put
|
||||
param_ops_ushort
|
||||
___ratelimit
|
||||
register_pernet_device
|
||||
regulatory_hint
|
||||
rhashtable_destroy
|
||||
rhashtable_init
|
||||
rhashtable_insert_slow
|
||||
__rht_bucket_nested
|
||||
rht_bucket_nested
|
||||
rht_bucket_nested_insert
|
||||
schedule_timeout_interruptible
|
||||
skb_copy
|
||||
skb_copy_expand
|
||||
__skb_ext_put
|
||||
skb_trim
|
||||
unregister_pernet_device
|
||||
wiphy_apply_custom_regulatory
|
||||
|
||||
# required by nd_virtio.ko
|
||||
bio_alloc_bioset
|
||||
bio_chain
|
||||
|
|
@ -380,6 +460,7 @@
|
|||
netdev_lower_state_changed
|
||||
netdev_pick_tx
|
||||
pci_bus_type
|
||||
register_netdev
|
||||
|
||||
# required by rtc-test.ko
|
||||
add_timer
|
||||
|
|
@ -466,7 +547,6 @@
|
|||
idr_remove
|
||||
idr_replace
|
||||
__init_rwsem
|
||||
jiffies_to_msecs
|
||||
jiffies_to_usecs
|
||||
krealloc
|
||||
memchr_inv
|
||||
|
|
@ -501,11 +581,8 @@
|
|||
cfg80211_scan_done
|
||||
__dev_get_by_index
|
||||
dev_printk
|
||||
ether_setup
|
||||
ktime_get_with_offset
|
||||
netdev_upper_dev_link
|
||||
netif_stacked_transfer_operstate
|
||||
register_netdevice
|
||||
rtnl_link_register
|
||||
rtnl_link_unregister
|
||||
unregister_netdevice_many
|
||||
|
|
@ -612,7 +689,6 @@
|
|||
drm_universal_plane_init
|
||||
__get_task_comm
|
||||
kmalloc_order_trace
|
||||
kvfree
|
||||
kvmalloc_node
|
||||
memdup_user
|
||||
mutex_trylock
|
||||
|
|
@ -701,11 +777,9 @@
|
|||
unregister_blkdev
|
||||
|
||||
# required by virtio_console.ko
|
||||
cancel_work_sync
|
||||
cdev_add
|
||||
cdev_alloc
|
||||
cdev_del
|
||||
device_create
|
||||
device_destroy
|
||||
dma_alloc_attrs
|
||||
dma_free_attrs
|
||||
|
|
@ -789,12 +863,10 @@
|
|||
netif_set_real_num_tx_queues
|
||||
__netif_set_xps_queue
|
||||
net_ratelimit
|
||||
nf_conntrack_destroy
|
||||
__num_online_cpus
|
||||
__pskb_pull_tail
|
||||
_raw_spin_trylock
|
||||
sched_clock
|
||||
skb_add_rx_frag
|
||||
skb_coalesce_rx_frag
|
||||
__skb_flow_dissect
|
||||
skb_page_frag_refill
|
||||
|
|
@ -820,6 +892,7 @@
|
|||
# required by virtio_pci.ko
|
||||
irq_set_affinity_hint
|
||||
pci_alloc_irq_vectors_affinity
|
||||
pci_device_is_present
|
||||
pci_find_capability
|
||||
pci_find_ext_capability
|
||||
pci_find_next_capability
|
||||
|
|
@ -831,8 +904,6 @@
|
|||
pci_release_region
|
||||
pci_release_selected_regions
|
||||
pci_request_selected_regions
|
||||
virtio_device_freeze
|
||||
virtio_device_restore
|
||||
|
||||
# required by virtio_pmem.ko
|
||||
nvdimm_bus_register
|
||||
|
|
@ -852,6 +923,7 @@
|
|||
# required by vsock.ko
|
||||
autoremove_wake_function
|
||||
init_user_ns
|
||||
mod_delayed_work_on
|
||||
ns_capable_noaudit
|
||||
prandom_u32
|
||||
prepare_to_wait
|
||||
|
|
@ -882,3 +954,8 @@
|
|||
sock_diag_save_cookie
|
||||
sock_diag_unregister
|
||||
sock_i_ino
|
||||
|
||||
# preserved by --additions-only
|
||||
generic_shutdown_super
|
||||
refcount_dec_and_test_checked
|
||||
refcount_inc_checked
|
||||
|
|
|
|||
|
|
@ -2173,6 +2173,19 @@ static struct clk_branch gcc_pcie_clkref_en = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_branch gcc_edp_clkref_en = {
|
||||
.halt_reg = 0x8c008,
|
||||
.halt_check = BRANCH_HALT,
|
||||
.clkr = {
|
||||
.enable_reg = 0x8c008,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gcc_edp_clkref_en",
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch gcc_pcie_throttle_core_clk = {
|
||||
.halt_reg = 0x90018,
|
||||
.halt_check = BRANCH_HALT_SKIP,
|
||||
|
|
@ -3510,6 +3523,7 @@ static struct clk_regmap *gcc_yupik_clocks[] = {
|
|||
[GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr,
|
||||
[GCC_VIDEO_MVP_THROTTLE_CORE_CLK] =
|
||||
&gcc_video_mvp_throttle_core_clk.clkr,
|
||||
[GCC_EDP_CLKREF_EN] = &gcc_edp_clkref_en.clkr,
|
||||
};
|
||||
|
||||
static const struct qcom_reset_map gcc_yupik_resets[] = {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2008-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef __ADRENO_H
|
||||
#define __ADRENO_H
|
||||
|
|
@ -16,9 +16,6 @@
|
|||
#include "adreno_ringbuffer.h"
|
||||
#include "kgsl_sharedmem.h"
|
||||
|
||||
/* Index to preemption scratch buffer to store KMD postamble */
|
||||
#define KMD_POSTAMBLE_IDX 100
|
||||
|
||||
/* ADRENO_DEVICE - Given a kgsl_device return the adreno device struct */
|
||||
#define ADRENO_DEVICE(device) \
|
||||
container_of(device, struct adreno_device, dev)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "adreno.h"
|
||||
|
|
@ -553,8 +553,7 @@ unsigned int a6xx_preemption_pre_ibsubmit(
|
|||
|
||||
/* Add a KMD post amble to clear the perf counters during preemption */
|
||||
if (!adreno_dev->perfcounter) {
|
||||
u64 kmd_postamble_addr =
|
||||
PREEMPT_SCRATCH_ADDR(adreno_dev, KMD_POSTAMBLE_IDX);
|
||||
u64 kmd_postamble_addr = SCRATCH_POSTAMBLE_ADDR(KGSL_DEVICE(adreno_dev));
|
||||
|
||||
*cmds++ = cp_type7_packet(CP_SET_AMBLE, 3);
|
||||
*cmds++ = lower_32_bits(kmd_postamble_addr);
|
||||
|
|
@ -695,6 +694,7 @@ static int a6xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev,
|
|||
|
||||
int a6xx_preemption_init(struct adreno_device *adreno_dev)
|
||||
{
|
||||
u32 flags = ADRENO_FEATURE(adreno_dev, ADRENO_APRIV) ? KGSL_MEMDESC_PRIVILEGED : 0;
|
||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
|
||||
struct adreno_preemption *preempt = &adreno_dev->preempt;
|
||||
|
|
@ -717,7 +717,7 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev)
|
|||
|
||||
if (IS_ERR_OR_NULL(preempt->scratch)) {
|
||||
preempt->scratch = kgsl_allocate_global(device, PAGE_SIZE,
|
||||
0, 0, 0, "preempt_scratch");
|
||||
0, 0, flags, "preempt_scratch");
|
||||
if (IS_ERR(preempt->scratch))
|
||||
return PTR_ERR(preempt->scratch);
|
||||
}
|
||||
|
|
@ -733,12 +733,13 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev)
|
|||
return ret;
|
||||
|
||||
/*
|
||||
* First 8 dwords of the preemption scratch buffer is used to store the address for CP
|
||||
* to save/restore VPC data. Reserve 11 dwords in the preemption scratch buffer from
|
||||
* index KMD_POSTAMBLE_IDX for KMD postamble pm4 packets
|
||||
* First 28 dwords of the device scratch buffer are used to store shadow rb data.
|
||||
* Reserve 11 dwords in the device scratch buffer from SCRATCH_POSTAMBLE_OFFSET for
|
||||
* KMD postamble pm4 packets. This should be in *device->scratch* so that userspace
|
||||
* cannot access it.
|
||||
*/
|
||||
if (!adreno_dev->perfcounter) {
|
||||
u32 *postamble = preempt->scratch->hostptr + (KMD_POSTAMBLE_IDX * sizeof(u64));
|
||||
u32 *postamble = device->scratch->hostptr + SCRATCH_POSTAMBLE_OFFSET;
|
||||
u32 count = 0;
|
||||
|
||||
postamble[count++] = cp_type7_packet(CP_REG_RMW, 3);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "adreno.h"
|
||||
|
|
@ -903,6 +904,23 @@ int adreno_hwsched_queue_cmds(struct kgsl_device_private *dev_priv,
|
|||
|
||||
user_ts = *timestamp;
|
||||
|
||||
/*
|
||||
* If there is only one drawobj in the array and it is of
|
||||
* type SYNCOBJ_TYPE, skip comparing user_ts as it can be 0
|
||||
*/
|
||||
if (!(count == 1 && drawobj[0]->type == SYNCOBJ_TYPE) &&
|
||||
(drawctxt->base.flags & KGSL_CONTEXT_USER_GENERATED_TS)) {
|
||||
/*
|
||||
* User specified timestamps need to be greater than the last
|
||||
* issued timestamp in the context
|
||||
*/
|
||||
if (timestamp_cmp(drawctxt->timestamp, user_ts) >= 0) {
|
||||
spin_unlock(&drawctxt->lock);
|
||||
kmem_cache_free(jobs_cache, job);
|
||||
return -ERANGE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
||||
switch (drawobj[i]->type) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2008-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef __KGSL_H
|
||||
#define __KGSL_H
|
||||
|
|
@ -71,6 +72,11 @@
|
|||
#define SCRATCH_RPTR_GPU_ADDR(dev, id) \
|
||||
((dev)->scratch->gpuaddr + SCRATCH_RPTR_OFFSET(id))
|
||||
|
||||
/* OFFSET to KMD postamble packets in scratch buffer */
|
||||
#define SCRATCH_POSTAMBLE_OFFSET (100 * sizeof(u64))
|
||||
#define SCRATCH_POSTAMBLE_ADDR(dev) \
|
||||
((dev)->scratch->gpuaddr + SCRATCH_POSTAMBLE_OFFSET)
|
||||
|
||||
/* Timestamp window used to detect rollovers (half of integer range) */
|
||||
#define KGSL_TIMESTAMP_WINDOW 0x80000000
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
|
@ -136,10 +137,12 @@ struct geni_i2c_dev {
|
|||
bool disable_dma_mode;
|
||||
bool prev_cancel_pending; //Halt cancel till IOS in good state
|
||||
bool is_i2c_rtl_based; /* doing pending cancel only for rtl based SE's */
|
||||
atomic_t is_xfer_in_progress; /* Used to maintain xfer inprogress status */
|
||||
};
|
||||
|
||||
static struct geni_i2c_dev *gi2c_dev_dbg[MAX_SE];
|
||||
static int arr_idx;
|
||||
static int geni_i2c_runtime_suspend(struct device *dev);
|
||||
|
||||
struct geni_i2c_err_log {
|
||||
int err;
|
||||
|
|
@ -1052,11 +1055,13 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
|
|||
int i, ret = 0, timeout = 0;
|
||||
|
||||
gi2c->err = 0;
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 1);
|
||||
|
||||
/* Client to respect system suspend */
|
||||
if (!pm_runtime_enabled(gi2c->dev)) {
|
||||
GENI_SE_ERR(gi2c->ipcl, false, gi2c->dev,
|
||||
"%s: System suspended\n", __func__);
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 0);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
|
|
@ -1068,6 +1073,7 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
|
|||
pm_runtime_put_noidle(gi2c->dev);
|
||||
/* Set device in suspended since resume failed */
|
||||
pm_runtime_set_suspended(gi2c->dev);
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 0);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -1078,12 +1084,13 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
|
|||
if (ret) {
|
||||
pm_runtime_mark_last_busy(gi2c->dev);
|
||||
pm_runtime_put_autosuspend(gi2c->dev);
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 0);
|
||||
return ret; //Don't perform xfer is cancel failed
|
||||
}
|
||||
}
|
||||
|
||||
GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
|
||||
"n:%d addr:0x%x\n", num, msgs[0].addr);
|
||||
"n:%d addr:0x%x\n", num, msgs[0].addr);
|
||||
|
||||
gi2c->dbg_num = num;
|
||||
kfree(gi2c->dbg_buf_ptr);
|
||||
|
|
@ -1268,7 +1275,7 @@ geni_i2c_txn_ret:
|
|||
pm_runtime_mark_last_busy(gi2c->dev);
|
||||
pm_runtime_put_autosuspend(gi2c->dev);
|
||||
}
|
||||
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 0);
|
||||
gi2c->cur = NULL;
|
||||
GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
|
||||
"i2c txn ret:%d, num:%d, err:%d\n", ret, num, gi2c->err);
|
||||
|
|
@ -1476,10 +1483,10 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 0);
|
||||
snprintf(boot_marker, sizeof(boot_marker),
|
||||
"M - DRIVER GENI_I2C_%d Ready", gi2c->adap.nr);
|
||||
"M - DRIVER GENI_I2C_%d Ready", gi2c->adap.nr);
|
||||
place_marker(boot_marker);
|
||||
|
||||
dev_info(gi2c->dev, "I2C probed\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1489,6 +1496,33 @@ static int geni_i2c_remove(struct platform_device *pdev)
|
|||
struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
if (atomic_read(&gi2c->is_xfer_in_progress)) {
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
"%s: Xfer is in progress\n", __func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!pm_runtime_status_suspended(gi2c->dev)) {
|
||||
if (geni_i2c_runtime_suspend(gi2c->dev))
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
"%s: runtime suspend failed\n", __func__);
|
||||
}
|
||||
|
||||
if (gi2c->se_mode == GSI_ONLY) {
|
||||
if (gi2c->tx_c) {
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
"%s: clearing tx dma resource\n", __func__);
|
||||
dma_release_channel(gi2c->tx_c);
|
||||
}
|
||||
if (gi2c->rx_c) {
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
"%s: clearing rx dma resource\n", __func__);
|
||||
dma_release_channel(gi2c->rx_c);
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_put_noidle(gi2c->dev);
|
||||
pm_runtime_set_suspended(gi2c->dev);
|
||||
pm_runtime_disable(gi2c->dev);
|
||||
i2c_del_adapter(&gi2c->adap);
|
||||
|
||||
|
|
@ -1594,6 +1628,19 @@ static int geni_i2c_suspend_late(struct device *device)
|
|||
int ret;
|
||||
|
||||
GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "%s\n", __func__);
|
||||
|
||||
if (atomic_read(&gi2c->is_xfer_in_progress)) {
|
||||
if (!pm_runtime_status_suspended(gi2c->dev)) {
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
":%s: runtime PM is active\n", __func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
"%s System suspend not allowed while xfer in progress\n",
|
||||
__func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Make sure no transactions are pending */
|
||||
ret = i2c_trylock_bus(&gi2c->adap, I2C_LOCK_SEGMENT);
|
||||
if (!ret) {
|
||||
|
|
|
|||
|
|
@ -177,14 +177,25 @@ static void iommu_free_dev_param(struct device *dev)
|
|||
int iommu_probe_device(struct device *dev)
|
||||
{
|
||||
const struct iommu_ops *ops = dev->bus->iommu_ops;
|
||||
static DEFINE_MUTEX(iommu_probe_device_lock);
|
||||
int ret;
|
||||
|
||||
WARN_ON(dev->iommu_group);
|
||||
if (!ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!iommu_get_dev_param(dev))
|
||||
return -ENOMEM;
|
||||
/*
|
||||
* Serialise to avoid races between IOMMU drivers registering in
|
||||
* parallel and/or the "replay" calls from ACPI/OF code via client
|
||||
* driver probe. Once the latter have been cleaned up we should
|
||||
* probably be able to use device_lock() here to minimise the scope,
|
||||
* but for now enforcing a simple global ordering is fine.
|
||||
*/
|
||||
mutex_lock(&iommu_probe_device_lock);
|
||||
if (!iommu_get_dev_param(dev)) {
|
||||
ret = -ENOMEM;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
if (!try_module_get(ops->owner)) {
|
||||
ret = -EINVAL;
|
||||
|
|
@ -195,12 +206,17 @@ int iommu_probe_device(struct device *dev)
|
|||
if (ret)
|
||||
goto err_module_put;
|
||||
|
||||
mutex_unlock(&iommu_probe_device_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
err_module_put:
|
||||
module_put(ops->owner);
|
||||
err_free_dev_param:
|
||||
iommu_free_dev_param(dev);
|
||||
err_unlock:
|
||||
mutex_unlock(&iommu_probe_device_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -800,6 +800,11 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
|
|||
if (mutex_lock_interruptible(&dmxdev->mutex))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (dmxdev->exit) {
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (i = 0; i < dmxdev->filternum; i++)
|
||||
if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
|
||||
break;
|
||||
|
|
@ -1458,7 +1463,10 @@ EXPORT_SYMBOL(dvb_dmxdev_init);
|
|||
|
||||
void dvb_dmxdev_release(struct dmxdev *dmxdev)
|
||||
{
|
||||
mutex_lock(&dmxdev->mutex);
|
||||
dmxdev->exit = 1;
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
|
||||
if (dmxdev->dvbdev->users > 1) {
|
||||
wait_event(dmxdev->dvbdev->wait_queue,
|
||||
dmxdev->dvbdev->users == 1);
|
||||
|
|
|
|||
|
|
@ -499,6 +499,7 @@ struct mac80211_hwsim_data {
|
|||
u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
|
||||
|
||||
struct mac_address addresses[2];
|
||||
struct ieee80211_chanctx_conf *chanctx;
|
||||
int channels, idx;
|
||||
bool use_chanctx;
|
||||
bool destroy_on_close;
|
||||
|
|
@ -1059,6 +1060,47 @@ static int hwsim_unicast_netgroup(struct mac80211_hwsim_data *data,
|
|||
return res;
|
||||
}
|
||||
|
||||
static void mac80211_hwsim_config_mac_nl(struct ieee80211_hw *hw,
|
||||
const u8 *addr, bool add)
|
||||
{
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
u32 _portid = READ_ONCE(data->wmediumd);
|
||||
struct sk_buff *skb;
|
||||
void *msg_head;
|
||||
|
||||
if (!_portid && !hwsim_virtio_enabled)
|
||||
return;
|
||||
|
||||
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0,
|
||||
add ? HWSIM_CMD_ADD_MAC_ADDR :
|
||||
HWSIM_CMD_DEL_MAC_ADDR);
|
||||
if (!msg_head) {
|
||||
pr_debug("mac80211_hwsim: problem with msg_head\n");
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER,
|
||||
ETH_ALEN, data->addresses[1].addr))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put(skb, HWSIM_ATTR_ADDR_RECEIVER, ETH_ALEN, addr))
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(skb, msg_head);
|
||||
|
||||
if (hwsim_virtio_enabled)
|
||||
hwsim_tx_virtio(data, skb);
|
||||
else
|
||||
hwsim_unicast_netgroup(data, skb, _portid);
|
||||
return;
|
||||
nla_put_failure:
|
||||
nlmsg_free(skb);
|
||||
}
|
||||
|
||||
static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate)
|
||||
{
|
||||
u16 result = 0;
|
||||
|
|
@ -1091,7 +1133,8 @@ static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate)
|
|||
|
||||
static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
|
||||
struct sk_buff *my_skb,
|
||||
int dst_portid)
|
||||
int dst_portid,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
|
|
@ -1146,7 +1189,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
|
|||
if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq))
|
||||
if (nla_put_u32(skb, HWSIM_ATTR_FREQ, channel->center_freq))
|
||||
goto nla_put_failure;
|
||||
|
||||
/* We get the tx control (rate and retries) info*/
|
||||
|
|
@ -1487,7 +1530,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
|||
_portid = READ_ONCE(data->wmediumd);
|
||||
|
||||
if (_portid || hwsim_virtio_enabled)
|
||||
return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
|
||||
return mac80211_hwsim_tx_frame_nl(hw, skb, _portid, channel);
|
||||
|
||||
/* NO wmediumd detected, perfect medium simulation */
|
||||
data->tx_pkts++;
|
||||
|
|
@ -1540,6 +1583,9 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
|
|||
vif->addr);
|
||||
hwsim_set_magic(vif);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_MONITOR)
|
||||
mac80211_hwsim_config_mac_nl(hw, vif->addr, true);
|
||||
|
||||
vif->cab_queue = 0;
|
||||
vif->hw_queue[IEEE80211_AC_VO] = 0;
|
||||
vif->hw_queue[IEEE80211_AC_VI] = 1;
|
||||
|
|
@ -1579,6 +1625,8 @@ static void mac80211_hwsim_remove_interface(
|
|||
vif->addr);
|
||||
hwsim_check_magic(vif);
|
||||
hwsim_clear_magic(vif);
|
||||
if (vif->type != NL80211_IFTYPE_MONITOR)
|
||||
mac80211_hwsim_config_mac_nl(hw, vif->addr, false);
|
||||
}
|
||||
|
||||
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
||||
|
|
@ -1598,7 +1646,7 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
|||
mac80211_hwsim_monitor_rx(hw, skb, chan);
|
||||
|
||||
if (_pid || hwsim_virtio_enabled)
|
||||
return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
|
||||
return mac80211_hwsim_tx_frame_nl(hw, skb, _pid, chan);
|
||||
|
||||
mac80211_hwsim_tx_frame_no_nl(hw, skb, chan);
|
||||
dev_kfree_skb(skb);
|
||||
|
|
@ -2092,6 +2140,8 @@ static void hw_scan_work(struct work_struct *work)
|
|||
hwsim->hw_scan_vif = NULL;
|
||||
hwsim->tmp_chan = NULL;
|
||||
mutex_unlock(&hwsim->mutex);
|
||||
mac80211_hwsim_config_mac_nl(hwsim->hw, hwsim->scan_addr,
|
||||
false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2177,6 +2227,7 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
|
|||
memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data));
|
||||
mutex_unlock(&hwsim->mutex);
|
||||
|
||||
mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, true);
|
||||
wiphy_dbg(hw->wiphy, "hwsim hw_scan request\n");
|
||||
|
||||
ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0);
|
||||
|
|
@ -2220,6 +2271,7 @@ static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw,
|
|||
pr_debug("hwsim sw_scan request, prepping stuff\n");
|
||||
|
||||
memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN);
|
||||
mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, true);
|
||||
hwsim->scanning = true;
|
||||
memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data));
|
||||
|
||||
|
|
@ -2236,6 +2288,7 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw,
|
|||
|
||||
pr_debug("hwsim sw_scan_complete\n");
|
||||
hwsim->scanning = false;
|
||||
mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, false);
|
||||
eth_zero_addr(hwsim->scan_addr);
|
||||
|
||||
mutex_unlock(&hwsim->mutex);
|
||||
|
|
@ -2316,6 +2369,11 @@ static int mac80211_hwsim_croc(struct ieee80211_hw *hw,
|
|||
static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct mac80211_hwsim_data *hwsim = hw->priv;
|
||||
|
||||
mutex_lock(&hwsim->mutex);
|
||||
hwsim->chanctx = ctx;
|
||||
mutex_unlock(&hwsim->mutex);
|
||||
hwsim_set_chanctx_magic(ctx);
|
||||
wiphy_dbg(hw->wiphy,
|
||||
"add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
|
||||
|
|
@ -2327,6 +2385,11 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
|
|||
static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct mac80211_hwsim_data *hwsim = hw->priv;
|
||||
|
||||
mutex_lock(&hwsim->mutex);
|
||||
hwsim->chanctx = NULL;
|
||||
mutex_unlock(&hwsim->mutex);
|
||||
wiphy_dbg(hw->wiphy,
|
||||
"remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
|
||||
ctx->def.chan->center_freq, ctx->def.width,
|
||||
|
|
@ -2339,6 +2402,11 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
|
|||
struct ieee80211_chanctx_conf *ctx,
|
||||
u32 changed)
|
||||
{
|
||||
struct mac80211_hwsim_data *hwsim = hw->priv;
|
||||
|
||||
mutex_lock(&hwsim->mutex);
|
||||
hwsim->chanctx = ctx;
|
||||
mutex_unlock(&hwsim->mutex);
|
||||
hwsim_check_chanctx_magic(ctx);
|
||||
wiphy_dbg(hw->wiphy,
|
||||
"change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
|
||||
|
|
@ -2926,6 +2994,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
|||
hw->wiphy->max_remain_on_channel_duration = 1000;
|
||||
data->if_combination.radar_detect_widths = 0;
|
||||
data->if_combination.num_different_channels = data->channels;
|
||||
data->chanctx = NULL;
|
||||
} else {
|
||||
data->if_combination.num_different_channels = 1;
|
||||
data->if_combination.radar_detect_widths =
|
||||
|
|
@ -3420,6 +3489,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
|||
int frame_data_len;
|
||||
void *frame_data;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct ieee80211_channel *channel = NULL;
|
||||
|
||||
if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
|
||||
!info->attrs[HWSIM_ATTR_FRAME] ||
|
||||
|
|
@ -3446,6 +3516,17 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
|||
if (!data2)
|
||||
goto out;
|
||||
|
||||
if (data2->use_chanctx) {
|
||||
if (data2->tmp_chan)
|
||||
channel = data2->tmp_chan;
|
||||
else if (data2->chanctx)
|
||||
channel = data2->chanctx->def.chan;
|
||||
} else {
|
||||
channel = data2->channel;
|
||||
}
|
||||
if (!channel)
|
||||
goto out;
|
||||
|
||||
if (!hwsim_virtio_enabled) {
|
||||
if (hwsim_net_get_netgroup(genl_info_net(info)) !=
|
||||
data2->netgroup)
|
||||
|
|
@ -3457,7 +3538,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
|||
|
||||
/* check if radio is configured properly */
|
||||
|
||||
if (data2->idle || !data2->started)
|
||||
if ((data2->idle && !data2->tmp_chan) || !data2->started)
|
||||
goto out;
|
||||
|
||||
/* A frame is received from user space */
|
||||
|
|
@ -3470,18 +3551,16 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
|||
mutex_lock(&data2->mutex);
|
||||
rx_status.freq = nla_get_u32(info->attrs[HWSIM_ATTR_FREQ]);
|
||||
|
||||
if (rx_status.freq != data2->channel->center_freq &&
|
||||
(!data2->tmp_chan ||
|
||||
rx_status.freq != data2->tmp_chan->center_freq)) {
|
||||
if (rx_status.freq != channel->center_freq) {
|
||||
mutex_unlock(&data2->mutex);
|
||||
goto out;
|
||||
}
|
||||
mutex_unlock(&data2->mutex);
|
||||
} else {
|
||||
rx_status.freq = data2->channel->center_freq;
|
||||
rx_status.freq = channel->center_freq;
|
||||
}
|
||||
|
||||
rx_status.band = data2->channel->band;
|
||||
rx_status.band = channel->band;
|
||||
rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
|
||||
if (rx_status.rate_idx >= data2->hw->wiphy->bands[rx_status.band]->n_bitrates)
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,12 @@ enum hwsim_tx_control_flags {
|
|||
* @HWSIM_CMD_DEL_RADIO: destroy a radio, reply is multicasted
|
||||
* @HWSIM_CMD_GET_RADIO: fetch information about existing radios, uses:
|
||||
* %HWSIM_ATTR_RADIO_ID
|
||||
* @HWSIM_CMD_ADD_MAC_ADDR: add a receive MAC address (given in the
|
||||
* %HWSIM_ATTR_ADDR_RECEIVER attribute) to a device identified by
|
||||
* %HWSIM_ATTR_ADDR_TRANSMITTER. This lets wmediumd forward frames
|
||||
* to this receiver address for a given station.
|
||||
* @HWSIM_CMD_DEL_MAC_ADDR: remove the MAC address again, the attributes
|
||||
* are the same as to @HWSIM_CMD_ADD_MAC_ADDR.
|
||||
* @__HWSIM_CMD_MAX: enum limit
|
||||
*/
|
||||
enum {
|
||||
|
|
@ -85,6 +91,8 @@ enum {
|
|||
HWSIM_CMD_NEW_RADIO,
|
||||
HWSIM_CMD_DEL_RADIO,
|
||||
HWSIM_CMD_GET_RADIO,
|
||||
HWSIM_CMD_ADD_MAC_ADDR,
|
||||
HWSIM_CMD_DEL_MAC_ADDR,
|
||||
__HWSIM_CMD_MAX,
|
||||
};
|
||||
#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
|
||||
|
|
|
|||
|
|
@ -168,6 +168,16 @@ config R8125
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called r8125.
|
||||
|
||||
config R8168
|
||||
tristate "Realtek R8168 driver"
|
||||
depends on PCI
|
||||
help
|
||||
This is a 1Gbps ethernet driver for the PCI network cards based on
|
||||
the Realtek RTL8111K chip. If you have one of those, say Y here.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called r8168.
|
||||
|
||||
config R8125_IOSS
|
||||
tristate "Realtek R8125 IOSS glue driver"
|
||||
depends on R8125
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -631,8 +632,12 @@ static int spcom_handle_create_channel_command(void *cmd_buf, int cmd_size)
|
|||
mutex_lock(&spcom_dev->chdev_count_lock);
|
||||
ret = spcom_create_channel_chardev(cmd->ch_name, cmd->is_sharable);
|
||||
mutex_unlock(&spcom_dev->chdev_count_lock);
|
||||
if (ret)
|
||||
spcom_pr_err("failed to create ch[%s], ret [%d]\n", cmd->ch_name, ret);
|
||||
if (ret) {
|
||||
if (-EINVAL == ret)
|
||||
spcom_pr_err("failed to create channel, ret [%d]\n", ret);
|
||||
else
|
||||
spcom_pr_err("failed to create ch[%s], ret [%d]\n", cmd->ch_name, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3277,7 +3277,13 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
|
|||
* processed by the core. Hence do not reclaim it until
|
||||
* it is processed by the core.
|
||||
*/
|
||||
if (req->trb->ctrl & DWC3_TRB_CTRL_HWO) {
|
||||
/*
|
||||
* If sg transfer are in progress, avoid checking
|
||||
* HWO bit here as these will get cleared during
|
||||
* ep reclaim.
|
||||
*/
|
||||
if ((req->trb->ctrl & DWC3_TRB_CTRL_HWO)
|
||||
&& (req->num_queued_sgs == 0)) {
|
||||
dbg_event(0xFF, "PEND TRB", dep->number);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4706,9 +4706,17 @@ static int __ext4_get_inode_loc(struct inode *inode,
|
|||
inodes_per_block = EXT4_SB(sb)->s_inodes_per_block;
|
||||
inode_offset = ((inode->i_ino - 1) %
|
||||
EXT4_INODES_PER_GROUP(sb));
|
||||
block = ext4_inode_table(sb, gdp) + (inode_offset / inodes_per_block);
|
||||
iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb);
|
||||
|
||||
block = ext4_inode_table(sb, gdp);
|
||||
if ((block <= le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) ||
|
||||
(block >= ext4_blocks_count(EXT4_SB(sb)->s_es))) {
|
||||
ext4_error(sb, "Invalid inode table block %llu in "
|
||||
"block_group %u", block, iloc->block_group);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
block += (inode_offset / inodes_per_block);
|
||||
|
||||
bh = sb_getblk(sb, block);
|
||||
if (unlikely(!bh))
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@
|
|||
#define GCC_AGGRE_NOC_PCIE_CENTER_SF_AXI_CLK 167
|
||||
#define GCC_AGGRE_NOC_PCIE_TBU_CLK 168
|
||||
#define GCC_PCIE_CLKREF_EN 169
|
||||
#define GCC_EDP_CLKREF_EN 170
|
||||
|
||||
/* GCC power domains */
|
||||
#define GCC_PCIE_0_GDSC 0
|
||||
|
|
|
|||
|
|
@ -277,6 +277,13 @@ struct css_set {
|
|||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
struct ext_css_set {
|
||||
struct css_set cset;
|
||||
|
||||
struct list_head mg_src_preload_node;
|
||||
struct list_head mg_dst_preload_node;
|
||||
};
|
||||
|
||||
struct cgroup_base_stat {
|
||||
struct task_cputime cputime;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -70,7 +70,8 @@ struct css_task_iter {
|
|||
};
|
||||
|
||||
extern struct cgroup_root cgrp_dfl_root;
|
||||
extern struct css_set init_css_set;
|
||||
extern struct ext_css_set init_ext_css_set;
|
||||
#define init_css_set init_ext_css_set.cset
|
||||
|
||||
#define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys;
|
||||
#include <linux/cgroup_subsys.h>
|
||||
|
|
|
|||
|
|
@ -1542,6 +1542,12 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
|
|||
#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
|
||||
static inline void vm_write_begin(struct vm_area_struct *vma)
|
||||
{
|
||||
/*
|
||||
* Isolated vma might be freed without exclusive mmap_lock but
|
||||
* speculative page fault handler still needs to know it was changed.
|
||||
*/
|
||||
if (!RB_EMPTY_NODE(&vma->vm_rb))
|
||||
WARN_ON_ONCE(!rwsem_is_locked(&(vma->vm_mm)->mmap_sem));
|
||||
/*
|
||||
* The reads never spins and preemption
|
||||
* disablement is not required.
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#define WAN_IOCTL_RMV_OFFLOAD_CONNECTION 19
|
||||
#define WAN_IOCTL_GET_WAN_MTU 20
|
||||
#define WAN_IOCTL_NOTIFY_NAT_MOVE_RES 21
|
||||
#define WAN_IOCTL_NOTIFY_DUAL_BACKHAUL_INFO 22
|
||||
|
||||
/* User space may not have this defined. */
|
||||
#ifndef IFNAMSIZ
|
||||
|
|
@ -195,6 +196,10 @@ struct wan_ioctl_query_per_client_stats {
|
|||
WAN_IOCTL_ADD_FLT_RULE, \
|
||||
struct ipa_install_fltr_rule_req_msg_v01 *)
|
||||
|
||||
#define WAN_IOC_NOTIFY_DUAL_BACKHAUL_INFO _IOWR(WAN_IOC_MAGIC, \
|
||||
WAN_IOCTL_NOTIFY_DUAL_BACKHAUL_INFO, \
|
||||
struct ipa_eth_backhaul_info_req_msg_v01 *)
|
||||
|
||||
#define WAN_IOC_ADD_FLT_RULE_INDEX _IOWR(WAN_IOC_MAGIC, \
|
||||
WAN_IOCTL_ADD_FLT_INDEX, \
|
||||
struct ipa_fltr_installed_notif_req_msg_v01 *)
|
||||
|
|
|
|||
|
|
@ -751,25 +751,28 @@ EXPORT_SYMBOL_GPL(of_css);
|
|||
* reference-counted, to improve performance when child cgroups
|
||||
* haven't been created.
|
||||
*/
|
||||
struct css_set init_css_set = {
|
||||
.refcount = REFCOUNT_INIT(1),
|
||||
.dom_cset = &init_css_set,
|
||||
.tasks = LIST_HEAD_INIT(init_css_set.tasks),
|
||||
.mg_tasks = LIST_HEAD_INIT(init_css_set.mg_tasks),
|
||||
.dying_tasks = LIST_HEAD_INIT(init_css_set.dying_tasks),
|
||||
.task_iters = LIST_HEAD_INIT(init_css_set.task_iters),
|
||||
.threaded_csets = LIST_HEAD_INIT(init_css_set.threaded_csets),
|
||||
.cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links),
|
||||
.mg_preload_node = LIST_HEAD_INIT(init_css_set.mg_preload_node),
|
||||
.mg_node = LIST_HEAD_INIT(init_css_set.mg_node),
|
||||
|
||||
/*
|
||||
* The following field is re-initialized when this cset gets linked
|
||||
* in cgroup_init(). However, let's initialize the field
|
||||
* statically too so that the default cgroup can be accessed safely
|
||||
* early during boot.
|
||||
*/
|
||||
.dfl_cgrp = &cgrp_dfl_root.cgrp,
|
||||
struct ext_css_set init_ext_css_set = {
|
||||
.cset = {
|
||||
.refcount = REFCOUNT_INIT(1),
|
||||
.dom_cset = &init_css_set,
|
||||
.tasks = LIST_HEAD_INIT(init_css_set.tasks),
|
||||
.mg_tasks = LIST_HEAD_INIT(init_css_set.mg_tasks),
|
||||
.dying_tasks = LIST_HEAD_INIT(init_css_set.dying_tasks),
|
||||
.task_iters = LIST_HEAD_INIT(init_css_set.task_iters),
|
||||
.threaded_csets = LIST_HEAD_INIT(init_css_set.threaded_csets),
|
||||
.cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links),
|
||||
.mg_preload_node = LIST_HEAD_INIT(init_css_set.mg_preload_node),
|
||||
.mg_node = LIST_HEAD_INIT(init_css_set.mg_node),
|
||||
/*
|
||||
* The following field is re-initialized when this cset gets linked
|
||||
* in cgroup_init(). However, let's initialize the field
|
||||
* statically too so that the default cgroup can be accessed safely
|
||||
* early during boot.
|
||||
*/
|
||||
.dfl_cgrp = &cgrp_dfl_root.cgrp,
|
||||
},
|
||||
.mg_src_preload_node = LIST_HEAD_INIT(init_ext_css_set.mg_src_preload_node),
|
||||
.mg_dst_preload_node = LIST_HEAD_INIT(init_ext_css_set.mg_dst_preload_node),
|
||||
};
|
||||
|
||||
static int css_set_count = 1; /* 1 for init_css_set */
|
||||
|
|
@ -1197,6 +1200,7 @@ static struct css_set *find_css_set(struct css_set *old_cset,
|
|||
struct cgroup *cgrp)
|
||||
{
|
||||
struct cgroup_subsys_state *template[CGROUP_SUBSYS_COUNT] = { };
|
||||
struct ext_css_set *ext_cset;
|
||||
struct css_set *cset;
|
||||
struct list_head tmp_links;
|
||||
struct cgrp_cset_link *link;
|
||||
|
|
@ -1217,9 +1221,10 @@ static struct css_set *find_css_set(struct css_set *old_cset,
|
|||
if (cset)
|
||||
return cset;
|
||||
|
||||
cset = kzalloc(sizeof(*cset), GFP_KERNEL);
|
||||
if (!cset)
|
||||
ext_cset = kzalloc(sizeof(*ext_cset), GFP_KERNEL);
|
||||
if (!ext_cset)
|
||||
return NULL;
|
||||
cset = &ext_cset->cset;
|
||||
|
||||
/* Allocate all the cgrp_cset_link objects that we'll need */
|
||||
if (allocate_cgrp_cset_links(cgroup_root_count, &tmp_links) < 0) {
|
||||
|
|
@ -1237,6 +1242,8 @@ static struct css_set *find_css_set(struct css_set *old_cset,
|
|||
INIT_HLIST_NODE(&cset->hlist);
|
||||
INIT_LIST_HEAD(&cset->cgrp_links);
|
||||
INIT_LIST_HEAD(&cset->mg_preload_node);
|
||||
INIT_LIST_HEAD(&ext_cset->mg_src_preload_node);
|
||||
INIT_LIST_HEAD(&ext_cset->mg_dst_preload_node);
|
||||
INIT_LIST_HEAD(&cset->mg_node);
|
||||
|
||||
/* Copy the set of subsystem state objects generated in
|
||||
|
|
@ -2687,22 +2694,28 @@ int cgroup_migrate_vet_dst(struct cgroup *dst_cgrp)
|
|||
*/
|
||||
void cgroup_migrate_finish(struct cgroup_mgctx *mgctx)
|
||||
{
|
||||
LIST_HEAD(preloaded);
|
||||
struct css_set *cset, *tmp_cset;
|
||||
struct ext_css_set *cset, *tmp_cset;
|
||||
|
||||
lockdep_assert_held(&cgroup_mutex);
|
||||
|
||||
spin_lock_irq(&css_set_lock);
|
||||
|
||||
list_splice_tail_init(&mgctx->preloaded_src_csets, &preloaded);
|
||||
list_splice_tail_init(&mgctx->preloaded_dst_csets, &preloaded);
|
||||
list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_src_csets,
|
||||
mg_src_preload_node) {
|
||||
cset->cset.mg_src_cgrp = NULL;
|
||||
cset->cset.mg_dst_cgrp = NULL;
|
||||
cset->cset.mg_dst_cset = NULL;
|
||||
list_del_init(&cset->mg_src_preload_node);
|
||||
put_css_set_locked(&cset->cset);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(cset, tmp_cset, &preloaded, mg_preload_node) {
|
||||
cset->mg_src_cgrp = NULL;
|
||||
cset->mg_dst_cgrp = NULL;
|
||||
cset->mg_dst_cset = NULL;
|
||||
list_del_init(&cset->mg_preload_node);
|
||||
put_css_set_locked(cset);
|
||||
list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_dst_csets,
|
||||
mg_dst_preload_node) {
|
||||
cset->cset.mg_src_cgrp = NULL;
|
||||
cset->cset.mg_dst_cgrp = NULL;
|
||||
cset->cset.mg_dst_cset = NULL;
|
||||
list_del_init(&cset->mg_dst_preload_node);
|
||||
put_css_set_locked(&cset->cset);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&css_set_lock);
|
||||
|
|
@ -2729,6 +2742,7 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
|
|||
struct cgroup_mgctx *mgctx)
|
||||
{
|
||||
struct cgroup *src_cgrp;
|
||||
struct ext_css_set *ext_src_cset;
|
||||
|
||||
lockdep_assert_held(&cgroup_mutex);
|
||||
lockdep_assert_held(&css_set_lock);
|
||||
|
|
@ -2742,8 +2756,9 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
|
|||
return;
|
||||
|
||||
src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
|
||||
ext_src_cset = container_of(src_cset, struct ext_css_set, cset);
|
||||
|
||||
if (!list_empty(&src_cset->mg_preload_node))
|
||||
if (!list_empty(&ext_src_cset->mg_src_preload_node))
|
||||
return;
|
||||
|
||||
WARN_ON(src_cset->mg_src_cgrp);
|
||||
|
|
@ -2754,7 +2769,7 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
|
|||
src_cset->mg_src_cgrp = src_cgrp;
|
||||
src_cset->mg_dst_cgrp = dst_cgrp;
|
||||
get_css_set(src_cset);
|
||||
list_add_tail(&src_cset->mg_preload_node, &mgctx->preloaded_src_csets);
|
||||
list_add_tail(&ext_src_cset->mg_src_preload_node, &mgctx->preloaded_src_csets);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2773,20 +2788,23 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
|
|||
*/
|
||||
int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
|
||||
{
|
||||
struct css_set *src_cset, *tmp_cset;
|
||||
struct ext_css_set *ext_src_set, *tmp_cset;
|
||||
|
||||
lockdep_assert_held(&cgroup_mutex);
|
||||
|
||||
/* look up the dst cset for each src cset and link it to src */
|
||||
list_for_each_entry_safe(src_cset, tmp_cset, &mgctx->preloaded_src_csets,
|
||||
mg_preload_node) {
|
||||
list_for_each_entry_safe(ext_src_set, tmp_cset, &mgctx->preloaded_src_csets,
|
||||
mg_src_preload_node) {
|
||||
struct css_set *src_cset = &ext_src_set->cset;
|
||||
struct css_set *dst_cset;
|
||||
struct ext_css_set *ext_dst_cset;
|
||||
struct cgroup_subsys *ss;
|
||||
int ssid;
|
||||
|
||||
dst_cset = find_css_set(src_cset, src_cset->mg_dst_cgrp);
|
||||
if (!dst_cset)
|
||||
return -ENOMEM;
|
||||
ext_dst_cset = container_of(dst_cset, struct ext_css_set, cset);
|
||||
|
||||
WARN_ON_ONCE(src_cset->mg_dst_cset || dst_cset->mg_dst_cset);
|
||||
|
||||
|
|
@ -2798,7 +2816,7 @@ int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
|
|||
if (src_cset == dst_cset) {
|
||||
src_cset->mg_src_cgrp = NULL;
|
||||
src_cset->mg_dst_cgrp = NULL;
|
||||
list_del_init(&src_cset->mg_preload_node);
|
||||
list_del_init(&ext_src_set->mg_src_preload_node);
|
||||
put_css_set(src_cset);
|
||||
put_css_set(dst_cset);
|
||||
continue;
|
||||
|
|
@ -2806,8 +2824,8 @@ int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
|
|||
|
||||
src_cset->mg_dst_cset = dst_cset;
|
||||
|
||||
if (list_empty(&dst_cset->mg_preload_node))
|
||||
list_add_tail(&dst_cset->mg_preload_node,
|
||||
if (list_empty(&ext_dst_cset->mg_dst_preload_node))
|
||||
list_add_tail(&ext_dst_cset->mg_dst_preload_node,
|
||||
&mgctx->preloaded_dst_csets);
|
||||
else
|
||||
put_css_set(dst_cset);
|
||||
|
|
@ -3026,8 +3044,8 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
|
|||
DEFINE_CGROUP_MGCTX(mgctx);
|
||||
struct cgroup_subsys_state *d_css;
|
||||
struct cgroup *dsct;
|
||||
struct css_set *src_cset;
|
||||
bool has_tasks;
|
||||
struct ext_css_set *ext_src_set;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&cgroup_mutex);
|
||||
|
|
@ -3057,11 +3075,12 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
|
|||
goto out_finish;
|
||||
|
||||
spin_lock_irq(&css_set_lock);
|
||||
list_for_each_entry(src_cset, &mgctx.preloaded_src_csets, mg_preload_node) {
|
||||
list_for_each_entry(ext_src_set, &mgctx.preloaded_src_csets,
|
||||
mg_src_preload_node) {
|
||||
struct task_struct *task, *ntask;
|
||||
|
||||
/* all tasks in src_csets need to be migrated */
|
||||
list_for_each_entry_safe(task, ntask, &src_cset->tasks, cg_list)
|
||||
list_for_each_entry_safe(task, ntask, &ext_src_set->cset.tasks, cg_list)
|
||||
cgroup_migrate_add_task(task, &mgctx);
|
||||
}
|
||||
spin_unlock_irq(&css_set_lock);
|
||||
|
|
|
|||
50
mm/filemap.c
50
mm/filemap.c
|
|
@ -2495,7 +2495,9 @@ static struct file *do_async_mmap_readahead(struct vm_fault *vmf,
|
|||
* it in the page cache, and handles the special cases reasonably without
|
||||
* having a lot of duplicated code.
|
||||
*
|
||||
* vma->vm_mm->mmap_sem must be held on entry (except FAULT_FLAG_SPECULATIVE).
|
||||
* If FAULT_FLAG_SPECULATIVE is set, this function runs with elevated vma
|
||||
* refcount and with mmap lock not held.
|
||||
* Otherwise, vma->vm_mm->mmap_sem must be held on entry.
|
||||
*
|
||||
* If our return value has VM_FAULT_RETRY set, it's because the mmap_sem
|
||||
* may be dropped before doing I/O or by lock_page_maybe_drop_mmap().
|
||||
|
|
@ -2520,6 +2522,52 @@ vm_fault_t filemap_fault(struct vm_fault *vmf)
|
|||
struct page *page;
|
||||
vm_fault_t ret = 0;
|
||||
|
||||
if (vmf->flags & FAULT_FLAG_SPECULATIVE) {
|
||||
page = find_get_page(mapping, offset);
|
||||
if (unlikely(!page))
|
||||
return VM_FAULT_RETRY;
|
||||
|
||||
if (unlikely(PageReadahead(page)))
|
||||
goto page_put;
|
||||
|
||||
if (!trylock_page(page))
|
||||
goto page_put;
|
||||
|
||||
if (unlikely(compound_head(page)->mapping != mapping))
|
||||
goto page_unlock;
|
||||
VM_BUG_ON_PAGE(page_to_pgoff(page) != offset, page);
|
||||
if (unlikely(!PageUptodate(page)))
|
||||
goto page_unlock;
|
||||
|
||||
max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
|
||||
if (unlikely(offset >= max_off))
|
||||
goto page_unlock;
|
||||
|
||||
/*
|
||||
* Update readahead mmap_miss statistic.
|
||||
*
|
||||
* Note that we are not sure if finish_fault() will
|
||||
* manage to complete the transaction. If it fails,
|
||||
* we'll come back to filemap_fault() non-speculative
|
||||
* case which will update mmap_miss a second time.
|
||||
* This is not ideal, we would prefer to guarantee the
|
||||
* update will happen exactly once.
|
||||
*/
|
||||
if (!(vmf->vma->vm_flags & VM_RAND_READ) && ra->ra_pages) {
|
||||
unsigned int mmap_miss = READ_ONCE(ra->mmap_miss);
|
||||
if (mmap_miss)
|
||||
WRITE_ONCE(ra->mmap_miss, --mmap_miss);
|
||||
}
|
||||
|
||||
vmf->page = page;
|
||||
return VM_FAULT_LOCKED;
|
||||
page_unlock:
|
||||
unlock_page(page);
|
||||
page_put:
|
||||
put_page(page);
|
||||
return VM_FAULT_RETRY;
|
||||
}
|
||||
|
||||
max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
|
||||
if (unlikely(offset >= max_off))
|
||||
return VM_FAULT_SIGBUS;
|
||||
|
|
|
|||
|
|
@ -1343,6 +1343,7 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr)
|
|||
if (!pmd)
|
||||
goto drop_hpage;
|
||||
|
||||
vm_write_begin(vma);
|
||||
start_pte = pte_offset_map_lock(mm, pmd, haddr, &ptl);
|
||||
|
||||
/* step 1: check all mapped PTEs are to the right huge page */
|
||||
|
|
@ -1392,6 +1393,7 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr)
|
|||
ptl = pmd_lock(vma->vm_mm, pmd);
|
||||
_pmd = pmdp_collapse_flush(vma, haddr, pmd);
|
||||
spin_unlock(ptl);
|
||||
vm_write_end(vma);
|
||||
mm_dec_nr_ptes(mm);
|
||||
pte_free(mm, pmd_pgtable(_pmd));
|
||||
|
||||
|
|
@ -1402,6 +1404,7 @@ drop_hpage:
|
|||
|
||||
abort:
|
||||
pte_unmap_unlock(start_pte, ptl);
|
||||
vm_write_end(vma);
|
||||
goto drop_hpage;
|
||||
}
|
||||
|
||||
|
|
@ -1473,10 +1476,12 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
|
|||
*/
|
||||
if (down_write_trylock(&mm->mmap_sem)) {
|
||||
if (!khugepaged_test_exit(mm)) {
|
||||
vm_write_begin(vma);
|
||||
spinlock_t *ptl = pmd_lock(mm, pmd);
|
||||
/* assume page table is clear */
|
||||
_pmd = pmdp_collapse_flush(vma, addr, pmd);
|
||||
spin_unlock(ptl);
|
||||
vm_write_end(vma);
|
||||
mm_dec_nr_ptes(mm);
|
||||
pte_free(mm, pmd_pgtable(_pmd));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -500,11 +500,9 @@ static void madvise_cold_page_range(struct mmu_gather *tlb,
|
|||
.target_task = task,
|
||||
};
|
||||
|
||||
vm_write_begin(vma);
|
||||
tlb_start_vma(tlb, vma);
|
||||
walk_page_range(vma->vm_mm, addr, end, &cold_walk_ops, &walk_private);
|
||||
tlb_end_vma(tlb, vma);
|
||||
vm_write_end(vma);
|
||||
}
|
||||
|
||||
static long madvise_cold(struct task_struct *task,
|
||||
|
|
@ -538,11 +536,9 @@ static void madvise_pageout_page_range(struct mmu_gather *tlb,
|
|||
.target_task = task,
|
||||
};
|
||||
|
||||
vm_write_begin(vma);
|
||||
tlb_start_vma(tlb, vma);
|
||||
walk_page_range(vma->vm_mm, addr, end, &cold_walk_ops, &walk_private);
|
||||
tlb_end_vma(tlb, vma);
|
||||
vm_write_end(vma);
|
||||
}
|
||||
|
||||
static inline bool can_do_pageout(struct vm_area_struct *vma)
|
||||
|
|
@ -745,12 +741,10 @@ static int madvise_free_single_vma(struct vm_area_struct *vma,
|
|||
update_hiwater_rss(mm);
|
||||
|
||||
mmu_notifier_invalidate_range_start(&range);
|
||||
vm_write_begin(vma);
|
||||
tlb_start_vma(&tlb, vma);
|
||||
walk_page_range(vma->vm_mm, range.start, range.end,
|
||||
&madvise_free_walk_ops, &tlb);
|
||||
tlb_end_vma(&tlb, vma);
|
||||
vm_write_end(vma);
|
||||
mmu_notifier_invalidate_range_end(&range);
|
||||
tlb_finish_mmu(&tlb, range.start, range.end);
|
||||
|
||||
|
|
|
|||
42
mm/memory.c
42
mm/memory.c
|
|
@ -1292,7 +1292,6 @@ void unmap_page_range(struct mmu_gather *tlb,
|
|||
unsigned long next;
|
||||
|
||||
BUG_ON(addr >= end);
|
||||
vm_write_begin(vma);
|
||||
tlb_start_vma(tlb, vma);
|
||||
pgd = pgd_offset(vma->vm_mm, addr);
|
||||
do {
|
||||
|
|
@ -1302,7 +1301,6 @@ void unmap_page_range(struct mmu_gather *tlb,
|
|||
next = zap_p4d_range(tlb, vma, pgd, addr, next, details);
|
||||
} while (pgd++, addr = next, addr != end);
|
||||
tlb_end_vma(tlb, vma);
|
||||
vm_write_end(vma);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3050,6 +3048,11 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
|
|||
int exclusive = 0;
|
||||
vm_fault_t ret;
|
||||
|
||||
if (vmf->flags & FAULT_FLAG_SPECULATIVE) {
|
||||
pte_unmap(vmf->pte);
|
||||
return VM_FAULT_RETRY;
|
||||
}
|
||||
|
||||
ret = pte_unmap_same(vmf);
|
||||
if (ret) {
|
||||
/*
|
||||
|
|
@ -3296,6 +3299,10 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
|
|||
if (vmf->vma_flags & VM_SHARED)
|
||||
return VM_FAULT_SIGBUS;
|
||||
|
||||
/* Do not check unstable pmd, if it's changed will retry later */
|
||||
if (vmf->flags & FAULT_FLAG_SPECULATIVE)
|
||||
goto skip_pmd_checks;
|
||||
|
||||
/*
|
||||
* Use pte_alloc() instead of pte_alloc_map(). We can't run
|
||||
* pte_offset_map() on pmds where a huge pmd might be created
|
||||
|
|
@ -3313,6 +3320,7 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
|
|||
if (unlikely(pmd_trans_unstable(vmf->pmd)))
|
||||
return 0;
|
||||
|
||||
skip_pmd_checks:
|
||||
/* Use the zero-page for reads */
|
||||
if (!(vmf->flags & FAULT_FLAG_WRITE) &&
|
||||
!mm_forbids_zeropage(vma->vm_mm)) {
|
||||
|
|
@ -3417,6 +3425,10 @@ static vm_fault_t __do_fault(struct vm_fault *vmf)
|
|||
struct vm_area_struct *vma = vmf->vma;
|
||||
vm_fault_t ret;
|
||||
|
||||
/* Do not check unstable pmd, if it's changed will retry later */
|
||||
if (vmf->flags & FAULT_FLAG_SPECULATIVE)
|
||||
goto skip_pmd_checks;
|
||||
|
||||
/*
|
||||
* Preallocate pte before we take page_lock because this might lead to
|
||||
* deadlocks for memcg reclaim which waits for pages under writeback:
|
||||
|
|
@ -3439,6 +3451,7 @@ static vm_fault_t __do_fault(struct vm_fault *vmf)
|
|||
smp_wmb(); /* See comment in __pte_alloc() */
|
||||
}
|
||||
|
||||
skip_pmd_checks:
|
||||
ret = vma->vm_ops->fault(vmf);
|
||||
if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY |
|
||||
VM_FAULT_DONE_COW)))
|
||||
|
|
@ -3812,7 +3825,8 @@ static vm_fault_t do_fault_around(struct vm_fault *vmf)
|
|||
end_pgoff = min3(end_pgoff, vma_pages(vmf->vma) + vmf->vma->vm_pgoff - 1,
|
||||
start_pgoff + nr_pages - 1);
|
||||
|
||||
if (pmd_none(*vmf->pmd)) {
|
||||
if (!(vmf->flags & FAULT_FLAG_SPECULATIVE) &&
|
||||
pmd_none(*vmf->pmd)) {
|
||||
vmf->prealloc_pte = pte_alloc_one(vmf->vma->vm_mm);
|
||||
if (!vmf->prealloc_pte)
|
||||
goto out;
|
||||
|
|
@ -4179,16 +4193,11 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
|
|||
pte_t entry;
|
||||
vm_fault_t ret = 0;
|
||||
|
||||
/* Do not check unstable pmd, if it's changed will retry later */
|
||||
if (vmf->flags & FAULT_FLAG_SPECULATIVE)
|
||||
goto skip_pmd_checks;
|
||||
|
||||
if (unlikely(pmd_none(*vmf->pmd))) {
|
||||
/*
|
||||
* In the case of the speculative page fault handler we abort
|
||||
* the speculative path immediately as the pmd is probably
|
||||
* in the way to be converted in a huge one. We will try
|
||||
* again holding the mmap_sem (which implies that the collapse
|
||||
* operation is done).
|
||||
*/
|
||||
if (vmf->flags & FAULT_FLAG_SPECULATIVE)
|
||||
return VM_FAULT_RETRY;
|
||||
/*
|
||||
* Leave __pte_alloc() until later: because vm_ops->fault may
|
||||
* want to allocate huge page, and if we expose page table
|
||||
|
|
@ -4196,8 +4205,7 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
|
|||
* concurrent faults and from rmap lookups.
|
||||
*/
|
||||
vmf->pte = NULL;
|
||||
} else if (!(vmf->flags & FAULT_FLAG_SPECULATIVE)) {
|
||||
/* See comment in pte_alloc_one_map() */
|
||||
} else {
|
||||
if (pmd_devmap_trans_unstable(vmf->pmd))
|
||||
return 0;
|
||||
/*
|
||||
|
|
@ -4227,6 +4235,7 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
|
|||
}
|
||||
}
|
||||
|
||||
skip_pmd_checks:
|
||||
if (!vmf->pte) {
|
||||
if (vma_is_anonymous(vmf->vma))
|
||||
return do_anonymous_page(vmf);
|
||||
|
|
@ -4465,9 +4474,8 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address,
|
|||
pol = __get_vma_policy(vmf.vma, address);
|
||||
if (!pol)
|
||||
pol = get_task_policy(current);
|
||||
if (!pol)
|
||||
if (pol && pol->mode == MPOL_INTERLEAVE)
|
||||
return VM_FAULT_RETRY;
|
||||
if (pol && pol->mode == MPOL_INTERLEAVE)
|
||||
return VM_FAULT_RETRY;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -599,11 +599,9 @@ unsigned long change_prot_numa(struct vm_area_struct *vma,
|
|||
{
|
||||
int nr_updated;
|
||||
|
||||
vm_write_begin(vma);
|
||||
nr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1);
|
||||
if (nr_updated)
|
||||
count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated);
|
||||
vm_write_end(vma);
|
||||
|
||||
return nr_updated;
|
||||
}
|
||||
|
|
|
|||
18
mm/mmap.c
18
mm/mmap.c
|
|
@ -2344,8 +2344,22 @@ struct vm_area_struct *get_vma(struct mm_struct *mm, unsigned long addr)
|
|||
|
||||
read_lock(&mm->mm_rb_lock);
|
||||
vma = __find_vma(mm, addr);
|
||||
if (vma)
|
||||
atomic_inc(&vma->vm_ref_count);
|
||||
|
||||
/*
|
||||
* If there is a concurrent fast mremap, bail out since the entire
|
||||
* PMD/PUD subtree may have been remapped.
|
||||
*
|
||||
* This is usually safe for conventional mremap since it takes the
|
||||
* PTE locks as does SPF. However fast mremap only takes the lock
|
||||
* at the PMD/PUD level which is ok as it is done with the mmap
|
||||
* write lock held. But since SPF, as the term implies forgoes,
|
||||
* taking the mmap read lock and also cannot take PTL lock at the
|
||||
* larger PMD/PUD granualrity, since it would introduce huge
|
||||
* contention in the page fault path; fall back to regular fault
|
||||
* handling.
|
||||
*/
|
||||
if (vma && !atomic_inc_unless_negative(&vma->vm_ref_count))
|
||||
vma = NULL;
|
||||
read_unlock(&mm->mm_rb_lock);
|
||||
|
||||
return vma;
|
||||
|
|
|
|||
41
mm/mremap.c
41
mm/mremap.c
|
|
@ -191,6 +191,38 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
|
|||
drop_rmap_locks(vma);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
|
||||
static inline bool trylock_vma_ref_count(struct vm_area_struct *vma)
|
||||
{
|
||||
/*
|
||||
* If we have the only reference, swap the refcount to -1. This
|
||||
* will prevent other concurrent references by get_vma() for SPFs.
|
||||
*/
|
||||
return atomic_cmpxchg(&vma->vm_ref_count, 1, -1) == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the VMA reference count to 1 after a fast mremap.
|
||||
*/
|
||||
static inline void unlock_vma_ref_count(struct vm_area_struct *vma)
|
||||
{
|
||||
/*
|
||||
* This should only be called after a corresponding,
|
||||
* successful trylock_vma_ref_count().
|
||||
*/
|
||||
VM_BUG_ON_VMA(atomic_cmpxchg(&vma->vm_ref_count, -1, 1) != -1,
|
||||
vma);
|
||||
}
|
||||
#else /* !CONFIG_SPECULATIVE_PAGE_FAULT */
|
||||
static inline bool trylock_vma_ref_count(struct vm_area_struct *vma)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
static inline void unlock_vma_ref_count(struct vm_area_struct *vma)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
|
||||
|
||||
#ifdef CONFIG_HAVE_MOVE_PMD
|
||||
static bool move_normal_pmd(struct vm_area_struct *vma, unsigned long old_addr,
|
||||
unsigned long new_addr, unsigned long old_end,
|
||||
|
|
@ -211,6 +243,14 @@ static bool move_normal_pmd(struct vm_area_struct *vma, unsigned long old_addr,
|
|||
if (WARN_ON(!pmd_none(*new_pmd)))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* We hold both exclusive mmap_lock and rmap_lock at this point and
|
||||
* cannot block. If we cannot immediately take exclusive ownership
|
||||
* of the VMA fallback to the move_ptes().
|
||||
*/
|
||||
if (!trylock_vma_ref_count(vma))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* We don't have to worry about the ordering of src and dst
|
||||
* ptlocks because exclusive mmap_sem prevents deadlock.
|
||||
|
|
@ -233,6 +273,7 @@ static bool move_normal_pmd(struct vm_area_struct *vma, unsigned long old_addr,
|
|||
spin_unlock(new_ptl);
|
||||
spin_unlock(old_ptl);
|
||||
|
||||
unlock_vma_ref_count(vma);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1137,14 +1137,16 @@ static void ip6gre_tnl_link_config_route(struct ip6_tnl *t, int set_mtu,
|
|||
dev->needed_headroom = dst_len;
|
||||
|
||||
if (set_mtu) {
|
||||
dev->mtu = rt->dst.dev->mtu - t_hlen;
|
||||
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
|
||||
dev->mtu -= 8;
|
||||
if (dev->type == ARPHRD_ETHER)
|
||||
dev->mtu -= ETH_HLEN;
|
||||
int mtu = rt->dst.dev->mtu - t_hlen;
|
||||
|
||||
if (dev->mtu < IPV6_MIN_MTU)
|
||||
dev->mtu = IPV6_MIN_MTU;
|
||||
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
|
||||
mtu -= 8;
|
||||
if (dev->type == ARPHRD_ETHER)
|
||||
mtu -= ETH_HLEN;
|
||||
|
||||
if (mtu < IPV6_MIN_MTU)
|
||||
mtu = IPV6_MIN_MTU;
|
||||
WRITE_ONCE(dev->mtu, mtu);
|
||||
}
|
||||
}
|
||||
ip6_rt_put(rt);
|
||||
|
|
|
|||
|
|
@ -1430,6 +1430,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
|
|||
struct __ip6_tnl_parm *p = &t->parms;
|
||||
struct flowi6 *fl6 = &t->fl.u.ip6;
|
||||
int t_hlen;
|
||||
int mtu;
|
||||
|
||||
memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr));
|
||||
memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr));
|
||||
|
|
@ -1472,12 +1473,13 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
|
|||
dev->hard_header_len = rt->dst.dev->hard_header_len +
|
||||
t_hlen;
|
||||
|
||||
dev->mtu = rt->dst.dev->mtu - t_hlen;
|
||||
mtu = rt->dst.dev->mtu - t_hlen;
|
||||
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
|
||||
dev->mtu -= 8;
|
||||
mtu -= 8;
|
||||
|
||||
if (dev->mtu < IPV6_MIN_MTU)
|
||||
dev->mtu = IPV6_MIN_MTU;
|
||||
if (mtu < IPV6_MIN_MTU)
|
||||
mtu = IPV6_MIN_MTU;
|
||||
WRITE_ONCE(dev->mtu, mtu);
|
||||
}
|
||||
ip6_rt_put(rt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1083,10 +1083,12 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
|
|||
|
||||
if (tdev && !netif_is_l3_master(tdev)) {
|
||||
int t_hlen = tunnel->hlen + sizeof(struct iphdr);
|
||||
int mtu;
|
||||
|
||||
dev->mtu = tdev->mtu - t_hlen;
|
||||
if (dev->mtu < IPV6_MIN_MTU)
|
||||
dev->mtu = IPV6_MIN_MTU;
|
||||
mtu = tdev->mtu - t_hlen;
|
||||
if (mtu < IPV6_MIN_MTU)
|
||||
mtu = IPV6_MIN_MTU;
|
||||
WRITE_ONCE(dev->mtu, mtu);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -255,6 +255,8 @@ static int tcf_em_validate(struct tcf_proto *tp,
|
|||
* the value carried.
|
||||
*/
|
||||
if (em_hdr->flags & TCF_EM_SIMPLE) {
|
||||
if (em->ops->datalen > 0)
|
||||
goto errout;
|
||||
if (data_len < sizeof(u32))
|
||||
goto errout;
|
||||
em->data = *(u32 *) data;
|
||||
|
|
|
|||
Loading…
Reference in a new issue